Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Oct 2010 00:58:44 +0000 (17:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 27 Oct 2010 00:58:44 +0000 (17:58 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (52 commits)
  split invalidate_inodes()
  fs: skip I_FREEING inodes in writeback_sb_inodes
  fs: fold invalidate_list into invalidate_inodes
  fs: do not drop inode_lock in dispose_list
  fs: inode split IO and LRU lists
  fs: switch bdev inode bdi's correctly
  fs: fix buffer invalidation in invalidate_list
  fsnotify: use dget_parent
  smbfs: use dget_parent
  exportfs: use dget_parent
  fs: use RCU read side protection in d_validate
  fs: clean up dentry lru modification
  fs: split __shrink_dcache_sb
  fs: improve DCACHE_REFERENCED usage
  fs: use percpu counter for nr_dentry and nr_dentry_unused
  fs: simplify __d_free
  fs: take dcache_lock inside __d_path
  fs: do not assign default i_ino in new_inode
  fs: introduce a per-cpu last_ino allocator
  new helper: ihold()
  ...

897 files changed:
Documentation/DocBook/device-drivers.tmpl
Documentation/DocBook/kernel-api.tmpl
Documentation/feature-removal-schedule.txt
Documentation/filesystems/nfs/00-INDEX
Documentation/filesystems/nfs/idmapper.txt [new file with mode: 0644]
Documentation/filesystems/nfs/nfsroot.txt
Documentation/filesystems/nfs/pnfs.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/hwmon/ltc4261 [new file with mode: 0644]
Documentation/kernel-parameters.txt
Documentation/misc-devices/apds990x.txt [new file with mode: 0644]
Documentation/misc-devices/bh1770glc.txt [new file with mode: 0644]
Documentation/sysrq.txt
Documentation/timers/hpet_example.c
Documentation/trace/postprocess/trace-vmscan-postprocess.pl
Documentation/vm/highmem.txt [new file with mode: 0644]
MAINTAINERS
arch/alpha/Kconfig
arch/alpha/include/asm/core_mcpcia.h
arch/alpha/include/asm/core_t2.h
arch/alpha/include/asm/pgtable.h
arch/alpha/kernel/core_t2.c
arch/alpha/kernel/machvec_impl.h
arch/arm/Kconfig
arch/arm/configs/n8x0_defconfig [deleted file]
arch/arm/configs/omap2plus_defconfig [new file with mode: 0644]
arch/arm/configs/omap3_defconfig [deleted file]
arch/arm/configs/omap_4430sdp_defconfig [deleted file]
arch/arm/configs/omap_generic_2420_defconfig [deleted file]
arch/arm/configs/pcontrol_g20_defconfig [new file with mode: 0644]
arch/arm/include/asm/highmem.h
arch/arm/include/asm/pgtable.h
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9_alt_reset.S [new file with mode: 0644]
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/board-pcontrol-g20.c [new file with mode: 0644]
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/pm_slowclock.S
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-kirkwood/netspace_v2-setup.c
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/board-h2-mmc.c
arch/arm/mach-omap1/board-h3-mmc.c
arch/arm/mach-omap1/board-htcherald.c
arch/arm/mach-omap1/board-sx1-mmc.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap1/include/mach/camera.h [new file with mode: 0644]
arch/arm/mach-omap1/pm_bus.c [new file with mode: 0644]
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-3630sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-am3517evm.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-cm-t3517.c [new file with mode: 0644]
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-flash.c
arch/arm/mach-omap2/board-flash.h [new file with mode: 0644]
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-igep0030.c [new file with mode: 0644]
arch/arm/mach-omap2/board-ldp.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3logic.c [new file with mode: 0644]
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/board-rx51-sdram.c
arch/arm/mach-omap2/board-rx51-video.c
arch/arm/mach-omap2/board-zoom-debugboard.c
arch/arm/mach-omap2/board-zoom-peripherals.c
arch/arm/mach-omap2/board-zoom2.c
arch/arm/mach-omap2/board-zoom3.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clockdomain.c
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm-regbits-44xx.h
arch/arm/mach-omap2/cm44xx.h
arch/arm/mach-omap2/cm4xxx.c
arch/arm/mach-omap2/common.c [new file with mode: 0644]
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/control.h [new file with mode: 0644]
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/gpmc-smsc911x.c [new file with mode: 0644]
arch/arm/mach-omap2/hsmmc.c
arch/arm/mach-omap2/hsmmc.h
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/include/mach/board-flash.h [deleted file]
arch/arm/mach-omap2/include/mach/board-rx51.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/board-zoom.h
arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h [new file with mode: 0644]
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/io.h [new file with mode: 0644]
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/mcbsp.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/mux.h
arch/arm/mach-omap2/mux2420.c
arch/arm/mach-omap2/mux2430.c
arch/arm/mach-omap2/mux34xx.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm24xx.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/pm_bus.c [new file with mode: 0644]
arch/arm/mach-omap2/powerdomains44xx.h
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prm-regbits-34xx.h
arch/arm/mach-omap2/prm-regbits-44xx.h
arch/arm/mach-omap2/prm.h
arch/arm/mach-omap2/prm2xxx_3xxx.c [new file with mode: 0644]
arch/arm/mach-omap2/prm44xx.c [new file with mode: 0644]
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/serial.c
arch/arm/mach-omap2/sleep34xx.S
arch/arm/mach-omap2/sram34xx.S
arch/arm/mach-omap2/timer-gp.c
arch/arm/mach-omap2/timer-gp.h [new file with mode: 0644]
arch/arm/mach-omap2/usb-fs.c
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board-harmony-pcie.c [new file with mode: 0644]
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/clock.h
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/cpu-tegra.c [new file with mode: 0644]
arch/arm/mach-tegra/dma.c [new file with mode: 0644]
arch/arm/mach-tegra/fuse.c [new file with mode: 0644]
arch/arm/mach-tegra/fuse.h [new file with mode: 0644]
arch/arm/mach-tegra/gpio.c
arch/arm/mach-tegra/include/mach/clk.h
arch/arm/mach-tegra/include/mach/dma.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/gpio.h
arch/arm/mach-tegra/include/mach/hardware.h
arch/arm/mach-tegra/include/mach/io.h
arch/arm/mach-tegra/include/mach/iomap.h
arch/arm/mach-tegra/include/mach/irqs.h
arch/arm/mach-tegra/include/mach/legacy_irq.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/pinmux-t2.h [new file with mode: 0644]
arch/arm/mach-tegra/include/mach/pinmux.h
arch/arm/mach-tegra/io.c
arch/arm/mach-tegra/irq.c
arch/arm/mach-tegra/legacy_irq.c [new file with mode: 0644]
arch/arm/mach-tegra/pcie.c [new file with mode: 0644]
arch/arm/mach-tegra/pinmux-t2-tables.c [new file with mode: 0644]
arch/arm/mach-tegra/pinmux.c
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mach-tegra/tegra2_dvfs.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra2_dvfs.h [new file with mode: 0644]
arch/arm/mm/fault-armv.c
arch/arm/mm/highmem.c
arch/arm/mm/pgd.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/clock.c
arch/arm/plat-omap/common.c
arch/arm/plat-omap/counter_32k.c [new file with mode: 0644]
arch/arm/plat-omap/cpu-omap.c
arch/arm/plat-omap/devices.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/fb.c
arch/arm/plat-omap/fb.h [new file with mode: 0644]
arch/arm/plat-omap/gpio.c
arch/arm/plat-omap/include/plat/common.h
arch/arm/plat-omap/include/plat/control.h [deleted file]
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/display.h
arch/arm/plat-omap/include/plat/dma.h
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-omap/include/plat/gpmc-smsc911x.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/i2c.h
arch/arm/plat-omap/include/plat/irqs.h
arch/arm/plat-omap/include/plat/mcbsp.h
arch/arm/plat-omap/include/plat/mmc.h
arch/arm/plat-omap/include/plat/omap-serial.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/omap24xx.h
arch/arm/plat-omap/include/plat/omap_device.h
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/include/plat/powerdomain.h
arch/arm/plat-omap/include/plat/prcm.h
arch/arm/plat-omap/include/plat/sdrc.h
arch/arm/plat-omap/include/plat/sram.h
arch/arm/plat-omap/include/plat/timer-gp.h [deleted file]
arch/arm/plat-omap/include/plat/uncompress.h
arch/arm/plat-omap/include/plat/usb.h
arch/arm/plat-omap/include/plat/vrfb.h
arch/arm/plat-omap/mcbsp.c
arch/arm/plat-omap/omap_device.c
arch/arm/plat-omap/sram.c
arch/arm/plat-omap/sram.h [new file with mode: 0644]
arch/avr32/include/asm/pgtable.h
arch/blackfin/Kconfig.debug
arch/blackfin/configs/BF518F-EZBRD_defconfig
arch/blackfin/configs/BF526-EZBRD_defconfig
arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
arch/blackfin/configs/BF527-EZKIT-V2_defconfig
arch/blackfin/configs/BF527-EZKIT_defconfig
arch/blackfin/configs/BF527-TLL6527M_defconfig
arch/blackfin/configs/BF533-EZKIT_defconfig
arch/blackfin/configs/BF533-STAMP_defconfig
arch/blackfin/configs/BF537-STAMP_defconfig
arch/blackfin/configs/BF538-EZKIT_defconfig
arch/blackfin/configs/BF548-EZKIT_defconfig
arch/blackfin/configs/BF561-ACVILON_defconfig
arch/blackfin/configs/BF561-EZKIT_defconfig
arch/blackfin/configs/BlackStamp_defconfig
arch/blackfin/configs/CM-BF527_defconfig
arch/blackfin/configs/CM-BF533_defconfig
arch/blackfin/configs/CM-BF537E_defconfig
arch/blackfin/configs/CM-BF537U_defconfig
arch/blackfin/configs/CM-BF548_defconfig
arch/blackfin/configs/CM-BF561_defconfig
arch/blackfin/configs/H8606_defconfig
arch/blackfin/configs/IP0X_defconfig
arch/blackfin/configs/PNAV-10_defconfig
arch/blackfin/configs/SRV1_defconfig
arch/blackfin/configs/TCM-BF518_defconfig
arch/blackfin/configs/TCM-BF537_defconfig
arch/blackfin/include/asm/bfin5xx_spi.h
arch/blackfin/include/asm/bfin_ppi.h
arch/blackfin/include/asm/bfin_twi.h [new file with mode: 0644]
arch/blackfin/include/asm/cdef_LPBlackfin.h
arch/blackfin/include/asm/entry.h
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/boards/tcm-bf518.c
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/boards/tll6527m.c
arch/blackfin/mach-bf537/boards/cm_bf537e.c
arch/blackfin/mach-bf537/boards/cm_bf537u.c
arch/blackfin/mach-bf537/boards/minotaur.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/boards/tcm_bf537.c
arch/blackfin/mach-common/Makefile
arch/blackfin/mach-common/irqpanic.c [deleted file]
arch/cris/include/asm/pgtable.h
arch/frv/include/asm/highmem.h
arch/frv/include/asm/pgtable.h
arch/frv/mb93090-mb00/pci-dma.c
arch/frv/mm/cache-page.c
arch/frv/mm/highmem.c
arch/ia64/include/asm/pgtable.h
arch/ia64/include/asm/siginfo.h
arch/m32r/include/asm/pgtable.h
arch/m68k/include/asm/entry_mm.h
arch/m68k/include/asm/entry_no.h
arch/m68k/include/asm/motorola_pgtable.h
arch/m68k/include/asm/sun3_pgtable.h
arch/microblaze/Kconfig
arch/microblaze/Kconfig.debug
arch/microblaze/Makefile
arch/microblaze/include/asm/byteorder.h
arch/microblaze/include/asm/checksum.h
arch/microblaze/include/asm/cpuinfo.h
arch/microblaze/include/asm/elf.h
arch/microblaze/include/asm/gpio.h
arch/microblaze/include/asm/io.h
arch/microblaze/include/asm/page.h
arch/microblaze/include/asm/pci.h
arch/microblaze/include/asm/pgalloc.h
arch/microblaze/include/asm/pgtable.h
arch/microblaze/include/asm/prom.h
arch/microblaze/include/asm/pvr.h
arch/microblaze/include/asm/seccomp.h [new file with mode: 0644]
arch/microblaze/include/asm/setup.h
arch/microblaze/include/asm/thread_info.h
arch/microblaze/include/asm/unaligned.h
arch/microblaze/include/asm/unistd.h
arch/microblaze/kernel/cpu/cpuinfo-pvr-full.c
arch/microblaze/kernel/cpu/cpuinfo-static.c
arch/microblaze/kernel/cpu/cpuinfo.c
arch/microblaze/kernel/cpu/mb.c
arch/microblaze/kernel/cpu/pvr.c
arch/microblaze/kernel/early_printk.c
arch/microblaze/kernel/entry.S
arch/microblaze/kernel/exceptions.c
arch/microblaze/kernel/heartbeat.c
arch/microblaze/kernel/intc.c
arch/microblaze/kernel/kgdb.c
arch/microblaze/kernel/microblaze_ksyms.c
arch/microblaze/kernel/prom.c
arch/microblaze/kernel/setup.c
arch/microblaze/kernel/syscall_table.S
arch/microblaze/kernel/timer.c
arch/microblaze/kernel/vmlinux.lds.S
arch/microblaze/lib/Makefile
arch/microblaze/lib/ashldi3.c [new file with mode: 0644]
arch/microblaze/lib/ashrdi3.c [new file with mode: 0644]
arch/microblaze/lib/divsi3.S [new file with mode: 0644]
arch/microblaze/lib/libgcc.h [new file with mode: 0644]
arch/microblaze/lib/lshrdi3.c [new file with mode: 0644]
arch/microblaze/lib/memcpy.c
arch/microblaze/lib/memmove.c
arch/microblaze/lib/memset.c
arch/microblaze/lib/modsi3.S [new file with mode: 0644]
arch/microblaze/lib/muldi3.S [new file with mode: 0644]
arch/microblaze/lib/mulsi3.S [new file with mode: 0644]
arch/microblaze/lib/udivsi3.S [new file with mode: 0644]
arch/microblaze/lib/umodsi3.S [new file with mode: 0644]
arch/microblaze/pci/pci-common.c
arch/microblaze/platform/generic/system.dts
arch/microblaze/platform/platform.c
arch/mips/include/asm/highmem.h
arch/mips/include/asm/pgtable-32.h
arch/mips/include/asm/pgtable-64.h
arch/mips/mm/highmem.c
arch/mn10300/include/asm/highmem.h
arch/mn10300/include/asm/pgtable.h
arch/mn10300/kernel/vmlinux.lds.S
arch/parisc/include/asm/pgtable.h
arch/powerpc/include/asm/highmem.h
arch/powerpc/include/asm/pgtable-ppc32.h
arch/powerpc/include/asm/pgtable-ppc64.h
arch/powerpc/kernel/vio.c
arch/powerpc/mm/highmem.c
arch/s390/include/asm/pgtable.h
arch/score/include/asm/pgtable.h
arch/sh/include/asm/pgtable_32.h
arch/sh/include/asm/pgtable_64.h
arch/sparc/include/asm/highmem.h
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/mm/highmem.c
arch/tile/Kconfig
arch/tile/Makefile
arch/tile/include/arch/sim.h [new file with mode: 0644]
arch/tile/include/arch/sim_def.h
arch/tile/include/arch/spr_def.h
arch/tile/include/arch/spr_def_32.h
arch/tile/include/asm/backtrace.h
arch/tile/include/asm/compat.h
arch/tile/include/asm/highmem.h
arch/tile/include/asm/irqflags.h
arch/tile/include/asm/mman.h
arch/tile/include/asm/page.h
arch/tile/include/asm/pgtable.h
arch/tile/include/asm/processor.h
arch/tile/include/asm/ptrace.h
arch/tile/include/asm/syscalls.h
arch/tile/include/asm/system.h
arch/tile/include/asm/traps.h
arch/tile/include/hv/hypervisor.h
arch/tile/kernel/backtrace.c
arch/tile/kernel/compat.c
arch/tile/kernel/compat_signal.c
arch/tile/kernel/entry.S
arch/tile/kernel/head_32.S
arch/tile/kernel/intvec_32.S
arch/tile/kernel/irq.c
arch/tile/kernel/messaging.c
arch/tile/kernel/process.c
arch/tile/kernel/ptrace.c
arch/tile/kernel/regs_32.S
arch/tile/kernel/setup.c
arch/tile/kernel/signal.c
arch/tile/kernel/single_step.c
arch/tile/kernel/smp.c
arch/tile/kernel/stack.c
arch/tile/kernel/sys.c
arch/tile/kernel/traps.c
arch/tile/kvm/Kconfig [new file with mode: 0644]
arch/tile/lib/Makefile
arch/tile/lib/atomic_32.c
arch/tile/lib/exports.c
arch/tile/lib/memcpy_32.S
arch/tile/lib/memmove.c [new file with mode: 0644]
arch/tile/lib/memmove_32.c [deleted file]
arch/tile/lib/memset_32.c
arch/tile/lib/strlen_32.c
arch/tile/mm/fault.c
arch/tile/mm/highmem.c
arch/tile/mm/homecache.c
arch/tile/mm/init.c
arch/um/Kconfig.um
arch/um/defconfig
arch/um/include/asm/dma-mapping.h [deleted file]
arch/um/include/asm/pgtable.h
arch/um/include/asm/system.h
arch/um/kernel/dyn.lds.S
arch/um/kernel/irq.c
arch/um/kernel/uml.lds.S
arch/um/os-Linux/time.c
arch/x86/include/asm/highmem.h
arch/x86/include/asm/iomap.h
arch/x86/include/asm/pgtable_32.h
arch/x86/include/asm/pgtable_64.h
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/cpu/cpufreq/cpufreq-nforce2.c
arch/x86/kernel/cpu/cpufreq/longrun.c
arch/x86/kernel/cpu/intel_cacheinfo.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/crash_dump_32.c
arch/x86/kernel/hpet.c
arch/x86/kernel/smpboot.c
arch/x86/mm/fault.c
arch/x86/mm/highmem_32.c
arch/x86/mm/iomap_32.c
arch/xtensa/include/asm/pgtable.h
crypto/async_tx/async_memcpy.c
crypto/blkcipher.c
drivers/acpi/Kconfig
drivers/acpi/ac.c
drivers/acpi/acpica/Makefile
drivers/acpi/acpica/acdebug.h
drivers/acpi/acpica/acevents.h
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/achware.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acnamesp.h
drivers/acpi/acpica/acobject.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/dsmethod.c
drivers/acpi/acpica/dswexec.c
drivers/acpi/acpica/evevent.c
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/evgpeinit.c
drivers/acpi/acpica/evmisc.c
drivers/acpi/acpica/evrgnini.c
drivers/acpi/acpica/evxface.c
drivers/acpi/acpica/evxfevnt.c
drivers/acpi/acpica/evxfregn.c
drivers/acpi/acpica/exfldio.c
drivers/acpi/acpica/exmutex.c
drivers/acpi/acpica/exprep.c
drivers/acpi/acpica/exregion.c
drivers/acpi/acpica/hwpci.c [new file with mode: 0644]
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/acpica/nsutils.c
drivers/acpi/acpica/tbfadt.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/acpica/uteval.c
drivers/acpi/acpica/utglobal.c
drivers/acpi/acpica/utids.c
drivers/acpi/acpica/utinit.c
drivers/acpi/acpica/utmath.c
drivers/acpi/acpica/utmisc.c
drivers/acpi/acpica/utmutex.c
drivers/acpi/acpica/utosi.c [new file with mode: 0644]
drivers/acpi/acpica/utxface.c
drivers/acpi/acpica/utxferror.c [new file with mode: 0644]
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/dock.c
drivers/acpi/ec.c
drivers/acpi/fan.c
drivers/acpi/osl.c
drivers/acpi/pci_irq.c
drivers/acpi/pci_link.c
drivers/acpi/pci_root.c
drivers/acpi/power.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_thermal.c
drivers/acpi/processor_throttling.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sleep.h
drivers/acpi/thermal.c
drivers/acpi/video.c
drivers/base/node.c
drivers/base/power/runtime.c
drivers/block/loop.c
drivers/char/hpet.c
drivers/char/hvc_tile.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/cpufreq/cpufreq.c
drivers/cpufreq/cpufreq_ondemand.c
drivers/crypto/hifn_795x.c
drivers/edac/edac_core.h
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/edac/i7core_edac.c
drivers/gpio/pca953x.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/ttm/ttm_bo_util.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/coretemp.c
drivers/hwmon/gpio-fan.c [new file with mode: 0644]
drivers/hwmon/hp_accel.c
drivers/hwmon/lis3lv02d.c
drivers/hwmon/lis3lv02d.h
drivers/hwmon/lis3lv02d_i2c.c
drivers/hwmon/lis3lv02d_spi.c
drivers/hwmon/ltc4261.c [new file with mode: 0644]
drivers/hwmon/pkgtemp.c
drivers/hwmon/via-cputemp.c
drivers/idle/intel_idle.c
drivers/infiniband/core/agent.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/iwcm.c
drivers/infiniband/core/mad.c
drivers/infiniband/core/multicast.c
drivers/infiniband/core/sa_query.c
drivers/infiniband/core/sysfs.c
drivers/infiniband/core/ucma.c
drivers/infiniband/core/ud_header.c
drivers/infiniband/core/user_mad.c
drivers/infiniband/core/uverbs_cmd.c
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/amso1100/Kbuild
drivers/infiniband/hw/amso1100/c2_intr.c
drivers/infiniband/hw/cxgb3/Makefile
drivers/infiniband/hw/cxgb3/cxio_hal.c
drivers/infiniband/hw/cxgb3/cxio_wr.h
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb3/iwch_ev.c
drivers/infiniband/hw/cxgb3/iwch_provider.c
drivers/infiniband/hw/cxgb3/iwch_qp.c
drivers/infiniband/hw/cxgb3/iwch_user.h
drivers/infiniband/hw/cxgb4/Makefile
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/cxgb4/device.c
drivers/infiniband/hw/cxgb4/ev.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/cxgb4/provider.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/cxgb4/resource.c
drivers/infiniband/hw/cxgb4/t4.h
drivers/infiniband/hw/cxgb4/user.h
drivers/infiniband/hw/ehca/ehca_mrmw.c
drivers/infiniband/hw/ipath/Makefile
drivers/infiniband/hw/mlx4/ah.c
drivers/infiniband/hw/mlx4/mad.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx4/mlx4_ib.h
drivers/infiniband/hw/mlx4/mr.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_nic.c
drivers/infiniband/hw/nes/nes_verbs.c
drivers/infiniband/hw/qib/qib.h
drivers/infiniband/hw/qib/qib_init.c
drivers/infiniband/hw/qib/qib_pcie.c
drivers/infiniband/hw/qib/qib_rc.c
drivers/infiniband/hw/qib/qib_uc.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/srp/ib_srp.c
drivers/infiniband/ulp/srp/ib_srp.h
drivers/macintosh/windfarm_pm121.c
drivers/md/dm-snap-persistent.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/ad525x_dpot-i2c.c
drivers/misc/ad525x_dpot-spi.c
drivers/misc/ad525x_dpot.c
drivers/misc/ad525x_dpot.h
drivers/misc/apds9802als.c [new file with mode: 0644]
drivers/misc/apds990x.c [new file with mode: 0644]
drivers/misc/bh1770glc.c [new file with mode: 0644]
drivers/misc/isl29020.c [new file with mode: 0644]
drivers/misc/lkdtm.c
drivers/misc/phantom.c
drivers/misc/sgi-xp/xpc_uv.c
drivers/mmc/host/Kconfig
drivers/mmc/host/omap_hsmmc.c
drivers/net/Kconfig
drivers/net/bfin_mac.c
drivers/net/bfin_mac.h
drivers/net/mlx4/en_main.c
drivers/net/mlx4/en_netdev.c
drivers/net/mlx4/en_port.c
drivers/net/mlx4/en_port.h
drivers/net/mlx4/fw.c
drivers/net/mlx4/intf.c
drivers/net/mlx4/main.c
drivers/net/mlx4/mlx4_en.h
drivers/net/mlx4/port.c
drivers/net/xilinx_emaclite.c
drivers/pnp/base.h
drivers/pnp/core.c
drivers/pnp/driver.c
drivers/pnp/pnpacpi/core.c
drivers/pnp/resource.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/bq20z75.c [new file with mode: 0644]
drivers/power/bq27x00_battery.c
drivers/power/ds2760_battery.c
drivers/power/ds2782_battery.c
drivers/power/isp1704_charger.c [new file with mode: 0644]
drivers/power/jz4740-battery.c
drivers/power/olpc_battery.c
drivers/power/pcf50633-charger.c
drivers/power/power_supply_sysfs.c
drivers/power/twl4030_charger.c [new file with mode: 0644]
drivers/power/wm831x_power.c
drivers/rtc/Kconfig
drivers/serial/Kconfig
drivers/serial/Makefile
drivers/serial/omap-serial.c [new file with mode: 0644]
drivers/spi/Kconfig
drivers/spi/Makefile
drivers/spi/spi_tegra.c [new file with mode: 0644]
drivers/usb/gadget/omap_udc.c
drivers/video/au1200fb.c
drivers/video/omap/lcd_omap3beagle.c
drivers/video/omap2/displays/Kconfig
drivers/video/omap2/displays/panel-acx565akm.c
drivers/video/omap2/displays/panel-generic.c
drivers/video/omap2/displays/panel-sharp-lq043t1dg01.c
drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c
drivers/video/omap2/displays/panel-toppoly-tdo35s.c
drivers/video/omap2/displays/panel-tpo-td043mtea1.c
drivers/video/omap2/dss/Makefile
drivers/video/omap2/dss/core.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss_features.c [new file with mode: 0644]
drivers/video/omap2/dss/dss_features.h [new file with mode: 0644]
drivers/video/omap2/dss/manager.c
drivers/video/omap2/dss/overlay.c
drivers/video/omap2/omapfb/Kconfig
drivers/video/omap2/omapfb/omapfb-main.c
drivers/video/xilinxfb.c
drivers/watchdog/omap_wdt.c
firmware/ihex2fw.c
fs/Makefile
fs/afs/write.c
fs/buffer.c
fs/ceph/addr.c
fs/cifs/file.c
fs/compat.c
fs/direct-io.c
fs/exec.c
fs/fs-writeback.c
fs/fuse/dev.c
fs/gfs2/meta_io.c
fs/hostfs/hostfs_user.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/lockd/host.c
fs/lockd/mon.c
fs/lockd/svc.c
fs/lockd/svc4proc.c
fs/lockd/svclock.c
fs/lockd/svcproc.c
fs/locks.c
fs/nfs/Kconfig
fs/nfs/Makefile
fs/nfs/callback.c
fs/nfs/callback_proc.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/dns_resolve.c
fs/nfs/file.c
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/mount_clnt.c
fs/nfs/nfs2xdr.c
fs/nfs/nfs3proc.c
fs/nfs/nfs3xdr.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4filelayout.c [new file with mode: 0644]
fs/nfs/nfs4filelayout.h [new file with mode: 0644]
fs/nfs/nfs4filelayoutdev.c [new file with mode: 0644]
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/nfsroot.c
fs/nfs/pnfs.c [new file with mode: 0644]
fs/nfs/pnfs.h [new file with mode: 0644]
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/nfs/sysctl.c
fs/nfs/unlink.c
fs/nfs/write.c
fs/nfsd/Kconfig
fs/nfsd/export.c
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/nfssvc.c
fs/nfsd/state.h
fs/nilfs2/segment.c
fs/proc/Kconfig
fs/proc/base.c
fs/reiserfs/inode.c
fs/signalfd.c
fs/xfs/linux-2.6/xfs_aops.c
include/acpi/acpi_bus.h
include/acpi/acpi_drivers.h
include/acpi/acpiosxf.h
include/acpi/acpixf.h
include/acpi/actypes.h
include/acpi/platform/acenv.h
include/acpi/platform/acgcc.h
include/acpi/platform/aclinux.h
include/asm-generic/vmlinux.lds.h
include/linux/acpi.h
include/linux/backing-dev.h
include/linux/bfin_mac.h [new file with mode: 0644]
include/linux/completion.h
include/linux/fs.h
include/linux/gfp.h
include/linux/gpio-fan.h [new file with mode: 0644]
include/linux/highmem.h
include/linux/hugetlb.h
include/linux/i2c/apds990x.h [new file with mode: 0644]
include/linux/i2c/bh1770glc.h [new file with mode: 0644]
include/linux/idr.h
include/linux/io-mapping.h
include/linux/kernel.h
include/linux/kfifo.h
include/linux/lis3lv02d.h
include/linux/math64.h
include/linux/memory_hotplug.h
include/linux/migrate.h
include/linux/mlx4/cmd.h
include/linux/mlx4/device.h
include/linux/mlx4/driver.h
include/linux/mlx4/qp.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/moduleparam.h
include/linux/net.h
include/linux/nfs4.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_idmap.h
include/linux/nfs_mount.h
include/linux/nfs_xdr.h
include/linux/pageblock-flags.h
include/linux/pagemap.h
include/linux/power_supply.h
include/linux/ratelimit.h
include/linux/rmap.h
include/linux/sched.h
include/linux/serial_core.h
include/linux/sfi.h
include/linux/signalfd.h
include/linux/sunrpc/auth.h
include/linux/sunrpc/cache.h
include/linux/sunrpc/clnt.h
include/linux/sunrpc/gss_spkm3.h [deleted file]
include/linux/sunrpc/stats.h
include/linux/sunrpc/svc_xprt.h
include/linux/sunrpc/svcauth.h
include/linux/sunrpc/xdr.h
include/linux/sunrpc/xprt.h
include/linux/swap.h
include/linux/types.h
include/linux/vmalloc.h
include/linux/workqueue.h
include/linux/writeback.h
include/rdma/ib_addr.h
include/rdma/ib_pack.h
include/rdma/ib_user_verbs.h
include/rdma/ib_verbs.h
include/scsi/srp.h
include/trace/events/ext4.h
include/trace/events/vmscan.h
include/trace/events/writeback.h
init/do_mounts.c
init/do_mounts_md.c
init/do_mounts_rd.c
init/initramfs.c
init/noinitramfs.c
kernel/exit.c
kernel/fork.c
kernel/kexec.c
kernel/power/snapshot.c
kernel/power/swap.c
kernel/printk.c
kernel/stop_machine.c
kernel/sysctl.c
kernel/user.c
kernel/wait.c
kernel/workqueue.c
lib/Kconfig.debug
lib/bitmap.c
lib/div64.c
lib/idr.c
lib/list_sort.c
lib/parser.c
lib/percpu_counter.c
lib/vsprintf.c
mm/backing-dev.c
mm/dmapool.c
mm/filemap.c
mm/highmem.c
mm/hugetlb.c
mm/internal.h
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/migrate.c
mm/mremap.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_isolation.c
mm/rmap.c
mm/slab.c
mm/swapfile.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/socket.c
net/sunrpc/Kconfig
net/sunrpc/auth.c
net/sunrpc/auth_generic.c
net/sunrpc/auth_gss/Makefile
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_spkm3_mech.c [deleted file]
net/sunrpc/auth_gss/gss_spkm3_seal.c [deleted file]
net/sunrpc/auth_gss/gss_spkm3_token.c [deleted file]
net/sunrpc/auth_gss/gss_spkm3_unseal.c [deleted file]
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c
net/sunrpc/clnt.c
net/sunrpc/netns.h [new file with mode: 0644]
net/sunrpc/rpcb_clnt.c
net/sunrpc/sched.c
net/sunrpc/stats.c
net/sunrpc/sunrpc_syms.c
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcauth_unix.c
net/sunrpc/svcsock.c
net/sunrpc/xdr.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/svc_rdma.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtsock.c
scripts/checkpatch.pl
scripts/get_maintainer.pl
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_iint.c
security/integrity/ima/ima_main.c
security/security.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c

index feca075..22edcbb 100644 (file)
      <sect1><title>Delaying, scheduling, and timer routines</title>
 !Iinclude/linux/sched.h
 !Ekernel/sched.c
+!Iinclude/linux/completion.h
 !Ekernel/timer.c
      </sect1>
+     <sect1><title>Wait queues and Wake events</title>
+!Iinclude/linux/wait.h
+!Ekernel/wait.c
+     </sect1>
      <sect1><title>High-resolution timers</title>
 !Iinclude/linux/ktime.h
 !Iinclude/linux/hrtimer.h
index 6b4e07f..7160652 100644 (file)
@@ -93,6 +93,12 @@ X!Ilib/string.c
 !Elib/crc32.c
 !Elib/crc-ccitt.c
      </sect1>
+
+     <sect1 id="idr"><title>idr/ida Functions</title>
+!Pinclude/linux/idr.h idr sync
+!Plib/idr.c IDA description
+!Elib/idr.c
+     </sect1>
   </chapter>
 
   <chapter id="mm">
index e833c8c..d2af87b 100644 (file)
@@ -535,3 +535,13 @@ Why:       Hareware scan is the prefer method for iwlwifi devices for
 Who:   Wey-Yi Guy <wey-yi.w.guy@intel.com>
 
 ----------------------------
+
+What:   access to nfsd auth cache through sys_nfsservctl or '.' files
+        in the 'nfsd' filesystem.
+When:   2.6.40
+Why:    This is a legacy interface which have been replaced by a more
+        dynamic cache.  Continuing to maintain this interface is an
+        unnecessary burden.
+Who:    NeilBrown <neilb@suse.de>
+
+----------------------------
index 2f68cd6..a57e124 100644 (file)
@@ -12,5 +12,9 @@ nfs-rdma.txt
        - how to install and setup the Linux NFS/RDMA client and server software
 nfsroot.txt
        - short guide on setting up a diskless box with NFS root filesystem.
+pnfs.txt
+       - short explanation of some of the internals of the pnfs client code
 rpc-cache.txt
        - introduction to the caching mechanisms in the sunrpc layer.
+idmapper.txt
+       - information for configuring request-keys to be used by idmapper
diff --git a/Documentation/filesystems/nfs/idmapper.txt b/Documentation/filesystems/nfs/idmapper.txt
new file mode 100644 (file)
index 0000000..b9b4192
--- /dev/null
@@ -0,0 +1,67 @@
+
+=========
+ID Mapper
+=========
+Id mapper is used by NFS to translate user and group ids into names, and to
+translate user and group names into ids.  Part of this translation involves
+performing an upcall to userspace to request the information.  Id mapper will
+user request-key to perform this upcall and cache the result.  The program
+/usr/sbin/nfs.idmap should be called by request-key, and will perform the
+translation and initialize a key with the resulting information.
+
+ NFS_USE_NEW_IDMAPPER must be selected when configuring the kernel to use this
+ feature.
+
+===========
+Configuring
+===========
+The file /etc/request-key.conf will need to be modified so /sbin/request-key can
+direct the upcall.  The following line should be added:
+
+#OP    TYPE    DESCRIPTION     CALLOUT INFO    PROGRAM ARG1 ARG2 ARG3 ...
+#======        ======= =============== =============== ===============================
+create id_resolver     *       *               /usr/sbin/nfs.idmap %k %d 600
+
+This will direct all id_resolver requests to the program /usr/sbin/nfs.idmap.
+The last parameter, 600, defines how many seconds into the future the key will
+expire.  This parameter is optional for /usr/sbin/nfs.idmap.  When the timeout
+is not specified, nfs.idmap will default to 600 seconds.
+
+id mapper uses for key descriptions:
+         uid:  Find the UID for the given user
+         gid:  Find the GID for the given group
+        user:  Find the user  name for the given UID
+       group:  Find the group name for the given GID
+
+You can handle any of these individually, rather than using the generic upcall
+program.  If you would like to use your own program for a uid lookup then you
+would edit your request-key.conf so it look similar to this:
+
+#OP    TYPE    DESCRIPTION     CALLOUT INFO    PROGRAM ARG1 ARG2 ARG3 ...
+#======        ======= =============== =============== ===============================
+create id_resolver     uid:*   *               /some/other/program %k %d 600
+create id_resolver     *       *               /usr/sbin/nfs.idmap %k %d 600
+
+Notice that the new line was added above the line for the generic program.
+request-key will find the first matching line and corresponding program.  In
+this case, /some/other/program will handle all uid lookups and
+/usr/sbin/nfs.idmap will handle gid, user, and group lookups.
+
+See <file:Documentation/keys-request-keys.txt> for more information about the
+request-key function.
+
+
+=========
+nfs.idmap
+=========
+nfs.idmap is designed to be called by request-key, and should not be run "by
+hand".  This program takes two arguments, a serialized key and a key
+description.  The serialized key is first converted into a key_serial_t, and
+then passed as an argument to keyctl_instantiate (both are part of keyutils.h).
+
+The actual lookups are performed by functions found in nfsidmap.h.  nfs.idmap
+determines the correct function to call by looking at the first part of the
+description string.  For example, a uid lookup description will appear as
+"uid:user@domain".
+
+nfs.idmap will return 0 if the key was instantiated, and non-zero otherwise.
index f2430a7..90c71c6 100644 (file)
@@ -159,6 +159,28 @@ ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
                 Default: any
 
 
+nfsrootdebug
+
+  This parameter enables debugging messages to appear in the kernel
+  log at boot time so that administrators can verify that the correct
+  NFS mount options, server address, and root path are passed to the
+  NFS client.
+
+
+rdinit=<executable file>
+
+  To specify which file contains the program that starts system
+  initialization, administrators can use this command line parameter.
+  The default value of this parameter is "/init".  If the specified
+  file exists and the kernel can execute it, root filesystem related
+  kernel command line parameters, including `nfsroot=', are ignored.
+
+  A description of the process of mounting the root file system can be
+  found in:
+
+    Documentation/early-userspace/README
+
+
 
 
 3.) Boot Loader
diff --git a/Documentation/filesystems/nfs/pnfs.txt b/Documentation/filesystems/nfs/pnfs.txt
new file mode 100644 (file)
index 0000000..bc0b9cf
--- /dev/null
@@ -0,0 +1,48 @@
+Reference counting in pnfs:
+==========================
+
+The are several inter-related caches.  We have layouts which can
+reference multiple devices, each of which can reference multiple data servers.
+Each data server can be referenced by multiple devices.  Each device
+can be referenced by multiple layouts.  To keep all of this straight,
+we need to reference count.
+
+
+struct pnfs_layout_hdr
+----------------------
+The on-the-wire command LAYOUTGET corresponds to struct
+pnfs_layout_segment, usually referred to by the variable name lseg.
+Each nfs_inode may hold a pointer to a cache of of these layout
+segments in nfsi->layout, of type struct pnfs_layout_hdr.
+
+We reference the header for the inode pointing to it, across each
+outstanding RPC call that references it (LAYOUTGET, LAYOUTRETURN,
+LAYOUTCOMMIT), and for each lseg held within.
+
+Each header is also (when non-empty) put on a list associated with
+struct nfs_client (cl_layouts).  Being put on this list does not bump
+the reference count, as the layout is kept around by the lseg that
+keeps it in the list.
+
+deviceid_cache
+--------------
+lsegs reference device ids, which are resolved per nfs_client and
+layout driver type.  The device ids are held in a RCU cache (struct
+nfs4_deviceid_cache).  The cache itself is referenced across each
+mount.  The entries (struct nfs4_deviceid) themselves are held across
+the lifetime of each lseg referencing them.
+
+RCU is used because the deviceid is basically a write once, read many
+data structure.  The hlist size of 32 buckets needs better
+justification, but seems reasonable given that we can have multiple
+deviceid's per filesystem, and multiple filesystems per nfs_client.
+
+The hash code is copied from the nfsd code base.  A discussion of
+hashing and variations of this algorithm can be found at:
+http://groups.google.com/group/comp.lang.c/browse_thread/thread/9522965e2b8d3809
+
+data server cache
+-----------------
+file driver devices refer to data servers, which are kept in a module
+level cache.  Its reference is held over the lifetime of the deviceid
+pointing to it.
index a6aca87..a563b74 100644 (file)
@@ -374,13 +374,13 @@ Swap:                  0 kB
 KernelPageSize:        4 kB
 MMUPageSize:           4 kB
 
-The first  of these lines shows  the same information  as is displayed for the
-mapping in /proc/PID/maps.  The remaining lines show  the size of the mapping,
-the amount of the mapping that is currently resident in RAM, the "proportional
-set size” (divide each shared page by the number of processes sharing it), the
-number of clean and dirty shared pages in the mapping, and the number of clean
-and dirty private pages in the mapping.  The "Referenced" indicates the amount
-of memory currently marked as referenced or accessed.
+The first of these lines shows the same information as is displayed for the
+mapping in /proc/PID/maps.  The remaining lines show the size of the mapping
+(size), the amount of the mapping that is currently resident in RAM (RSS), the
+process' proportional share of this mapping (PSS), the number of clean and
+dirty shared pages in the mapping, and the number of clean and dirty private
+pages in the mapping.  The "Referenced" indicates the amount of memory
+currently marked as referenced or accessed.
 
 This file is only present if the CONFIG_MMU kernel configuration option is
 enabled.
diff --git a/Documentation/hwmon/ltc4261 b/Documentation/hwmon/ltc4261
new file mode 100644 (file)
index 0000000..eba2e2c
--- /dev/null
@@ -0,0 +1,63 @@
+Kernel driver ltc4261
+=====================
+
+Supported chips:
+  * Linear Technology LTC4261
+    Prefix: 'ltc4261'
+    Addresses scanned: -
+    Datasheet:
+        http://cds.linear.com/docs/Datasheet/42612fb.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+The LTC4261/LTC4261-2 negative voltage Hot Swap controllers allow a board
+to be safely inserted and removed from a live backplane.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC4261 devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for an LTC4261 at address 0x10
+on I2C bus #1:
+$ modprobe ltc4261
+$ echo ltc4261 0x10 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Sysfs entries
+-------------
+
+Voltage readings provided by this driver are reported as obtained from the ADC
+registers. If a set of voltage divider resistors is installed, calculate the
+real voltage by multiplying the reported value with (R1+R2)/R2, where R1 is the
+value of the divider resistor against the measured voltage and R2 is the value
+of the divider resistor against Ground.
+
+Current reading provided by this driver is reported as obtained from the ADC
+Current Sense register. The reported value assumes that a 1 mOhm sense resistor
+is installed. If a different sense resistor is installed, calculate the real
+current by dividing the reported value by the sense resistor value in mOhm.
+
+The chip has two voltage sensors, but only one set of voltage alarm status bits.
+In many many designs, those alarms are associated with the ADIN2 sensor, due to
+the proximity of the ADIN2 pin to the OV pin. ADIN2 is, however, not available
+on all chip variants. To ensure that the alarm condition is reported to the user,
+report it with both voltage sensors.
+
+in1_input              ADIN2 voltage (mV)
+in1_min_alarm          ADIN/ADIN2 Undervoltage alarm
+in1_max_alarm          ADIN/ADIN2 Overvoltage alarm
+
+in2_input              ADIN voltage (mV)
+in2_min_alarm          ADIN/ADIN2 Undervoltage alarm
+in2_max_alarm          ADIN/ADIN2 Overvoltage alarm
+
+curr1_input            SENSE current (mA)
+curr1_alarm            SENSE overcurrent alarm
index b660085..4bc2f3c 100644 (file)
@@ -1541,12 +1541,15 @@ and is between 256 and 4096 characters. It is defined in the file
                        1 to enable accounting
                        Default value is 0.
 
-       nfsaddrs=       [NFS]
+       nfsaddrs=       [NFS] Deprecated.  Use ip= instead.
                        See Documentation/filesystems/nfs/nfsroot.txt.
 
        nfsroot=        [NFS] nfs root filesystem for disk-less boxes.
                        See Documentation/filesystems/nfs/nfsroot.txt.
 
+       nfsrootdebug    [NFS] enable nfsroot debugging messages.
+                       See Documentation/filesystems/nfs/nfsroot.txt.
+
        nfs.callback_tcpport=
                        [NFS] set the TCP port on which the NFSv4 callback
                        channel should listen.
diff --git a/Documentation/misc-devices/apds990x.txt b/Documentation/misc-devices/apds990x.txt
new file mode 100644 (file)
index 0000000..d5408ca
--- /dev/null
@@ -0,0 +1,111 @@
+Kernel driver apds990x
+======================
+
+Supported chips:
+Avago APDS990X
+
+Data sheet:
+Not freely available
+
+Author:
+Samu Onkalo <samu.p.onkalo@nokia.com>
+
+Description
+-----------
+
+APDS990x is a combined ambient light and proximity sensor. ALS and proximity
+functionality are highly connected. ALS measurement path must be running
+while the proximity functionality is enabled.
+
+ALS produces raw measurement values for two channels: Clear channel
+(infrared + visible light) and IR only. However, threshold comparisons happen
+using clear channel only. Lux value and the threshold level on the HW
+might vary quite much depending the spectrum of the light source.
+
+Driver makes necessary conversions to both directions so that user handles
+only lux values. Lux value is calculated using information from the both
+channels. HW threshold level is calculated from the given lux value to match
+with current type of the lightning. Sometimes inaccuracy of the estimations
+lead to false interrupt, but that doesn't harm.
+
+ALS contains 4 different gain steps. Driver automatically
+selects suitable gain step. After each measurement, reliability of the results
+is estimated and new measurement is trigged if necessary.
+
+Platform data can provide tuned values to the conversion formulas if
+values are known. Otherwise plain sensor default values are used.
+
+Proximity side is little bit simpler. There is no need for complex conversions.
+It produces directly usable values.
+
+Driver controls chip operational state using pm_runtime framework.
+Voltage regulators are controlled based on chip operational state.
+
+SYSFS
+-----
+
+
+chip_id
+       RO - shows detected chip type and version
+
+power_state
+       RW - enable / disable chip. Uses counting logic
+            1 enables the chip
+            0 disables the chip
+lux0_input
+       RO - measured lux value
+            sysfs_notify called when threshold interrupt occurs
+
+lux0_sensor_range
+       RO - lux0_input max value. Actually never reaches since sensor tends
+            to saturate much before that. Real max value varies depending
+            on the light spectrum etc.
+
+lux0_rate
+       RW - measurement rate in Hz
+
+lux0_rate_avail
+       RO - supported measurement rates
+
+lux0_calibscale
+       RW - calibration value. Set to neutral value by default.
+            Output results are multiplied with calibscale / calibscale_default
+            value.
+
+lux0_calibscale_default
+       RO - neutral calibration value
+
+lux0_thresh_above_value
+       RW - HI level threshold value. All results above the value
+            trigs an interrupt. 65535 (i.e. sensor_range) disables the above
+            interrupt.
+
+lux0_thresh_below_value
+       RW - LO level threshold value. All results below the value
+            trigs an interrupt. 0 disables the below interrupt.
+
+prox0_raw
+       RO - measured proximity value
+            sysfs_notify called when threshold interrupt occurs
+
+prox0_sensor_range
+       RO - prox0_raw max value (1023)
+
+prox0_raw_en
+       RW - enable / disable proximity - uses counting logic
+            1 enables the proximity
+            0 disables the proximity
+
+prox0_reporting_mode
+       RW - trigger / periodic. In "trigger" mode the driver tells two possible
+            values: 0 or prox0_sensor_range value. 0 means no proximity,
+            1023 means proximity. This causes minimal number of interrupts.
+            In "periodic" mode the driver reports all values above
+            prox0_thresh_above. This causes more interrupts, but it can give
+            _rough_ estimate about the distance.
+
+prox0_reporting_mode_avail
+       RO - accepted values to prox0_reporting_mode (trigger, periodic)
+
+prox0_thresh_above_value
+       RW - threshold level which trigs proximity events.
diff --git a/Documentation/misc-devices/bh1770glc.txt b/Documentation/misc-devices/bh1770glc.txt
new file mode 100644 (file)
index 0000000..7d64c01
--- /dev/null
@@ -0,0 +1,116 @@
+Kernel driver bh1770glc
+=======================
+
+Supported chips:
+ROHM BH1770GLC
+OSRAM SFH7770
+
+Data sheet:
+Not freely available
+
+Author:
+Samu Onkalo <samu.p.onkalo@nokia.com>
+
+Description
+-----------
+BH1770GLC and SFH7770 are combined ambient light and proximity sensors.
+ALS and proximity parts operates on their own, but they shares common I2C
+interface and interrupt logic. In principle they can run on their own,
+but ALS side results are used to estimate reliability of the proximity sensor.
+
+ALS produces 16 bit lux values. The chip contains interrupt logic to produce
+low and high threshold interrupts.
+
+Proximity part contains IR-led driver up to 3 IR leds. The chip measures
+amount of reflected IR light and produces proximity result. Resolution is
+8 bit. Driver supports only one channel. Driver uses ALS results to estimate
+reliability of the proximity results. Thus ALS is always running while
+proximity detection is needed.
+
+Driver uses threshold interrupts to avoid need for polling the values.
+Proximity low interrupt doesn't exists in the chip. This is simulated
+by using a delayed work. As long as there is proximity threshold above
+interrupts the delayed work is pushed forward. So, when proximity level goes
+below the threshold value, there is no interrupt and the delayed work will
+finally run. This is handled as no proximity indication.
+
+Chip state is controlled via runtime pm framework when enabled in config.
+
+Calibscale factor is used to hide differences between the chips. By default
+value set to neutral state meaning factor of 1.00. To get proper values,
+calibrated source of light is needed as a reference. Calibscale factor is set
+so that measurement produces about the expected lux value.
+
+SYSFS
+-----
+
+chip_id
+       RO - shows detected chip type and version
+
+power_state
+       RW - enable / disable chip. Uses counting logic
+            1 enables the chip
+            0 disables the chip
+
+lux0_input
+       RO - measured lux value
+            sysfs_notify called when threshold interrupt occurs
+
+lux0_sensor_range
+       RO - lux0_input max value
+
+lux0_rate
+       RW - measurement rate in Hz
+
+lux0_rate_avail
+       RO - supported measurement rates
+
+lux0_thresh_above_value
+       RW - HI level threshold value. All results above the value
+            trigs an interrupt. 65535 (i.e. sensor_range) disables the above
+            interrupt.
+
+lux0_thresh_below_value
+       RW - LO level threshold value. All results below the value
+            trigs an interrupt. 0 disables the below interrupt.
+
+lux0_calibscale
+       RW - calibration value. Set to neutral value by default.
+            Output results are multiplied with calibscale / calibscale_default
+            value.
+
+lux0_calibscale_default
+       RO - neutral calibration value
+
+prox0_raw
+       RO - measured proximity value
+            sysfs_notify called when threshold interrupt occurs
+
+prox0_sensor_range
+       RO - prox0_raw max value
+
+prox0_raw_en
+       RW - enable / disable proximity - uses counting logic
+            1 enables the proximity
+            0 disables the proximity
+
+prox0_thresh_above_count
+       RW - number of proximity interrupts needed before triggering the event
+
+prox0_rate_above
+       RW - Measurement rate (in Hz) when the level is above threshold
+            i.e. when proximity on has been reported.
+
+prox0_rate_below
+       RW - Measurement rate (in Hz) when the level is below threshold
+            i.e. when proximity off has been reported.
+
+prox0_rate_avail
+       RO - Supported proximity measurement rates in Hz
+
+prox0_thresh_above0_value
+       RW - threshold level which trigs proximity events.
+            Filtered by persistence filter (prox0_thresh_above_count)
+
+prox0_thresh_above1_value
+       RW - threshold level which trigs event immediately
index 5c17196..312e375 100644 (file)
@@ -75,7 +75,7 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 
 'f'    - Will call oom_kill to kill a memory hog process.
 
-'g'    - Used by kgdb on ppc and sh platforms.
+'g'    - Used by kgdb (kernel debugger)
 
 'h'     - Will display help (actually any other key than those listed
           here will display help. but 'h' is easy to remember :-)
@@ -110,12 +110,15 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 
 'u'     - Will attempt to remount all mounted filesystems read-only.
 
-'v'    - Dumps Voyager SMP processor info to your console.
+'v'    - Forcefully restores framebuffer console
+'v'    - Causes ETM buffer dump [ARM-specific]
 
 'w'    - Dumps tasks that are in uninterruptable (blocked) state.
 
 'x'    - Used by xmon interface on ppc/powerpc platforms.
 
+'y'    - Show global CPU Registers [SPARC-64 specific]
+
 'z'    - Dump the ftrace buffer
 
 '0'-'9' - Sets the console log level, controlling which kernel messages
index 4bfafb7..9a3e701 100644 (file)
@@ -97,6 +97,33 @@ hpet_open_close(int argc, const char **argv)
 void
 hpet_info(int argc, const char **argv)
 {
+       struct hpet_info        info;
+       int                     fd;
+
+       if (argc != 1) {
+               fprintf(stderr, "hpet_info: device-name\n");
+               return;
+       }
+
+       fd = open(argv[0], O_RDONLY);
+       if (fd < 0) {
+               fprintf(stderr, "hpet_info: open of %s failed\n", argv[0]);
+               return;
+       }
+
+       if (ioctl(fd, HPET_INFO, &info) < 0) {
+               fprintf(stderr, "hpet_info: failed to get info\n");
+               goto out;
+       }
+
+       fprintf(stderr, "hpet_info: hi_irqfreq 0x%lx hi_flags 0x%lx ",
+               info.hi_ireqfreq, info.hi_flags);
+       fprintf(stderr, "hi_hpet %d hi_timer %d\n",
+               info.hi_hpet, info.hi_timer);
+
+out:
+       close(fd);
+       return;
 }
 
 void
index 1b55146..b3e73dd 100644 (file)
@@ -46,7 +46,7 @@ use constant HIGH_KSWAPD_LATENCY              => 20;
 use constant HIGH_KSWAPD_REWAKEUP              => 21;
 use constant HIGH_NR_SCANNED                   => 22;
 use constant HIGH_NR_TAKEN                     => 23;
-use constant HIGH_NR_RECLAIM                   => 24;
+use constant HIGH_NR_RECLAIMED                 => 24;
 use constant HIGH_NR_CONTIG_DIRTY              => 25;
 
 my %perprocesspid;
@@ -58,11 +58,13 @@ my $opt_read_procstat;
 my $total_wakeup_kswapd;
 my ($total_direct_reclaim, $total_direct_nr_scanned);
 my ($total_direct_latency, $total_kswapd_latency);
+my ($total_direct_nr_reclaimed);
 my ($total_direct_writepage_file_sync, $total_direct_writepage_file_async);
 my ($total_direct_writepage_anon_sync, $total_direct_writepage_anon_async);
 my ($total_kswapd_nr_scanned, $total_kswapd_wake);
 my ($total_kswapd_writepage_file_sync, $total_kswapd_writepage_file_async);
 my ($total_kswapd_writepage_anon_sync, $total_kswapd_writepage_anon_async);
+my ($total_kswapd_nr_reclaimed);
 
 # Catch sigint and exit on request
 my $sigint_report = 0;
@@ -104,7 +106,7 @@ my $regex_kswapd_wake_default = 'nid=([0-9]*) order=([0-9]*)';
 my $regex_kswapd_sleep_default = 'nid=([0-9]*)';
 my $regex_wakeup_kswapd_default = 'nid=([0-9]*) zid=([0-9]*) order=([0-9]*)';
 my $regex_lru_isolate_default = 'isolate_mode=([0-9]*) order=([0-9]*) nr_requested=([0-9]*) nr_scanned=([0-9]*) nr_taken=([0-9]*) contig_taken=([0-9]*) contig_dirty=([0-9]*) contig_failed=([0-9]*)';
-my $regex_lru_shrink_inactive_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) priority=([0-9]*)';
+my $regex_lru_shrink_inactive_default = 'nid=([0-9]*) zid=([0-9]*) nr_scanned=([0-9]*) nr_reclaimed=([0-9]*) priority=([0-9]*) flags=([A-Z_|]*)';
 my $regex_lru_shrink_active_default = 'lru=([A-Z_]*) nr_scanned=([0-9]*) nr_rotated=([0-9]*) priority=([0-9]*)';
 my $regex_writepage_default = 'page=([0-9a-f]*) pfn=([0-9]*) flags=([A-Z_|]*)';
 
@@ -203,8 +205,8 @@ $regex_lru_shrink_inactive = generate_traceevent_regex(
                        "vmscan/mm_vmscan_lru_shrink_inactive",
                        $regex_lru_shrink_inactive_default,
                        "nid", "zid",
-                       "lru",
-                       "nr_scanned", "nr_reclaimed", "priority");
+                       "nr_scanned", "nr_reclaimed", "priority",
+                       "flags");
 $regex_lru_shrink_active = generate_traceevent_regex(
                        "vmscan/mm_vmscan_lru_shrink_active",
                        $regex_lru_shrink_active_default,
@@ -375,6 +377,16 @@ EVENT_PROCESS:
                        my $nr_contig_dirty = $7;
                        $perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
                        $perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
+               } elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
+                       $details = $5;
+                       if ($details !~ /$regex_lru_shrink_inactive/o) {
+                               print "WARNING: Failed to parse mm_vmscan_lru_shrink_inactive as expected\n";
+                               print "         $details\n";
+                               print "         $regex_lru_shrink_inactive/o\n";
+                               next;
+                       }
+                       my $nr_reclaimed = $4;
+                       $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED} += $nr_reclaimed;
                } elsif ($tracepoint eq "mm_vmscan_writepage") {
                        $details = $5;
                        if ($details !~ /$regex_writepage/o) {
@@ -464,8 +476,8 @@ sub dump_stats {
 
        # Print out process activity
        printf("\n");
-       printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s %8s\n", "Process", "Direct",  "Wokeup", "Pages",   "Pages",   "Pages",     "Time");
-       printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s %8s\n", "details", "Rclms",   "Kswapd", "Scanned", "Sync-IO", "ASync-IO",  "Stalled");
+       printf("%-" . $max_strlen . "s %8s %10s   %8s %8s  %8s %8s %8s %8s\n", "Process", "Direct",  "Wokeup", "Pages",   "Pages",   "Pages",   "Pages",     "Time");
+       printf("%-" . $max_strlen . "s %8s %10s   %8s %8s  %8s %8s %8s %8s\n", "details", "Rclms",   "Kswapd", "Scanned", "Rclmed",  "Sync-IO", "ASync-IO",  "Stalled");
        foreach $process_pid (keys %stats) {
 
                if (!$stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN}) {
@@ -475,6 +487,7 @@ sub dump_stats {
                $total_direct_reclaim += $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN};
                $total_wakeup_kswapd += $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
                $total_direct_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+               $total_direct_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
                $total_direct_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
                $total_direct_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
                $total_direct_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
@@ -489,11 +502,12 @@ sub dump_stats {
                        $index++;
                }
 
-               printf("%-" . $max_strlen . "s %8d %10d   %8u   %8u %8u %8.3f",
+               printf("%-" . $max_strlen . "s %8d %10d   %8u %8u  %8u %8u %8.3f",
                        $process_pid,
                        $stats{$process_pid}->{MM_VMSCAN_DIRECT_RECLAIM_BEGIN},
                        $stats{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD},
                        $stats{$process_pid}->{HIGH_NR_SCANNED},
+                       $stats{$process_pid}->{HIGH_NR_RECLAIMED},
                        $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
                        $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC},
                        $this_reclaim_delay / 1000);
@@ -529,8 +543,8 @@ sub dump_stats {
 
        # Print out kswapd activity
        printf("\n");
-       printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Kswapd",   "Kswapd",  "Order",     "Pages",   "Pages",  "Pages");
-       printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Instance", "Wakeups", "Re-wakeup", "Scanned", "Sync-IO", "ASync-IO");
+       printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Kswapd",   "Kswapd",  "Order",     "Pages",   "Pages",   "Pages",  "Pages");
+       printf("%-" . $max_strlen . "s %8s %10s   %8s   %8s %8s %8s\n", "Instance", "Wakeups", "Re-wakeup", "Scanned", "Rclmed",  "Sync-IO", "ASync-IO");
        foreach $process_pid (keys %stats) {
 
                if (!$stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE}) {
@@ -539,16 +553,18 @@ sub dump_stats {
 
                $total_kswapd_wake += $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE};
                $total_kswapd_nr_scanned += $stats{$process_pid}->{HIGH_NR_SCANNED};
+               $total_kswapd_nr_reclaimed += $stats{$process_pid}->{HIGH_NR_RECLAIMED};
                $total_kswapd_writepage_file_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
                $total_kswapd_writepage_anon_sync += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
                $total_kswapd_writepage_file_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
                $total_kswapd_writepage_anon_async += $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC};
 
-               printf("%-" . $max_strlen . "s %8d %10d   %8u   %8i %8u",
+               printf("%-" . $max_strlen . "s %8d %10d   %8u %8u  %8i %8u",
                        $process_pid,
                        $stats{$process_pid}->{MM_VMSCAN_KSWAPD_WAKE},
                        $stats{$process_pid}->{HIGH_KSWAPD_REWAKEUP},
                        $stats{$process_pid}->{HIGH_NR_SCANNED},
+                       $stats{$process_pid}->{HIGH_NR_RECLAIMED},
                        $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC},
                        $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} + $stats{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_ASYNC});
 
@@ -579,6 +595,7 @@ sub dump_stats {
        print "\nSummary\n";
        print "Direct reclaims:                         $total_direct_reclaim\n";
        print "Direct reclaim pages scanned:            $total_direct_nr_scanned\n";
+       print "Direct reclaim pages reclaimed:          $total_direct_nr_reclaimed\n";
        print "Direct reclaim write file sync I/O:      $total_direct_writepage_file_sync\n";
        print "Direct reclaim write anon sync I/O:      $total_direct_writepage_anon_sync\n";
        print "Direct reclaim write file async I/O:     $total_direct_writepage_file_async\n";
@@ -588,6 +605,7 @@ sub dump_stats {
        print "\n";
        print "Kswapd wakeups:                          $total_kswapd_wake\n";
        print "Kswapd pages scanned:                    $total_kswapd_nr_scanned\n";
+       print "Kswapd pages reclaimed:                  $total_kswapd_nr_reclaimed\n";
        print "Kswapd reclaim write file sync I/O:      $total_kswapd_writepage_file_sync\n";
        print "Kswapd reclaim write anon sync I/O:      $total_kswapd_writepage_anon_sync\n";
        print "Kswapd reclaim write file async I/O:     $total_kswapd_writepage_file_async\n";
@@ -612,6 +630,7 @@ sub aggregate_perprocesspid() {
                $perprocess{$process}->{MM_VMSCAN_WAKEUP_KSWAPD} += $perprocesspid{$process_pid}->{MM_VMSCAN_WAKEUP_KSWAPD};
                $perprocess{$process}->{HIGH_KSWAPD_REWAKEUP} += $perprocesspid{$process_pid}->{HIGH_KSWAPD_REWAKEUP};
                $perprocess{$process}->{HIGH_NR_SCANNED} += $perprocesspid{$process_pid}->{HIGH_NR_SCANNED};
+               $perprocess{$process}->{HIGH_NR_RECLAIMED} += $perprocesspid{$process_pid}->{HIGH_NR_RECLAIMED};
                $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_SYNC};
                $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_ANON_SYNC};
                $perprocess{$process}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC} += $perprocesspid{$process_pid}->{MM_VMSCAN_WRITEPAGE_FILE_ASYNC};
diff --git a/Documentation/vm/highmem.txt b/Documentation/vm/highmem.txt
new file mode 100644 (file)
index 0000000..4324d24
--- /dev/null
@@ -0,0 +1,162 @@
+
+                            ====================
+                            HIGH MEMORY HANDLING
+                            ====================
+
+By: Peter Zijlstra <a.p.zijlstra@chello.nl>
+
+Contents:
+
+ (*) What is high memory?
+
+ (*) Temporary virtual mappings.
+
+ (*) Using kmap_atomic.
+
+ (*) Cost of temporary mappings.
+
+ (*) i386 PAE.
+
+
+====================
+WHAT IS HIGH MEMORY?
+====================
+
+High memory (highmem) is used when the size of physical memory approaches or
+exceeds the maximum size of virtual memory.  At that point it becomes
+impossible for the kernel to keep all of the available physical memory mapped
+at all times.  This means the kernel needs to start using temporary mappings of
+the pieces of physical memory that it wants to access.
+
+The part of (physical) memory not covered by a permanent mapping is what we
+refer to as 'highmem'.  There are various architecture dependent constraints on
+where exactly that border lies.
+
+In the i386 arch, for example, we choose to map the kernel into every process's
+VM space so that we don't have to pay the full TLB invalidation costs for
+kernel entry/exit.  This means the available virtual memory space (4GiB on
+i386) has to be divided between user and kernel space.
+
+The traditional split for architectures using this approach is 3:1, 3GiB for
+userspace and the top 1GiB for kernel space:
+
+               +--------+ 0xffffffff
+               | Kernel |
+               +--------+ 0xc0000000
+               |        |
+               | User   |
+               |        |
+               +--------+ 0x00000000
+
+This means that the kernel can at most map 1GiB of physical memory at any one
+time, but because we need virtual address space for other things - including
+temporary maps to access the rest of the physical memory - the actual direct
+map will typically be less (usually around ~896MiB).
+
+Other architectures that have mm context tagged TLBs can have separate kernel
+and user maps.  Some hardware (like some ARMs), however, have limited virtual
+space when they use mm context tags.
+
+
+==========================
+TEMPORARY VIRTUAL MAPPINGS
+==========================
+
+The kernel contains several ways of creating temporary mappings:
+
+ (*) vmap().  This can be used to make a long duration mapping of multiple
+     physical pages into a contiguous virtual space.  It needs global
+     synchronization to unmap.
+
+ (*) kmap().  This permits a short duration mapping of a single page.  It needs
+     global synchronization, but is amortized somewhat.  It is also prone to
+     deadlocks when using in a nested fashion, and so it is not recommended for
+     new code.
+
+ (*) kmap_atomic().  This permits a very short duration mapping of a single
+     page.  Since the mapping is restricted to the CPU that issued it, it
+     performs well, but the issuing task is therefore required to stay on that
+     CPU until it has finished, lest some other task displace its mappings.
+
+     kmap_atomic() may also be used by interrupt contexts, since it is does not
+     sleep and the caller may not sleep until after kunmap_atomic() is called.
+
+     It may be assumed that k[un]map_atomic() won't fail.
+
+
+=================
+USING KMAP_ATOMIC
+=================
+
+When and where to use kmap_atomic() is straightforward.  It is used when code
+wants to access the contents of a page that might be allocated from high memory
+(see __GFP_HIGHMEM), for example a page in the pagecache.  The API has two
+functions, and they can be used in a manner similar to the following:
+
+       /* Find the page of interest. */
+       struct page *page = find_get_page(mapping, offset);
+
+       /* Gain access to the contents of that page. */
+       void *vaddr = kmap_atomic(page);
+
+       /* Do something to the contents of that page. */
+       memset(vaddr, 0, PAGE_SIZE);
+
+       /* Unmap that page. */
+       kunmap_atomic(vaddr);
+
+Note that the kunmap_atomic() call takes the result of the kmap_atomic() call
+not the argument.
+
+If you need to map two pages because you want to copy from one page to
+another you need to keep the kmap_atomic calls strictly nested, like:
+
+       vaddr1 = kmap_atomic(page1);
+       vaddr2 = kmap_atomic(page2);
+
+       memcpy(vaddr1, vaddr2, PAGE_SIZE);
+
+       kunmap_atomic(vaddr2);
+       kunmap_atomic(vaddr1);
+
+
+==========================
+COST OF TEMPORARY MAPPINGS
+==========================
+
+The cost of creating temporary mappings can be quite high.  The arch has to
+manipulate the kernel's page tables, the data TLB and/or the MMU's registers.
+
+If CONFIG_HIGHMEM is not set, then the kernel will try and create a mapping
+simply with a bit of arithmetic that will convert the page struct address into
+a pointer to the page contents rather than juggling mappings about.  In such a
+case, the unmap operation may be a null operation.
+
+If CONFIG_MMU is not set, then there can be no temporary mappings and no
+highmem.  In such a case, the arithmetic approach will also be used.
+
+
+========
+i386 PAE
+========
+
+The i386 arch, under some circumstances, will permit you to stick up to 64GiB
+of RAM into your 32-bit machine.  This has a number of consequences:
+
+ (*) Linux needs a page-frame structure for each page in the system and the
+     pageframes need to live in the permanent mapping, which means:
+
+ (*) you can have 896M/sizeof(struct page) page-frames at most; with struct
+     page being 32-bytes that would end up being something in the order of 112G
+     worth of pages; the kernel, however, needs to store more than just
+     page-frames in that memory...
+
+ (*) PAE makes your page tables larger - which slows the system down as more
+     data has to be accessed to traverse in TLB fills and the like.  One
+     advantage is that PAE has more PTE bits and can provide advanced features
+     like NX and PAT.
+
+The general recommendation is that you don't use more than 8GiB on a 32-bit
+machine - although more might work for you and your workload, you're pretty
+much on your own - don't expect kernel developers to really care much if things
+come apart.
index 5414510..bbcaf31 100644 (file)
@@ -243,21 +243,6 @@ F: drivers/pnp/pnpacpi/
 F:     include/linux/acpi.h
 F:     include/acpi/
 
-ACPI BATTERY DRIVERS
-M:     Alexey Starikovskiy <astarikovskiy@suse.de>
-L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
-S:     Supported
-F:     drivers/acpi/battery.c
-F:     drivers/acpi/*sbs*
-
-ACPI EC DRIVER
-M:     Alexey Starikovskiy <astarikovskiy@suse.de>
-L:     linux-acpi@vger.kernel.org
-W:     http://www.lesswatts.org/projects/acpi/
-S:     Supported
-F:     drivers/acpi/ec.c
-
 ACPI FAN DRIVER
 M:     Zhang Rui <rui.zhang@intel.com>
 L:     linux-acpi@vger.kernel.org
@@ -657,7 +642,7 @@ ARM/FARADAY FA526 PORT
 M:     Hans Ulli Kroll <ulli.kroll@googlemail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git://git.berlios.de/gemini-board
+T:     git git://git.berlios.de/gemini-board
 F:     arch/arm/mm/*-fa*
 
 ARM/FOOTBRIDGE ARCHITECTURE
@@ -672,7 +657,7 @@ ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
 M:     Sascha Hauer <kernel@pengutronix.de>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-T:     git://git.pengutronix.de/git/imx/linux-2.6.git
+T:     git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:     arch/arm/mach-mx*/
 F:     arch/arm/plat-mxc/
 
@@ -710,8 +695,7 @@ ARM/INCOME PXA270 SUPPORT
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     arch/arm/mach-pxa/income.c
-F:     arch/arm/mach-pxa/include/mach-pxa/income.h
+F:     arch/arm/mach-pxa/colibri-pxa270-income.c
 
 ARM/INTEL IOP32X ARM ARCHITECTURE
 M:     Lennert Buytenhek <kernel@wantstofly.org>
@@ -758,13 +742,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-ixp4xx/
 
-ARM/INTEL RESEARCH IMOTE 2 MACHINE SUPPORT
-M:     Jonathan Cameron <jic23@cam.ac.uk>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     arch/arm/mach-pxa/imote2.c
-
-ARM/INTEL RESEARCH STARGATE 2 MACHINE SUPPORT
+ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT
 M:     Jonathan Cameron <jic23@cam.ac.uk>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
@@ -929,40 +907,20 @@ W:        http://www.fluff.org/ben/linux/
 S:     Maintained
 F:     arch/arm/mach-s3c2410/
 
-ARM/S3C2440 ARM ARCHITECTURE
+ARM/S3C244x ARM ARCHITECTURE
 M:     Ben Dooks <ben-linux@fluff.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.fluff.org/ben/linux/
 S:     Maintained
 F:     arch/arm/mach-s3c2440/
-
-ARM/S3C2442 ARM ARCHITECTURE
-M:     Ben Dooks <ben-linux@fluff.org>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:     http://www.fluff.org/ben/linux/
-S:     Maintained
-F:     arch/arm/mach-s3c2442/
-
-ARM/S3C2443 ARM ARCHITECTURE
-M:     Ben Dooks <ben-linux@fluff.org>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:     http://www.fluff.org/ben/linux/
-S:     Maintained
 F:     arch/arm/mach-s3c2443/
 
-ARM/S3C6400 ARM ARCHITECTURE
+ARM/S3C64xx ARM ARCHITECTURE
 M:     Ben Dooks <ben-linux@fluff.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.fluff.org/ben/linux/
 S:     Maintained
-F:     arch/arm/mach-s3c6400/
-
-ARM/S3C6410 ARM ARCHITECTURE
-M:     Ben Dooks <ben-linux@fluff.org>
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W:     http://www.fluff.org/ben/linux/
-S:     Maintained
-F:     arch/arm/mach-s3c6410/
+F:     arch/arm/mach-s3c64xx/
 
 ARM/S5P ARM ARCHITECTURES
 M:     Kukjin Kim <kgene.kim@samsung.com>
@@ -3015,7 +2973,7 @@ M:        Roland Dreier <rolandd@cisco.com>
 M:     Sean Hefty <sean.hefty@intel.com>
 M:     Hal Rosenstock <hal.rosenstock@gmail.com>
 L:     linux-rdma@vger.kernel.org
-W:     http://www.openib.org/
+W:     http://www.openfabrics.org/
 Q:     http://patchwork.kernel.org/project/linux-rdma/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
 S:     Supported
@@ -3765,6 +3723,13 @@ L:       linux-scsi@vger.kernel.org
 S:     Maintained
 F:     drivers/scsi/sym53c8xx_2/
 
+LTC4261 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/ltc4261
+F:     drivers/hwmon/ltc4261.c
+
 LTP (Linux Test Project)
 M:     Rishikesh K Rajak <risrajak@linux.vnet.ibm.com>
 M:     Garrett Cooper <yanegomi@gmail.com>
@@ -3860,7 +3825,7 @@ F:        drivers/net/wireless/mwl8k.c
 MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER
 M:     Nicolas Pitre <nico@fluxnic.net>
 S:     Odd Fixes
-F: drivers/mmc/host/mvsdio.*
+F:     drivers/mmc/host/mvsdio.*
 
 MARVELL YUKON / SYSKONNECT DRIVER
 M:     Mirko Lindner <mlindner@syskonnect.de>
@@ -4951,7 +4916,7 @@ RCUTORTURE MODULE
 M:     Josh Triplett <josh@freedesktop.org>
 M:     "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 S:     Supported
-T:     git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 F:     Documentation/RCU/torture.txt
 F:     kernel/rcutorture.c
 
@@ -4976,7 +4941,7 @@ M:        Dipankar Sarma <dipankar@in.ibm.com>
 M:     "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
 W:     http://www.rdrop.com/users/paulmck/rclock/
 S:     Supported
-T:     git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-2.6-rcu.git
 F:     Documentation/RCU/
 F:     include/linux/rcu*
 F:     include/linux/srcu*
@@ -5166,6 +5131,16 @@ W:       http://www.kernel.dk
 S:     Maintained
 F:     drivers/scsi/sr*
 
+SCSI RDMA PROTOCOL (SRP) INITIATOR
+M:     David Dillow <dillowda@ornl.gov>
+L:     linux-rdma@vger.kernel.org
+S:     Supported
+W:     http://www.openfabrics.org
+Q:     http://patchwork.kernel.org/project/linux-rdma/list/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/dad/srp-initiator.git
+F:     drivers/infiniband/ulp/srp/
+F:     include/scsi/srp.h
+
 SCSI SG DRIVER
 M:     Doug Gilbert <dgilbert@interlog.com>
 L:     linux-scsi@vger.kernel.org
@@ -6134,13 +6109,6 @@ L:       linux-usb@vger.kernel.org
 S:     Maintained
 F:     drivers/usb/serial/option.c
 
-USB OV511 DRIVER
-M:     Mark McClelland <mmcclell@bigfoot.com>
-L:     linux-usb@vger.kernel.org
-W:     http://alpha.dyndns.org/ov511/
-S:     Maintained
-F:     drivers/media/video/ov511.*
-
 USB PEGASUS DRIVER
 M:     Petko Manolov <petkan@users.sourceforge.net>
 L:     linux-usb@vger.kernel.org
@@ -6301,16 +6269,6 @@ S:       Supported
 F:     drivers/usb/host/xhci*
 F:     drivers/usb/host/pci-quirks*
 
-USB ZC0301 DRIVER
-M:     Luca Risolia <luca.risolia@studio.unibo.it>
-L:     linux-usb@vger.kernel.org
-L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6.git
-W:     http://www.linux-projects.org
-S:     Maintained
-F:     Documentation/video4linux/zc0301.txt
-F:     drivers/media/video/zc0301/
-
 USB ZD1201 DRIVER
 L:     linux-wireless@vger.kernel.org
 W:     http://linux-lc100020.sourceforge.net
index d04ccd7..28f93a6 100644 (file)
@@ -55,6 +55,9 @@ config ZONE_DMA
        bool
        default y
 
+config ARCH_DMA_ADDR_T_64BIT
+       def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
index 21ac533..9f67a05 100644 (file)
@@ -247,7 +247,7 @@ struct el_MCPCIA_uncorrected_frame_mcheck {
 #define vip    volatile int __force *
 #define vuip   volatile unsigned int __force *
 
-#ifdef MCPCIA_ONE_HAE_WINDOW
+#ifndef MCPCIA_ONE_HAE_WINDOW
 #define MCPCIA_FROB_MMIO                                               \
        if (__mcpcia_is_mmio(hose)) {                                   \
                set_hae(hose & 0xffffffff);                             \
index 471c072..91b4680 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef __ALPHA_T2__H__
 #define __ALPHA_T2__H__
 
+/* Fit everything into one 128MB HAE window. */
+#define T2_ONE_HAE_WINDOW 1
+
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/compiler.h>
@@ -19,7 +22,7 @@
  *
  */
 
-#define T2_MEM_R1_MASK 0x07ffffff  /* Mem sparse region 1 mask is 26 bits */
+#define T2_MEM_R1_MASK 0x07ffffff  /* Mem sparse region 1 mask is 27 bits */
 
 /* GAMMA-SABLE is a SABLE with EV5-based CPUs */
 /* All LYNX machines, EV4 or EV5, use the GAMMA bias also */
@@ -85,7 +88,9 @@
 #define T2_DIR                 (IDENT_ADDR + GAMMA_BIAS + 0x38e0004a0UL)
 #define T2_ICE                 (IDENT_ADDR + GAMMA_BIAS + 0x38e0004c0UL)
 
+#ifndef T2_ONE_HAE_WINDOW
 #define T2_HAE_ADDRESS         T2_HAE_1
+#endif
 
 /*  T2 CSRs are in the non-cachable primary IO space from 3.8000.0000 to
  3.8fff.ffff
@@ -429,13 +434,15 @@ extern inline void t2_outl(u32 b, unsigned long addr)
  *
  */
 
+#ifdef T2_ONE_HAE_WINDOW
+#define t2_set_hae
+#else
 #define t2_set_hae { \
-       msb = addr  >> 27; \
+       unsigned long msb = addr >> 27; \
        addr &= T2_MEM_R1_MASK; \
        set_hae(msb); \
 }
-
-extern raw_spinlock_t t2_hae_lock;
+#endif
 
 /*
  * NOTE: take T2_DENSE_MEM off in each readX/writeX routine, since
@@ -446,28 +453,22 @@ extern raw_spinlock_t t2_hae_lock;
 __EXTERN_INLINE u8 t2_readb(const volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long result, msb;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
+       unsigned long result;
 
        t2_set_hae;
 
        result = *(vip) ((addr << 5) + T2_SPARSE_MEM + 0x00);
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
        return __kernel_extbl(result, addr & 3);
 }
 
 __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long result, msb;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
+       unsigned long result;
 
        t2_set_hae;
 
        result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08);
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
        return __kernel_extwl(result, addr & 3);
 }
 
@@ -478,59 +479,47 @@ __EXTERN_INLINE u16 t2_readw(const volatile void __iomem *xaddr)
 __EXTERN_INLINE u32 t2_readl(const volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long result, msb;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
+       unsigned long result;
 
        t2_set_hae;
 
        result = *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18);
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
        return result & 0xffffffffUL;
 }
 
 __EXTERN_INLINE u64 t2_readq(const volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long r0, r1, work, msb;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
+       unsigned long r0, r1, work;
 
        t2_set_hae;
 
        work = (addr << 5) + T2_SPARSE_MEM + 0x18;
        r0 = *(vuip)(work);
        r1 = *(vuip)(work + (4 << 5));
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
        return r1 << 32 | r0;
 }
 
 __EXTERN_INLINE void t2_writeb(u8 b, volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long msb, w;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
+       unsigned long w;
 
        t2_set_hae;
 
        w = __kernel_insbl(b, addr & 3);
        *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x00) = w;
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long msb, w;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
+       unsigned long w;
 
        t2_set_hae;
 
        w = __kernel_inswl(b, addr & 3);
        *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x08) = w;
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 /*
@@ -540,29 +529,22 @@ __EXTERN_INLINE void t2_writew(u16 b, volatile void __iomem *xaddr)
 __EXTERN_INLINE void t2_writel(u32 b, volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long msb;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
 
        t2_set_hae;
 
        *(vuip) ((addr << 5) + T2_SPARSE_MEM + 0x18) = b;
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 __EXTERN_INLINE void t2_writeq(u64 b, volatile void __iomem *xaddr)
 {
        unsigned long addr = (unsigned long) xaddr - T2_DENSE_MEM;
-       unsigned long msb, work;
-       unsigned long flags;
-       raw_spin_lock_irqsave(&t2_hae_lock, flags);
+       unsigned long work;
 
        t2_set_hae;
 
        work = (addr << 5) + T2_SPARSE_MEM + 0x18;
        *(vuip)work = b;
        *(vuip)(work + (4 << 5)) = b >> 32;
-       raw_spin_unlock_irqrestore(&t2_hae_lock, flags);
 }
 
 __EXTERN_INLINE void __iomem *t2_ioportmap(unsigned long addr)
index 71a2432..de98a73 100644 (file)
@@ -318,9 +318,7 @@ extern inline pte_t * pte_offset_kernel(pmd_t * dir, unsigned long address)
 }
 
 #define pte_offset_map(dir,addr)       pte_offset_kernel((dir),(addr))
-#define pte_offset_map_nested(dir,addr)        pte_offset_kernel((dir),(addr))
 #define pte_unmap(pte)                 do { } while (0)
-#define pte_unmap_nested(pte)          do { } while (0)
 
 extern pgd_t swapper_pg_dir[1024];
 
index e6d9056..2f770e9 100644 (file)
@@ -74,8 +74,6 @@
 # define DBG(args)
 #endif
 
-DEFINE_RAW_SPINLOCK(t2_hae_lock);
-
 static volatile unsigned int t2_mcheck_any_expected;
 static volatile unsigned int t2_mcheck_last_taken;
 
@@ -406,6 +404,7 @@ void __init
 t2_init_arch(void)
 {
        struct pci_controller *hose;
+       struct resource *hae_mem;
        unsigned long temp;
        unsigned int i;
 
@@ -433,7 +432,13 @@ t2_init_arch(void)
         */
        pci_isa_hose = hose = alloc_pci_controller();
        hose->io_space = &ioport_resource;
-       hose->mem_space = &iomem_resource;
+       hae_mem = alloc_resource();
+       hae_mem->start = 0;
+       hae_mem->end = T2_MEM_R1_MASK;
+       hae_mem->name = pci_hae0_name;
+       if (request_resource(&iomem_resource, hae_mem) < 0)
+               printk(KERN_ERR "Failed to request HAE_MEM\n");
+       hose->mem_space = hae_mem;
        hose->index = 0;
 
        hose->sparse_mem_base = T2_SPARSE_MEM - IDENT_ADDR;
index 512685f..7fa6248 100644 (file)
@@ -25,6 +25,9 @@
 #ifdef MCPCIA_ONE_HAE_WINDOW
 #define MCPCIA_HAE_ADDRESS     (&alpha_mv.hae_cache)
 #endif
+#ifdef T2_ONE_HAE_WINDOW
+#define T2_HAE_ADDRESS         (&alpha_mv.hae_cache)
+#endif
 
 /* Only a few systems don't define IACK_SC, handling all interrupts through
    the SRM console.  But splitting out that one case from IO() below
index b64e465..bf7273f 100644 (file)
@@ -573,6 +573,7 @@ config ARCH_TEGRA
        select HAVE_CLK
        select COMMON_CLKDEV
        select ARCH_HAS_BARRIERS if CACHE_L2X0
+       select ARCH_HAS_CPUFREQ
        help
          This enables support for NVIDIA Tegra based systems (Tegra APX,
          Tegra 6xx and Tegra 2 series).
@@ -831,7 +832,7 @@ config ARCH_OMAP
        select GENERIC_CLOCKEVENTS
        select ARCH_HAS_HOLES_MEMORYMODEL
        help
-         Support for TI's OMAP platform (OMAP1 and OMAP2).
+         Support for TI's OMAP platform (OMAP1/2/3/4).
 
 config PLAT_SPEAR
        bool "ST SPEAr"
diff --git a/arch/arm/configs/n8x0_defconfig b/arch/arm/configs/n8x0_defconfig
deleted file mode 100644 (file)
index 56aebb6..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_LBDAF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP2=y
-CONFIG_OMAP_RESET_CLOCKS=y
-# CONFIG_OMAP_MUX is not set
-# CONFIG_OMAP_MCBSP is not set
-CONFIG_OMAP_MBOX_FWK=y
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_ARCH_OMAP2420=y
-CONFIG_MACH_NOKIA_N8X0=y
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x10C08000
-CONFIG_ZBOOT_ROM_BSS=0x10200000
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 console=ttyS2,115200n8 debug earlyprintk rootwait"
-CONFIG_FPE_NWFPE=y
-CONFIG_VFP=y
-CONFIG_PM=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_ONENAND=y
-CONFIG_MTD_ONENAND_OMAP2=y
-CONFIG_MTD_ONENAND_OTP=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-# CONFIG_I2C_COMPAT is not set
-# CONFIG_I2C_HELPER_AUTO is not set
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP24XX=y
-# CONFIG_HWMON is not set
-CONFIG_MENELAUS=y
-CONFIG_REGULATOR=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG_WHITELIST is not set
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_OTG=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-# CONFIG_MUSB_PIO_ONLY is not set
-CONFIG_USB_MUSB_DEBUG=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG=y
-CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_ETH=m
-CONFIG_USB_ETH_EEM=y
-CONFIG_MMC=y
-CONFIG_MMC_OMAP=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_LZO=y
-CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
new file mode 100644 (file)
index 0000000..ccedde1
--- /dev/null
@@ -0,0 +1,293 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_SLAB=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_KPROBES=y
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_OMAP=y
+CONFIG_ARCH_OMAP2=y
+CONFIG_ARCH_OMAP3=y
+CONFIG_ARCH_OMAP4=y
+CONFIG_OMAP_RESET_CLOCKS=y
+CONFIG_OMAP_MUX_DEBUG=y
+CONFIG_OMAP_32K_TIMER=y
+CONFIG_MACH_OMAP_GENERIC=y
+CONFIG_ARCH_OMAP2420=y
+CONFIG_ARCH_OMAP2430=y
+CONFIG_ARCH_OMAP3430=y
+CONFIG_MACH_OMAP_H4=y
+CONFIG_MACH_OMAP_APOLLON=y
+CONFIG_MACH_OMAP_2430SDP=y
+CONFIG_MACH_OMAP3_BEAGLE=y
+CONFIG_MACH_DEVKIT8000=y
+CONFIG_MACH_OMAP_LDP=y
+CONFIG_MACH_OVERO=y
+CONFIG_MACH_OMAP3EVM=y
+CONFIG_MACH_OMAP3517EVM=y
+CONFIG_MACH_OMAP3_PANDORA=y
+CONFIG_MACH_OMAP3_TOUCHBOOK=y
+CONFIG_MACH_OMAP_3430SDP=y
+CONFIG_MACH_NOKIA_N8X0=y
+CONFIG_MACH_NOKIA_RX51=y
+CONFIG_MACH_OMAP_ZOOM2=y
+CONFIG_MACH_OMAP_ZOOM3=y
+CONFIG_MACH_CM_T35=y
+CONFIG_MACH_IGEP0020=y
+CONFIG_MACH_SBC3530=y
+CONFIG_MACH_OMAP_3630SDP=y
+CONFIG_MACH_OMAP_4430SDP=y
+CONFIG_ARM_THUMBEE=y
+CONFIG_ARM_L1_CACHE_SHIFT=5
+CONFIG_ARM_ERRATA_411920=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+# CONFIG_LOCAL_TIMERS is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyO2,115200"
+CONFIG_KEXEC=y
+CONFIG_FPE_NWFPE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+CONFIG_PM_RUNTIME=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETFILTER=y
+CONFIG_BT=m
+CONFIG_BT_L2CAP=m
+CONFIG_BT_SCO=m
+CONFIG_BT_RFCOMM=y
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_H4=y
+CONFIG_BT_HCIUART_BCSP=y
+CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIBCM203X=m
+CONFIG_BT_HCIBPA10X=m
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_MAC80211_RC_PID=y
+CONFIG_MAC80211_RC_DEFAULT_PID=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_OOPS=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_OMAP2=y
+CONFIG_MTD_ONENAND=y
+CONFIG_MTD_ONENAND_VERIFY_WRITE=y
+CONFIG_MTD_ONENAND_OMAP2=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_EEPROM_LEGACY=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_MD=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC_PHY=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMC91X=y
+CONFIG_SMSC911X=y
+CONFIG_KS8851=y
+CONFIG_KS8851_MLL=y
+CONFIG_LIBERTAS=m
+CONFIG_LIBERTAS_USB=m
+CONFIG_LIBERTAS_SDIO=m
+CONFIG_LIBERTAS_DEBUG=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_EPSON2888=y
+CONFIG_USB_KC2190=y
+CONFIG_INPUT_JOYDEV=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_TWL4030=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_TWL4030_PWRBUTTON=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=32
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_MANY_PORTS=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_8250_DETECT_IRQ=y
+CONFIG_SERIAL_8250_RSA=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_OMAP=y
+CONFIG_SPI=y
+CONFIG_SPI_OMAP24XX=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_TWL4030=y
+CONFIG_W1=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_WATCHDOG=y
+CONFIG_OMAP_WATCHDOG=y
+CONFIG_TWL4030_WATCHDOG=y
+CONFIG_MENELAUS=y
+CONFIG_TWL4030_CORE=y
+CONFIG_TWL4030_POWER=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_TWL4030=y
+CONFIG_REGULATOR_TPS65023=y
+CONFIG_REGULATOR_TPS6507X=y
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_OMAP_LCD_VGA=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_DISPLAY_SUPPORT=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_SOUND=m
+CONFIG_SND=m
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_VERBOSE_PRINTK=y
+CONFIG_SND_DEBUG=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_SND_OMAP_SOC=y
+CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG_WHITELIST is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_MUSB_OTG is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+CONFIG_USB_MUSB_DEBUG=y
+CONFIG_USB_WDM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_TEST=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_ZERO=m
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_SDIO_UART=y
+CONFIG_MMC_OMAP=y
+CONFIG_MMC_OMAP_HS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_TWL92330=y
+CONFIG_RTC_DRV_TWL4030=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_INOTIFY=y
+CONFIG_QUOTA=y
+CONFIG_QFMT_V2=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RUBIN=y
+CONFIG_UBIFS_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_PROVE_LOCKING=y
+# CONFIG_LOCK_STAT is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SECURITY=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/omap3_defconfig b/arch/arm/configs/omap3_defconfig
deleted file mode 100644 (file)
index 5db9a6b..0000000
+++ /dev/null
@@ -1,292 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-# CONFIG_SYSCTL_SYSCALL is not set
-CONFIG_KALLSYMS_EXTRA_PASS=y
-CONFIG_SLAB=y
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
-CONFIG_KPROBES=y
-CONFIG_MODULES=y
-CONFIG_MODULE_FORCE_LOAD=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP2=y
-CONFIG_ARCH_OMAP3=y
-CONFIG_ARCH_OMAP4=y
-CONFIG_OMAP_RESET_CLOCKS=y
-CONFIG_OMAP_MUX_DEBUG=y
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_ARCH_OMAP2420=y
-CONFIG_ARCH_OMAP2430=y
-CONFIG_ARCH_OMAP3430=y
-CONFIG_MACH_OMAP_H4=y
-CONFIG_MACH_OMAP_APOLLON=y
-CONFIG_MACH_OMAP_2430SDP=y
-CONFIG_MACH_OMAP3_BEAGLE=y
-CONFIG_MACH_DEVKIT8000=y
-CONFIG_MACH_OMAP_LDP=y
-CONFIG_MACH_OVERO=y
-CONFIG_MACH_OMAP3EVM=y
-CONFIG_MACH_OMAP3517EVM=y
-CONFIG_MACH_OMAP3_PANDORA=y
-CONFIG_MACH_OMAP3_TOUCHBOOK=y
-CONFIG_MACH_OMAP_3430SDP=y
-CONFIG_MACH_NOKIA_N8X0=y
-CONFIG_MACH_NOKIA_RX51=y
-CONFIG_MACH_OMAP_ZOOM2=y
-CONFIG_MACH_OMAP_ZOOM3=y
-CONFIG_MACH_CM_T35=y
-CONFIG_MACH_IGEP0020=y
-CONFIG_MACH_SBC3530=y
-CONFIG_MACH_OMAP_3630SDP=y
-CONFIG_MACH_OMAP_4430SDP=y
-CONFIG_ARM_THUMBEE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/mmcblk0p2 rootwait console=ttyS2,115200"
-CONFIG_KEXEC=y
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_FPE_NWFPE=y
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=y
-CONFIG_PM=y
-CONFIG_PM_DEBUG=y
-CONFIG_PM_RUNTIME=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_NET_KEY=y
-CONFIG_NET_KEY_MIGRATE=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-CONFIG_BT=y
-CONFIG_BT_L2CAP=y
-CONFIG_BT_SCO=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-CONFIG_BT_HCIUART=y
-CONFIG_BT_HCIUART_H4=y
-CONFIG_BT_HCIUART_BCSP=y
-CONFIG_BT_HCIUART_LL=y
-CONFIG_BT_HCIBCM203X=y
-CONFIG_BT_HCIBPA10X=y
-CONFIG_CFG80211=y
-CONFIG_MAC80211=y
-CONFIG_MAC80211_RC_PID=y
-CONFIG_MAC80211_RC_DEFAULT_PID=y
-CONFIG_MAC80211_LEDS=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_CONNECTOR=y
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_OOPS=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_OMAP2=y
-CONFIG_MTD_ONENAND=y
-CONFIG_MTD_ONENAND_VERIFY_WRITE=y
-CONFIG_MTD_ONENAND_OMAP2=y
-CONFIG_MTD_UBI=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-CONFIG_EEPROM_LEGACY=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_SCAN_ASYNC=y
-CONFIG_MD=y
-CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-CONFIG_SMSC911X=y
-CONFIG_LIBERTAS=y
-CONFIG_LIBERTAS_USB=y
-CONFIG_LIBERTAS_SDIO=y
-CONFIG_LIBERTAS_DEBUG=y
-CONFIG_USB_USBNET=y
-CONFIG_USB_ALI_M5632=y
-CONFIG_USB_AN2720=y
-CONFIG_USB_EPSON2888=y
-CONFIG_USB_KC2190=y
-CONFIG_INPUT_JOYDEV=y
-CONFIG_INPUT_EVDEV=y
-CONFIG_KEYBOARD_GPIO=y
-CONFIG_KEYBOARD_TWL4030=y
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-CONFIG_INPUT_MISC=y
-CONFIG_INPUT_TWL4030_PWRBUTTON=y
-CONFIG_VT_HW_CONSOLE_BINDING=y
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=32
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP24XX=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_GPIO_SYSFS=y
-CONFIG_GPIO_TWL4030=y
-CONFIG_W1=y
-CONFIG_POWER_SUPPLY=y
-CONFIG_WATCHDOG=y
-CONFIG_OMAP_WATCHDOG=y
-CONFIG_TWL4030_WATCHDOG=y
-CONFIG_MENELAUS=y
-CONFIG_TWL4030_CORE=y
-CONFIG_TWL4030_POWER=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_TWL4030=y
-CONFIG_REGULATOR_TPS65023=y
-CONFIG_REGULATOR_TPS6507X=y
-CONFIG_FB=y
-CONFIG_FIRMWARE_EDID=y
-CONFIG_FB_MODE_HELPERS=y
-CONFIG_FB_TILEBLITTING=y
-CONFIG_FB_OMAP_LCD_VGA=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_LCD_PLATFORM=y
-CONFIG_DISPLAY_SUPPORT=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
-CONFIG_FONTS=y
-CONFIG_FONT_8x8=y
-CONFIG_FONT_8x16=y
-CONFIG_LOGO=y
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_VERBOSE_PRINTK=y
-CONFIG_SND_DEBUG=y
-CONFIG_SND_USB_AUDIO=y
-CONFIG_SND_SOC=y
-CONFIG_SND_OMAP_SOC=y
-CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=y
-CONFIG_USB=y
-CONFIG_USB_DEBUG=y
-CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_SUSPEND=y
-# CONFIG_USB_OTG_WHITELIST is not set
-CONFIG_USB_MON=y
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_MUSB_OTG=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-CONFIG_USB_MUSB_DEBUG=y
-CONFIG_USB_WDM=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_LIBUSUAL=y
-CONFIG_USB_TEST=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_DEBUG=y
-CONFIG_USB_GADGET_DEBUG_FILES=y
-CONFIG_USB_GADGET_DEBUG_FS=y
-CONFIG_USB_ZERO=m
-CONFIG_MMC=y
-CONFIG_MMC_UNSAFE_RESUME=y
-CONFIG_SDIO_UART=y
-CONFIG_MMC_OMAP=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_TWL92330=y
-CONFIG_RTC_DRV_TWL4030=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_QUOTA=y
-CONFIG_QFMT_V2=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_JFFS2_FS_XATTR=y
-CONFIG_JFFS2_COMPRESSION_OPTIONS=y
-CONFIG_JFFS2_LZO=y
-CONFIG_JFFS2_RUBIN=y
-CONFIG_UBIFS_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_PRINTK_TIME=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
-CONFIG_PROVE_LOCKING=y
-CONFIG_LOCK_STAT=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_DEBUG_LL=y
-CONFIG_SECURITY=y
-CONFIG_CRYPTO_MICHAEL_MIC=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=y
-CONFIG_CRC7=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/omap_4430sdp_defconfig b/arch/arm/configs/omap_4430sdp_defconfig
deleted file mode 100644 (file)
index 14c1e18..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_EMBEDDED=y
-# CONFIG_SYSCTL_SYSCALL is not set
-# CONFIG_ELF_CORE is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-CONFIG_MODULE_SRCVERSION_ALL=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP4=y
-# CONFIG_ARCH_OMAP2PLUS_TYPICAL is not set
-# CONFIG_ARCH_OMAP2 is not set
-# CONFIG_ARCH_OMAP3 is not set
-# CONFIG_OMAP_MUX is not set
-CONFIG_OMAP_32K_TIMER=y
-CONFIG_OMAP_DM_TIMER=y
-CONFIG_MACH_OMAP_4430SDP=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_PL310_ERRATA_588369=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=2
-# CONFIG_LOCAL_TIMERS is not set
-CONFIG_PREEMPT=y
-CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M console=ttyS2,115200n8 initrd=0x81600000,20M ramdisk_size=20480"
-CONFIG_VFP=y
-CONFIG_NEON=y
-CONFIG_BINFMT_MISC=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_IPV6 is not set
-# CONFIG_WIRELESS is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=16384
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_KS8851=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_WLAN is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=32
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-CONFIG_SERIAL_8250_DETECT_IRQ=y
-CONFIG_SERIAL_8250_RSA=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_OMAP=y
-CONFIG_SPI=y
-CONFIG_SPI_OMAP24XX=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_OMAP_WATCHDOG=y
-CONFIG_TWL4030_CORE=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_TWL4030=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_MMC=y
-CONFIG_MMC_OMAP_HS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_TWL4030=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
-CONFIG_QUOTA=y
-CONFIG_QFMT_V2=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V3_ACL=y
-CONFIG_NFS_V4=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_ISO8859_1=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-# CONFIG_DETECT_SOFTLOCKUP is not set
-CONFIG_DETECT_HUNG_TASK=y
-# CONFIG_SCHED_DEBUG is not set
-# CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_FTRACE is not set
-# CONFIG_ARM_UNWIND is not set
-CONFIG_CRYPTO_ECB=m
-CONFIG_CRYPTO_PCBC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRC_CCITT=y
-CONFIG_CRC_T10DIF=y
-CONFIG_LIBCRC32C=y
diff --git a/arch/arm/configs/omap_generic_2420_defconfig b/arch/arm/configs/omap_generic_2420_defconfig
deleted file mode 100644 (file)
index ac08e51..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP2=y
-# CONFIG_OMAP_MUX is not set
-CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_ARCH_OMAP2420=y
-CONFIG_LEDS=y
-CONFIG_ZBOOT_ROM_TEXT=0x10C08000
-CONFIG_ZBOOT_ROM_BSS=0x10200000
-CONFIG_FPE_NWFPE=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_VIDEO_OUTPUT_CONTROL=m
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_INOTIFY=y
-CONFIG_ROMFS_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
-CONFIG_DEBUG_LL=y
-CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/pcontrol_g20_defconfig b/arch/arm/configs/pcontrol_g20_defconfig
new file mode 100644 (file)
index 0000000..b42ee62
--- /dev/null
@@ -0,0 +1,175 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_CROSS_COMPILE="/opt/arm-2010q1/bin/arm-none-linux-gnueabi-"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_TREE_PREEMPT_RCU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_KALLSYMS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_DEFAULT_DEADLINE=y
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G20=y
+CONFIG_MACH_PCONTROL_G20=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 mem=128M mtdparts=atmel_nand:128k(bootstrap)ro,256k(uboot)ro,128k(env1)ro,128k(env2)ro,2M(linux),-(root) root=/dev/mmcblk0p1 rootwait rw"
+CONFIG_VFP=y
+CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_VLAN_8021Q=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHRAM=m
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_ATMEL_TCLIB=y
+CONFIG_EEPROM_AT24=m
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MACVLAN=m
+CONFIG_TUN=m
+CONFIG_SMSC_PHY=m
+CONFIG_BROADCOM_PHY=m
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_MACB=y
+CONFIG_SMSC911X=m
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_MPPE=m
+CONFIG_INPUT_POLLDEV=y
+CONFIG_INPUT_SPARSEKMAP=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_KEYBOARD_MATRIX=m
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=m
+CONFIG_INPUT_GPIO_ROTARY_ENCODER=m
+# CONFIG_SERIO is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_MAX3100=m
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_R3964=m
+CONFIG_I2C=m
+CONFIG_I2C_CHARDEV=m
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_GPIO=m
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=m
+CONFIG_SPI_SPIDEV=m
+CONFIG_GPIO_SYSFS=y
+CONFIG_W1=m
+CONFIG_W1_MASTER_GPIO=m
+CONFIG_W1_SLAVE_DS2431=m
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=m
+CONFIG_USB_LIBUSUAL=y
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_G_HID=m
+CONFIG_MMC=y
+CONFIG_MMC_UNSAFE_RESUME=y
+CONFIG_MMC_ATMELMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_AUXDISPLAY=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_IIO=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V4=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
index 5aff581..1fc684e 100644 (file)
@@ -35,9 +35,9 @@ extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte);
 #ifdef CONFIG_HIGHMEM
 extern void *kmap(struct page *page);
 extern void kunmap(struct page *page);
-extern void *kmap_atomic(struct page *page, enum km_type type);
-extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
+extern void *__kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
+extern void *kmap_atomic_pfn(unsigned long pfn);
 extern struct page *kmap_atomic_to_page(const void *ptr);
 #endif
 
index a9672e8..b155414 100644 (file)
@@ -263,17 +263,15 @@ extern struct page *empty_zero_page;
 #define pte_page(pte)          (pfn_to_page(pte_pfn(pte)))
 #define pte_offset_kernel(dir,addr)    (pmd_page_vaddr(*(dir)) + __pte_index(addr))
 
-#define pte_offset_map(dir,addr)       (__pte_map(dir, KM_PTE0) + __pte_index(addr))
-#define pte_offset_map_nested(dir,addr)        (__pte_map(dir, KM_PTE1) + __pte_index(addr))
-#define pte_unmap(pte)                 __pte_unmap(pte, KM_PTE0)
-#define pte_unmap_nested(pte)          __pte_unmap(pte, KM_PTE1)
+#define pte_offset_map(dir,addr)       (__pte_map(dir) + __pte_index(addr))
+#define pte_unmap(pte)                 __pte_unmap(pte)
 
 #ifndef CONFIG_HIGHPTE
-#define __pte_map(dir,km)      pmd_page_vaddr(*(dir))
-#define __pte_unmap(pte,km)    do { } while (0)
+#define __pte_map(dir)         pmd_page_vaddr(*(dir))
+#define __pte_unmap(pte)       do { } while (0)
 #else
-#define __pte_map(dir,km)      ((pte_t *)kmap_atomic(pmd_page(*(dir)), km) + PTRS_PER_PTE)
-#define __pte_unmap(pte,km)    kunmap_atomic((pte - PTRS_PER_PTE), km)
+#define __pte_map(dir)         ((pte_t *)kmap_atomic(pmd_page(*(dir))) + PTRS_PER_PTE)
+#define __pte_unmap(pte)       kunmap_atomic((pte - PTRS_PER_PTE))
 #endif
 
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
index abed4d1..c015b68 100644 (file)
@@ -375,6 +375,12 @@ config MACH_STAMP9G20
          evaluation board.
          <http://www.taskit.de/en/>
 
+config MACH_PCONTROL_G20
+       bool "PControl G20 CPU module"
+       help
+         Select this if you are using taskit's Stamp9G20 CPU module on this
+         carrier board, beeing the decentralized unit of a building automation
+         system; featuring nvram, eth-switch, iso-rs485, display, io
 endif
 
 if (ARCH_AT91SAM9260 || ARCH_AT91SAM9G20)
index 412b3a4..821eb84 100644 (file)
@@ -11,12 +11,12 @@ obj-$(CONFIG_AT91_PMC_UNIT) += clock.o
 
 # CPU-specific support
 obj-$(CONFIG_ARCH_AT91RM9200)  += at91rm9200.o at91rm9200_time.o at91rm9200_devices.o
-obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9RL)  += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o
-obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o
+obj-$(CONFIG_ARCH_AT91SAM9260) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9261) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9G10) += at91sam9261.o at91sam926x_time.o at91sam9261_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9263) += at91sam9263.o at91sam926x_time.o at91sam9263_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9RL)  += at91sam9rl.o at91sam926x_time.o at91sam9rl_devices.o sam9_smc.o at91sam9_alt_reset.o
+obj-$(CONFIG_ARCH_AT91SAM9G20) += at91sam9260.o at91sam926x_time.o at91sam9260_devices.o sam9_smc.o at91sam9_alt_reset.o
 obj-$(CONFIG_ARCH_AT91SAM9G45) += at91sam9g45.o at91sam926x_time.o at91sam9g45_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT91CAP9)    += at91cap9.o at91sam926x_time.o at91cap9_devices.o sam9_smc.o
 obj-$(CONFIG_ARCH_AT572D940HF)  += at572d940hf.o at91sam926x_time.o at572d940hf_devices.o sam9_smc.o
@@ -65,6 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
 obj-$(CONFIG_MACH_CPU9G20)     += board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)   += board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)   += board-stamp9g20.o
+obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)        += board-snapper9260.o
index 0894f10..195208b 100644 (file)
@@ -279,11 +279,6 @@ static struct at91_gpio_bank at91sam9260_gpio[] = {
        }
 };
 
-static void at91sam9260_reset(void)
-{
-       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9260_poweroff(void)
 {
        at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -327,7 +322,7 @@ void __init at91sam9260_initialize(unsigned long main_clock)
        else
                iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
 
-       at91_arch_reset = at91sam9260_reset;
+       at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9260_poweroff;
        at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
                        | (1 << AT91SAM9260_ID_IRQ2);
index 4ecf379..fcad886 100644 (file)
@@ -257,11 +257,6 @@ static struct at91_gpio_bank at91sam9261_gpio[] = {
        }
 };
 
-static void at91sam9261_reset(void)
-{
-       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9261_poweroff(void)
 {
        at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -283,7 +278,7 @@ void __init at91sam9261_initialize(unsigned long main_clock)
                iotable_init(at91sam9261_sram_desc, ARRAY_SIZE(at91sam9261_sram_desc));
 
 
-       at91_arch_reset = at91sam9261_reset;
+       at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9261_poweroff;
        at91_extern_irq = (1 << AT91SAM9261_ID_IRQ0) | (1 << AT91SAM9261_ID_IRQ1)
                        | (1 << AT91SAM9261_ID_IRQ2);
index 942792d..249f900 100644 (file)
@@ -269,11 +269,6 @@ static struct at91_gpio_bank at91sam9263_gpio[] = {
        }
 };
 
-static void at91sam9263_reset(void)
-{
-       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9263_poweroff(void)
 {
        at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -289,7 +284,7 @@ void __init at91sam9263_initialize(unsigned long main_clock)
        /* Map peripherals */
        iotable_init(at91sam9263_io_desc, ARRAY_SIZE(at91sam9263_io_desc));
 
-       at91_arch_reset = at91sam9263_reset;
+       at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9263_poweroff;
        at91_extern_irq = (1 << AT91SAM9263_ID_IRQ0) | (1 << AT91SAM9263_ID_IRQ1);
 
diff --git a/arch/arm/mach-at91/at91sam9_alt_reset.S b/arch/arm/mach-at91/at91sam9_alt_reset.S
new file mode 100644 (file)
index 0000000..e0256de
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * reset AT91SAM9G20 as per errata
+ *
+ * (C) BitBox Ltd 2010
+ *
+ * unless the SDRAM is cleanly shutdown before we hit the
+ * reset register it can be left driving the data bus and
+ * killing the chance of a subsequent boot from NAND
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/linkage.h>
+#include <asm/system.h>
+#include <mach/hardware.h>
+#include <mach/at91sam9_sdramc.h>
+#include <mach/at91_rstc.h>
+
+                       .arm
+
+                       .globl  at91sam9_alt_reset
+
+at91sam9_alt_reset:    mrc     p15, 0, r0, c1, c0, 0
+                       orr     r0, r0, #CR_I
+                       mcr     p15, 0, r0, c1, c0, 0           @ enable I-cache
+
+                       ldr     r0, .at91_va_base_sdramc        @ preload constants
+                       ldr     r1, .at91_va_base_rstc_cr
+
+                       mov     r2, #1
+                       mov     r3, #AT91_SDRAMC_LPCB_POWER_DOWN
+                       ldr     r4, =AT91_RSTC_KEY | AT91_RSTC_PERRST | AT91_RSTC_PROCRST
+
+                       .balign 32                              @ align to cache line
+
+                       str     r2, [r0, #AT91_SDRAMC_TR]       @ disable SDRAM access
+                       str     r3, [r0, #AT91_SDRAMC_LPR]      @ power down SDRAM
+                       str     r4, [r1]                        @ reset processor
+
+                       b       .
+
+.at91_va_base_sdramc:
+       .word AT91_VA_BASE_SYS + AT91_SDRAMC0
+.at91_va_base_rstc_cr:
+       .word AT91_VA_BASE_SYS + AT91_RSTC_CR
index 1276bab..1e8f275 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
 #include <linux/i2c-gpio.h>
+#include <linux/atmel-mci.h>
 
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
@@ -25,6 +26,7 @@
 #include <mach/at91sam9g45_matrix.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at_hdmac.h>
+#include <mach/atmel-mci.h>
 
 #include "generic.h"
 
@@ -350,6 +352,169 @@ void __init at91_add_device_eth(struct at91_eth_data *data) {}
 
 
 /* --------------------------------------------------------------------
+ *  MMC / SD
+ * -------------------------------------------------------------------- */
+
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static u64 mmc_dmamask = DMA_BIT_MASK(32);
+static struct mci_platform_data mmc0_data, mmc1_data;
+
+static struct resource mmc0_resources[] = {
+       [0] = {
+               .start  = AT91SAM9G45_BASE_MCI0,
+               .end    = AT91SAM9G45_BASE_MCI0 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9G45_ID_MCI0,
+               .end    = AT91SAM9G45_ID_MCI0,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9g45_mmc0_device = {
+       .name           = "atmel_mci",
+       .id             = 0,
+       .dev            = {
+                               .dma_mask               = &mmc_dmamask,
+                               .coherent_dma_mask      = DMA_BIT_MASK(32),
+                               .platform_data          = &mmc0_data,
+       },
+       .resource       = mmc0_resources,
+       .num_resources  = ARRAY_SIZE(mmc0_resources),
+};
+
+static struct resource mmc1_resources[] = {
+       [0] = {
+               .start  = AT91SAM9G45_BASE_MCI1,
+               .end    = AT91SAM9G45_BASE_MCI1 + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = AT91SAM9G45_ID_MCI1,
+               .end    = AT91SAM9G45_ID_MCI1,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device at91sam9g45_mmc1_device = {
+       .name           = "atmel_mci",
+       .id             = 1,
+       .dev            = {
+                               .dma_mask               = &mmc_dmamask,
+                               .coherent_dma_mask      = DMA_BIT_MASK(32),
+                               .platform_data          = &mmc1_data,
+       },
+       .resource       = mmc1_resources,
+       .num_resources  = ARRAY_SIZE(mmc1_resources),
+};
+
+/* Consider only one slot : slot 0 */
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
+{
+
+       if (!data)
+               return;
+
+       /* Must have at least one usable slot */
+       if (!data->slot[0].bus_width)
+               return;
+
+#if defined(CONFIG_AT_HDMAC) || defined(CONFIG_AT_HDMAC_MODULE)
+       {
+       struct at_dma_slave     *atslave;
+       struct mci_dma_data     *alt_atslave;
+
+       alt_atslave = kzalloc(sizeof(struct mci_dma_data), GFP_KERNEL);
+       atslave = &alt_atslave->sdata;
+
+       /* DMA slave channel configuration */
+       atslave->dma_dev = &at_hdmac_device.dev;
+       atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
+       atslave->cfg = ATC_FIFOCFG_HALFFIFO
+                       | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
+       atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
+       if (mmc_id == 0)        /* MCI0 */
+               atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI0)
+                             | ATC_DST_PER(AT_DMA_ID_MCI0);
+
+       else                    /* MCI1 */
+               atslave->cfg |= ATC_SRC_PER(AT_DMA_ID_MCI1)
+                             | ATC_DST_PER(AT_DMA_ID_MCI1);
+
+       data->dma_slave = alt_atslave;
+       }
+#endif
+
+
+       /* input/irq */
+       if (data->slot[0].detect_pin) {
+               at91_set_gpio_input(data->slot[0].detect_pin, 1);
+               at91_set_deglitch(data->slot[0].detect_pin, 1);
+       }
+       if (data->slot[0].wp_pin)
+               at91_set_gpio_input(data->slot[0].wp_pin, 1);
+
+       if (mmc_id == 0) {              /* MCI0 */
+
+               /* CLK */
+               at91_set_A_periph(AT91_PIN_PA0, 0);
+
+               /* CMD */
+               at91_set_A_periph(AT91_PIN_PA1, 1);
+
+               /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
+               at91_set_A_periph(AT91_PIN_PA2, 1);
+               if (data->slot[0].bus_width == 4) {
+                       at91_set_A_periph(AT91_PIN_PA3, 1);
+                       at91_set_A_periph(AT91_PIN_PA4, 1);
+                       at91_set_A_periph(AT91_PIN_PA5, 1);
+                       if (data->slot[0].bus_width == 8) {
+                               at91_set_A_periph(AT91_PIN_PA6, 1);
+                               at91_set_A_periph(AT91_PIN_PA7, 1);
+                               at91_set_A_periph(AT91_PIN_PA8, 1);
+                               at91_set_A_periph(AT91_PIN_PA9, 1);
+                       }
+               }
+
+               mmc0_data = *data;
+               at91_clock_associate("mci0_clk", &at91sam9g45_mmc0_device.dev, "mci_clk");
+               platform_device_register(&at91sam9g45_mmc0_device);
+
+       } else {                        /* MCI1 */
+
+               /* CLK */
+               at91_set_A_periph(AT91_PIN_PA31, 0);
+
+               /* CMD */
+               at91_set_A_periph(AT91_PIN_PA22, 1);
+
+               /* DAT0, maybe DAT1..DAT3 and maybe DAT4..DAT7 */
+               at91_set_A_periph(AT91_PIN_PA23, 1);
+               if (data->slot[0].bus_width == 4) {
+                       at91_set_A_periph(AT91_PIN_PA24, 1);
+                       at91_set_A_periph(AT91_PIN_PA25, 1);
+                       at91_set_A_periph(AT91_PIN_PA26, 1);
+                       if (data->slot[0].bus_width == 8) {
+                               at91_set_A_periph(AT91_PIN_PA27, 1);
+                               at91_set_A_periph(AT91_PIN_PA28, 1);
+                               at91_set_A_periph(AT91_PIN_PA29, 1);
+                               at91_set_A_periph(AT91_PIN_PA30, 1);
+                       }
+               }
+
+               mmc1_data = *data;
+               at91_clock_associate("mci1_clk", &at91sam9g45_mmc1_device.dev, "mci_clk");
+               platform_device_register(&at91sam9g45_mmc1_device);
+
+       }
+}
+#else
+void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {}
+#endif
+
+
+/* --------------------------------------------------------------------
  *  NAND / SmartMedia
  * -------------------------------------------------------------------- */
 
index 211c5c1..6a9d24e 100644 (file)
@@ -242,11 +242,6 @@ static struct at91_gpio_bank at91sam9rl_gpio[] = {
        }
 };
 
-static void at91sam9rl_reset(void)
-{
-       at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
-}
-
 static void at91sam9rl_poweroff(void)
 {
        at91_sys_write(AT91_SHDW_CR, AT91_SHDW_KEY | AT91_SHDW_SHDW);
@@ -281,7 +276,7 @@ void __init at91sam9rl_initialize(unsigned long main_clock)
        /* Map SRAM */
        iotable_init(at91sam9rl_sram_desc, ARRAY_SIZE(at91sam9rl_sram_desc));
 
-       at91_arch_reset = at91sam9rl_reset;
+       at91_arch_reset = at91sam9_alt_reset;
        pm_power_off = at91sam9rl_poweroff;
        at91_extern_irq = (1 << AT91SAM9RL_ID_IRQ0);
 
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
new file mode 100644 (file)
index 0000000..bba5a56
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ *  Copyright (C) 2010 Christian Glindkamp <christian.glindkamp@taskit.de>
+ *                     taskit GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/*
+ * copied and adjusted from board-stamp9g20.c
+ * by Peter Gsellmann <pgsellmann@portner-elektronik.at>
+ */
+
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/w1-gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/board.h>
+#include <mach/at91sam9_smc.h>
+
+#include "sam9_smc.h"
+#include "generic.h"
+
+
+static void __init pcontrol_g20_map_io(void)
+{
+       /* Initialize processor: 18.432 MHz crystal */
+       at91sam9260_initialize(18432000);
+
+       /* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */
+       at91_register_uart(0, 0, 0);
+
+       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
+       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
+                                               | ATMEL_UART_RTS);
+
+       /* USART1 on ttyS2. (Rx, Tx, CTS, RTS) isolated RS485  X5 */
+       at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS
+                                               | ATMEL_UART_RTS);
+
+       /* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
+       at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
+
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
+}
+
+
+static void __init init_irq(void)
+{
+       at91sam9260_init_interrupts(NULL);
+}
+
+
+/*
+ * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB
+ */
+static struct atmel_nand_data __initdata nand_data = {
+       .ale            = 21,
+       .cle            = 22,
+       .rdy_pin        = AT91_PIN_PC13,
+       .enable_pin     = AT91_PIN_PC14,
+};
+
+/*
+ * Bus timings; unit = 7.57ns
+ */
+static struct sam9_smc_config __initdata nand_smc_config = {
+       .ncs_read_setup         = 0,
+       .nrd_setup              = 2,
+       .ncs_write_setup        = 0,
+       .nwe_setup              = 2,
+
+       .ncs_read_pulse         = 4,
+       .nrd_pulse              = 4,
+       .ncs_write_pulse        = 4,
+       .nwe_pulse              = 4,
+
+       .read_cycle             = 7,
+       .write_cycle            = 7,
+
+       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
+                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
+       .tdf_cycles             = 3,
+};
+
+static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
+       .ncs_read_setup         = 16,
+       .nrd_setup              = 18,
+       .ncs_write_setup        = 16,
+       .nwe_setup              = 18,
+
+       .ncs_read_pulse         = 63,
+       .nrd_pulse              = 55,
+       .ncs_write_pulse        = 63,
+       .nwe_pulse              = 55,
+
+       .read_cycle             = 127,
+       .write_cycle            = 127,
+
+       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
+                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_SELECT
+                       | AT91_SMC_DBW_8 | AT91_SMC_PS_4
+                       | AT91_SMC_TDFMODE,
+       .tdf_cycles             = 3,
+}, {
+       .ncs_read_setup         = 0,
+       .nrd_setup              = 0,
+       .ncs_write_setup        = 0,
+       .nwe_setup              = 1,
+
+       .ncs_read_pulse         = 8,
+       .nrd_pulse              = 8,
+       .ncs_write_pulse        = 5,
+       .nwe_pulse              = 4,
+
+       .read_cycle             = 8,
+       .write_cycle            = 7,
+
+       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
+                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_BAT_SELECT
+                       | AT91_SMC_DBW_16 | AT91_SMC_PS_8
+                       | AT91_SMC_TDFMODE,
+       .tdf_cycles             = 1,
+} };
+
+static void __init add_device_nand(void)
+{
+       /* configure chip-select 3 (NAND) */
+       sam9_smc_configure(3, &nand_smc_config);
+       at91_add_device_nand(&nand_data);
+}
+
+
+static void __init add_device_pcontrol(void)
+{
+       /* configure chip-select 4 (IO compatible to 8051  X4 ) */
+       sam9_smc_configure(4, &pcontrol_smc_config[0]);
+       /* configure chip-select 7 (FerroRAM 256KiBx16bit MR2A16A  D4 ) */
+       sam9_smc_configure(7, &pcontrol_smc_config[1]);
+}
+
+
+/*
+ * MCI (SD/MMC)
+ * det_pin, wp_pin and vcc_pin are not connected
+ */
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+static struct mci_platform_data __initdata mmc_data = {
+       .slot[0] = {
+               .bus_width      = 4,
+       },
+};
+#else
+static struct at91_mmc_data __initdata mmc_data = {
+       .wire4          = 1,
+};
+#endif
+
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata usbh_data = {
+       .ports          = 2,
+};
+
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata pcontrol_g20_udc_data = {
+       .vbus_pin       = AT91_PIN_PA22,        /* Detect +5V bus voltage */
+       .pullup_pin     = AT91_PIN_PA4,         /* K-state, active low */
+};
+
+
+/*
+ * MACB Ethernet device
+ */
+static struct at91_eth_data __initdata macb_data = {
+       .phy_irq_pin    = AT91_PIN_PA28,
+       .is_rmii        = 1,
+};
+
+
+/*
+ * I2C devices: eeprom and phy/switch
+ */
+static struct i2c_board_info __initdata pcontrol_g20_i2c_devices[] = {
+{              /* D7  address width=2, 8KiB */
+       I2C_BOARD_INFO("24c64", 0x50)
+}, {           /* D8  address width=1, 1 byte has 32 bits! */
+       I2C_BOARD_INFO("lan9303", 0x0a)
+}, };
+
+
+/*
+ * LEDs
+ */
+static struct gpio_led pcontrol_g20_leds[] = {
+       {
+               .name                   = "LED1",       /* red  H5 */
+               .gpio                   = AT91_PIN_PB18,
+               .active_low             = 1,
+               .default_trigger        = "none",       /* supervisor */
+       }, {
+               .name                   = "LED2",       /* yellow  H7 */
+               .gpio                   = AT91_PIN_PB19,
+               .active_low             = 1,
+               .default_trigger        = "mmc0",       /* SD-card activity */
+       }, {
+               .name                   = "LED3",       /* green  H2 */
+               .gpio                   = AT91_PIN_PB20,
+               .active_low             = 1,
+               .default_trigger        = "heartbeat",  /* blinky */
+       }, {
+               .name                   = "LED4",       /* red  H3 */
+               .gpio                   = AT91_PIN_PC6,
+               .active_low             = 1,
+               .default_trigger        = "none",       /* connection lost */
+       }, {
+               .name                   = "LED5",       /* yellow  H6 */
+               .gpio                   = AT91_PIN_PC7,
+               .active_low             = 1,
+               .default_trigger        = "none",       /* unsent data */
+       }, {
+               .name                   = "LED6",       /* green  H1 */
+               .gpio                   = AT91_PIN_PC9,
+               .active_low             = 1,
+               .default_trigger        = "none",       /* snafu */
+       }
+};
+
+
+/*
+ * SPI devices
+ */
+static struct spi_board_info pcontrol_g20_spi_devices[] = {
+       {
+               .modalias       = "spidev",     /* HMI port  X4 */
+               .chip_select    = 1,
+               .max_speed_hz   = 50 * 1000 * 1000,
+               .bus_num        = 0,
+       }, {
+               .modalias       = "spidev",     /* piggyback  A2 */
+               .chip_select    = 0,
+               .max_speed_hz   = 50 * 1000 * 1000,
+               .bus_num        = 1,
+       },
+};
+
+
+/*
+ * Dallas 1-Wire  DS2431
+ */
+static struct w1_gpio_platform_data w1_gpio_pdata = {
+       .pin            = AT91_PIN_PA29,
+       .is_open_drain  = 1,
+};
+
+static struct platform_device w1_device = {
+       .name                   = "w1-gpio",
+       .id                     = -1,
+       .dev.platform_data      = &w1_gpio_pdata,
+};
+
+static void add_wire1(void)
+{
+       at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
+       at91_set_multi_drive(w1_gpio_pdata.pin, 1);
+       platform_device_register(&w1_device);
+}
+
+
+static void __init pcontrol_g20_board_init(void)
+{
+       at91_add_device_serial();
+       add_device_nand();
+#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
+       at91_add_device_mci(0, &mmc_data);
+#else
+       at91_add_device_mmc(0, &mmc_data);
+#endif
+       at91_add_device_usbh(&usbh_data);
+       at91_add_device_eth(&macb_data);
+       at91_add_device_i2c(pcontrol_g20_i2c_devices,
+               ARRAY_SIZE(pcontrol_g20_i2c_devices));
+       add_wire1();
+       add_device_pcontrol();
+       at91_add_device_spi(pcontrol_g20_spi_devices,
+               ARRAY_SIZE(pcontrol_g20_spi_devices));
+       at91_add_device_udc(&pcontrol_g20_udc_data);
+       at91_gpio_leds(pcontrol_g20_leds,
+               ARRAY_SIZE(pcontrol_g20_leds));
+       /* piggyback  A2 */
+       at91_set_gpio_output(AT91_PIN_PB31, 1);
+}
+
+
+MACHINE_START(PCONTROL_G20, "PControl G20")
+       /* Maintainer: pgsellmann@portner-elektronik.at */
+       .boot_params    = AT91_SDRAM_BASE + 0x100,
+       .timer          = &at91sam926x_timer,
+       .map_io         = pcontrol_g20_map_io,
+       .init_irq       = init_irq,
+       .init_machine   = pcontrol_g20_board_init,
+MACHINE_END
index 7913984..86ff4b5 100644 (file)
@@ -24,7 +24,9 @@
 #include <linux/input.h>
 #include <linux/leds.h>
 #include <linux/clk.h>
+#include <linux/atmel-mci.h>
 
+#include <mach/hardware.h>
 #include <video/atmel_lcdc.h>
 
 #include <asm/setup.h>
@@ -98,6 +100,25 @@ static struct spi_board_info ek_spi_devices[] = {
 
 
 /*
+ * MCI (SD/MMC)
+ */
+static struct mci_platform_data __initdata mci0_data = {
+       .slot[0] = {
+               .bus_width      = 4,
+               .detect_pin     = AT91_PIN_PD10,
+       },
+};
+
+static struct mci_platform_data __initdata mci1_data = {
+       .slot[0] = {
+               .bus_width      = 4,
+               .detect_pin     = AT91_PIN_PD11,
+               .wp_pin         = AT91_PIN_PD29,
+       },
+};
+
+
+/*
  * MACB Ethernet device
  */
 static struct at91_eth_data __initdata ek_macb_data = {
@@ -380,6 +401,9 @@ static void __init ek_board_init(void)
        at91_add_device_usba(&ek_usba_udc_data);
        /* SPI */
        at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices));
+       /* MMC */
+       at91_add_device_mci(0, &mci0_data);
+       at91_add_device_mci(1, &mci1_data);
        /* Ethernet */
        at91_add_device_eth(&ek_macb_data);
        /* NAND */
index 65c3dc5..0c66deb 100644 (file)
@@ -46,6 +46,9 @@ extern void __init at91_clock_associate(const char *id, struct device *dev, cons
 extern void at91_irq_suspend(void);
 extern void at91_irq_resume(void);
 
+/* reset */
+extern void at91sam9_alt_reset(void);
+
  /* GPIO */
 #define AT91RM9200_PQFP                3       /* AT91RM9200 PQFP package has 3 banks */
 #define AT91RM9200_BGA         4       /* AT91RM9200 BGA package has 4 banks */
index 6156689..dafbacc 100644 (file)
@@ -258,16 +258,23 @@ static int at91_pm_enter(suspend_state_t state)
                         * NOTE: the Wait-for-Interrupt instruction needs to be
                         * in icache so no SDRAM accesses are needed until the
                         * wakeup IRQ occurs and self-refresh is terminated.
+                        * For ARM 926 based chips, this requirement is weaker
+                        * as at91sam9 can access a RAM in self-refresh mode.
                         */
-                       asm("b 1f; .align 5; 1:");
-                       asm("mcr p15, 0, r0, c7, c10, 4");      /* drain write buffer */
+                       asm volatile (  "mov r0, #0\n\t"
+                                       "b 1f\n\t"
+                                       ".align 5\n\t"
+                                       "1: mcr p15, 0, r0, c7, c10, 4\n\t"
+                                       : /* no output */
+                                       : /* no input */
+                                       : "r0");
                        saved_lpr = sdram_selfrefresh_enable();
-                       asm("mcr p15, 0, r0, c7, c0, 4");       /* wait for interrupt */
+                       wait_for_interrupt_enable();
                        sdram_selfrefresh_disable(saved_lpr);
                        break;
 
                case PM_SUSPEND_ON:
-                       asm("mcr p15, 0, r0, c7, c0, 4");       /* wait for interrupt */
+                       cpu_do_idle();
                        break;
 
                default:
index 8c87d0c..ce9a206 100644 (file)
@@ -21,6 +21,8 @@ static inline u32 sdram_selfrefresh_enable(void)
 }
 
 #define sdram_selfrefresh_disable(saved_lpr)   at91_sys_write(AT91_SDRAMC_LPR, saved_lpr)
+#define wait_for_interrupt_enable()            asm volatile ("mcr p15, 0, %0, c7, c0, 4" \
+                                                               : : "r" (0))
 
 #elif defined(CONFIG_ARCH_AT91CAP9)
 #include <mach/at91cap9_ddrsdr.h>
@@ -38,6 +40,7 @@ static inline u32 sdram_selfrefresh_enable(void)
 }
 
 #define sdram_selfrefresh_disable(saved_lpr)   at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr)
+#define wait_for_interrupt_enable()            cpu_do_idle()
 
 #elif defined(CONFIG_ARCH_AT91SAM9G45)
 #include <mach/at91sam9_ddrsdr.h>
@@ -74,6 +77,7 @@ static inline u32 sdram_selfrefresh_enable(void)
                at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0); \
                at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1); \
        } while (0)
+#define wait_for_interrupt_enable()            cpu_do_idle()
 
 #else
 #include <mach/at91sam9_sdramc.h>
@@ -98,5 +102,6 @@ static inline u32 sdram_selfrefresh_enable(void)
 }
 
 #define sdram_selfrefresh_disable(saved_lpr)   at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr)
+#define wait_for_interrupt_enable()            cpu_do_idle()
 
 #endif
index b6b00a1..f7922a4 100644 (file)
@@ -124,6 +124,7 @@ ENTRY(at91_slow_clock)
        ldr     r5, .at91_va_base_ramc1
 
        /* Drain write buffer */
+       mov     r0, #0
        mcr     p15, 0, r0, c7, c10, 4
 
 #ifdef CONFIG_ARCH_AT91RM9200
index 4566bd1..ef06c66 100644 (file)
@@ -358,8 +358,7 @@ static int calc_clk_div(struct clk *clk, unsigned long rate,
        int i, found = 0, __div = 0, __pdiv = 0;
 
        /* Don't exceed the maximum rate */
-       max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4),
-                      clk_xtali.rate / 4);
+       max_rate = max3(clk_pll1.rate / 4, clk_pll2.rate / 4, clk_xtali.rate / 4);
        rate = min(rate, max_rate);
 
        /*
index 5e28644..5ea66f1 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
+#include <linux/gpio-fan.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -137,6 +138,46 @@ static struct platform_device netspace_v2_leds = {
 };
 
 /*****************************************************************************
+ * GPIO fan
+ ****************************************************************************/
+
+/* Designed for fan 40x40x16: ADDA AD0412LB-D50 6000rpm@12v */
+static struct gpio_fan_speed netspace_max_v2_fan_speed[] = {
+       {    0,  0 },
+       { 1500, 15 },
+       { 1700, 14 },
+       { 1800, 13 },
+       { 2100, 12 },
+       { 3100, 11 },
+       { 3300, 10 },
+       { 4300,  9 },
+       { 5500,  8 },
+};
+
+static unsigned netspace_max_v2_fan_ctrl[] = { 22, 7, 33, 23 };
+
+static struct gpio_fan_alarm netspace_max_v2_fan_alarm = {
+       .gpio           = 25,
+       .active_low     = 1,
+};
+
+static struct gpio_fan_platform_data netspace_max_v2_fan_data = {
+       .num_ctrl       = ARRAY_SIZE(netspace_max_v2_fan_ctrl),
+       .ctrl           = netspace_max_v2_fan_ctrl,
+       .alarm          = &netspace_max_v2_fan_alarm,
+       .num_speed      = ARRAY_SIZE(netspace_max_v2_fan_speed),
+       .speed          = netspace_max_v2_fan_speed,
+};
+
+static struct platform_device netspace_max_v2_gpio_fan = {
+       .name   = "gpio-fan",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &netspace_max_v2_fan_data,
+       },
+};
+
+/*****************************************************************************
  * General Setup
  ****************************************************************************/
 
@@ -205,6 +246,8 @@ static void __init netspace_v2_init(void)
        platform_device_register(&netspace_v2_leds);
        platform_device_register(&netspace_v2_gpio_leds);
        platform_device_register(&netspace_v2_gpio_buttons);
+       if (machine_is_netspace_max_v2())
+               platform_device_register(&netspace_max_v2_gpio_fan);
 
        if (gpio_request(NETSPACE_V2_GPIO_POWER_OFF, "power-off") == 0 &&
            gpio_direction_output(NETSPACE_V2_GPIO_POWER_OFF, 0) == 0)
index facfaeb..9a304d8 100644 (file)
@@ -12,7 +12,7 @@ obj-$(CONFIG_OMAP_MPU_TIMER)  += time.o
 obj-$(CONFIG_OMAP_32K_TIMER)   += timer32k.o
 
 # Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o
+obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o
 
 # DSP
 obj-$(CONFIG_OMAP_MBOX_FWK)    += mailbox_mach.o
index 73c8639..1d4163b 100644 (file)
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/leds.h>
 #include <linux/platform_device.h>
 #include <linux/serial_8250.h>
 
+#include <media/soc_camera.h>
+
 #include <asm/serial.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -32,6 +35,7 @@
 #include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/common.h>
+#include <mach/camera.h>
 
 #include <mach/ams-delta-fiq.h>
 
@@ -213,10 +217,56 @@ static struct platform_device ams_delta_led_device = {
        .id     = -1
 };
 
+static struct i2c_board_info ams_delta_camera_board_info[] = {
+       {
+               I2C_BOARD_INFO("ov6650", 0x60),
+       },
+};
+
+#ifdef CONFIG_LEDS_TRIGGERS
+DEFINE_LED_TRIGGER(ams_delta_camera_led_trigger);
+
+static int ams_delta_camera_power(struct device *dev, int power)
+{
+       /*
+        * turn on camera LED
+        */
+       if (power)
+               led_trigger_event(ams_delta_camera_led_trigger, LED_FULL);
+       else
+               led_trigger_event(ams_delta_camera_led_trigger, LED_OFF);
+       return 0;
+}
+#else
+#define ams_delta_camera_power NULL
+#endif
+
+static struct soc_camera_link __initdata ams_delta_iclink = {
+       .bus_id         = 0,    /* OMAP1 SoC camera bus */
+       .i2c_adapter_id = 1,
+       .board_info     = &ams_delta_camera_board_info[0],
+       .module_name    = "ov6650",
+       .power          = ams_delta_camera_power,
+};
+
+static struct platform_device ams_delta_camera_device = {
+       .name   = "soc-camera-pdrv",
+       .id     = 0,
+       .dev    = {
+               .platform_data = &ams_delta_iclink,
+       },
+};
+
+static struct omap1_cam_platform_data ams_delta_camera_platform_data = {
+       .camexclk_khz   = 12000,        /* default 12MHz clock, no extra DPLL */
+       .lclk_khz_max   = 1334,         /* results in 5fps CIF, 10fps QCIF */
+};
+
 static struct platform_device *ams_delta_devices[] __initdata = {
        &ams_delta_kp_device,
        &ams_delta_lcd_device,
        &ams_delta_led_device,
+       &ams_delta_camera_device,
 };
 
 static void __init ams_delta_init(void)
@@ -225,6 +275,20 @@ static void __init ams_delta_init(void)
        omap_cfg_reg(UART1_TX);
        omap_cfg_reg(UART1_RTS);
 
+       /* parallel camera interface */
+       omap_cfg_reg(H19_1610_CAM_EXCLK);
+       omap_cfg_reg(J15_1610_CAM_LCLK);
+       omap_cfg_reg(L18_1610_CAM_VS);
+       omap_cfg_reg(L15_1610_CAM_HS);
+       omap_cfg_reg(L19_1610_CAM_D0);
+       omap_cfg_reg(K14_1610_CAM_D1);
+       omap_cfg_reg(K15_1610_CAM_D2);
+       omap_cfg_reg(K19_1610_CAM_D3);
+       omap_cfg_reg(K18_1610_CAM_D4);
+       omap_cfg_reg(J14_1610_CAM_D5);
+       omap_cfg_reg(J19_1610_CAM_D6);
+       omap_cfg_reg(J18_1610_CAM_D7);
+
        iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
 
        omap_board_config = ams_delta_config;
@@ -236,6 +300,11 @@ static void __init ams_delta_init(void)
        ams_delta_latch2_write(~0, 0);
 
        omap1_usb_init(&ams_delta_usb_config);
+       omap1_set_camera_info(&ams_delta_camera_platform_data);
+#ifdef CONFIG_LEDS_TRIGGERS
+       led_trigger_register_simple("ams_delta_camera",
+                       &ams_delta_camera_led_trigger);
+#endif
        platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
 
 #ifdef CONFIG_AMS_DELTA_FIQ
index b30c499..f2fc43d 100644 (file)
@@ -58,8 +58,7 @@ static struct omap_mmc_platform_data mmc1_data = {
        .dma_mask                       = 0xffffffff,
        .slots[0]       = {
                .set_power              = mmc_set_power,
-               .ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-                                         MMC_VDD_32_33 | MMC_VDD_33_34,
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
                .name                   = "mmcblk",
        },
 };
index 54b0f06..2098525 100644 (file)
@@ -40,8 +40,7 @@ static struct omap_mmc_platform_data mmc1_data = {
        .dma_mask                       = 0xffffffff,
        .slots[0]       = {
                .set_power              = mmc_set_power,
-               .ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-                                         MMC_VDD_32_33 | MMC_VDD_33_34,
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
                .name                   = "mmcblk",
        },
 };
index 86afb29..071af3e 100644 (file)
 #include <linux/input.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/i2c.h>
+#include <linux/i2c-gpio.h>
+#include <linux/htcpld.h>
+#include <linux/leds.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/ads7846.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -39,6 +46,7 @@
 #include <plat/board.h>
 #include <plat/keypad.h>
 #include <plat/usb.h>
+#include <plat/mmc.h>
 
 #include <mach/irqs.h>
 
 #define       OMAP_LCDC_CTRL_LCD_EN           (1 << 0)
 #define       OMAP_LCDC_STAT_DONE             (1 << 0)
 
-static struct omap_lcd_config htcherald_lcd_config __initdata = {
-       .ctrl_name      = "internal",
-};
+/* GPIO definitions for the power button and keyboard slide switch */
+#define HTCHERALD_GPIO_POWER 139
+#define HTCHERALD_GPIO_SLIDE 174
+#define HTCHERALD_GIRQ_BTNS 141
 
-static struct omap_board_config_kernel htcherald_config[] __initdata = {
-       { OMAP_TAG_LCD, &htcherald_lcd_config },
-};
+/* GPIO definitions for the touchscreen */
+#define HTCHERALD_GPIO_TS 76
+
+/* HTCPLD definitions */
+
+/*
+ * CPLD Logic
+ *
+ * Chip 3 - 0x03
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * DPAD light          x x x x  x x x 1
+ * SoundDev            x x x x  1 x x x
+ * Screen white        1 x x x  x x x x
+ * MMC power on        x x x x  x 1 x x
+ * Happy times (n)     0 x x x  x 1 x x
+ *
+ * Chip 4 - 0x04
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Keyboard light      x x x x  x x x 1
+ * LCD Bright (4)      x x x x  x 1 1 x
+ * LCD Bright (3)      x x x x  x 0 1 x
+ * LCD Bright (2)      x x x x  x 1 0 x
+ * LCD Bright (1)      x x x x  x 0 0 x
+ * LCD Off             x x x x  0 x x x
+ * LCD image (fb)      1 x x x  x x x x
+ * LCD image (white)   0 x x x  x x x x
+ * Caps lock LED       x x 1 x  x x x x
+ *
+ * Chip 5 - 0x05
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Red (solid)         x x x x  x 1 x x
+ * Red (flash)         x x x x  x x 1 x
+ * Green (GSM flash)   x x x x  1 x x x
+ * Green (GSM solid)   x x x 1  x x x x
+ * Green (wifi flash)  x x 1 x  x x x x
+ * Blue (bt flash)     x 1 x x  x x x x
+ * DPAD Int Enable     1 x x x  x x x 0
+ *
+ * (Combinations of the above can be made for different colors.)
+ * The direction pad interrupt enable must be set each time the
+ * interrupt is handled.
+ *
+ * Chip 6 - 0x06
+ *
+ * Function            7 6 5 4  3 2 1 0
+ * ------------------------------------
+ * Vibrator            x x x x  1 x x x
+ * Alt LED             x x x 1  x x x x
+ * Screen white        1 x x x  x x x x
+ * Screen white        x x 1 x  x x x x
+ * Screen white        x 0 x x  x x x x
+ * Enable kbd dpad     x x x x  x x 0 x
+ * Happy Times         0 1 0 x  x x 0 x
+ */
+
+/*
+ * HTCPLD GPIO lines start 16 after OMAP_MAX_GPIO_LINES to account
+ * for the 16 MPUIO lines.
+ */
+#define HTCPLD_GPIO_START_OFFSET       (OMAP_MAX_GPIO_LINES + 16)
+#define HTCPLD_IRQ(chip, offset)       (OMAP_IRQ_END + 8 * (chip) + (offset))
+#define HTCPLD_BASE(chip, offset)      \
+       (HTCPLD_GPIO_START_OFFSET + 8 * (chip) + (offset))
+
+#define HTCPLD_GPIO_LED_DPAD           HTCPLD_BASE(0, 0)
+#define HTCPLD_GPIO_LED_KBD            HTCPLD_BASE(1, 0)
+#define HTCPLD_GPIO_LED_CAPS           HTCPLD_BASE(1, 5)
+#define HTCPLD_GPIO_LED_RED_FLASH      HTCPLD_BASE(2, 1)
+#define HTCPLD_GPIO_LED_RED_SOLID      HTCPLD_BASE(2, 2)
+#define HTCPLD_GPIO_LED_GREEN_FLASH    HTCPLD_BASE(2, 3)
+#define HTCPLD_GPIO_LED_GREEN_SOLID    HTCPLD_BASE(2, 4)
+#define HTCPLD_GPIO_LED_WIFI           HTCPLD_BASE(2, 5)
+#define HTCPLD_GPIO_LED_BT             HTCPLD_BASE(2, 6)
+#define HTCPLD_GPIO_LED_VIBRATE                HTCPLD_BASE(3, 3)
+#define HTCPLD_GPIO_LED_ALT            HTCPLD_BASE(3, 4)
+
+#define HTCPLD_GPIO_RIGHT_KBD          HTCPLD_BASE(6, 7)
+#define HTCPLD_GPIO_UP_KBD             HTCPLD_BASE(6, 6)
+#define HTCPLD_GPIO_LEFT_KBD           HTCPLD_BASE(6, 5)
+#define HTCPLD_GPIO_DOWN_KBD           HTCPLD_BASE(6, 4)
+
+#define HTCPLD_GPIO_RIGHT_DPAD         HTCPLD_BASE(7, 7)
+#define HTCPLD_GPIO_UP_DPAD            HTCPLD_BASE(7, 6)
+#define HTCPLD_GPIO_LEFT_DPAD          HTCPLD_BASE(7, 5)
+#define HTCPLD_GPIO_DOWN_DPAD          HTCPLD_BASE(7, 4)
+#define HTCPLD_GPIO_ENTER_DPAD         HTCPLD_BASE(7, 3)
+
+/*
+ * The htcpld chip requires a gpio write to a specific line
+ * to re-enable interrupts after one has occurred.
+ */
+#define HTCPLD_GPIO_INT_RESET_HI       HTCPLD_BASE(2, 7)
+#define HTCPLD_GPIO_INT_RESET_LO       HTCPLD_BASE(2, 0)
+
+/* Chip 5 */
+#define HTCPLD_IRQ_RIGHT_KBD           HTCPLD_IRQ(0, 7)
+#define HTCPLD_IRQ_UP_KBD              HTCPLD_IRQ(0, 6)
+#define HTCPLD_IRQ_LEFT_KBD            HTCPLD_IRQ(0, 5)
+#define HTCPLD_IRQ_DOWN_KBD            HTCPLD_IRQ(0, 4)
+
+/* Chip 6 */
+#define HTCPLD_IRQ_RIGHT_DPAD          HTCPLD_IRQ(1, 7)
+#define HTCPLD_IRQ_UP_DPAD             HTCPLD_IRQ(1, 6)
+#define HTCPLD_IRQ_LEFT_DPAD           HTCPLD_IRQ(1, 5)
+#define HTCPLD_IRQ_DOWN_DPAD           HTCPLD_IRQ(1, 4)
+#define HTCPLD_IRQ_ENTER_DPAD          HTCPLD_IRQ(1, 3)
 
 /* Keyboard definition */
 
@@ -140,6 +258,129 @@ static struct platform_device kp_device = {
        .resource       = kp_resources,
 };
 
+/* GPIO buttons for keyboard slide and power button */
+static struct gpio_keys_button herald_gpio_keys_table[] = {
+       {BTN_0,  HTCHERALD_GPIO_POWER, 1, "POWER", EV_KEY, 1, 20},
+       {SW_LID, HTCHERALD_GPIO_SLIDE, 0, "SLIDE", EV_SW,  1, 20},
+
+       {KEY_LEFT,  HTCPLD_GPIO_LEFT_KBD,  1, "LEFT",  EV_KEY, 1, 20},
+       {KEY_RIGHT, HTCPLD_GPIO_RIGHT_KBD, 1, "RIGHT", EV_KEY, 1, 20},
+       {KEY_UP,    HTCPLD_GPIO_UP_KBD,    1, "UP",    EV_KEY, 1, 20},
+       {KEY_DOWN,  HTCPLD_GPIO_DOWN_KBD,  1, "DOWN",  EV_KEY, 1, 20},
+
+       {KEY_LEFT,  HTCPLD_GPIO_LEFT_DPAD,   1, "DLEFT",  EV_KEY, 1, 20},
+       {KEY_RIGHT, HTCPLD_GPIO_RIGHT_DPAD,  1, "DRIGHT", EV_KEY, 1, 20},
+       {KEY_UP,    HTCPLD_GPIO_UP_DPAD,     1, "DUP",    EV_KEY, 1, 20},
+       {KEY_DOWN,  HTCPLD_GPIO_DOWN_DPAD,   1, "DDOWN",  EV_KEY, 1, 20},
+       {KEY_ENTER, HTCPLD_GPIO_ENTER_DPAD,  1, "DENTER", EV_KEY, 1, 20},
+};
+
+static struct gpio_keys_platform_data herald_gpio_keys_data = {
+       .buttons        = herald_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(herald_gpio_keys_table),
+       .rep            = 1,
+};
+
+static struct platform_device herald_gpiokeys_device = {
+       .name      = "gpio-keys",
+       .id             = -1,
+       .dev = {
+               .platform_data = &herald_gpio_keys_data,
+       },
+};
+
+/* LEDs for the Herald.  These connect to the HTCPLD GPIO device. */
+static struct gpio_led gpio_leds[] = {
+       {"dpad",        NULL, HTCPLD_GPIO_LED_DPAD,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"kbd",         NULL, HTCPLD_GPIO_LED_KBD,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"vibrate",     NULL, HTCPLD_GPIO_LED_VIBRATE,     0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"green_solid", NULL, HTCPLD_GPIO_LED_GREEN_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"green_flash", NULL, HTCPLD_GPIO_LED_GREEN_FLASH, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"red_solid",   "mmc0", HTCPLD_GPIO_LED_RED_SOLID, 0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"red_flash",   NULL, HTCPLD_GPIO_LED_RED_FLASH,   0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"wifi",        NULL, HTCPLD_GPIO_LED_WIFI,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"bt",          NULL, HTCPLD_GPIO_LED_BT,          0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"caps",        NULL, HTCPLD_GPIO_LED_CAPS,        0, 0, LEDS_GPIO_DEFSTATE_OFF},
+       {"alt",         NULL, HTCPLD_GPIO_LED_ALT,         0, 0, LEDS_GPIO_DEFSTATE_OFF},
+};
+
+static struct gpio_led_platform_data gpio_leds_data = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+       .name           = "leds-gpio",
+       .id             = 0,
+       .dev    = {
+               .platform_data  = &gpio_leds_data,
+       },
+};
+
+/* HTC PLD chips */
+
+static struct resource htcpld_resources[] = {
+       [0] = {
+               .start  = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+               .end    = OMAP_GPIO_IRQ(HTCHERALD_GIRQ_BTNS),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+struct htcpld_chip_platform_data htcpld_chips[] = {
+       [0] = {
+               .addr           = 0x03,
+               .reset          = 0x04,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(0, 0),
+               .gpio_in_base   = HTCPLD_BASE(4, 0),
+       },
+       [1] = {
+               .addr           = 0x04,
+               .reset          = 0x8e,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(1, 0),
+               .gpio_in_base   = HTCPLD_BASE(5, 0),
+       },
+       [2] = {
+               .addr           = 0x05,
+               .reset          = 0x80,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(2, 0),
+               .gpio_in_base   = HTCPLD_BASE(6, 0),
+               .irq_base       = HTCPLD_IRQ(0, 0),
+               .num_irqs       = 8,
+       },
+       [3] = {
+               .addr           = 0x06,
+               .reset          = 0x40,
+               .num_gpios      = 8,
+               .gpio_out_base  = HTCPLD_BASE(3, 0),
+               .gpio_in_base   = HTCPLD_BASE(7, 0),
+               .irq_base       = HTCPLD_IRQ(1, 0),
+               .num_irqs       = 8,
+       },
+};
+
+struct htcpld_core_platform_data htcpld_pfdata = {
+       .int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
+       .int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
+       .i2c_adapter_id    = 1,
+
+       .chip              = htcpld_chips,
+       .num_chip          = ARRAY_SIZE(htcpld_chips),
+};
+
+static struct platform_device htcpld_device = {
+       .name           = "i2c-htcpld",
+       .id             = -1,
+       .resource       = htcpld_resources,
+       .num_resources  = ARRAY_SIZE(htcpld_resources),
+       .dev    = {
+               .platform_data  = &htcpld_pfdata,
+       },
+};
+
 /* USB Device */
 static struct omap_usb_config htcherald_usb_config __initdata = {
        .otg = 0,
@@ -150,14 +391,71 @@ static struct omap_usb_config htcherald_usb_config __initdata = {
 };
 
 /* LCD Device resources */
+static struct omap_lcd_config htcherald_lcd_config __initdata = {
+       .ctrl_name      = "internal",
+};
+
+static struct omap_board_config_kernel htcherald_config[] __initdata = {
+       { OMAP_TAG_LCD, &htcherald_lcd_config },
+};
+
 static struct platform_device lcd_device = {
        .name           = "lcd_htcherald",
        .id             = -1,
 };
 
+/* MMC Card */
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+static struct omap_mmc_platform_data htc_mmc1_data = {
+       .nr_slots                       = 1,
+       .switch_slot                    = NULL,
+       .slots[0]       = {
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
+               .name                   = "mmcblk",
+               .nomux                  = 1,
+               .wires                  = 4,
+               .switch_pin             = -1,
+       },
+};
+
+static struct omap_mmc_platform_data *htc_mmc_data[1];
+#endif
+
+
+/* Platform devices for the Herald */
 static struct platform_device *devices[] __initdata = {
        &kp_device,
        &lcd_device,
+       &htcpld_device,
+       &gpio_leds_device,
+       &herald_gpiokeys_device,
+};
+
+/*
+ * Touchscreen
+ */
+static const struct ads7846_platform_data htcherald_ts_platform_data = {
+       .model                  = 7846,
+       .keep_vref_on           = 1,
+       .x_plate_ohms           = 496,
+       .gpio_pendown           = HTCHERALD_GPIO_TS,
+       .pressure_max           = 100000,
+       .pressure_min           = 5000,
+       .x_min                  = 528,
+       .x_max                  = 3760,
+       .y_min                  = 624,
+       .y_max                  = 3760,
+};
+
+static struct spi_board_info __initdata htcherald_spi_board_info[] = {
+       {
+               .modalias               = "ads7846",
+               .platform_data          = &htcherald_ts_platform_data,
+               .irq                    = OMAP_GPIO_IRQ(HTCHERALD_GPIO_TS),
+               .max_speed_hz           = 2500000,
+               .bus_num                = 2,
+               .chip_select            = 1,
+       }
 };
 
 /*
@@ -278,6 +576,7 @@ static void __init htcherald_init(void)
 {
        printk(KERN_INFO "HTC Herald init.\n");
 
+       /* Do board initialization before we register all the devices */
        omap_gpio_init();
 
        omap_board_config = htcherald_config;
@@ -288,6 +587,16 @@ static void __init htcherald_init(void)
 
        htcherald_usb_enable();
        omap1_usb_init(&htcherald_usb_config);
+
+       spi_register_board_info(htcherald_spi_board_info,
+               ARRAY_SIZE(htcherald_spi_board_info));
+
+       omap_register_i2c_bus(1, 100, NULL, 0);
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+       htc_mmc_data[0] = &htc_mmc1_data;
+       omap1_init_mmc(htc_mmc_data, 1);
+#endif
 }
 
 static void __init htcherald_init_irq(void)
index 5b33ae8..e8ddd86 100644 (file)
@@ -44,8 +44,7 @@ static struct omap_mmc_platform_data mmc1_data = {
        .nr_slots                       = 1,
        .slots[0]       = {
                .set_power              = mmc_set_power,
-               .ocr_mask               = MMC_VDD_28_29 | MMC_VDD_30_31 |
-                                         MMC_VDD_32_33 | MMC_VDD_33_34,
+               .ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
                .name                   = "mmcblk",
        },
 };
index b583121..ea0d80a 100644 (file)
@@ -9,6 +9,7 @@
  * (at your option) any later version.
  */
 
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -192,6 +193,48 @@ static inline void omap_init_spi100k(void)
 }
 #endif
 
+
+#define OMAP1_CAMERA_BASE      0xfffb6800
+#define OMAP1_CAMERA_IOSIZE    0x1c
+
+static struct resource omap1_camera_resources[] = {
+       [0] = {
+               .start  = OMAP1_CAMERA_BASE,
+               .end    = OMAP1_CAMERA_BASE + OMAP1_CAMERA_IOSIZE - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = INT_CAMERA,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static u64 omap1_camera_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device omap1_camera_device = {
+       .name           = "omap1-camera",
+       .id             = 0, /* This is used to put cameras on this interface */
+       .dev            = {
+               .dma_mask               = &omap1_camera_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .num_resources  = ARRAY_SIZE(omap1_camera_resources),
+       .resource       = omap1_camera_resources,
+};
+
+void __init omap1_camera_init(void *info)
+{
+       struct platform_device *dev = &omap1_camera_device;
+       int ret;
+
+       dev->dev.platform_data = info;
+
+       ret = platform_device_register(dev);
+       if (ret)
+               dev_err(&dev->dev, "unable to register device: %d\n", ret);
+}
+
+
 /*-------------------------------------------------------------------------*/
 
 static inline void omap_init_sti(void) {}
@@ -258,3 +301,30 @@ static int __init omap1_init_devices(void)
 }
 arch_initcall(omap1_init_devices);
 
+#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+
+static struct resource wdt_resources[] = {
+       {
+               .start          = 0xfffeb000,
+               .end            = 0xfffeb07F,
+               .flags          = IORESOURCE_MEM,
+       },
+};
+
+static struct platform_device omap_wdt_device = {
+       .name      = "omap_wdt",
+       .id          = -1,
+       .num_resources  = ARRAY_SIZE(wdt_resources),
+       .resource       = wdt_resources,
+};
+
+static int __init omap_init_wdt(void)
+{
+       if (!cpu_is_omap16xx())
+               return;
+
+       platform_device_register(&omap_wdt_device);
+       return 0;
+}
+subsys_initcall(omap_init_wdt);
+#endif
diff --git a/arch/arm/mach-omap1/include/mach/camera.h b/arch/arm/mach-omap1/include/mach/camera.h
new file mode 100644 (file)
index 0000000..fd54b45
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __ASM_ARCH_CAMERA_H_
+#define __ASM_ARCH_CAMERA_H_
+
+void omap1_camera_init(void *);
+
+static inline void omap1_set_camera_info(struct omap1_cam_platform_data *info)
+{
+       omap1_camera_init(info);
+}
+
+#endif /* __ASM_ARCH_CAMERA_H_ */
diff --git a/arch/arm/mach-omap1/pm_bus.c b/arch/arm/mach-omap1/pm_bus.c
new file mode 100644 (file)
index 0000000..8b66392
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Runtime PM support code for OMAP1
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+static int omap1_pm_runtime_suspend(struct device *dev)
+{
+       struct clk *iclk, *fclk;
+       int ret = 0;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       ret = pm_generic_runtime_suspend(dev);
+
+       fclk = clk_get(dev, "fck");
+       if (!IS_ERR(fclk)) {
+               clk_disable(fclk);
+               clk_put(fclk);
+       }
+
+       iclk = clk_get(dev, "ick");
+       if (!IS_ERR(iclk)) {
+               clk_disable(iclk);
+               clk_put(iclk);
+       }
+
+       return 0;
+};
+
+static int omap1_pm_runtime_resume(struct device *dev)
+{
+       int ret = 0;
+       struct clk *iclk, *fclk;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       iclk = clk_get(dev, "ick");
+       if (!IS_ERR(iclk)) {
+               clk_enable(iclk);
+               clk_put(iclk);
+       }
+
+       fclk = clk_get(dev, "fck");
+       if (!IS_ERR(fclk)) {
+               clk_enable(fclk);
+               clk_put(fclk);
+       }
+
+       return pm_generic_runtime_resume(dev);
+};
+
+static int __init omap1_pm_runtime_init(void)
+{
+       const struct dev_pm_ops *pm;
+       struct dev_pm_ops *omap_pm;
+
+       pm = platform_bus_get_pm_ops();
+       if (!pm) {
+               pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
+       if (!omap_pm) {
+               pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       omap_pm->runtime_suspend = omap1_pm_runtime_suspend;
+       omap_pm->runtime_resume = omap1_pm_runtime_resume;
+
+       platform_bus_set_pm_ops(omap_pm);
+
+       return 0;
+}
+core_initcall(omap1_pm_runtime_init);
+#endif /* CONFIG_PM_RUNTIME */
index b48bacf..ab784bf 100644 (file)
@@ -11,9 +11,8 @@ config ARCH_OMAP2PLUS_TYPICAL
        select PM_RUNTIME
        select VFP
        select NEON if ARCH_OMAP3 || ARCH_OMAP4
-       select SERIAL_8250
-       select SERIAL_CORE_CONSOLE
-       select SERIAL_8250_CONSOLE
+       select SERIAL_OMAP
+       select SERIAL_OMAP_CONSOLE
        select I2C
        select I2C_OMAP
        select MFD
@@ -35,7 +34,7 @@ config ARCH_OMAP3
        default y
        select CPU_V7
        select USB_ARCH_HAS_EHCI
-       select ARM_L1_CACHE_SHIFT_6
+       select ARM_L1_CACHE_SHIFT_6 if !ARCH_OMAP4
 
 config ARCH_OMAP4
        bool "TI OMAP4"
@@ -43,6 +42,8 @@ config ARCH_OMAP4
        depends on ARCH_OMAP2PLUS
        select CPU_V7
        select ARM_GIC
+       select PL310_ERRATA_588369
+       select ARM_ERRATA_720789
 
 comment "OMAP Core Type"
        depends on ARCH_OMAP2
@@ -99,20 +100,20 @@ config MACH_OMAP2_TUSB6010
 
 config MACH_OMAP_H4
        bool "OMAP 2420 H4 board"
-       depends on ARCH_OMAP2
+       depends on ARCH_OMAP2420
        default y
        select OMAP_PACKAGE_ZAF
        select OMAP_DEBUG_DEVICES
 
 config MACH_OMAP_APOLLON
        bool "OMAP 2420 Apollon board"
-       depends on ARCH_OMAP2
+       depends on ARCH_OMAP2420
        default y
        select OMAP_PACKAGE_ZAC
 
 config MACH_OMAP_2430SDP
        bool "OMAP 2430 SDP board"
-       depends on ARCH_OMAP2
+       depends on ARCH_OMAP2430
        default y
        select OMAP_PACKAGE_ZAC
 
@@ -135,6 +136,26 @@ config MACH_OMAP_LDP
        default y
        select OMAP_PACKAGE_CBB
 
+config MACH_OMAP3530_LV_SOM
+       bool "OMAP3 Logic 3530 LV SOM board"
+       depends on ARCH_OMAP3
+       select OMAP_PACKAGE_CBB
+       default y
+       help
+        Support for the LogicPD OMAP3530 SOM Development kit
+        for full description please see the products webpage at
+        http://www.logicpd.com/products/development-kits/texas-instruments-zoom%E2%84%A2-omap35x-development-kit
+
+config MACH_OMAP3_TORPEDO
+       bool "OMAP3 Logic 35x Torpedo board"
+       depends on ARCH_OMAP3
+       select OMAP_PACKAGE_CBB
+       default y
+       help
+        Support for the LogicPD OMAP35x Torpedo Development kit
+        for full description please see the products webpage at
+        http://www.logicpd.com/products/development-kits/zoom-omap35x-torpedo-development-kit
+
 config MACH_OVERO
        bool "Gumstix Overo board"
        depends on ARCH_OMAP3
@@ -200,12 +221,18 @@ config MACH_OMAP_ZOOM2
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBB
+       select SERIAL_8250
+       select SERIAL_CORE_CONSOLE
+       select SERIAL_8250_CONSOLE
 
 config MACH_OMAP_ZOOM3
        bool "OMAP3630 Zoom3 board"
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBP
+       select SERIAL_8250
+       select SERIAL_CORE_CONSOLE
+       select SERIAL_8250_CONSOLE
 
 config MACH_CM_T35
        bool "CompuLab CM-T35 module"
@@ -214,12 +241,25 @@ config MACH_CM_T35
        select OMAP_PACKAGE_CUS
        select OMAP_MUX
 
+config MACH_CM_T3517
+       bool "CompuLab CM-T3517 module"
+       depends on ARCH_OMAP3
+       default y
+       select OMAP_PACKAGE_CBB
+       select OMAP_MUX
+
 config MACH_IGEP0020
        bool "IGEP v2 board"
        depends on ARCH_OMAP3
        default y
        select OMAP_PACKAGE_CBB
 
+config MACH_IGEP0030
+       bool "IGEP OMAP3 module"
+       depends on ARCH_OMAP3
+       default y
+       select OMAP_PACKAGE_CBB
+
 config MACH_SBC3530
        bool "OMAP3 SBC STALKER board"
        depends on ARCH_OMAP3
index 88d3a1e..7352412 100644 (file)
@@ -3,9 +3,10 @@
 #
 
 # Common support
-obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o
+obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer-gp.o pm.o \
+        common.o
 
-omap-2-3-common                                = irq.o sdrc.o
+omap-2-3-common                                = irq.o sdrc.o prm2xxx_3xxx.o
 hwmod-common                           = omap_hwmod.o \
                                          omap_hwmod_common_data.o
 prcm-common                            = prcm.o powerdomain.o
@@ -15,7 +16,7 @@ clock-common                          = clock.o clock_common_data.o \
 
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(prcm-common) $(hwmod-common)
-obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) $(hwmod-common)
+obj-$(CONFIG_ARCH_OMAP4) += $(prcm-common) prm44xx.o $(hwmod-common)
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
@@ -49,14 +50,18 @@ obj-$(CONFIG_ARCH_OMAP2)            += sdrc2xxx.o
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)               += pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o
-obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o cpuidle34xx.o
-obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o
+obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o cpuidle34xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)                 += pm-debug.o
 
 AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
 AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a
 
+ifeq ($(CONFIG_PM_VERBOSE),y)
+CFLAGS_pm_bus.o                                += -DDEBUG
+endif
+
 endif
 
 # PRCM
@@ -87,6 +92,7 @@ obj-$(CONFIG_ARCH_OMAP2430)           += opp2430_data.o
 obj-$(CONFIG_ARCH_OMAP2420)            += omap_hwmod_2420_data.o
 obj-$(CONFIG_ARCH_OMAP2430)            += omap_hwmod_2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)               += omap_hwmod_3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)               += omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)                        += emu.o
@@ -115,6 +121,10 @@ obj-$(CONFIG_MACH_DEVKIT8000)      += board-devkit8000.o \
 obj-$(CONFIG_MACH_OMAP_LDP)            += board-ldp.o \
                                           board-flash.o \
                                           hsmmc.o
+obj-$(CONFIG_MACH_OMAP3530_LV_SOM)      += board-omap3logic.o \
+                                          hsmmc.o
+obj-$(CONFIG_MACH_OMAP3_TORPEDO)        += board-omap3logic.o \
+                                          hsmmc.o
 obj-$(CONFIG_MACH_OVERO)               += board-overo.o \
                                           hsmmc.o
 obj-$(CONFIG_MACH_OMAP3EVM)            += board-omap3evm.o \
@@ -146,8 +156,11 @@ obj-$(CONFIG_MACH_OMAP_3630SDP)            += board-3630sdp.o \
                                           hsmmc.o
 obj-$(CONFIG_MACH_CM_T35)              += board-cm-t35.o \
                                           hsmmc.o
+obj-$(CONFIG_MACH_CM_T3517)            += board-cm-t3517.o
 obj-$(CONFIG_MACH_IGEP0020)            += board-igep0020.o \
                                           hsmmc.o
+obj-$(CONFIG_MACH_IGEP0030)            += board-igep0030.o \
+                                          hsmmc.o
 obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)     += board-omap3touchbook.o \
                                           hsmmc.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)                += board-4430sdp.o \
@@ -174,3 +187,6 @@ obj-y                                       += $(nand-m) $(nand-y)
 
 smc91x-$(CONFIG_SMC91X)                        := gpmc-smc91x.o
 obj-y                                  += $(smc91x-m) $(smc91x-y)
+
+smsc911x-$(CONFIG_SMSC911X)            := gpmc-smsc911x.o
+obj-y                                  += $(smsc911x-m) $(smsc911x-y)
index b857ce4..b527f8d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
+#include <linux/mmc/host.h>
 #include <linux/delay.h>
 #include <linux/i2c/twl.h>
 #include <linux/err.h>
@@ -190,7 +191,7 @@ static int __init omap2430_i2c_init(void)
 static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .ext_clock      = 1,
index a5b095c..4e3742c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
 #include <plat/display.h>
 
-#include <plat/control.h>
 #include <plat/gpmc-smc91x.h>
 
-#include <mach/board-flash.h>
-
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-qimonda-hyb18m512160af-6.h"
 #include "hsmmc.h"
 #include "pm.h"
+#include "control.h"
 
 #define CONFIG_DISABLE_HFCLK 1
 
@@ -76,7 +76,7 @@ static struct cpuidle_params omap3_cpuidle_params_table[] = {
        {1, 10000, 30000, 300000},
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_LEFT),
        KEY(0, 1, KEY_RIGHT),
        KEY(0, 2, KEY_A),
@@ -353,12 +353,12 @@ static struct omap2_hsmmc_info mmc[] = {
                /* 8 bits (default) requires S6.3 == ON,
                 * so the SIM card isn't used; else 4 bits.
                 */
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 4,
        },
        {
                .mmc            = 2,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 7,
        },
        {}      /* Terminator */
index fd27ac0..bbcf580 100644 (file)
@@ -21,8 +21,8 @@
 #include <plat/usb.h>
 
 #include <mach/board-zoom.h>
-#include <mach/board-flash.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
@@ -208,7 +208,6 @@ static struct flash_partitions sdp_flash_partitions[] = {
 static void __init omap_sdp_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
-       omap_serial_init();
        zoom_peripherals_init();
        board_smc91x_init();
        board_flash_init(sdp_flash_partitions, chip_sel_sdp);
index 0b6a65f..69a4ae9 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/otg.h>
 #include <linux/spi/spi.h>
 #include <linux/i2c/twl.h>
+#include <linux/gpio_keys.h>
 #include <linux/regulator/machine.h>
 #include <linux/leds.h>
 
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
-#include <plat/timer-gp.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+
 #include "hsmmc.h"
+#include "timer-gp.h"
+#include "control.h"
 
 #define ETH_KS8851_IRQ                 34
 #define ETH_KS8851_POWER_ON            48
 #define ETH_KS8851_QUART               138
+#define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO       184
+#define OMAP4_SFH7741_ENABLE_GPIO              188
 
 static struct gpio_led sdp4430_gpio_leds[] = {
        {
@@ -77,11 +81,47 @@ static struct gpio_led sdp4430_gpio_leds[] = {
 
 };
 
+static struct gpio_keys_button sdp4430_gpio_keys[] = {
+       {
+               .desc                   = "Proximity Sensor",
+               .type                   = EV_SW,
+               .code                   = SW_FRONT_PROXIMITY,
+               .gpio                   = OMAP4_SFH7741_SENSOR_OUTPUT_GPIO,
+               .active_low             = 0,
+       }
+};
+
 static struct gpio_led_platform_data sdp4430_led_data = {
        .leds   = sdp4430_gpio_leds,
        .num_leds       = ARRAY_SIZE(sdp4430_gpio_leds),
 };
 
+static int omap_prox_activate(struct device *dev)
+{
+       gpio_set_value(OMAP4_SFH7741_ENABLE_GPIO , 1);
+       return 0;
+}
+
+static void omap_prox_deactivate(struct device *dev)
+{
+       gpio_set_value(OMAP4_SFH7741_ENABLE_GPIO , 0);
+}
+
+static struct gpio_keys_platform_data sdp4430_gpio_keys_data = {
+       .buttons        = sdp4430_gpio_keys,
+       .nbuttons       = ARRAY_SIZE(sdp4430_gpio_keys),
+       .enable         = omap_prox_activate,
+       .disable        = omap_prox_deactivate,
+};
+
+static struct platform_device sdp4430_gpio_keys_device = {
+       .name   = "gpio-keys",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &sdp4430_gpio_keys_data,
+       },
+};
+
 static struct platform_device sdp4430_leds_gpio = {
        .name   = "leds-gpio",
        .id     = -1,
@@ -161,6 +201,7 @@ static struct platform_device sdp4430_lcd_device = {
 
 static struct platform_device *sdp4430_devices[] __initdata = {
        &sdp4430_lcd_device,
+       &sdp4430_gpio_keys_device,
        &sdp4430_leds_gpio,
 };
 
@@ -193,15 +234,16 @@ static struct omap_musb_board_data musb_board_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = -EINVAL,
        },
        {
                .mmc            = 2,
-               .wires          = 8,
+               .caps           =  MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
+               .ocr_mask       = MMC_VDD_29_30,
        },
        {}      /* Terminator */
 };
@@ -235,8 +277,14 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
 {
-       struct omap_mmc_platform_data *pdata = dev->platform_data;
+       struct omap_mmc_platform_data *pdata;
 
+       /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+       if (!dev) {
+               pr_err("Failed %s\n", __func__);
+               return;
+       }
+       pdata = dev->platform_data;
        pdata->init =   omap4_twl6030_hsmmc_late_init;
 }
 
@@ -412,6 +460,11 @@ static struct i2c_board_info __initdata sdp4430_i2c_3_boardinfo[] = {
                I2C_BOARD_INFO("tmp105", 0x48),
        },
 };
+static struct i2c_board_info __initdata sdp4430_i2c_4_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("hmc5843", 0x1e),
+       },
+};
 static int __init omap4_i2c_init(void)
 {
        /*
@@ -423,14 +476,36 @@ static int __init omap4_i2c_init(void)
        omap_register_i2c_bus(2, 400, NULL, 0);
        omap_register_i2c_bus(3, 400, sdp4430_i2c_3_boardinfo,
                                ARRAY_SIZE(sdp4430_i2c_3_boardinfo));
-       omap_register_i2c_bus(4, 400, NULL, 0);
+       omap_register_i2c_bus(4, 400, sdp4430_i2c_4_boardinfo,
+                               ARRAY_SIZE(sdp4430_i2c_4_boardinfo));
        return 0;
 }
+
+static void __init omap_sfh7741prox_init(void)
+{
+       int  error;
+
+       error = gpio_request(OMAP4_SFH7741_ENABLE_GPIO, "sfh7741");
+       if (error < 0) {
+               pr_err("%s:failed to request GPIO %d, error %d\n",
+                       __func__, OMAP4_SFH7741_ENABLE_GPIO, error);
+               return;
+       }
+
+       error = gpio_direction_output(OMAP4_SFH7741_ENABLE_GPIO , 0);
+       if (error < 0) {
+               pr_err("%s: GPIO configuration failed: GPIO %d,error %d\n",
+                        __func__, OMAP4_SFH7741_ENABLE_GPIO, error);
+               gpio_free(OMAP4_SFH7741_ENABLE_GPIO);
+       }
+}
+
 static void __init omap_4430sdp_init(void)
 {
        int status;
 
        omap4_i2c_init();
+       omap_sfh7741prox_init();
        platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
        omap_serial_init();
        omap4_twl6030_hsmmc_init(mmc);
index e1f8dda..0739950 100644 (file)
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/usb.h>
 #include <plat/display.h>
 
 #include "mux.h"
+#include "control.h"
 
 #define AM35XX_EVM_MDIO_FREQUENCY      (1000000)
 
@@ -125,7 +125,7 @@ static void am3517_disable_ethernet_int(void)
        regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
 }
 
-void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
+static void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 {
        unsigned int regval;
 
@@ -160,7 +160,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 static struct i2c_board_info __initdata am3517evm_i2c1_boardinfo[] = {
        {
                I2C_BOARD_INFO("s35390a", 0x30),
-               .type           = "s35390a",
        },
 };
 
@@ -368,7 +367,7 @@ static struct omap_dss_board_info am3517_evm_dss_data = {
        .default_device = &am3517_evm_lcd_device,
 };
 
-struct platform_device am3517_evm_dss_device = {
+static struct platform_device am3517_evm_dss_device = {
        .name           = "omapdss",
        .id             = -1,
        .dev            = {
index 68f07f5..2c6db1a 100644 (file)
@@ -39,9 +39,9 @@
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/gpmc.h>
-#include <plat/control.h>
 
 #include "mux.h"
+#include "control.h"
 
 /* LED & Switch macros */
 #define LED0_GPIO13            13
index 934d938..63f764e 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/i2c/at24.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/tdo24m.h>
@@ -237,8 +238,6 @@ static inline void cm_t35_init_nand(void) {}
        defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 #include <linux/spi/ads7846.h>
 
-#include <plat/mcspi.h>
-
 static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .turbo_mode     = 0,
        .single_channel = 1,    /* 0: slave, 1: master */
@@ -558,7 +557,7 @@ static struct twl4030_usb_data cm_t35_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
 
-static int cm_t35_keymap[] = {
+static uint32_t cm_t35_keymap[] = {
        KEY(0, 0, KEY_A),       KEY(0, 1, KEY_B),       KEY(0, 2, KEY_LEFT),
        KEY(1, 0, KEY_UP),      KEY(1, 1, KEY_ENTER),   KEY(1, 2, KEY_DOWN),
        KEY(2, 0, KEY_RIGHT),   KEY(2, 1, KEY_C),       KEY(2, 2, KEY_D),
@@ -579,14 +578,14 @@ static struct twl4030_keypad_data cm_t35_kp_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
 
        },
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .transceiver    = 1,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
new file mode 100644 (file)
index 0000000..1dd303e
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * linux/arch/arm/mach-omap2/board-cm-t3517.c
+ *
+ * Support for the CompuLab CM-T3517 modules
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Author: Igor Grinberg <grinberg@compulab.co.il>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/rtc-v3020.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/can/platform/ti_hecc.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/usb.h>
+#include <plat/nand.h>
+#include <plat/gpmc.h>
+
+#include <mach/am35xx.h>
+
+#include "mux.h"
+#include "control.h"
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led cm_t3517_leds[] = {
+       [0] = {
+               .gpio                   = 186,
+               .name                   = "cm-t3517:green",
+               .default_trigger        = "heartbeat",
+               .active_low             = 0,
+       },
+};
+
+static struct gpio_led_platform_data cm_t3517_led_pdata = {
+       .num_leds       = ARRAY_SIZE(cm_t3517_leds),
+       .leds           = cm_t3517_leds,
+};
+
+static struct platform_device cm_t3517_led_device = {
+       .name           = "leds-gpio",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &cm_t3517_led_pdata,
+       },
+};
+
+static void __init cm_t3517_init_leds(void)
+{
+       platform_device_register(&cm_t3517_led_device);
+}
+#else
+static inline void cm_t3517_init_leds(void) {}
+#endif
+
+#if defined(CONFIG_CAN_TI_HECC) || defined(CONFIG_CAN_TI_HECC_MODULE)
+static struct resource cm_t3517_hecc_resources[] = {
+       {
+               .start  = AM35XX_IPSS_HECC_BASE,
+               .end    = AM35XX_IPSS_HECC_BASE + SZ_16K - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+               .start  = INT_35XX_HECC0_IRQ,
+               .end    = INT_35XX_HECC0_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct ti_hecc_platform_data cm_t3517_hecc_pdata = {
+       .scc_hecc_offset        = AM35XX_HECC_SCC_HECC_OFFSET,
+       .scc_ram_offset         = AM35XX_HECC_SCC_RAM_OFFSET,
+       .hecc_ram_offset        = AM35XX_HECC_RAM_OFFSET,
+       .mbx_offset             = AM35XX_HECC_MBOX_OFFSET,
+       .int_line               = AM35XX_HECC_INT_LINE,
+       .version                = AM35XX_HECC_VERSION,
+};
+
+static struct platform_device cm_t3517_hecc_device = {
+       .name           = "ti_hecc",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(cm_t3517_hecc_resources),
+       .resource       = cm_t3517_hecc_resources,
+       .dev            = {
+               .platform_data  = &cm_t3517_hecc_pdata,
+       },
+};
+
+static void cm_t3517_init_hecc(void)
+{
+       platform_device_register(&cm_t3517_hecc_device);
+}
+#else
+static inline void cm_t3517_init_hecc(void) {}
+#endif
+
+#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
+#define RTC_IO_GPIO            (153)
+#define RTC_WR_GPIO            (154)
+#define RTC_RD_GPIO            (160)
+#define RTC_CS_GPIO            (163)
+
+struct v3020_platform_data cm_t3517_v3020_pdata = {
+       .use_gpio       = 1,
+       .gpio_cs        = RTC_CS_GPIO,
+       .gpio_wr        = RTC_WR_GPIO,
+       .gpio_rd        = RTC_RD_GPIO,
+       .gpio_io        = RTC_IO_GPIO,
+};
+
+static struct platform_device cm_t3517_rtc_device = {
+       .name           = "v3020",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &cm_t3517_v3020_pdata,
+       }
+};
+
+static void __init cm_t3517_init_rtc(void)
+{
+       platform_device_register(&cm_t3517_rtc_device);
+}
+#else
+static inline void cm_t3517_init_rtc(void) {}
+#endif
+
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
+#define HSUSB1_RESET_GPIO      (146)
+#define HSUSB2_RESET_GPIO      (147)
+#define USB_HUB_RESET_GPIO     (152)
+
+static struct ehci_hcd_omap_platform_data cm_t3517_ehci_pdata __initdata = {
+       .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+       .port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+       .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+
+       .phy_reset  = true,
+       .reset_gpio_port[0]  = HSUSB1_RESET_GPIO,
+       .reset_gpio_port[1]  = HSUSB2_RESET_GPIO,
+       .reset_gpio_port[2]  = -EINVAL,
+};
+
+static int cm_t3517_init_usbh(void)
+{
+       int err;
+
+       err = gpio_request(USB_HUB_RESET_GPIO, "usb hub rst");
+       if (err) {
+               pr_err("CM-T3517: usb hub rst gpio request failed: %d\n", err);
+       } else {
+               gpio_direction_output(USB_HUB_RESET_GPIO, 0);
+               udelay(10);
+               gpio_set_value(USB_HUB_RESET_GPIO, 1);
+               msleep(1);
+       }
+
+       usb_ehci_init(&cm_t3517_ehci_pdata);
+
+       return 0;
+}
+#else
+static inline int cm_t3517_init_usbh(void)
+{
+       return 0;
+}
+#endif
+
+#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE)
+#define NAND_BLOCK_SIZE                SZ_128K
+
+static struct mtd_partition cm_t3517_nand_partitions[] = {
+       {
+               .name           = "xloader",
+               .offset         = 0,                    /* Offset = 0x00000 */
+               .size           = 4 * NAND_BLOCK_SIZE,
+               .mask_flags     = MTD_WRITEABLE
+       },
+       {
+               .name           = "uboot",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x80000 */
+               .size           = 15 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "uboot environment",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x260000 */
+               .size           = 2 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "linux",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x280000 */
+               .size           = 32 * NAND_BLOCK_SIZE,
+       },
+       {
+               .name           = "rootfs",
+               .offset         = MTDPART_OFS_APPEND,   /* Offset = 0x680000 */
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct omap_nand_platform_data cm_t3517_nand_data = {
+       .parts                  = cm_t3517_nand_partitions,
+       .nr_parts               = ARRAY_SIZE(cm_t3517_nand_partitions),
+       .dma_channel            = -1,   /* disable DMA in OMAP NAND driver */
+       .cs                     = 0,
+};
+
+static void __init cm_t3517_init_nand(void)
+{
+       if (gpmc_nand_init(&cm_t3517_nand_data) < 0)
+               pr_err("CM-T3517: NAND initialization failed\n");
+}
+#else
+static inline void cm_t3517_init_nand(void) {}
+#endif
+
+static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
+};
+
+static void __init cm_t3517_init_irq(void)
+{
+       omap_board_config = cm_t3517_config;
+       omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
+
+       omap2_init_common_hw(NULL, NULL);
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct omap_board_mux board_mux[] __initdata = {
+       /* GPIO186 - Green LED */
+       OMAP3_MUX(SYS_CLKOUT2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* RTC GPIOs: IO, WR#, RD#, CS# */
+       OMAP3_MUX(MCBSP4_DR, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       OMAP3_MUX(MCBSP4_DX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       OMAP3_MUX(MCBSP_CLKS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       OMAP3_MUX(UART3_CTS_RCTX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+       /* HSUSB1 RESET */
+       OMAP3_MUX(UART2_TX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* HSUSB2 RESET */
+       OMAP3_MUX(UART2_RX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* CM-T3517 USB HUB nRESET */
+       OMAP3_MUX(MCBSP4_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+
+       { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+static void __init cm_t3517_init(void)
+{
+       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+       omap_serial_init();
+       cm_t3517_init_leds();
+       cm_t3517_init_nand();
+       cm_t3517_init_rtc();
+       cm_t3517_init_usbh();
+       cm_t3517_init_hecc();
+}
+
+MACHINE_START(CM_T3517, "Compulab CM-T3517")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .reserve        = omap_reserve,
+       .init_irq       = cm_t3517_init_irq,
+       .init_machine   = cm_t3517_init,
+       .timer          = &omap_timer,
+MACHINE_END
index 2205c20..067f437 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -44,7 +45,6 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 #include <plat/display.h>
 
 #include <plat/mcspi.h>
@@ -58,6 +58,7 @@
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #define NAND_BLOCK_SIZE                SZ_128K
 
@@ -105,7 +106,7 @@ static struct omap_nand_platform_data devkit8000_nand_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 29,
        },
        {}      /* Terminator */
@@ -198,7 +199,7 @@ static struct platform_device devkit8000_dss_device = {
 static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
        REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_1),
        KEY(1, 0, KEY_2),
        KEY(2, 0, KEY_3),
index ac834aa..fd38c05 100644 (file)
@@ -21,7 +21,8 @@
 #include <plat/nand.h>
 #include <plat/onenand.h>
 #include <plat/tc.h>
-#include <mach/board-flash.h>
+
+#include "board-flash.h"
 
 #define REG_FPGA_REV                   0x10
 #define REG_FPGA_DIP_SWITCH_INPUT2     0x60
diff --git a/arch/arm/mach-omap2/board-flash.h b/arch/arm/mach-omap2/board-flash.h
new file mode 100644 (file)
index 0000000..69befe0
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ *  board-sdp.h
+ *
+ *  Information structures for SDP-specific board config data
+ *
+ *  Copyright (C) 2009 Nokia Corporation
+ *  Copyright (C) 2009 Texas Instruments
+ *
+ * This 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/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <plat/gpmc.h>
+
+#define PDC_NOR                1
+#define PDC_NAND       2
+#define PDC_ONENAND    3
+#define DBG_MPDB       4
+
+struct flash_partitions {
+       struct mtd_partition *parts;
+       int nr_parts;
+};
+
+extern void board_flash_init(struct flash_partitions [],
+                               char chip_sel[][GPMC_CS_NUM]);
+extern void board_nand_init(struct mtd_partition *nand_parts,
+                                       u8 nr_parts, u8 cs);
index 69064b1..b1c2c9a 100644 (file)
@@ -48,10 +48,22 @@ static void __init omap_generic_init(void)
 
 static void __init omap_generic_map_io(void)
 {
-       omap2_set_globals_242x(); /* should be 242x, 243x, or 343x */
-       omap242x_map_common_io();
+       if (cpu_is_omap242x()) {
+               omap2_set_globals_242x();
+               omap242x_map_common_io();
+       } else if (cpu_is_omap243x()) {
+               omap2_set_globals_243x();
+               omap243x_map_common_io();
+       } else if (cpu_is_omap34xx()) {
+               omap2_set_globals_3xxx();
+               omap34xx_map_common_io();
+       } else if (cpu_is_omap44xx()) {
+               omap2_set_globals_443x();
+               omap44xx_map_common_io();
+       }
 }
 
+/* XXX This machine entry name should be updated */
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
        /* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
        .boot_params    = 0x80000100,
index cc39fc8..929993b 100644 (file)
@@ -31,7 +31,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/control.h>
 #include <mach/gpio.h>
 #include <plat/usb.h>
 #include <plat/board.h>
@@ -42,6 +41,7 @@
 #include <plat/gpmc.h>
 
 #include "mux.h"
+#include "control.h"
 
 #define H4_FLASH_CS    0
 #define H4_SMC91X_CS   1
index b62a68b..5e035a5 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #define IGEP2_SMSC911X_CS       5
 #define IGEP2_SMSC911X_GPIO     176
 #define IGEP2_GPIO_USBH_NRESET  24
-#define IGEP2_GPIO_LED0_GREEN  26
-#define IGEP2_GPIO_LED0_RED    27
-#define IGEP2_GPIO_LED1_RED    28
-#define IGEP2_GPIO_DVI_PUP     170
-#define IGEP2_GPIO_WIFI_NPD    94
-#define IGEP2_GPIO_WIFI_NRESET         95
+#define IGEP2_GPIO_LED0_GREEN   26
+#define IGEP2_GPIO_LED0_RED     27
+#define IGEP2_GPIO_LED1_RED     28
+#define IGEP2_GPIO_DVI_PUP      170
+
+#define IGEP2_RB_GPIO_WIFI_NPD     94
+#define IGEP2_RB_GPIO_WIFI_NRESET  95
+#define IGEP2_RB_GPIO_BT_NRESET    137
+#define IGEP2_RC_GPIO_WIFI_NPD     138
+#define IGEP2_RC_GPIO_WIFI_NRESET  139
+#define IGEP2_RC_GPIO_BT_NRESET    137
+
+/*
+ * IGEP2 Hardware Revision Table
+ *
+ *  --------------------------------------------------------------------------
+ * | Id. | Hw Rev.            | HW0 (28) | WIFI_NPD | WIFI_NRESET | BT_NRESET |
+ *  --------------------------------------------------------------------------
+ * |  0  | B                  |   high   |  gpio94  |   gpio95    |     -     |
+ * |  0  | B/C (B-compatible) |   high   |  gpio94  |   gpio95    |  gpio137  |
+ * |  1  | C                  |   low    |  gpio138 |   gpio139   |  gpio137  |
+ *  --------------------------------------------------------------------------
+ */
+
+#define IGEP2_BOARD_HWREV_B    0
+#define IGEP2_BOARD_HWREV_C    1
+
+static u8 hwrev;
+
+static void __init igep2_get_revision(void)
+{
+       u8 ret;
+
+       omap_mux_init_gpio(IGEP2_GPIO_LED1_RED, OMAP_PIN_INPUT);
+
+       if ((gpio_request(IGEP2_GPIO_LED1_RED, "GPIO_HW0_REV") == 0) &&
+           (gpio_direction_input(IGEP2_GPIO_LED1_RED) == 0)) {
+               ret = gpio_get_value(IGEP2_GPIO_LED1_RED);
+               if (ret == 0) {
+                       pr_info("IGEP2: Hardware Revision C (B-NON compatible)\n");
+                       hwrev = IGEP2_BOARD_HWREV_C;
+               } else if (ret ==  1) {
+                       pr_info("IGEP2: Hardware Revision B/C (B compatible)\n");
+                       hwrev = IGEP2_BOARD_HWREV_B;
+               } else {
+                       pr_err("IGEP2: Unknown Hardware Revision\n");
+                       hwrev = -1;
+               }
+       } else {
+               pr_warning("IGEP2: Could not obtain gpio GPIO_HW0_REV\n");
+               pr_err("IGEP2: Unknown Hardware Revision\n");
+       }
+
+       gpio_free(IGEP2_GPIO_LED1_RED);
+}
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
        defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
@@ -107,7 +157,7 @@ static struct platform_device igep2_onenand_device = {
        },
 };
 
-void __init igep2_flash_init(void)
+static void __init igep2_flash_init(void)
 {
        u8              cs = 0;
        u8              onenandcs = GPMC_CS_NUM + 1;
@@ -141,7 +191,7 @@ void __init igep2_flash_init(void)
 }
 
 #else
-void __init igep2_flash_init(void) {}
+static void __init igep2_flash_init(void) {}
 #endif
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
@@ -211,10 +261,6 @@ static struct regulator_consumer_supply igep2_vmmc1_supply = {
        .supply         = "vmmc",
 };
 
-static struct regulator_consumer_supply igep2_vmmc2_supply = {
-       .supply         = "vmmc",
-};
-
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep2_vmmc1 = {
        .constraints = {
@@ -230,37 +276,95 @@ static struct regulator_init_data igep2_vmmc1 = {
        .consumer_supplies      = &igep2_vmmc1_supply,
 };
 
-/* VMMC2 for OMAP VDD_MMC2 (i/o) and MMC2 WIFI */
-static struct regulator_init_data igep2_vmmc2 = {
-       .constraints = {
-               .min_uV                 = 1850000,
-               .max_uV                 = 3150000,
-               .valid_modes_mask       = REGULATOR_MODE_NORMAL
-                                       | REGULATOR_MODE_STANDBY,
-               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
-                                       | REGULATOR_CHANGE_MODE
-                                       | REGULATOR_CHANGE_STATUS,
-       },
-       .num_consumer_supplies  = 1,
-       .consumer_supplies      = &igep2_vmmc2_supply,
-};
-
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
+#endif
        {}      /* Terminator */
 };
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep2_gpio_leds[] = {
+       [0] = {
+               .name                   = "gpio-led:red:d0",
+               .gpio                   = IGEP2_GPIO_LED0_RED,
+               .default_trigger        = "default-off"
+       },
+       [1] = {
+               .name                   = "gpio-led:green:d0",
+               .gpio                   = IGEP2_GPIO_LED0_GREEN,
+               .default_trigger        = "default-off",
+       },
+       [2] = {
+               .name                   = "gpio-led:red:d1",
+               .gpio                   = IGEP2_GPIO_LED1_RED,
+               .default_trigger        = "default-off",
+       },
+       [3] = {
+               .name                   = "gpio-led:green:d1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = -EINVAL, /* gets replaced */
+       },
+};
+
+static struct gpio_led_platform_data igep2_led_pdata = {
+       .leds           = igep2_gpio_leds,
+       .num_leds       = ARRAY_SIZE(igep2_gpio_leds),
+};
+
+static struct platform_device igep2_led_device = {
+        .name   = "leds-gpio",
+        .id     = -1,
+        .dev    = {
+                .platform_data  =  &igep2_led_pdata,
+       },
+};
+
+static void __init igep2_leds_init(void)
+{
+       platform_device_register(&igep2_led_device);
+}
+
+#else
+static inline void igep2_leds_init(void)
+{
+       if ((gpio_request(IGEP2_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED0_RED, 0);
+               gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
+
+       if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
+               gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+       if ((gpio_request(IGEP2_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
+           (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
+               gpio_export(IGEP2_GPIO_LED1_RED, 0);
+               gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
+
+}
+#endif
+
 static int igep2_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
@@ -268,20 +372,48 @@ static int igep2_twl_gpio_setup(struct device *dev,
        mmc[0].gpio_cd = gpio + 0;
        omap2_hsmmc_init(mmc);
 
-       /* link regulators to MMC adapters ... we "know" the
+       /*
+        * link regulators to MMC adapters ... we "know" the
         * regulators will be set up only *after* we return.
-       */
+        */
        igep2_vmmc1_supply.dev = mmc[0].dev;
-       igep2_vmmc2_supply.dev = mmc[1].dev;
+
+       /*
+        * REVISIT: need ehci-omap hooks for external VBUS
+        * power switch and overcurrent detect
+        */
+       if ((gpio_request(gpio + 1, "GPIO_EHCI_NOC") < 0) ||
+           (gpio_direction_input(gpio + 1) < 0))
+               pr_err("IGEP2: Could not obtain gpio for EHCI NOC");
+
+       /*
+        * TWL4030_GPIO_MAX + 0 == ledA, GPIO_USBH_CPEN
+        * (out, active low)
+        */
+       if ((gpio_request(gpio + TWL4030_GPIO_MAX, "GPIO_USBH_CPEN") < 0) ||
+           (gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0) < 0))
+               pr_err("IGEP2: Could not obtain gpio for USBH_CPEN");
+
+       /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+       if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
+           && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+               gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+               gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+       } else
+               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+       igep2_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
 
        return 0;
 };
 
-static struct twl4030_gpio_platform_data igep2_gpio_data = {
+static struct twl4030_gpio_platform_data igep2_twl4030_gpio_pdata = {
        .gpio_base      = OMAP_MAX_GPIO_LINES,
        .irq_base       = TWL4030_GPIO_IRQ_BASE,
        .irq_end        = TWL4030_GPIO_IRQ_END,
-       .use_leds       = false,
+       .use_leds       = true,
        .setup          = igep2_twl_gpio_setup,
 };
 
@@ -355,47 +487,6 @@ static void __init igep2_display_init(void)
                pr_err("IGEP v2: Could not obtain gpio GPIO_DVI_PUP\n");
 }
 
-#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
-#include <linux/leds.h>
-
-static struct gpio_led igep2_gpio_leds[] = {
-       {
-               .name = "led0:red",
-               .gpio = IGEP2_GPIO_LED0_RED,
-       },
-       {
-               .name = "led0:green",
-               .default_trigger = "heartbeat",
-               .gpio = IGEP2_GPIO_LED0_GREEN,
-       },
-       {
-               .name = "led1:red",
-               .gpio = IGEP2_GPIO_LED1_RED,
-       },
-};
-
-static struct gpio_led_platform_data igep2_led_pdata = {
-       .leds           = igep2_gpio_leds,
-       .num_leds       = ARRAY_SIZE(igep2_gpio_leds),
-};
-
-static struct platform_device igep2_led_device = {
-        .name   = "leds-gpio",
-        .id     = -1,
-        .dev    = {
-                .platform_data  =  &igep2_led_pdata,
-       },
-};
-
-static void __init igep2_init_led(void)
-{
-       platform_device_register(&igep2_led_device);
-}
-
-#else
-static inline void igep2_init_led(void) {}
-#endif
-
 static struct platform_device *igep2_devices[] __initdata = {
        &igep2_dss_device,
 };
@@ -425,14 +516,13 @@ static struct twl4030_platform_data igep2_twldata = {
        /* platform_data for children goes here */
        .usb            = &igep2_usb_data,
        .codec          = &igep2_codec_data,
-       .gpio           = &igep2_gpio_data,
+       .gpio           = &igep2_twl4030_gpio_pdata,
        .vmmc1          = &igep2_vmmc1,
-       .vmmc2          = &igep2_vmmc2,
        .vpll2          = &igep2_vpll2,
 
 };
 
-static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
+static struct i2c_board_info __initdata igep2_i2c1_boardinfo[] = {
        {
                I2C_BOARD_INFO("twl4030", 0x48),
                .flags          = I2C_CLIENT_WAKE,
@@ -441,14 +531,29 @@ static struct i2c_board_info __initdata igep2_i2c_boardinfo[] = {
        },
 };
 
-static int __init igep2_i2c_init(void)
+static struct i2c_board_info __initdata igep2_i2c3_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
+static void __init igep2_i2c_init(void)
 {
-       omap_register_i2c_bus(1, 2600, igep2_i2c_boardinfo,
-                       ARRAY_SIZE(igep2_i2c_boardinfo));
-       /* Bus 3 is attached to the DVI port where devices like the pico DLP
-        * projector don't work reliably with 400kHz */
-       omap_register_i2c_bus(3, 100, NULL, 0);
-       return 0;
+       int ret;
+
+       ret = omap_register_i2c_bus(1, 2600, igep2_i2c1_boardinfo,
+               ARRAY_SIZE(igep2_i2c1_boardinfo));
+       if (ret)
+               pr_warning("IGEP2: Could not register I2C1 bus (%d)\n", ret);
+
+       /*
+        * Bus 3 is attached to the DVI port where devices like the pico DLP
+        * projector don't work reliably with 400kHz
+        */
+       ret = omap_register_i2c_bus(3, 100, igep2_i2c3_boardinfo,
+               ARRAY_SIZE(igep2_i2c3_boardinfo));
+       if (ret)
+               pr_warning("IGEP2: Could not register I2C3 bus (%d)\n", ret);
 }
 
 static struct omap_musb_board_data musb_board_data = {
@@ -476,9 +581,57 @@ static struct omap_board_mux board_mux[] __initdata = {
 #define board_mux      NULL
 #endif
 
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+
+static void __init igep2_wlan_bt_init(void)
+{
+       unsigned npd, wreset, btreset;
+
+       /* GPIO's for WLAN-BT combo depends on hardware revision */
+       if (hwrev == IGEP2_BOARD_HWREV_B) {
+               npd = IGEP2_RB_GPIO_WIFI_NPD;
+               wreset = IGEP2_RB_GPIO_WIFI_NRESET;
+               btreset = IGEP2_RB_GPIO_BT_NRESET;
+       } else if (hwrev == IGEP2_BOARD_HWREV_C) {
+               npd = IGEP2_RC_GPIO_WIFI_NPD;
+               wreset = IGEP2_RC_GPIO_WIFI_NRESET;
+               btreset = IGEP2_RC_GPIO_BT_NRESET;
+       } else
+               return;
+
+       /* Set GPIO's for  WLAN-BT combo module */
+       if ((gpio_request(npd, "GPIO_WIFI_NPD") == 0) &&
+           (gpio_direction_output(npd, 1) == 0)) {
+               gpio_export(npd, 0);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+       if ((gpio_request(wreset, "GPIO_WIFI_NRESET") == 0) &&
+           (gpio_direction_output(wreset, 1) == 0)) {
+               gpio_export(wreset, 0);
+               gpio_set_value(wreset, 0);
+               udelay(10);
+               gpio_set_value(wreset, 1);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+       if ((gpio_request(btreset, "GPIO_BT_NRESET") == 0) &&
+           (gpio_direction_output(btreset, 1) == 0)) {
+               gpio_export(btreset, 0);
+       } else
+               pr_warning("IGEP2: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+#else
+static inline void __init igep2_wlan_bt_init(void) { }
+#endif
+
 static void __init igep2_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+       /* Get IGEP2 hardware revision */
+       igep2_get_revision();
+       /* Register I2C busses and drivers */
        igep2_i2c_init();
        platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
        omap_serial_init();
@@ -486,50 +639,16 @@ static void __init igep2_init(void)
        usb_ehci_init(&ehci_pdata);
 
        igep2_flash_init();
-       igep2_init_led();
+       igep2_leds_init();
        igep2_display_init();
        igep2_init_smsc911x();
 
-       /* GPIO userspace leds */
-#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
-       if ((gpio_request(IGEP2_GPIO_LED0_RED, "led0:red") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED0_RED, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED0_RED, 0);
-               gpio_set_value(IGEP2_GPIO_LED0_RED, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_RED\n");
-
-       if ((gpio_request(IGEP2_GPIO_LED0_GREEN, "led0:green") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED0_GREEN, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED0_GREEN, 0);
-               gpio_set_value(IGEP2_GPIO_LED0_GREEN, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED0_GREEN\n");
-
-       if ((gpio_request(IGEP2_GPIO_LED1_RED, "led1:red") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_LED1_RED, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_LED1_RED, 0);
-               gpio_set_value(IGEP2_GPIO_LED1_RED, 0);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_LED1_RED\n");
-#endif
-
-       /* GPIO W-LAN + Bluetooth combo module */
-       if ((gpio_request(IGEP2_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_WIFI_NPD, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_WIFI_NPD, 0);
-/*             gpio_set_value(IGEP2_GPIO_WIFI_NPD, 0); */
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NPD\n");
+       /*
+        * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+        * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
+        */
+       igep2_wlan_bt_init();
 
-       if ((gpio_request(IGEP2_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
-           (gpio_direction_output(IGEP2_GPIO_WIFI_NRESET, 1) == 0)) {
-               gpio_export(IGEP2_GPIO_WIFI_NRESET, 0);
-               gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 0);
-               udelay(10);
-               gpio_set_value(IGEP2_GPIO_WIFI_NRESET, 1);
-       } else
-               pr_warning("IGEP v2: Could not obtain gpio GPIO_WIFI_NRESET\n");
 }
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
diff --git a/arch/arm/mach-omap2/board-igep0030.c b/arch/arm/mach-omap2/board-igep0030.c
new file mode 100644 (file)
index 0000000..22b0b25
--- /dev/null
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2010 - ISEE 2007 SL
+ *
+ * Modified from mach-omap2/board-generic.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/gpmc.h>
+#include <plat/usb.h>
+#include <plat/onenand.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "sdram-numonyx-m65kxxxxam.h"
+
+#define IGEP3_GPIO_LED0_GREEN  54
+#define IGEP3_GPIO_LED0_RED    53
+#define IGEP3_GPIO_LED1_RED    16
+
+#define IGEP3_GPIO_WIFI_NPD    138
+#define IGEP3_GPIO_WIFI_NRESET 139
+#define IGEP3_GPIO_BT_NRESET   137
+
+#define IGEP3_GPIO_USBH_NRESET  115
+
+
+#if defined(CONFIG_MTD_ONENAND_OMAP2) || \
+       defined(CONFIG_MTD_ONENAND_OMAP2_MODULE)
+
+#define ONENAND_MAP             0x20000000
+
+/*
+ * x2 Flash built-in COMBO POP MEMORY
+ * Since the device is equipped with two DataRAMs, and two-plane NAND
+ * Flash memory array, these two component enables simultaneous program
+ * of 4KiB. Plane1 has only even blocks such as block0, block2, block4
+ * while Plane2 has only odd blocks such as block1, block3, block5.
+ * So MTD regards it as 4KiB page size and 256KiB block size 64*(2*2048)
+ */
+
+static struct mtd_partition igep3_onenand_partitions[] = {
+       {
+               .name           = "X-Loader",
+               .offset         = 0,
+               .size           = 2 * (64*(2*2048))
+       },
+       {
+               .name           = "U-Boot",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 6 * (64*(2*2048)),
+       },
+       {
+               .name           = "Environment",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 2 * (64*(2*2048)),
+       },
+       {
+               .name           = "Kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 12 * (64*(2*2048)),
+       },
+       {
+               .name           = "File System",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct omap_onenand_platform_data igep3_onenand_pdata = {
+       .parts = igep3_onenand_partitions,
+       .nr_parts = ARRAY_SIZE(igep3_onenand_partitions),
+       .onenand_setup = NULL,
+       .dma_channel    = -1,   /* disable DMA in OMAP OneNAND driver */
+};
+
+static struct platform_device igep3_onenand_device = {
+       .name           = "omap2-onenand",
+       .id             = -1,
+       .dev = {
+               .platform_data = &igep3_onenand_pdata,
+       },
+};
+
+void __init igep3_flash_init(void)
+{
+       u8 cs = 0;
+       u8 onenandcs = GPMC_CS_NUM + 1;
+
+       for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+               u32 ret;
+               ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
+
+               /* Check if NAND/oneNAND is configured */
+               if ((ret & 0xC00) == 0x800)
+                       /* NAND found */
+                       pr_err("IGEP3: Unsupported NAND found\n");
+               else {
+                       ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
+
+                       if ((ret & 0x3F) == (ONENAND_MAP >> 24))
+                               /* OneNAND found */
+                               onenandcs = cs;
+               }
+       }
+
+       if (onenandcs > GPMC_CS_NUM) {
+               pr_err("IGEP3: Unable to find configuration in GPMC\n");
+               return;
+       }
+
+       igep3_onenand_pdata.cs = onenandcs;
+
+       if (platform_device_register(&igep3_onenand_device) < 0)
+               pr_err("IGEP3: Unable to register OneNAND device\n");
+}
+
+#else
+void __init igep3_flash_init(void) {}
+#endif
+
+static struct regulator_consumer_supply igep3_vmmc1_supply = {
+       .supply         = "vmmc",
+};
+
+/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
+static struct regulator_init_data igep3_vmmc1 = {
+       .constraints = {
+               .min_uV                 = 1850000,
+               .max_uV                 = 3150000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
+                                       | REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &igep3_vmmc1_supply,
+};
+
+static struct omap2_hsmmc_info mmc[] = {
+       [0] = {
+               .mmc            = 1,
+               .caps           = MMC_CAP_4_BIT_DATA,
+               .gpio_cd        = -EINVAL,
+               .gpio_wp        = -EINVAL,
+       },
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+       [1] = {
+               .mmc            = 2,
+               .caps           = MMC_CAP_4_BIT_DATA,
+               .gpio_cd        = -EINVAL,
+               .gpio_wp        = -EINVAL,
+       },
+#endif
+       {}      /* Terminator */
+};
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led igep3_gpio_leds[] = {
+       [0] = {
+               .name                   = "gpio-led:red:d0",
+               .gpio                   = IGEP3_GPIO_LED0_RED,
+               .default_trigger        = "default-off"
+       },
+       [1] = {
+               .name                   = "gpio-led:green:d0",
+               .gpio                   = IGEP3_GPIO_LED0_GREEN,
+               .default_trigger        = "default-off",
+       },
+       [2] = {
+               .name                   = "gpio-led:red:d1",
+               .gpio                   = IGEP3_GPIO_LED1_RED,
+               .default_trigger        = "default-off",
+       },
+       [3] = {
+               .name                   = "gpio-led:green:d1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = -EINVAL, /* gets replaced */
+       },
+};
+
+static struct gpio_led_platform_data igep3_led_pdata = {
+       .leds           = igep3_gpio_leds,
+       .num_leds       = ARRAY_SIZE(igep3_gpio_leds),
+};
+
+static struct platform_device igep3_led_device = {
+        .name   = "leds-gpio",
+        .id     = -1,
+        .dev    = {
+                .platform_data = &igep3_led_pdata,
+       },
+};
+
+static void __init igep3_leds_init(void)
+{
+       platform_device_register(&igep3_led_device);
+}
+
+#else
+static inline void igep3_leds_init(void)
+{
+       if ((gpio_request(IGEP3_GPIO_LED0_RED, "gpio-led:red:d0") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_LED0_RED, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_LED0_RED, 0);
+               gpio_set_value(IGEP3_GPIO_LED0_RED, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_RED\n");
+
+       if ((gpio_request(IGEP3_GPIO_LED0_GREEN, "gpio-led:green:d0") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_LED0_GREEN, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_LED0_GREEN, 0);
+               gpio_set_value(IGEP3_GPIO_LED0_GREEN, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED0_GREEN\n");
+
+       if ((gpio_request(IGEP3_GPIO_LED1_RED, "gpio-led:red:d1") == 0) &&
+               (gpio_direction_output(IGEP3_GPIO_LED1_RED, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_LED1_RED, 0);
+               gpio_set_value(IGEP3_GPIO_LED1_RED, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_RED\n");
+}
+#endif
+
+static int igep3_twl4030_gpio_setup(struct device *dev,
+               unsigned gpio, unsigned ngpio)
+{
+       /* gpio + 0 is "mmc0_cd" (input/IRQ) */
+       mmc[0].gpio_cd = gpio + 0;
+       omap2_hsmmc_init(mmc);
+
+       /*
+        * link regulators to MMC adapters ... we "know" the
+        * regulators will be set up only *after* we return.
+        */
+       igep3_vmmc1_supply.dev = mmc[0].dev;
+
+       /* TWL4030_GPIO_MAX + 1 == ledB (out, active low LED) */
+#if !defined(CONFIG_LEDS_GPIO) && !defined(CONFIG_LEDS_GPIO_MODULE)
+       if ((gpio_request(gpio+TWL4030_GPIO_MAX+1, "gpio-led:green:d1") == 0)
+           && (gpio_direction_output(gpio + TWL4030_GPIO_MAX + 1, 1) == 0)) {
+               gpio_export(gpio + TWL4030_GPIO_MAX + 1, 0);
+               gpio_set_value(gpio + TWL4030_GPIO_MAX + 1, 0);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_LED1_GREEN\n");
+#else
+       igep3_gpio_leds[3].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+
+       return 0;
+};
+
+static struct twl4030_gpio_platform_data igep3_twl4030_gpio_pdata = {
+       .gpio_base      = OMAP_MAX_GPIO_LINES,
+       .irq_base       = TWL4030_GPIO_IRQ_BASE,
+       .irq_end        = TWL4030_GPIO_IRQ_END,
+       .use_leds       = true,
+       .setup          = igep3_twl4030_gpio_setup,
+};
+
+static struct twl4030_usb_data igep3_twl4030_usb_data = {
+       .usb_mode       = T2_USB_MODE_ULPI,
+};
+
+static void __init igep3_init_irq(void)
+{
+       omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+static struct twl4030_platform_data igep3_twl4030_pdata = {
+       .irq_base       = TWL4030_IRQ_BASE,
+       .irq_end        = TWL4030_IRQ_END,
+
+       /* platform_data for children goes here */
+       .usb            = &igep3_twl4030_usb_data,
+       .gpio           = &igep3_twl4030_gpio_pdata,
+       .vmmc1          = &igep3_vmmc1,
+};
+
+static struct i2c_board_info __initdata igep3_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("twl4030", 0x48),
+               .flags          = I2C_CLIENT_WAKE,
+               .irq            = INT_34XX_SYS_NIRQ,
+               .platform_data  = &igep3_twl4030_pdata,
+       },
+};
+
+static int __init igep3_i2c_init(void)
+{
+       omap_register_i2c_bus(1, 2600, igep3_i2c_boardinfo,
+                       ARRAY_SIZE(igep3_i2c_boardinfo));
+
+       return 0;
+}
+
+static struct omap_musb_board_data musb_board_data = {
+       .interface_type = MUSB_INTERFACE_ULPI,
+       .mode           = MUSB_OTG,
+       .power          = 100,
+};
+
+#if defined(CONFIG_LIBERTAS_SDIO) || defined(CONFIG_LIBERTAS_SDIO_MODULE)
+
+static void __init igep3_wifi_bt_init(void)
+{
+       /* Configure MUX values for W-LAN + Bluetooth GPIO's */
+       omap_mux_init_gpio(IGEP3_GPIO_WIFI_NPD, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(IGEP3_GPIO_WIFI_NRESET, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(IGEP3_GPIO_BT_NRESET, OMAP_PIN_OUTPUT);
+
+       /* Set GPIO's for  W-LAN + Bluetooth combo module */
+       if ((gpio_request(IGEP3_GPIO_WIFI_NPD, "GPIO_WIFI_NPD") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_WIFI_NPD, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_WIFI_NPD, 0);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NPD\n");
+
+       if ((gpio_request(IGEP3_GPIO_WIFI_NRESET, "GPIO_WIFI_NRESET") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_WIFI_NRESET, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_WIFI_NRESET, 0);
+               gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 0);
+               udelay(10);
+               gpio_set_value(IGEP3_GPIO_WIFI_NRESET, 1);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_WIFI_NRESET\n");
+
+       if ((gpio_request(IGEP3_GPIO_BT_NRESET, "GPIO_BT_NRESET") == 0) &&
+           (gpio_direction_output(IGEP3_GPIO_BT_NRESET, 1) == 0)) {
+               gpio_export(IGEP3_GPIO_BT_NRESET, 0);
+       } else
+               pr_warning("IGEP3: Could not obtain gpio GPIO_BT_NRESET\n");
+}
+#else
+void __init igep3_wifi_bt_init(void) {}
+#endif
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+       { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux      NULL
+#endif
+
+static void __init igep3_init(void)
+{
+       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+       /* Register I2C busses and drivers */
+       igep3_i2c_init();
+
+       omap_serial_init();
+       usb_musb_init(&musb_board_data);
+
+       igep3_flash_init();
+       igep3_leds_init();
+
+       /*
+        * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+        * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
+        */
+       igep3_wifi_bt_init();
+
+}
+
+MACHINE_START(IGEP0030, "IGEP OMAP3 module")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .init_irq       = igep3_init_irq,
+       .init_machine   = igep3_init,
+       .timer          = &omap_timer,
+MACHINE_END
index f28fd77..001fd97 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/i2c/twl.h>
 #include <linux/io.h>
 #include <linux/smsc911x.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <mach/board-zoom.h>
 
 #include <asm/delay.h>
-#include <plat/control.h>
 #include <plat/usb.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "hsmmc.h"
+#include "control.h"
 
 #define LDP_SMSC911X_CS                1
 #define LDP_SMSC911X_GPIO      152
@@ -82,7 +84,7 @@ static struct platform_device ldp_smsc911x_device = {
        },
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_1),
        KEY(1, 0, KEY_2),
        KEY(2, 0, KEY_3),
@@ -362,7 +364,7 @@ static int __init omap_i2c_init(void)
 static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
index 3f79668..e823c70 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/usb/musb.h>
+#include <sound/tlv320aic3x.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -383,15 +384,6 @@ static void n8x0_mmc_callback(void *data, u8 card_mask)
        omap_mmc_notify_cover_event(mmc_device, index, *openp);
 }
 
-void n8x0_mmc_slot1_cover_handler(void *arg, int closed_state)
-{
-       if (mmc_device == NULL)
-               return;
-
-       slot1_cover_open = !closed_state;
-       omap_mmc_notify_cover_event(mmc_device, 0, closed_state);
-}
-
 static int n8x0_mmc_late_init(struct device *dev)
 {
        int r, bit, *openp;
@@ -511,7 +503,7 @@ static struct omap_mmc_platform_data mmc1_data = {
 
 static struct omap_mmc_platform_data *mmc_data[OMAP24XX_NR_MMC];
 
-void __init n8x0_mmc_init(void)
+static void __init n8x0_mmc_init(void)
 
 {
        int err;
@@ -560,11 +552,6 @@ void __init n8x0_mmc_init(void)
 void __init n8x0_mmc_init(void)
 {
 }
-
-void n8x0_mmc_slot1_cover_handler(void *arg, int state)
-{
-}
-
 #endif /* CONFIG_MMC_OMAP */
 
 #ifdef CONFIG_MENELAUS
@@ -614,29 +601,35 @@ static int n8x0_menelaus_late_init(struct device *dev)
        return 0;
 }
 
-static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] = {
+#else
+static int n8x0_menelaus_late_init(struct device *dev)
+{
+       return 0;
+}
+#endif
+
+static struct menelaus_platform_data n8x0_menelaus_platform_data __initdata = {
+       .late_init = n8x0_menelaus_late_init,
+};
+
+static struct i2c_board_info __initdata n8x0_i2c_board_info_1[] __initdata = {
        {
                I2C_BOARD_INFO("menelaus", 0x72),
                .irq = INT_24XX_SYS_NIRQ,
+               .platform_data = &n8x0_menelaus_platform_data,
        },
 };
 
-static struct menelaus_platform_data n8x0_menelaus_platform_data = {
-       .late_init = n8x0_menelaus_late_init,
+static struct aic3x_pdata n810_aic33_data __initdata = {
+       .gpio_reset = 118,
 };
 
-static void __init n8x0_menelaus_init(void)
-{
-       n8x0_i2c_board_info_1[0].platform_data = &n8x0_menelaus_platform_data;
-       omap_register_i2c_bus(1, 400, n8x0_i2c_board_info_1,
-                             ARRAY_SIZE(n8x0_i2c_board_info_1));
-}
-
-#else
-static inline void __init n8x0_menelaus_init(void)
-{
-}
-#endif
+static struct i2c_board_info n810_i2c_board_info_2[] __initdata = {
+       {
+               I2C_BOARD_INFO("tlv320aic3x", 0x18),
+               .platform_data = &n810_aic33_data,
+       },
+};
 
 static void __init n8x0_map_io(void)
 {
@@ -653,6 +646,11 @@ static void __init n8x0_init_irq(void)
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+       /* I2S codec port pins for McBSP block */
+       OMAP2420_MUX(EAC_AC_SCLK, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+       OMAP2420_MUX(EAC_AC_FS, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+       OMAP2420_MUX(EAC_AC_DIN, OMAP_MUX_MODE1 | OMAP_PIN_INPUT),
+       OMAP2420_MUX(EAC_AC_DOUT, OMAP_MUX_MODE1 | OMAP_PIN_OUTPUT),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #else
@@ -665,9 +663,14 @@ static void __init n8x0_init_machine(void)
        /* FIXME: add n810 spi devices */
        spi_register_board_info(n800_spi_board_info,
                                ARRAY_SIZE(n800_spi_board_info));
+       omap_register_i2c_bus(1, 400, n8x0_i2c_board_info_1,
+                             ARRAY_SIZE(n8x0_i2c_board_info_1));
+       omap_register_i2c_bus(2, 400, NULL, 0);
+       if (machine_is_nokia_n810())
+               i2c_register_board_info(2, n810_i2c_board_info_2,
+                                       ARRAY_SIZE(n810_i2c_board_info_2));
 
        omap_serial_init();
-       n8x0_menelaus_init();
        n8x0_onenand_init();
        n8x0_mmc_init();
        n8x0_usb_init();
index 9d9f5b8..14f4224 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #define NAND_BLOCK_SIZE                SZ_128K
 
+/*
+ * OMAP3 Beagle revision
+ * Run time detection of Beagle revision is done by reading GPIO.
+ * GPIO ID -
+ *     AXBX    = GPIO173, GPIO172, GPIO171: 1 1 1
+ *     C1_3    = GPIO173, GPIO172, GPIO171: 1 1 0
+ *     C4      = GPIO173, GPIO172, GPIO171: 1 0 1
+ *     XM      = GPIO173, GPIO172, GPIO171: 0 0 0
+ */
+enum {
+       OMAP3BEAGLE_BOARD_UNKN = 0,
+       OMAP3BEAGLE_BOARD_AXBX,
+       OMAP3BEAGLE_BOARD_C1_3,
+       OMAP3BEAGLE_BOARD_C4,
+       OMAP3BEAGLE_BOARD_XM,
+};
+
+static u8 omap3_beagle_version;
+
+static u8 omap3_beagle_get_rev(void)
+{
+       return omap3_beagle_version;
+}
+
+static void __init omap3_beagle_init_rev(void)
+{
+       int ret;
+       u16 beagle_rev = 0;
+
+       omap_mux_init_gpio(171, OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_gpio(172, OMAP_PIN_INPUT_PULLUP);
+       omap_mux_init_gpio(173, OMAP_PIN_INPUT_PULLUP);
+
+       ret = gpio_request(171, "rev_id_0");
+       if (ret < 0)
+               goto fail0;
+
+       ret = gpio_request(172, "rev_id_1");
+       if (ret < 0)
+               goto fail1;
+
+       ret = gpio_request(173, "rev_id_2");
+       if (ret < 0)
+               goto fail2;
+
+       gpio_direction_input(171);
+       gpio_direction_input(172);
+       gpio_direction_input(173);
+
+       beagle_rev = gpio_get_value(171) | (gpio_get_value(172) << 1)
+                       | (gpio_get_value(173) << 2);
+
+       switch (beagle_rev) {
+       case 7:
+               printk(KERN_INFO "OMAP3 Beagle Rev: Ax/Bx\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_AXBX;
+               break;
+       case 6:
+               printk(KERN_INFO "OMAP3 Beagle Rev: C1/C2/C3\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_C1_3;
+               break;
+       case 5:
+               printk(KERN_INFO "OMAP3 Beagle Rev: C4\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
+               break;
+       case 0:
+               printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+               break;
+       default:
+               printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
+               omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+       }
+
+       return;
+
+fail2:
+       gpio_free(172);
+fail1:
+       gpio_free(171);
+fail0:
+       printk(KERN_ERR "Unable to get revision detection GPIO pins\n");
+       omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
+
+       return;
+}
+
 static struct mtd_partition omap3beagle_nand_partitions[] = {
        /* All the partition sizes are listed in terms of NAND block size */
        {
@@ -166,7 +254,7 @@ static void __init beagle_display_init(void)
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 29,
        },
        {}      /* Terminator */
@@ -185,7 +273,10 @@ static struct gpio_led gpio_leds[];
 static int beagle_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
-       if (system_rev >= 0x20 && system_rev <= 0x34301000) {
+       if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+               mmc[0].gpio_wp = -EINVAL;
+       } else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
+               (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
                omap_mux_init_gpio(23, OMAP_PIN_INPUT);
                mmc[0].gpio_wp = 23;
        } else {
@@ -322,13 +413,19 @@ static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
        },
 };
 
+static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
+       {
+               I2C_BOARD_INFO("eeprom", 0x50),
+       },
+};
+
 static int __init omap3_beagle_i2c_init(void)
 {
        omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
                        ARRAY_SIZE(beagle_i2c_boardinfo));
        /* Bus 3 is attached to the DVI port where devices like the pico DLP
         * projector don't work reliably with 400kHz */
-       omap_register_i2c_bus(3, 100, NULL, 0);
+       omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
        return 0;
 }
 
@@ -464,6 +561,7 @@ static struct omap_musb_board_data musb_board_data = {
 static void __init omap3_beagle_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+       omap3_beagle_init_rev();
        omap3_beagle_i2c_init();
        platform_add_devices(omap3_beagle_devices,
                        ARRAY_SIZE(omap3_beagle_devices));
index 8936e4f..b04365c 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/smsc911x.h>
 
 #include <linux/regulator/machine.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -370,7 +371,7 @@ static struct regulator_init_data omap3evm_vsim = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = 63,
        },
@@ -446,7 +447,7 @@ static struct twl4030_usb_data omap3evm_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_LEFT),
        KEY(0, 1, KEY_DOWN),
        KEY(0, 2, KEY_ENTER),
@@ -584,7 +585,7 @@ static int ads7846_get_pendown_state(void)
        return !gpio_get_value(OMAP3_EVM_TS_GPIO);
 }
 
-struct ads7846_platform_data ads7846_config = {
+static struct ads7846_platform_data ads7846_config = {
        .x_max                  = 0x0fff,
        .y_max                  = 0x0fff,
        .x_plate_ohms           = 180,
@@ -603,7 +604,7 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .single_channel = 1,    /* 0: slave, 1: master */
 };
 
-struct spi_board_info omap3evm_spi_board_info[] = {
+static struct spi_board_info omap3evm_spi_board_info[] = {
        [0] = {
                .modalias               = "ads7846",
                .bus_num                = 1,
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
new file mode 100644 (file)
index 0000000..5f7d2c1
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * linux/arch/arm/mach-omap2/board-omap3logic.c
+ *
+ * Copyright (C) 2010 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Copyright (C) 2010 Logic Product Development, Inc.
+ * Peter Barada <peter.barada@logicpd.com>
+ *
+ * Modified from Beagle, EVM, and RX51
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <linux/regulator/machine.h>
+
+#include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
+
+#include <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include "mux.h"
+#include "hsmmc.h"
+#include "timer-gp.h"
+#include "control.h"
+
+#include <plat/mux.h>
+#include <plat/board.h>
+#include <plat/common.h>
+#include <plat/gpmc-smsc911x.h>
+#include <plat/gpmc.h>
+#include <plat/sdrc.h>
+
+#define OMAP3LOGIC_SMSC911X_CS                 1
+
+#define OMAP3530_LV_SOM_MMC_GPIO_CD            110
+#define OMAP3530_LV_SOM_MMC_GPIO_WP            126
+#define OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ      152
+
+#define OMAP3_TORPEDO_MMC_GPIO_CD              127
+#define OMAP3_TORPEDO_SMSC911X_GPIO_IRQ                129
+
+static struct regulator_consumer_supply omap3logic_vmmc1_supply = {
+       .supply                 = "vmmc",
+};
+
+/* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
+static struct regulator_init_data omap3logic_vmmc1 = {
+       .constraints = {
+               .name                   = "VMMC1",
+               .min_uV                 = 1850000,
+               .max_uV                 = 3150000,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_VOLTAGE
+                                       | REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &omap3logic_vmmc1_supply,
+};
+
+static struct twl4030_gpio_platform_data omap3logic_gpio_data = {
+       .gpio_base      = OMAP_MAX_GPIO_LINES,
+       .irq_base       = TWL4030_GPIO_IRQ_BASE,
+       .irq_end        = TWL4030_GPIO_IRQ_END,
+       .use_leds       = true,
+       .pullups        = BIT(1),
+       .pulldowns      = BIT(2)  | BIT(6)  | BIT(7)  | BIT(8)
+                       | BIT(13) | BIT(15) | BIT(16) | BIT(17),
+};
+
+static struct twl4030_platform_data omap3logic_twldata = {
+       .irq_base       = TWL4030_IRQ_BASE,
+       .irq_end        = TWL4030_IRQ_END,
+
+       /* platform_data for children goes here */
+       .gpio           = &omap3logic_gpio_data,
+       .vmmc1          = &omap3logic_vmmc1,
+};
+
+static struct i2c_board_info __initdata omap3logic_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("twl4030", 0x48),
+               .flags = I2C_CLIENT_WAKE,
+               .irq = INT_34XX_SYS_NIRQ,
+               .platform_data = &omap3logic_twldata,
+       },
+};
+
+static int __init omap3logic_i2c_init(void)
+{
+       omap_register_i2c_bus(1, 2600, omap3logic_i2c_boardinfo,
+                               ARRAY_SIZE(omap3logic_i2c_boardinfo));
+       return 0;
+}
+
+static struct omap2_hsmmc_info __initdata board_mmc_info[] = {
+       {
+               .name           = "external",
+               .mmc            = 1,
+               .caps           = MMC_CAP_4_BIT_DATA,
+               .gpio_cd        = -EINVAL,
+               .gpio_wp        = -EINVAL,
+       },
+       {}      /* Terminator */
+};
+
+static void __init board_mmc_init(void)
+{
+       if (machine_is_omap3530_lv_som()) {
+               /* OMAP3530 LV SOM board */
+               board_mmc_info[0].gpio_cd = OMAP3530_LV_SOM_MMC_GPIO_CD;
+               board_mmc_info[0].gpio_wp = OMAP3530_LV_SOM_MMC_GPIO_WP;
+               omap_mux_init_signal("gpio_110", OMAP_PIN_OUTPUT);
+               omap_mux_init_signal("gpio_126", OMAP_PIN_OUTPUT);
+       } else if (machine_is_omap3_torpedo()) {
+               /* OMAP3 Torpedo board */
+               board_mmc_info[0].gpio_cd = OMAP3_TORPEDO_MMC_GPIO_CD;
+               omap_mux_init_signal("gpio_127", OMAP_PIN_OUTPUT);
+       } else {
+               /* unsupported board */
+               printk(KERN_ERR "%s(): unknown machine type\n", __func__);
+               return;
+       }
+
+       omap2_hsmmc_init(board_mmc_info);
+       /* link regulators to MMC adapters */
+       omap3logic_vmmc1_supply.dev = board_mmc_info[0].dev;
+}
+
+static struct omap_smsc911x_platform_data __initdata board_smsc911x_data = {
+       .cs             = OMAP3LOGIC_SMSC911X_CS,
+       .gpio_irq       = -EINVAL,
+       .gpio_reset     = -EINVAL,
+       .flags          = IORESOURCE_IRQ_LOWLEVEL,
+};
+
+/* TODO/FIXME (comment by Peter Barada, LogicPD):
+ * Fix the PBIAS voltage for Torpedo MMC1 pins that
+ * are used for other needs (IRQs, etc).            */
+static void omap3torpedo_fix_pbias_voltage(void)
+{
+       u16 control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
+       u32 reg;
+
+       if (machine_is_omap3_torpedo())
+       {
+               /* Set the bias for the pin */
+               reg = omap_ctrl_readl(control_pbias_offset);
+
+               reg &= ~OMAP343X_PBIASLITEPWRDNZ1;
+               omap_ctrl_writel(reg, control_pbias_offset);
+
+               /* 100ms delay required for PBIAS configuration */
+               msleep(100);
+
+               reg |= OMAP343X_PBIASLITEVMODE1;
+               reg |= OMAP343X_PBIASLITEPWRDNZ1;
+               omap_ctrl_writel(reg | 0x300, control_pbias_offset);
+       }
+}
+
+static inline void __init board_smsc911x_init(void)
+{
+       if (machine_is_omap3530_lv_som()) {
+               /* OMAP3530 LV SOM board */
+               board_smsc911x_data.gpio_irq =
+                                       OMAP3530_LV_SOM_SMSC911X_GPIO_IRQ;
+               omap_mux_init_signal("gpio_152", OMAP_PIN_INPUT);
+       } else if (machine_is_omap3_torpedo()) {
+               /* OMAP3 Torpedo board */
+               board_smsc911x_data.gpio_irq = OMAP3_TORPEDO_SMSC911X_GPIO_IRQ;
+               omap_mux_init_signal("gpio_129", OMAP_PIN_INPUT);
+       } else {
+               /* unsupported board */
+               printk(KERN_ERR "%s(): unknown machine type\n", __func__);
+               return;
+       }
+
+       gpmc_smsc911x_init(&board_smsc911x_data);
+}
+
+static void __init omap3logic_init_irq(void)
+{
+       omap2_init_common_hw(NULL, NULL);
+       omap_init_irq();
+       omap_gpio_init();
+}
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+       { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#else
+#define board_mux       NULL
+#endif
+
+static void __init omap3logic_init(void)
+{
+       omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+       omap3torpedo_fix_pbias_voltage();
+       omap3logic_i2c_init();
+       omap_serial_init();
+       board_mmc_init();
+       board_smsc911x_init();
+
+       /* Ensure SDRC pins are mux'd for self-refresh */
+       omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
+       omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
+}
+
+MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .init_irq       = omap3logic_init_irq,
+       .init_machine   = omap3logic_init,
+       .timer          = &omap_timer,
+MACHINE_END
+
+MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
+       .boot_params    = 0x80000100,
+       .map_io         = omap3_map_io,
+       .init_irq       = omap3logic_init_irq,
+       .init_machine   = omap3logic_init,
+       .timer          = &omap_timer,
+MACHINE_END
index 41d6f54..89ed1be 100644 (file)
@@ -32,7 +32,9 @@
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 #include <linux/gpio_keys.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
+#include <linux/regulator/fixed.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -276,14 +278,14 @@ static void pandora_wl1251_init_card(struct mmc_card *card)
 static struct omap2_hsmmc_info omap3pandora_mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = 126,
                .ext_clock      = 0,
        },
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = 127,
                .ext_clock      = 1,
@@ -291,7 +293,7 @@ static struct omap2_hsmmc_info omap3pandora_mmc[] = {
        },
        {
                .mmc            = 3,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .init_card      = pandora_wl1251_init_card,
@@ -344,6 +346,9 @@ static struct regulator_consumer_supply pandora_vmmc1_supply =
 static struct regulator_consumer_supply pandora_vmmc2_supply =
        REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
 
+static struct regulator_consumer_supply pandora_vmmc3_supply =
+       REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.2");
+
 static struct regulator_consumer_supply pandora_vdda_dac_supply =
        REGULATOR_SUPPLY("vdda_dac", "omapdss");
 
@@ -488,6 +493,33 @@ static struct regulator_init_data pandora_vsim = {
        .consumer_supplies      = &pandora_adac_supply,
 };
 
+/* Fixed regulator internal to Wifi module */
+static struct regulator_init_data pandora_vmmc3 = {
+       .constraints = {
+               .valid_ops_mask         = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies  = 1,
+       .consumer_supplies      = &pandora_vmmc3_supply,
+};
+
+static struct fixed_voltage_config pandora_vwlan = {
+       .supply_name            = "vwlan",
+       .microvolts             = 1800000, /* 1.8V */
+       .gpio                   = PANDORA_WIFI_NRESET_GPIO,
+       .startup_delay          = 50000, /* 50ms */
+       .enable_high            = 1,
+       .enabled_at_boot        = 0,
+       .init_data              = &pandora_vmmc3,
+};
+
+static struct platform_device pandora_vwlan_device = {
+       .name           = "reg-fixed-voltage",
+       .id             = 1,
+       .dev = {
+               .platform_data = &pandora_vwlan,
+       },
+};
+
 static struct twl4030_usb_data omap3pandora_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
@@ -501,6 +533,8 @@ static struct twl4030_codec_data omap3pandora_codec_data = {
        .audio = &omap3pandora_audio_data,
 };
 
+static struct twl4030_bci_platform_data pandora_bci_data;
+
 static struct twl4030_platform_data omap3pandora_twldata = {
        .irq_base       = TWL4030_IRQ_BASE,
        .irq_end        = TWL4030_IRQ_END,
@@ -516,6 +550,7 @@ static struct twl4030_platform_data omap3pandora_twldata = {
        .vaux4          = &pandora_vaux4,
        .vsim           = &pandora_vsim,
        .keypad         = &pandora_kp_data,
+       .bci            = &pandora_bci_data,
 };
 
 static struct i2c_board_info __initdata omap3pandora_i2c_boardinfo[] = {
@@ -644,19 +679,8 @@ static void pandora_wl1251_init(void)
        if (pandora_wl1251_pdata.irq < 0)
                goto fail_irq;
 
-       ret = gpio_request(PANDORA_WIFI_NRESET_GPIO, "wl1251 nreset");
-       if (ret < 0)
-               goto fail_irq;
-
-       /* start powered so that it probes with MMC subsystem */
-       ret = gpio_direction_output(PANDORA_WIFI_NRESET_GPIO, 1);
-       if (ret < 0)
-               goto fail_nreset;
-
        return;
 
-fail_nreset:
-       gpio_free(PANDORA_WIFI_NRESET_GPIO);
 fail_irq:
        gpio_free(PANDORA_WIFI_IRQ_GPIO);
 fail:
@@ -668,6 +692,7 @@ static struct platform_device *omap3pandora_devices[] __initdata = {
        &pandora_keys_gpio,
        &pandora_dss_device,
        &pandora_wl1251_data,
+       &pandora_vwlan_device,
 };
 
 static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
index bc5ac83..f252721 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
+#include <linux/mmc/host.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -38,7 +39,6 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 #include <plat/display.h>
 
 #include <plat/mcspi.h>
@@ -52,6 +52,7 @@
 #include "sdram-micron-mt46h32m32lf-6.h"
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE)
 #define OMAP3STALKER_ETHR_START        0x2c000000
@@ -275,7 +276,7 @@ static struct regulator_init_data omap3stalker_vsim = {
 static struct omap2_hsmmc_info mmc[] = {
        {
         .mmc           = 1,
-        .wires         = 4,
+        .caps          = MMC_CAP_4_BIT_DATA,
         .gpio_cd       = -EINVAL,
         .gpio_wp       = 23,
         },
@@ -389,7 +390,7 @@ static struct twl4030_usb_data omap3stalker_usb_data = {
        .usb_mode       = T2_USB_MODE_ULPI,
 };
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_LEFT),
        KEY(0, 1, KEY_DOWN),
        KEY(0, 2, KEY_ENTER),
@@ -564,7 +565,7 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .single_channel         = 1,    /* 0: slave, 1: master */
 };
 
-struct spi_board_info omap3stalker_spi_board_info[] = {
+static struct spi_board_info omap3stalker_spi_board_info[] = {
        [0] = {
               .modalias        = "ads7846",
               .bus_num         = 1,
index 0e99ce5..41104bb 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/nand.h>
+#include <linux/mmc/host.h>
 
 #include <plat/mcspi.h>
 #include <linux/spi/spi.h>
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
-#include <plat/timer-gp.h>
 
 #include "mux.h"
 #include "hsmmc.h"
+#include "timer-gp.h"
 
 #include <asm/setup.h>
 
@@ -61,7 +62,7 @@
 #define TB_BL_PWM_TIMER                9
 #define TB_KILL_POWER_GPIO     168
 
-unsigned long touchbook_revision;
+static unsigned long touchbook_revision;
 
 static struct mtd_partition omap3touchbook_nand_partitions[] = {
        /* All the partition sizes are listed in terms of NAND block size */
@@ -108,7 +109,7 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = 29,
        },
        {}      /* Terminator */
index db69bca..702f2a6 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl.h>
 
 #include <plat/board.h>
 #include <plat/common.h>
-#include <plat/control.h>
-#include <plat/timer-gp.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+#include "timer-gp.h"
+
 #include "hsmmc.h"
+#include "control.h"
+
+#define GPIO_HUB_POWER         1
+#define GPIO_HUB_NRESET                62
+
+static struct gpio_led gpio_leds[] = {
+       {
+               .name                   = "pandaboard::status1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = 7,
+       },
+       {
+               .name                   = "pandaboard::status2",
+               .default_trigger        = "mmc0",
+               .gpio                   = 8,
+       },
+};
 
+static struct gpio_led_platform_data gpio_led_info = {
+       .leds           = gpio_leds,
+       .num_leds       = ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device leds_gpio = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &gpio_led_info,
+       },
+};
+
+static struct platform_device *panda_devices[] __initdata = {
+       &leds_gpio,
+};
 
 static void __init omap4_panda_init_irq(void)
 {
@@ -47,6 +81,56 @@ static void __init omap4_panda_init_irq(void)
        omap_gpio_init();
 }
 
+static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+       .port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+       .port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+       .port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+       .phy_reset  = false,
+       .reset_gpio_port[0]  = -EINVAL,
+       .reset_gpio_port[1]  = -EINVAL,
+       .reset_gpio_port[2]  = -EINVAL
+};
+
+static void __init omap4_ehci_init(void)
+{
+       int ret;
+
+
+       /* disable the power to the usb hub prior to init */
+       ret = gpio_request(GPIO_HUB_POWER, "hub_power");
+       if (ret) {
+               pr_err("Cannot request GPIO %d\n", GPIO_HUB_POWER);
+               goto error1;
+       }
+       gpio_export(GPIO_HUB_POWER, 0);
+       gpio_direction_output(GPIO_HUB_POWER, 0);
+       gpio_set_value(GPIO_HUB_POWER, 0);
+
+       /* reset phy+hub */
+       ret = gpio_request(GPIO_HUB_NRESET, "hub_nreset");
+       if (ret) {
+               pr_err("Cannot request GPIO %d\n", GPIO_HUB_NRESET);
+               goto error2;
+       }
+       gpio_export(GPIO_HUB_NRESET, 0);
+       gpio_direction_output(GPIO_HUB_NRESET, 0);
+       gpio_set_value(GPIO_HUB_NRESET, 0);
+       gpio_set_value(GPIO_HUB_NRESET, 1);
+
+       usb_ehci_init(&ehci_pdata);
+
+       /* enable power to hub */
+       gpio_set_value(GPIO_HUB_POWER, 1);
+       return;
+
+error2:
+       gpio_free(GPIO_HUB_POWER);
+error1:
+       pr_err("Unable to initialize EHCI power/reset\n");
+       return;
+
+}
+
 static struct omap_musb_board_data musb_board_data = {
        .interface_type         = MUSB_INTERFACE_UTMI,
        .mode                   = MUSB_PERIPHERAL,
@@ -56,7 +140,7 @@ static struct omap_musb_board_data musb_board_data = {
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_wp        = -EINVAL,
        },
        {}      /* Terminator */
@@ -67,10 +151,6 @@ static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
                .supply = "vmmc",
                .dev_name = "mmci-omap-hs.0",
        },
-       {
-               .supply = "vmmc",
-               .dev_name = "mmci-omap-hs.1",
-       },
 };
 
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
@@ -89,7 +169,14 @@ static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 
 static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
 {
-       struct omap_mmc_platform_data *pdata = dev->platform_data;
+       struct omap_mmc_platform_data *pdata;
+
+       /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
+       if (!dev) {
+               pr_err("Failed omap4_twl6030_hsmmc_set_late_init\n");
+               return;
+       }
+       pdata = dev->platform_data;
 
        pdata->init =   omap4_twl6030_hsmmc_late_init;
 }
@@ -156,7 +243,7 @@ static struct regulator_init_data omap4_panda_vmmc = {
                                        | REGULATOR_CHANGE_MODE
                                        | REGULATOR_CHANGE_STATUS,
        },
-       .num_consumer_supplies  = 2,
+       .num_consumer_supplies  = 1,
        .consumer_supplies      = omap4_panda_vmmc_supply,
 };
 
@@ -274,13 +361,13 @@ static int __init omap4_panda_i2c_init(void)
 }
 static void __init omap4_panda_init(void)
 {
-       int status;
-
        omap4_panda_i2c_init();
+       platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
        omap_serial_init();
        omap4_twl6030_hsmmc_init(mmc);
        /* OMAP4 Panda uses internal transceiver so register nop transceiver */
        usb_nop_xceiv_register();
+       omap4_ehci_init();
        /* FIXME: allow multi-omap to boot until musb is updated for omap4 */
        if (!cpu_is_omap44xx())
                usb_musb_init(&musb_board_data);
index 5e528ca..7053bc0 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -303,13 +304,13 @@ static void __init overo_flash_init(void)
 static struct omap2_hsmmc_info mmc[] = {
        {
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
        },
        {
                .mmc            = 2,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .transceiver    = true,
index 63d786b..3fec4d6 100644 (file)
@@ -33,6 +33,8 @@
 #include <plat/onenand.h>
 #include <plat/gpmc-smc91x.h>
 
+#include <mach/board-rx51.h>
+
 #include <sound/tlv320aic3x.h>
 #include <sound/tpa6130a2-plat.h>
 
@@ -105,6 +107,10 @@ static struct spi_board_info rx51_peripherals_spi_board_info[] __initdata = {
        },
 };
 
+static struct platform_device rx51_charger_device = {
+       .name = "isp1704_charger",
+};
+
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 
 #define RX51_GPIO_CAMERA_LENS_COVER    110
@@ -185,7 +191,7 @@ static void __init rx51_add_gpio_keys(void)
 }
 #endif /* CONFIG_KEYBOARD_GPIO || CONFIG_KEYBOARD_GPIO_MODULE */
 
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        /*
         * Note that KEY(x, 8, KEY_XXX) entries represent "entrire row
         * connected to the ground" matrix state.
@@ -303,7 +309,7 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "external",
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .cover_only     = true,
                .gpio_cd        = 160,
                .gpio_wp        = -EINVAL,
@@ -312,7 +318,8 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "internal",
                .mmc            = 2,
-               .wires          = 8, /* See also rx51_mmc2_remux */
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+                                               /* See also rx51_mmc2_remux */
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
@@ -916,5 +923,6 @@ void __init rx51_peripherals_init(void)
        spi_register_board_info(rx51_peripherals_spi_board_info,
                                ARRAY_SIZE(rx51_peripherals_spi_board_info));
        omap2_hsmmc_init(mmc);
+       platform_device_register(&rx51_charger_device);
 }
 
index f392844..a43b2c5 100644 (file)
@@ -43,7 +43,7 @@ struct sdram_timings {
        u32 tWTR;
 };
 
-struct omap_sdrc_params rx51_sdrc_params[4];
+static struct omap_sdrc_params rx51_sdrc_params[4];
 
 static const struct sdram_timings rx51_timings[] = {
        {
index 5a1005b..85503fe 100644 (file)
@@ -20,6 +20,8 @@
 #include <plat/vram.h>
 #include <plat/mcspi.h>
 
+#include <mach/board-rx51.h>
+
 #include "mux.h"
 
 #define RX51_LCD_RESET_GPIO    90
index 1d7f827..007ebdc 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <plat/gpmc.h>
 
+#include <mach/board-zoom.h>
+
 #define ZOOM_SMSC911X_CS       7
 #define ZOOM_SMSC911X_GPIO     158
 #define ZOOM_QUADUART_CS       3
index bc82328..86c9b21 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 #include <linux/wl12xx.h>
+#include <linux/mmc/host.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,7 +36,7 @@
 #define OMAP_ZOOM_WLAN_IRQ_GPIO                (162)
 
 /* Zoom2 has Qwerty keyboard*/
-static int board_keymap[] = {
+static uint32_t board_keymap[] = {
        KEY(0, 0, KEY_E),
        KEY(0, 1, KEY_R),
        KEY(0, 2, KEY_T),
@@ -199,14 +200,14 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {
                .name           = "external",
                .mmc            = 1,
-               .wires          = 4,
+               .caps           = MMC_CAP_4_BIT_DATA,
                .gpio_wp        = -EINVAL,
                .power_saving   = true,
        },
        {
                .name           = "internal",
                .mmc            = 2,
-               .wires          = 8,
+               .caps           = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
                .gpio_cd        = -EINVAL,
                .gpio_wp        = -EINVAL,
                .nonremovable   = true,
@@ -348,4 +349,5 @@ void __init zoom_peripherals_init(void)
        platform_device_register(&omap_vwlan_device);
        usb_musb_init(&musb_board_data);
        enable_board_wakeup_source();
+       omap_serial_init();
 }
index 4ccbc32..2992a9f 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <mach/board-zoom.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-micron-mt46h32m32lf-6.h"
 
index b2bb3ff..5adde12 100644 (file)
@@ -22,6 +22,7 @@
 #include <plat/board.h>
 #include <plat/usb.h>
 
+#include "board-flash.h"
 #include "mux.h"
 #include "sdram-hynix-h8mbx00u0mer-0em.h"
 
index 605f531..b5babf5 100644 (file)
@@ -395,7 +395,7 @@ void omap2_clk_disable_unused(struct clk *clk)
        if ((regval32 & (1 << clk->enable_bit)) == v)
                return;
 
-       printk(KERN_DEBUG "Disabling unused clock \"%s\"\n", clk->name);
+       pr_debug("Disabling unused clock \"%s\"\n", clk->name);
        if (cpu_is_omap34xx()) {
                omap2_clk_enable(clk);
                omap2_clk_disable(clk);
index 5f2066a..21f8562 100644 (file)
@@ -27,6 +27,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define OMAP_CM_REGADDR                 OMAP2420_CM_REGADDR
 
@@ -89,6 +90,12 @@ static struct clk alt_ck = {         /* Typical 54M or 48M, may not exist */
        .clkdm_name     = "wkup_clkdm",
 };
 
+/* Optional external clock input for McBSP CLKS */
+static struct clk mcbsp_clks = {
+       .name           = "mcbsp_clks",
+       .ops            = &clkops_null,
+};
+
 /*
  * Analog domain root source clocks
  */
@@ -1135,14 +1142,34 @@ static struct clk mcbsp1_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+       { .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
+       { .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
+       { .parent = NULL }
+};
+
 static struct clk mcbsp1_fck = {
        .name           = "mcbsp1_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP1_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP1_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp2_ick = {
@@ -1159,10 +1186,14 @@ static struct clk mcbsp2_fck = {
        .name           = "mcbsp2_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP2_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP242X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP2_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcspi1_ick = {
@@ -1721,6 +1752,9 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "osc_ck",       &osc_ck,        CK_242X),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_242X),
        CLK(NULL,       "alt_ck",       &alt_ck,        CK_242X),
+       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_242X),
+       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_242X),
+       CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_242X),
        /* internal analog sources */
        CLK(NULL,       "dpll_ck",      &dpll_ck,       CK_242X),
        CLK(NULL,       "apll96_ck",    &apll96_ck,     CK_242X),
@@ -1728,6 +1762,8 @@ static struct omap_clk omap2420_clks[] = {
        /* internal prcm root sources */
        CLK(NULL,       "func_54m_ck",  &func_54m_ck,   CK_242X),
        CLK(NULL,       "core_ck",      &core_ck,       CK_242X),
+       CLK("omap-mcbsp.1",     "prcm_fck",     &func_96m_ck,   CK_242X),
+       CLK("omap-mcbsp.2",     "prcm_fck",     &func_96m_ck,   CK_242X),
        CLK(NULL,       "func_96m_ck",  &func_96m_ck,   CK_242X),
        CLK(NULL,       "func_48m_ck",  &func_48m_ck,   CK_242X),
        CLK(NULL,       "func_12m_ck",  &func_12m_ck,   CK_242X),
index 701a171..e32afcb 100644 (file)
@@ -27,6 +27,7 @@
 #include "prm-regbits-24xx.h"
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define OMAP_CM_REGADDR                        OMAP2430_CM_REGADDR
 
@@ -89,6 +90,12 @@ static struct clk alt_ck = {         /* Typical 54M or 48M, may not exist */
        .clkdm_name     = "wkup_clkdm",
 };
 
+/* Optional external clock input for McBSP CLKS */
+static struct clk mcbsp_clks = {
+       .name           = "mcbsp_clks",
+       .ops            = &clkops_null,
+};
+
 /*
  * Analog domain root source clocks
  */
@@ -1123,14 +1130,34 @@ static struct clk mcbsp1_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static const struct clksel_rate common_mcbsp_96m_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel_rate common_mcbsp_mcbsp_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_24XX },
+       { .div = 0 }
+};
+
+static const struct clksel mcbsp_fck_clksel[] = {
+       { .parent = &func_96m_ck,  .rates = common_mcbsp_96m_rates },
+       { .parent = &mcbsp_clks,   .rates = common_mcbsp_mcbsp_rates },
+       { .parent = NULL }
+};
+
 static struct clk mcbsp1_fck = {
        .name           = "mcbsp1_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP1_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP1_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp2_ick = {
@@ -1147,10 +1174,14 @@ static struct clk mcbsp2_fck = {
        .name           = "mcbsp2_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
        .enable_bit     = OMAP24XX_EN_MCBSP2_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP2_CONTROL_DEVCONF0),
+       .clksel_mask    = OMAP2_MCBSP2_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp3_ick = {
@@ -1167,10 +1198,14 @@ static struct clk mcbsp3_fck = {
        .name           = "mcbsp3_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP3_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+       .clksel_mask    = OMAP2_MCBSP3_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp4_ick = {
@@ -1187,10 +1222,14 @@ static struct clk mcbsp4_fck = {
        .name           = "mcbsp4_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP4_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+       .clksel_mask    = OMAP2_MCBSP4_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcbsp5_ick = {
@@ -1207,10 +1246,14 @@ static struct clk mcbsp5_fck = {
        .name           = "mcbsp5_fck",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &func_96m_ck,
+       .init           = &omap2_init_clksel_parent,
        .clkdm_name     = "core_l4_clkdm",
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
        .enable_bit     = OMAP2430_EN_MCBSP5_SHIFT,
-       .recalc         = &followparent_recalc,
+       .clksel_reg     = OMAP243X_CTRL_REGADDR(OMAP243X_CONTROL_DEVCONF1),
+       .clksel_mask    = OMAP2_MCBSP5_CLKS_MASK,
+       .clksel         = mcbsp_fck_clksel,
+       .recalc         = &omap2_clksel_recalc,
 };
 
 static struct clk mcspi1_ick = {
@@ -1808,6 +1851,12 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "osc_ck",       &osc_ck,        CK_243X),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_243X),
        CLK(NULL,       "alt_ck",       &alt_ck,        CK_243X),
+       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.3",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.4",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK("omap-mcbsp.5",     "pad_fck",      &mcbsp_clks,    CK_243X),
+       CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_243X),
        /* internal analog sources */
        CLK(NULL,       "dpll_ck",      &dpll_ck,       CK_243X),
        CLK(NULL,       "apll96_ck",    &apll96_ck,     CK_243X),
@@ -1815,6 +1864,11 @@ static struct omap_clk omap2430_clks[] = {
        /* internal prcm root sources */
        CLK(NULL,       "func_54m_ck",  &func_54m_ck,   CK_243X),
        CLK(NULL,       "core_ck",      &core_ck,       CK_243X),
+       CLK("omap-mcbsp.1",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.2",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.3",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.4",     "prcm_fck",     &func_96m_ck,   CK_243X),
+       CLK("omap-mcbsp.5",     "prcm_fck",     &func_96m_ck,   CK_243X),
        CLK(NULL,       "func_96m_ck",  &func_96m_ck,   CK_243X),
        CLK(NULL,       "func_48m_ck",  &func_48m_ck,   CK_243X),
        CLK(NULL,       "func_12m_ck",  &func_12m_ck,   CK_243X),
index c73906d..d85ecd5 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/clk.h>
 #include <linux/list.h>
 
-#include <plat/control.h>
 #include <plat/clkdev_omap.h>
 
 #include "clock.h"
@@ -33,6 +32,7 @@
 #include "cm-regbits-34xx.h"
 #include "prm.h"
 #include "prm-regbits-34xx.h"
+#include "control.h"
 
 /*
  * clocks
@@ -2465,6 +2465,16 @@ static struct clk uart3_fck = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk uart4_fck = {
+       .name           = "uart4_fck",
+       .ops            = &clkops_omap2_dflt_wait,
+       .parent         = &per_48m_fck,
+       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_FCLKEN),
+       .enable_bit     = OMAP3630_EN_UART4_SHIFT,
+       .clkdm_name     = "per_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpt2_fck = {
        .name           = "gpt2_fck",
        .ops            = &clkops_omap2_dflt_wait,
@@ -2715,6 +2725,16 @@ static struct clk uart3_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk uart4_ick = {
+       .name           = "uart4_ick",
+       .ops            = &clkops_omap2_dflt_wait,
+       .parent         = &per_l4_ick,
+       .enable_reg     = OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
+       .enable_bit     = OMAP3630_EN_UART4_SHIFT,
+       .clkdm_name     = "per_clkdm",
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpt9_ick = {
        .name           = "gpt9_ick",
        .ops            = &clkops_omap2_dflt_wait,
@@ -3188,6 +3208,11 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "osc_sys_ck",   &osc_sys_ck,    CK_3XXX),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_3XXX),
        CLK(NULL,       "sys_altclk",   &sys_altclk,    CK_3XXX),
+       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.3",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.4",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
+       CLK("omap-mcbsp.5",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
        CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_3XXX),
        CLK(NULL,       "sys_clkout1",  &sys_clkout1,   CK_3XXX),
        CLK(NULL,       "dpll1_ck",     &dpll1_ck,      CK_3XXX),
@@ -3253,6 +3278,8 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "cpefuse_fck",  &cpefuse_fck,   CK_3430ES2 | CK_AM35XX),
        CLK(NULL,       "ts_fck",       &ts_fck,        CK_3430ES2 | CK_AM35XX),
        CLK(NULL,       "usbtll_fck",   &usbtll_fck,    CK_3430ES2 | CK_AM35XX),
+       CLK("omap-mcbsp.1",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
+       CLK("omap-mcbsp.5",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
        CLK(NULL,       "core_96m_fck", &core_96m_fck,  CK_3XXX),
        CLK("mmci-omap-hs.2",   "fck",  &mmchs3_fck,    CK_3430ES2 | CK_AM35XX),
        CLK("mmci-omap-hs.1",   "fck",  &mmchs2_fck,    CK_3XXX),
@@ -3346,9 +3373,13 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
        CLK(NULL,       "gpt12_ick",    &gpt12_ick,     CK_3XXX),
        CLK(NULL,       "gpt1_ick",     &gpt1_ick,      CK_3XXX),
+       CLK("omap-mcbsp.2",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
+       CLK("omap-mcbsp.3",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
+       CLK("omap-mcbsp.4",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
        CLK(NULL,       "per_96m_fck",  &per_96m_fck,   CK_3XXX),
        CLK(NULL,       "per_48m_fck",  &per_48m_fck,   CK_3XXX),
        CLK(NULL,       "uart3_fck",    &uart3_fck,     CK_3XXX),
+       CLK(NULL,       "uart4_fck",    &uart4_fck,     CK_36XX),
        CLK(NULL,       "gpt2_fck",     &gpt2_fck,      CK_3XXX),
        CLK(NULL,       "gpt3_fck",     &gpt3_fck,      CK_3XXX),
        CLK(NULL,       "gpt4_fck",     &gpt4_fck,      CK_3XXX),
@@ -3372,6 +3403,7 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "gpio2_ick",    &gpio2_ick,     CK_3XXX),
        CLK(NULL,       "wdt3_ick",     &wdt3_ick,      CK_3XXX),
        CLK(NULL,       "uart3_ick",    &uart3_ick,     CK_3XXX),
+       CLK(NULL,       "uart4_ick",    &uart4_ick,     CK_36XX),
        CLK(NULL,       "gpt9_ick",     &gpt9_ick,      CK_3XXX),
        CLK(NULL,       "gpt8_ick",     &gpt8_ick,      CK_3XXX),
        CLK(NULL,       "gpt7_ick",     &gpt7_ick,      CK_3XXX),
index e10db7a..1599836 100644 (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.
+ *
+ * XXX Some of the ES1 clocks have been removed/changed; once support
+ * is added for discriminating clocks by ES level, these should be added back
+ * in.
  */
 
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/clk.h>
-
-#include <plat/control.h>
 #include <plat/clkdev_omap.h>
 
 #include "clock.h"
@@ -32,6 +34,7 @@
 #include "cm-regbits-44xx.h"
 #include "prm.h"
 #include "prm-regbits-44xx.h"
+#include "control.h"
 
 /* Root clocks */
 
@@ -175,21 +178,27 @@ static struct clk sys_clkin_ck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
+static struct clk tie_low_clock_ck = {
+       .name           = "tie_low_clock_ck",
+       .rate           = 0,
+       .ops            = &clkops_null,
+};
+
 static struct clk utmi_phy_clkout_ck = {
        .name           = "utmi_phy_clkout_ck",
-       .rate           = 12000000,
+       .rate           = 60000000,
        .ops            = &clkops_null,
 };
 
 static struct clk xclk60mhsp1_ck = {
        .name           = "xclk60mhsp1_ck",
-       .rate           = 12000000,
+       .rate           = 60000000,
        .ops            = &clkops_null,
 };
 
 static struct clk xclk60mhsp2_ck = {
        .name           = "xclk60mhsp2_ck",
-       .rate           = 12000000,
+       .rate           = 60000000,
        .ops            = &clkops_null,
 };
 
@@ -201,39 +210,23 @@ static struct clk xclk60motg_ck = {
 
 /* Module clocks and DPLL outputs */
 
-static const struct clksel_rate div2_1to2_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
-       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-static const struct clksel dpll_sys_ref_clk_div[] = {
-       { .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
+static const struct clksel abe_dpll_bypass_clk_mux_sel[] = {
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
-static struct clk dpll_sys_ref_clk = {
-       .name           = "dpll_sys_ref_clk",
+static struct clk abe_dpll_bypass_clk_mux_ck = {
+       .name           = "abe_dpll_bypass_clk_mux_ck",
        .parent         = &sys_clkin_ck,
-       .clksel         = dpll_sys_ref_clk_div,
-       .clksel_reg     = OMAP4430_CM_DPLL_SYS_REF_CLKSEL,
-       .clksel_mask    = OMAP4430_CLKSEL_0_0_MASK,
        .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
-};
-
-static const struct clksel abe_dpll_refclk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk abe_dpll_refclk_mux_ck = {
        .name           = "abe_dpll_refclk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
-       .clksel         = abe_dpll_refclk_mux_sel,
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP4430_CM_ABE_PLL_REF_CLKSEL,
        .clksel_mask    = OMAP4430_CLKSEL_0_0_MASK,
@@ -244,7 +237,7 @@ static struct clk abe_dpll_refclk_mux_ck = {
 /* DPLL_ABE */
 static struct dpll_data dpll_abe_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_ABE,
-       .clk_bypass     = &sys_clkin_ck,
+       .clk_bypass     = &abe_dpll_bypass_clk_mux_ck,
        .clk_ref        = &abe_dpll_refclk_mux_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_ABE,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
@@ -310,6 +303,12 @@ static struct clk abe_clk = {
        .set_rate       = &omap2_clksel_set_rate,
 };
 
+static const struct clksel_rate div2_1to2_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
+       { .div = 2, .val = 1, .flags = RATE_IN_4430 },
+       { .div = 0 },
+};
+
 static const struct clksel aess_fclk_div[] = {
        { .parent = &abe_clk, .rates = div2_1to2_rates },
        { .parent = NULL },
@@ -380,14 +379,14 @@ static struct clk dpll_abe_m3_ck = {
 };
 
 static const struct clksel core_hsd_byp_clk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &dpll_abe_m3_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
 static struct clk core_hsd_byp_clk_mux_ck = {
        .name           = "core_hsd_byp_clk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .clksel         = core_hsd_byp_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP4430_CM_CLKSEL_DPLL_CORE,
@@ -400,7 +399,7 @@ static struct clk core_hsd_byp_clk_mux_ck = {
 static struct dpll_data dpll_core_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_CORE,
        .clk_bypass     = &core_hsd_byp_clk_mux_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_CORE,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_CORE,
@@ -418,7 +417,7 @@ static struct dpll_data dpll_core_dd = {
 
 static struct clk dpll_core_ck = {
        .name           = "dpll_core_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_core_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_null,
@@ -596,14 +595,14 @@ static struct clk dpll_core_m7_ck = {
 };
 
 static const struct clksel iva_hsd_byp_clk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &div_iva_hs_clk, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
 static struct clk iva_hsd_byp_clk_mux_ck = {
        .name           = "iva_hsd_byp_clk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .ops            = &clkops_null,
        .recalc         = &followparent_recalc,
 };
@@ -612,7 +611,7 @@ static struct clk iva_hsd_byp_clk_mux_ck = {
 static struct dpll_data dpll_iva_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_IVA,
        .clk_bypass     = &iva_hsd_byp_clk_mux_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_IVA,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_IVA,
@@ -630,7 +629,7 @@ static struct dpll_data dpll_iva_dd = {
 
 static struct clk dpll_iva_ck = {
        .name           = "dpll_iva_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_iva_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -672,7 +671,7 @@ static struct clk dpll_iva_m5_ck = {
 static struct dpll_data dpll_mpu_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_MPU,
        .clk_bypass     = &div_mpu_hs_clk,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_MPU,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_MPU,
@@ -690,7 +689,7 @@ static struct dpll_data dpll_mpu_dd = {
 
 static struct clk dpll_mpu_ck = {
        .name           = "dpll_mpu_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_mpu_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -724,14 +723,14 @@ static struct clk per_hs_clk_div_ck = {
 };
 
 static const struct clksel per_hsd_byp_clk_mux_sel[] = {
-       { .parent = &dpll_sys_ref_clk, .rates = div_1_0_rates },
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &per_hs_clk_div_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
 static struct clk per_hsd_byp_clk_mux_ck = {
        .name           = "per_hsd_byp_clk_mux_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .clksel         = per_hsd_byp_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
        .clksel_reg     = OMAP4430_CM_CLKSEL_DPLL_PER,
@@ -744,7 +743,7 @@ static struct clk per_hsd_byp_clk_mux_ck = {
 static struct dpll_data dpll_per_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_PER,
        .clk_bypass     = &per_hsd_byp_clk_mux_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_PER,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_PER,
@@ -762,7 +761,7 @@ static struct dpll_data dpll_per_dd = {
 
 static struct clk dpll_per_ck = {
        .name           = "dpll_per_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_per_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -858,8 +857,8 @@ static struct clk dpll_per_m7_ck = {
 /* DPLL_UNIPRO */
 static struct dpll_data dpll_unipro_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_UNIPRO,
-       .clk_bypass     = &dpll_sys_ref_clk,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .clk_bypass     = &sys_clkin_ck,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_UNIPRO,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_UNIPRO,
@@ -877,7 +876,7 @@ static struct dpll_data dpll_unipro_dd = {
 
 static struct clk dpll_unipro_ck = {
        .name           = "dpll_unipro_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_unipro_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -914,7 +913,8 @@ static struct clk usb_hs_clk_div_ck = {
 static struct dpll_data dpll_usb_dd = {
        .mult_div1_reg  = OMAP4430_CM_CLKSEL_DPLL_USB,
        .clk_bypass     = &usb_hs_clk_div_ck,
-       .clk_ref        = &dpll_sys_ref_clk,
+       .flags          = DPLL_J_TYPE | DPLL_NO_DCO_SEL,
+       .clk_ref        = &sys_clkin_ck,
        .control_reg    = OMAP4430_CM_CLKMODE_DPLL_USB,
        .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        .autoidle_reg   = OMAP4430_CM_AUTOIDLE_DPLL_USB,
@@ -927,13 +927,12 @@ static struct dpll_data dpll_usb_dd = {
        .max_multiplier = OMAP4430_MAX_DPLL_MULT,
        .max_divider    = OMAP4430_MAX_DPLL_DIV,
        .min_divider    = 1,
-       .flags          = DPLL_J_TYPE | DPLL_NO_DCO_SEL
 };
 
 
 static struct clk dpll_usb_ck = {
        .name           = "dpll_usb_ck",
-       .parent         = &dpll_sys_ref_clk,
+       .parent         = &sys_clkin_ck,
        .dpll_data      = &dpll_usb_dd,
        .init           = &omap2_init_dpll_parent,
        .ops            = &clkops_omap3_noncore_dpll_ops,
@@ -1222,7 +1221,7 @@ static struct clk per_abe_24m_fclk = {
 static const struct clksel pmd_stm_clock_mux_sel[] = {
        { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
        { .parent = &dpll_core_m6_ck, .rates = div_1_1_rates },
-       { .parent = &dpll_per_m7_ck, .rates = div_1_2_rates },
+       { .parent = &tie_low_clock_ck, .rates = div_1_2_rates },
        { .parent = NULL },
 };
 
@@ -1240,10 +1239,15 @@ static struct clk pmd_trace_clk_mux_ck = {
        .recalc         = &followparent_recalc,
 };
 
+static const struct clksel syc_clk_div_div[] = {
+       { .parent = &sys_clkin_ck, .rates = div2_1to2_rates },
+       { .parent = NULL },
+};
+
 static struct clk syc_clk_div_ck = {
        .name           = "syc_clk_div_ck",
        .parent         = &sys_clkin_ck,
-       .clksel         = dpll_sys_ref_clk_div,
+       .clksel         = syc_clk_div_div,
        .clksel_reg     = OMAP4430_CM_ABE_DSS_SYS_CLKSEL,
        .clksel_mask    = OMAP4430_CLKSEL_0_0_MASK,
        .ops            = &clkops_null,
@@ -1284,13 +1288,13 @@ static struct clk aess_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk cust_efuse_fck = {
-       .name           = "cust_efuse_fck",
+static struct clk bandgap_fclk = {
+       .name           = "bandgap_fclk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_cefuse_clkdm",
-       .parent         = &sys_clkin_ck,
+       .enable_reg     = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
        .recalc         = &followparent_recalc,
 };
 
@@ -1344,6 +1348,56 @@ static struct clk dmic_fck = {
        .clkdm_name     = "abe_clkdm",
 };
 
+static struct clk dsp_fck = {
+       .name           = "dsp_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "tesla_clkdm",
+       .parent         = &dpll_iva_m4_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_sys_clk = {
+       .name           = "dss_sys_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &syc_clk_div_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_tv_clk = {
+       .name           = "dss_tv_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_TV_CLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &extalt_clkin_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_dss_clk = {
+       .name           = "dss_dss_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DSSCLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &dpll_per_m5_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dss_48mhz_clk = {
+       .name           = "dss_48mhz_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_DSS_DSS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT,
+       .clkdm_name     = "l3_dss_clkdm",
+       .parent         = &func_48mc_fclk,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk dss_fck = {
        .name           = "dss_fck",
        .ops            = &clkops_omap2_dflt,
@@ -1354,18 +1408,18 @@ static struct clk dss_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk ducati_ick = {
-       .name           = "ducati_ick",
+static struct clk efuse_ctrl_cust_fck = {
+       .name           = "efuse_ctrl_cust_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "ducati_clkdm",
-       .parent         = &ducati_clk_mux_ck,
+       .enable_reg     = OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_cefuse_clkdm",
+       .parent         = &sys_clkin_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk emif1_ick = {
-       .name           = "emif1_ick",
+static struct clk emif1_fck = {
+       .name           = "emif1_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1375,8 +1429,8 @@ static struct clk emif1_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk emif2_ick = {
-       .name           = "emif2_ick",
+static struct clk emif2_fck = {
+       .name           = "emif2_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1407,42 +1461,24 @@ static struct clk fdif_fck = {
        .clkdm_name     = "iss_clkdm",
 };
 
-static const struct clksel per_sgx_fclk_div[] = {
-       { .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
-       { .parent = NULL },
-};
-
-static struct clk per_sgx_fclk = {
-       .name           = "per_sgx_fclk",
-       .parent         = &dpll_per_m2x2_ck,
-       .clksel         = per_sgx_fclk_div,
-       .clksel_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_PER_192M_MASK,
-       .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
-};
-
-static const struct clksel sgx_clk_mux_sel[] = {
-       { .parent = &dpll_core_m7_ck, .rates = div_1_0_rates },
-       { .parent = &per_sgx_fclk, .rates = div_1_1_rates },
-       { .parent = NULL },
+static struct clk fpka_fck = {
+       .name           = "fpka_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_secure_clkdm",
+       .parent         = &l4_div_ck,
+       .recalc         = &followparent_recalc,
 };
 
-/* Merged sgx_clk_mux into gfx */
-static struct clk gfx_fck = {
-       .name           = "gfx_fck",
-       .parent         = &dpll_core_m7_ck,
-       .clksel         = sgx_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_SGX_FCLK_MASK,
+static struct clk gpio1_dbclk = {
+       .name           = "gpio1_dbclk",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l3_gfx_clkdm",
+       .enable_reg     = OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk gpio1_ick = {
@@ -1455,6 +1491,16 @@ static struct clk gpio1_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio2_dbclk = {
+       .name           = "gpio2_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio2_ick = {
        .name           = "gpio2_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1465,6 +1511,16 @@ static struct clk gpio2_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio3_dbclk = {
+       .name           = "gpio3_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio3_ick = {
        .name           = "gpio3_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1475,6 +1531,16 @@ static struct clk gpio3_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio4_dbclk = {
+       .name           = "gpio4_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio4_ick = {
        .name           = "gpio4_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1485,6 +1551,16 @@ static struct clk gpio4_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio5_dbclk = {
+       .name           = "gpio5_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio5_ick = {
        .name           = "gpio5_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1495,6 +1571,16 @@ static struct clk gpio5_ick = {
        .recalc         = &followparent_recalc,
 };
 
+static struct clk gpio6_dbclk = {
+       .name           = "gpio6_dbclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk gpio6_ick = {
        .name           = "gpio6_ick",
        .ops            = &clkops_omap2_dflt,
@@ -1515,278 +1601,114 @@ static struct clk gpmc_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static const struct clksel dmt1_clk_mux_sel[] = {
-       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
+static const struct clksel sgx_clk_mux_sel[] = {
+       { .parent = &dpll_core_m7_ck, .rates = div_1_0_rates },
+       { .parent = &dpll_per_m7_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
-/*
- * Merged dmt1_clk_mux into gptimer1
- * gptimer1 renamed temporarily into gpt1 to match OMAP3 convention
- */
-static struct clk gpt1_fck = {
-       .name           = "gpt1_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
+/* Merged sgx_clk_mux into gpu */
+static struct clk gpu_fck = {
+       .name           = "gpu_fck",
+       .parent         = &dpll_core_m7_ck,
+       .clksel         = sgx_clk_mux_sel,
        .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .clksel_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_SGX_FCLK_MASK,
        .ops            = &clkops_omap2_dflt,
        .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_GFX_GFX_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_wkup_clkdm",
+       .clkdm_name     = "l3_gfx_clkdm",
 };
 
-/*
- * Merged cm2_dm10_mux into gptimer10
- * gptimer10 renamed temporarily into gpt10 to match OMAP3 convention
- */
-static struct clk gpt10_fck = {
-       .name           = "gpt10_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static struct clk hdq1w_fck = {
+       .name           = "hdq1w_fck",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_12m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm11_mux into gptimer11
- * gptimer11 renamed temporarily into gpt11 to match OMAP3 convention
- */
-static struct clk gpt11_fck = {
-       .name           = "gpt11_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static const struct clksel hsi_fclk_div[] = {
+       { .parent = &dpll_per_m2x2_ck, .rates = div3_1to4_rates },
+       { .parent = NULL },
+};
+
+/* Merged hsi_fclk into hsi */
+static struct clk hsi_fck = {
+       .name           = "hsi_fck",
+       .parent         = &dpll_per_m2x2_ck,
+       .clksel         = hsi_fclk_div,
+       .clksel_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_24_25_MASK,
        .ops            = &clkops_omap2_dflt,
        .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+       .enable_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+};
+
+static struct clk i2c1_fck = {
+       .name           = "i2c1_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_96m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm2_mux into gptimer2
- * gptimer2 renamed temporarily into gpt2 to match OMAP3 convention
- */
-static struct clk gpt2_fck = {
-       .name           = "gpt2_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static struct clk i2c2_fck = {
+       .name           = "i2c2_fck",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_96m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm3_mux into gptimer3
- * gptimer3 renamed temporarily into gpt3 to match OMAP3 convention
- */
-static struct clk gpt3_fck = {
-       .name           = "gpt3_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+static struct clk i2c3_fck = {
+       .name           = "i2c3_fck",
        .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_96m_fclk,
+       .recalc         = &followparent_recalc,
 };
 
-/*
- * Merged cm2_dm4_mux into gptimer4
- * gptimer4 renamed temporarily into gpt4 to match OMAP3 convention
- */
-static struct clk gpt4_fck = {
-       .name           = "gpt4_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-};
-
-static const struct clksel timer5_sync_mux_sel[] = {
-       { .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
-       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
-       { .parent = NULL },
-};
-
-/*
- * Merged timer5_sync_mux into gptimer5
- * gptimer5 renamed temporarily into gpt5 to match OMAP3 convention
- */
-static struct clk gpt5_fck = {
-       .name           = "gpt5_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged timer6_sync_mux into gptimer6
- * gptimer6 renamed temporarily into gpt6 to match OMAP3 convention
- */
-static struct clk gpt6_fck = {
-       .name           = "gpt6_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged timer7_sync_mux into gptimer7
- * gptimer7 renamed temporarily into gpt7 to match OMAP3 convention
- */
-static struct clk gpt7_fck = {
-       .name           = "gpt7_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged timer8_sync_mux into gptimer8
- * gptimer8 renamed temporarily into gpt8 to match OMAP3 convention
- */
-static struct clk gpt8_fck = {
-       .name           = "gpt8_fck",
-       .parent         = &syc_clk_div_ck,
-       .clksel         = timer5_sync_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-};
-
-/*
- * Merged cm2_dm9_mux into gptimer9
- * gptimer9 renamed temporarily into gpt9 to match OMAP3 convention
- */
-static struct clk gpt9_fck = {
-       .name           = "gpt9_fck",
-       .parent         = &sys_clkin_ck,
-       .clksel         = dmt1_clk_mux_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-};
-
-static struct clk hdq1w_fck = {
-       .name           = "hdq1w_fck",
-       .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_12m_fclk,
-       .recalc         = &followparent_recalc,
-};
-
-/* Merged hsi_fclk into hsi */
-static struct clk hsi_ick = {
-       .name           = "hsi_ick",
-       .parent         = &dpll_per_m2x2_ck,
-       .clksel         = per_sgx_fclk_div,
-       .clksel_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_24_25_MASK,
-       .ops            = &clkops_omap2_dflt,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
-       .enable_reg     = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "l3_init_clkdm",
-};
-
-static struct clk i2c1_fck = {
-       .name           = "i2c1_fck",
-       .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C1_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_96m_fclk,
-       .recalc         = &followparent_recalc,
-};
-
-static struct clk i2c2_fck = {
-       .name           = "i2c2_fck",
+static struct clk i2c4_fck = {
+       .name           = "i2c4_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C2_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
        .parent         = &func_96m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk i2c3_fck = {
-       .name           = "i2c3_fck",
+static struct clk ipu_fck = {
+       .name           = "ipu_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C3_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_96m_fclk,
+       .enable_reg     = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "ducati_clkdm",
+       .parent         = &ducati_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk i2c4_fck = {
-       .name           = "i2c4_fck",
+static struct clk iss_ctrlclk = {
+       .name           = "iss_ctrlclk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_I2C4_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
+       .enable_reg     = OMAP4430_CM_CAM_ISS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
+       .clkdm_name     = "iss_clkdm",
        .parent         = &func_96m_fclk,
        .recalc         = &followparent_recalc,
 };
@@ -1801,8 +1723,8 @@ static struct clk iss_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk ivahd_ick = {
-       .name           = "ivahd_ick",
+static struct clk iva_fck = {
+       .name           = "iva_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1811,8 +1733,8 @@ static struct clk ivahd_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk keyboard_fck = {
-       .name           = "keyboard_fck",
+static struct clk kbd_fck = {
+       .name           = "kbd_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
@@ -1821,8 +1743,8 @@ static struct clk keyboard_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk l3_instr_interconnect_ick = {
-       .name           = "l3_instr_interconnect_ick",
+static struct clk l3_instr_ick = {
+       .name           = "l3_instr_ick",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -1831,8 +1753,8 @@ static struct clk l3_instr_interconnect_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk l3_interconnect_3_ick = {
-       .name           = "l3_interconnect_3_ick",
+static struct clk l3_main_3_ick = {
+       .name           = "l3_main_3_ick",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -2005,6 +1927,16 @@ static struct clk mcbsp4_fck = {
        .clkdm_name     = "l4_per_clkdm",
 };
 
+static struct clk mcpdm_fck = {
+       .name           = "mcpdm_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &pad_clks_ck,
+       .recalc         = &followparent_recalc,
+};
+
 static struct clk mcspi1_fck = {
        .name           = "mcspi1_fck",
        .ops            = &clkops_omap2_dflt,
@@ -2105,33 +2037,33 @@ static struct clk mmc5_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk ocp_wp1_ick = {
-       .name           = "ocp_wp1_ick",
+static struct clk ocp2scp_usb_phy_phy_48m = {
+       .name           = "ocp2scp_usb_phy_phy_48m",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "l3_instr_clkdm",
-       .parent         = &l3_div_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_PHY_48M_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &func_48m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk pdm_fck = {
-       .name           = "pdm_fck",
+static struct clk ocp2scp_usb_phy_ick = {
+       .name           = "ocp2scp_usb_phy_ick",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM1_ABE_PDM_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-       .parent         = &pad_clks_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &l4_div_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk pkaeip29_fck = {
-       .name           = "pkaeip29_fck",
+static struct clk ocp_wp_noc_ick = {
+       .name           = "ocp_wp_noc_ick",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_secure_clkdm",
-       .parent         = &l4_div_ck,
+       .enable_reg     = OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_instr_clkdm",
+       .parent         = &l3_div_ck,
        .recalc         = &followparent_recalc,
 };
 
@@ -2145,8 +2077,8 @@ static struct clk rng_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sha2md51_fck = {
-       .name           = "sha2md51_fck",
+static struct clk sha2md5_fck = {
+       .name           = "sha2md5_fck",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
@@ -2155,8 +2087,8 @@ static struct clk sha2md51_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sl2_ick = {
-       .name           = "sl2_ick",
+static struct clk sl2if_ick = {
+       .name           = "sl2if_ick",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_IVAHD_SL2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
@@ -2165,129 +2097,340 @@ static struct clk sl2_ick = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk slimbus1_fck = {
-       .name           = "slimbus1_fck",
+static struct clk slimbus1_fclk_1 = {
+       .name           = "slimbus1_fclk_1",
        .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK1_SHIFT,
        .clkdm_name     = "abe_clkdm",
-       .parent         = &ocp_abe_iclk,
+       .parent         = &func_24m_clk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk slimbus2_fck = {
-       .name           = "slimbus2_fck",
+static struct clk slimbus1_fclk_0 = {
+       .name           = "slimbus1_fclk_0",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &l4_div_ck,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK0_SHIFT,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &abe_24m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sr_core_fck = {
-       .name           = "sr_core_fck",
+static struct clk slimbus1_fclk_2 = {
+       .name           = "slimbus1_fclk_2",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_ao_clkdm",
-       .parent         = &l4_wkup_clk_mux_ck,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK2_SHIFT,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &pad_clks_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sr_iva_fck = {
-       .name           = "sr_iva_fck",
+static struct clk slimbus1_slimbus_clk = {
+       .name           = "slimbus1_slimbus_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_ao_clkdm",
-       .parent         = &l4_wkup_clk_mux_ck,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &slimbus_clk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk sr_mpu_fck = {
-       .name           = "sr_mpu_fck",
+static struct clk slimbus1_fck = {
+       .name           = "slimbus1_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
+       .enable_reg     = OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_ao_clkdm",
-       .parent         = &l4_wkup_clk_mux_ck,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &ocp_abe_iclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk tesla_ick = {
-       .name           = "tesla_ick",
+static struct clk slimbus2_fclk_1 = {
+       .name           = "slimbus2_fclk_1",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_TESLA_TESLA_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
-       .clkdm_name     = "tesla_clkdm",
-       .parent         = &dpll_iva_m4_ck,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &per_abe_24m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart1_fck = {
-       .name           = "uart1_fck",
+static struct clk slimbus2_fclk_0 = {
+       .name           = "slimbus2_fclk_0",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART1_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT,
        .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .parent         = &func_24mc_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart2_fck = {
-       .name           = "uart2_fck",
+static struct clk slimbus2_slimbus_clk = {
+       .name           = "slimbus2_slimbus_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART2_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT,
        .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .parent         = &pad_slimbus_core_clks_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart3_fck = {
-       .name           = "uart3_fck",
+static struct clk slimbus2_fck = {
+       .name           = "slimbus2_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .parent         = &l4_div_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk uart4_fck = {
-       .name           = "uart4_fck",
+static struct clk smartreflex_core_fck = {
+       .name           = "smartreflex_core_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_per_clkdm",
-       .parent         = &func_48m_fclk,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &l4_wkup_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk unipro1_fck = {
-       .name           = "unipro1_fck",
+static struct clk smartreflex_iva_fck = {
+       .name           = "smartreflex_iva_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_UNIPRO1_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_ALWON_SR_IVA_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l3_init_clkdm",
-       .parent         = &func_96m_fclk,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &l4_wkup_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_host_fck = {
-       .name           = "usb_host_fck",
+static struct clk smartreflex_mpu_fck = {
+       .name           = "smartreflex_mpu_fck",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_ALWON_SR_MPU_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l3_init_clkdm",
-       .parent         = &init_60m_fclk,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &l4_wkup_clk_mux_ck,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_host_fs_fck = {
-       .name           = "usb_host_fs_fck",
-       .ops            = &clkops_omap2_dflt,
+/* Merged dmt1_clk_mux into timer1 */
+static struct clk timer1_fck = {
+       .name           = "timer1_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_wkup_clkdm",
+};
+
+/* Merged cm2_dm10_mux into timer10 */
+static struct clk timer10_fck = {
+       .name           = "timer10_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm11_mux into timer11 */
+static struct clk timer11_fck = {
+       .name           = "timer11_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm2_mux into timer2 */
+static struct clk timer2_fck = {
+       .name           = "timer2_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm3_mux into timer3 */
+static struct clk timer3_fck = {
+       .name           = "timer3_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+/* Merged cm2_dm4_mux into timer4 */
+static struct clk timer4_fck = {
+       .name           = "timer4_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+static const struct clksel timer5_sync_mux_sel[] = {
+       { .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
+       { .parent = &sys_32k_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+/* Merged timer5_sync_mux into timer5 */
+static struct clk timer5_fck = {
+       .name           = "timer5_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged timer6_sync_mux into timer6 */
+static struct clk timer6_fck = {
+       .name           = "timer6_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged timer7_sync_mux into timer7 */
+static struct clk timer7_fck = {
+       .name           = "timer7_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged timer8_sync_mux into timer8 */
+static struct clk timer8_fck = {
+       .name           = "timer8_fck",
+       .parent         = &syc_clk_div_ck,
+       .clksel         = timer5_sync_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+};
+
+/* Merged cm2_dm9_mux into timer9 */
+static struct clk timer9_fck = {
+       .name           = "timer9_fck",
+       .parent         = &sys_clkin_ck,
+       .clksel         = abe_dpll_bypass_clk_mux_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_MASK,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &omap2_clksel_recalc,
+       .enable_reg     = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+};
+
+static struct clk uart1_fck = {
+       .name           = "uart1_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk uart2_fck = {
+       .name           = "uart2_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk uart3_fck = {
+       .name           = "uart3_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk uart4_fck = {
+       .name           = "uart4_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_per_clkdm",
+       .parent         = &func_48m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_fs_fck = {
+       .name           = "usb_host_fs_fck",
+       .ops            = &clkops_omap2_dflt,
        .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_FS_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
        .clkdm_name     = "l3_init_clkdm",
@@ -2295,75 +2438,138 @@ static struct clk usb_host_fs_fck = {
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_otg_ick = {
-       .name           = "usb_otg_ick",
+static struct clk usb_host_hs_utmi_p3_clk = {
+       .name           = "usb_host_hs_utmi_p3_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT,
        .clkdm_name     = "l3_init_clkdm",
-       .parent         = &l3_div_ck,
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usb_tll_ick = {
-       .name           = "usb_tll_ick",
+static struct clk usb_host_hs_hsic60m_p1_clk = {
+       .name           = "usb_host_hs_hsic60m_p1_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT,
        .clkdm_name     = "l3_init_clkdm",
-       .parent         = &l4_div_ck,
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usbphyocp2scp_ick = {
-       .name           = "usbphyocp2scp_ick",
+static struct clk usb_host_hs_hsic60m_p2_clk = {
+       .name           = "usb_host_hs_hsic60m_p2_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT,
        .clkdm_name     = "l3_init_clkdm",
-       .parent         = &l4_div_ck,
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk usim_fck = {
-       .name           = "usim_fck",
+static const struct clksel utmi_p1_gfclk_sel[] = {
+       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
+       { .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk utmi_p1_gfclk = {
+       .name           = "utmi_p1_gfclk",
+       .parent         = &init_60m_fclk,
+       .clksel         = utmi_p1_gfclk_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk usb_host_hs_utmi_p1_clk = {
+       .name           = "usb_host_hs_utmi_p1_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .parent         = &sys_32k_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &utmi_p1_gfclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk wdt2_fck = {
-       .name           = "wdt2_fck",
+static const struct clksel utmi_p2_gfclk_sel[] = {
+       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
+       { .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk utmi_p2_gfclk = {
+       .name           = "utmi_p2_gfclk",
+       .parent         = &init_60m_fclk,
+       .clksel         = utmi_p2_gfclk_sel,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P2_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk usb_host_hs_utmi_p2_clk = {
+       .name           = "usb_host_hs_utmi_p2_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
-       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "l4_wkup_clkdm",
-       .parent         = &sys_32k_ck,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &utmi_p2_gfclk,
        .recalc         = &followparent_recalc,
 };
 
-static struct clk wdt3_fck = {
-       .name           = "wdt3_fck",
+static struct clk usb_host_hs_hsic480m_p1_clk = {
+       .name           = "usb_host_hs_hsic480m_p1_clk",
        .ops            = &clkops_omap2_dflt,
-       .enable_reg     = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &dpll_usb_m2_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_hs_hsic480m_p2_clk = {
+       .name           = "usb_host_hs_hsic480m_p2_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &dpll_usb_m2_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_hs_func48mclk = {
+       .name           = "usb_host_hs_func48mclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &func_48mc_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_host_hs_fck = {
+       .name           = "usb_host_hs_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
        .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
-       .clkdm_name     = "abe_clkdm",
-       .parent         = &sys_32k_ck,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
        .recalc         = &followparent_recalc,
 };
 
-/* Remaining optional clocks */
 static const struct clksel otg_60m_gfclk_sel[] = {
        { .parent = &utmi_phy_clkout_ck, .rates = div_1_0_rates },
        { .parent = &xclk60motg_ck, .rates = div_1_1_rates },
        { .parent = NULL },
 };
 
-static struct clk otg_60m_gfclk_ck = {
-       .name           = "otg_60m_gfclk_ck",
+static struct clk otg_60m_gfclk = {
+       .name           = "otg_60m_gfclk",
        .parent         = &utmi_phy_clkout_ck,
        .clksel         = otg_60m_gfclk_sel,
        .init           = &omap2_init_clksel_parent,
@@ -2373,38 +2579,74 @@ static struct clk otg_60m_gfclk_ck = {
        .recalc         = &omap2_clksel_recalc,
 };
 
-static const struct clksel stm_clk_div_div[] = {
-       { .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates },
-       { .parent = NULL },
+static struct clk usb_otg_hs_xclk = {
+       .name           = "usb_otg_hs_xclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_XCLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &otg_60m_gfclk,
+       .recalc         = &followparent_recalc,
 };
 
-static struct clk stm_clk_div_ck = {
-       .name           = "stm_clk_div_ck",
-       .parent         = &pmd_stm_clock_mux_ck,
-       .clksel         = stm_clk_div_div,
-       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_PMD_STM_CLK_MASK,
-       .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
+static struct clk usb_otg_hs_ick = {
+       .name           = "usb_otg_hs_ick",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &l3_div_ck,
+       .recalc         = &followparent_recalc,
 };
 
-static const struct clksel trace_clk_div_div[] = {
-       { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
-       { .parent = NULL },
+static struct clk usb_phy_cm_clk32k = {
+       .name           = "usb_phy_cm_clk32k",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_ALWON_USBPHY_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_CLK32K_SHIFT,
+       .clkdm_name     = "l4_ao_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
 };
 
-static struct clk trace_clk_div_ck = {
-       .name           = "trace_clk_div_ck",
-       .parent         = &pmd_trace_clk_mux_ck,
-       .clksel         = trace_clk_div_div,
-       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
-       .ops            = &clkops_null,
-       .recalc         = &omap2_clksel_recalc,
-       .round_rate     = &omap2_clksel_round_rate,
-       .set_rate       = &omap2_clksel_set_rate,
+static struct clk usb_tll_hs_usb_ch2_clk = {
+       .name           = "usb_tll_hs_usb_ch2_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_usb_ch0_clk = {
+       .name           = "usb_tll_hs_usb_ch0_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_usb_ch1_clk = {
+       .name           = "usb_tll_hs_usb_ch1_clk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &init_60m_fclk,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usb_tll_hs_ick = {
+       .name           = "usb_tll_hs_ick",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l3_init_clkdm",
+       .parent         = &l4_div_ck,
+       .recalc         = &followparent_recalc,
 };
 
 static const struct clksel_rate div2_14to18_rates[] = {
@@ -2418,8 +2660,8 @@ static const struct clksel usim_fclk_div[] = {
        { .parent = NULL },
 };
 
-static struct clk usim_fclk = {
-       .name           = "usim_fclk",
+static struct clk usim_ck = {
+       .name           = "usim_ck",
        .parent         = &dpll_per_m4_ck,
        .clksel         = usim_fclk_div,
        .clksel_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
@@ -2430,38 +2672,79 @@ static struct clk usim_fclk = {
        .set_rate       = &omap2_clksel_set_rate,
 };
 
-static const struct clksel utmi_p1_gfclk_sel[] = {
-       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
-       { .parent = &xclk60mhsp1_ck, .rates = div_1_1_rates },
+static struct clk usim_fclk = {
+       .name           = "usim_fclk",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
+       .enable_bit     = OMAP4430_OPTFCLKEN_FCLK_SHIFT,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &usim_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk usim_fck = {
+       .name           = "usim_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_WKUP_USIM_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_HWCTRL,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk wd_timer2_fck = {
+       .name           = "wd_timer2_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk wd_timer3_fck = {
+       .name           = "wd_timer3_fck",
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+       .enable_bit     = OMAP4430_MODULEMODE_SWCTRL,
+       .clkdm_name     = "abe_clkdm",
+       .parent         = &sys_32k_ck,
+       .recalc         = &followparent_recalc,
+};
+
+/* Remaining optional clocks */
+static const struct clksel stm_clk_div_div[] = {
+       { .parent = &pmd_stm_clock_mux_ck, .rates = div3_1to4_rates },
        { .parent = NULL },
 };
 
-static struct clk utmi_p1_gfclk_ck = {
-       .name           = "utmi_p1_gfclk_ck",
-       .parent         = &init_60m_fclk,
-       .clksel         = utmi_p1_gfclk_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P1_MASK,
+static struct clk stm_clk_div_ck = {
+       .name           = "stm_clk_div_ck",
+       .parent         = &pmd_stm_clock_mux_ck,
+       .clksel         = stm_clk_div_div,
+       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_PMD_STM_CLK_MASK,
        .ops            = &clkops_null,
        .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
 };
 
-static const struct clksel utmi_p2_gfclk_sel[] = {
-       { .parent = &init_60m_fclk, .rates = div_1_0_rates },
-       { .parent = &xclk60mhsp2_ck, .rates = div_1_1_rates },
+static const struct clksel trace_clk_div_div[] = {
+       { .parent = &pmd_trace_clk_mux_ck, .rates = div3_1to4_rates },
        { .parent = NULL },
 };
 
-static struct clk utmi_p2_gfclk_ck = {
-       .name           = "utmi_p2_gfclk_ck",
-       .parent         = &init_60m_fclk,
-       .clksel         = utmi_p2_gfclk_sel,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
-       .clksel_mask    = OMAP4430_CLKSEL_UTMI_P2_MASK,
+static struct clk trace_clk_div_ck = {
+       .name           = "trace_clk_div_ck",
+       .parent         = &pmd_trace_clk_mux_ck,
+       .clksel         = trace_clk_div_div,
+       .clksel_reg     = OMAP4430_CM_EMU_DEBUGSS_CLKCTRL,
+       .clksel_mask    = OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK,
        .ops            = &clkops_null,
        .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
 };
 
 /*
@@ -2483,11 +2766,12 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "virt_27000000_ck",             &virt_27000000_ck,      CK_443X),
        CLK(NULL,       "virt_38400000_ck",             &virt_38400000_ck,      CK_443X),
        CLK(NULL,       "sys_clkin_ck",                 &sys_clkin_ck,  CK_443X),
+       CLK(NULL,       "tie_low_clock_ck",             &tie_low_clock_ck,      CK_443X),
        CLK(NULL,       "utmi_phy_clkout_ck",           &utmi_phy_clkout_ck,    CK_443X),
        CLK(NULL,       "xclk60mhsp1_ck",               &xclk60mhsp1_ck,        CK_443X),
        CLK(NULL,       "xclk60mhsp2_ck",               &xclk60mhsp2_ck,        CK_443X),
        CLK(NULL,       "xclk60motg_ck",                &xclk60motg_ck, CK_443X),
-       CLK(NULL,       "dpll_sys_ref_clk",             &dpll_sys_ref_clk,      CK_443X),
+       CLK(NULL,       "abe_dpll_bypass_clk_mux_ck",   &abe_dpll_bypass_clk_mux_ck,    CK_443X),
        CLK(NULL,       "abe_dpll_refclk_mux_ck",       &abe_dpll_refclk_mux_ck,        CK_443X),
        CLK(NULL,       "dpll_abe_ck",                  &dpll_abe_ck,   CK_443X),
        CLK(NULL,       "dpll_abe_m2x2_ck",             &dpll_abe_m2x2_ck,      CK_443X),
@@ -2557,46 +2841,48 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "aes1_fck",                     &aes1_fck,      CK_443X),
        CLK(NULL,       "aes2_fck",                     &aes2_fck,      CK_443X),
        CLK(NULL,       "aess_fck",                     &aess_fck,      CK_443X),
-       CLK(NULL,       "cust_efuse_fck",               &cust_efuse_fck,        CK_443X),
+       CLK(NULL,       "bandgap_fclk",                 &bandgap_fclk,  CK_443X),
        CLK(NULL,       "des3des_fck",                  &des3des_fck,   CK_443X),
        CLK(NULL,       "dmic_sync_mux_ck",             &dmic_sync_mux_ck,      CK_443X),
        CLK(NULL,       "dmic_fck",                     &dmic_fck,      CK_443X),
+       CLK(NULL,       "dsp_fck",                      &dsp_fck,       CK_443X),
+       CLK(NULL,       "dss_sys_clk",                  &dss_sys_clk,   CK_443X),
+       CLK(NULL,       "dss_tv_clk",                   &dss_tv_clk,    CK_443X),
+       CLK(NULL,       "dss_dss_clk",                  &dss_dss_clk,   CK_443X),
+       CLK(NULL,       "dss_48mhz_clk",                &dss_48mhz_clk, CK_443X),
        CLK(NULL,       "dss_fck",                      &dss_fck,       CK_443X),
-       CLK(NULL,       "ducati_ick",                   &ducati_ick,    CK_443X),
-       CLK(NULL,       "emif1_ick",                    &emif1_ick,     CK_443X),
-       CLK(NULL,       "emif2_ick",                    &emif2_ick,     CK_443X),
+       CLK(NULL,       "efuse_ctrl_cust_fck",          &efuse_ctrl_cust_fck,   CK_443X),
+       CLK(NULL,       "emif1_fck",                    &emif1_fck,     CK_443X),
+       CLK(NULL,       "emif2_fck",                    &emif2_fck,     CK_443X),
        CLK(NULL,       "fdif_fck",                     &fdif_fck,      CK_443X),
-       CLK(NULL,       "per_sgx_fclk",                 &per_sgx_fclk,  CK_443X),
-       CLK(NULL,       "gfx_fck",                      &gfx_fck,       CK_443X),
+       CLK(NULL,       "fpka_fck",                     &fpka_fck,      CK_443X),
+       CLK(NULL,       "gpio1_dbck",                   &gpio1_dbclk,   CK_443X),
        CLK(NULL,       "gpio1_ick",                    &gpio1_ick,     CK_443X),
+       CLK(NULL,       "gpio2_dbck",                   &gpio2_dbclk,   CK_443X),
        CLK(NULL,       "gpio2_ick",                    &gpio2_ick,     CK_443X),
+       CLK(NULL,       "gpio3_dbck",                   &gpio3_dbclk,   CK_443X),
        CLK(NULL,       "gpio3_ick",                    &gpio3_ick,     CK_443X),
+       CLK(NULL,       "gpio4_dbck",                   &gpio4_dbclk,   CK_443X),
        CLK(NULL,       "gpio4_ick",                    &gpio4_ick,     CK_443X),
+       CLK(NULL,       "gpio5_dbck",                   &gpio5_dbclk,   CK_443X),
        CLK(NULL,       "gpio5_ick",                    &gpio5_ick,     CK_443X),
+       CLK(NULL,       "gpio6_dbck",                   &gpio6_dbclk,   CK_443X),
        CLK(NULL,       "gpio6_ick",                    &gpio6_ick,     CK_443X),
        CLK(NULL,       "gpmc_ick",                     &gpmc_ick,      CK_443X),
-       CLK(NULL,       "gpt1_fck",                     &gpt1_fck,      CK_443X),
-       CLK(NULL,       "gpt10_fck",                    &gpt10_fck,     CK_443X),
-       CLK(NULL,       "gpt11_fck",                    &gpt11_fck,     CK_443X),
-       CLK(NULL,       "gpt2_fck",                     &gpt2_fck,      CK_443X),
-       CLK(NULL,       "gpt3_fck",                     &gpt3_fck,      CK_443X),
-       CLK(NULL,       "gpt4_fck",                     &gpt4_fck,      CK_443X),
-       CLK(NULL,       "gpt5_fck",                     &gpt5_fck,      CK_443X),
-       CLK(NULL,       "gpt6_fck",                     &gpt6_fck,      CK_443X),
-       CLK(NULL,       "gpt7_fck",                     &gpt7_fck,      CK_443X),
-       CLK(NULL,       "gpt8_fck",                     &gpt8_fck,      CK_443X),
-       CLK(NULL,       "gpt9_fck",                     &gpt9_fck,      CK_443X),
+       CLK(NULL,       "gpu_fck",                      &gpu_fck,       CK_443X),
        CLK("omap2_hdq.0",      "fck",                          &hdq1w_fck,     CK_443X),
-       CLK(NULL,       "hsi_ick",                      &hsi_ick,       CK_443X),
+       CLK(NULL,       "hsi_fck",                      &hsi_fck,       CK_443X),
        CLK("i2c_omap.1",       "fck",                          &i2c1_fck,      CK_443X),
        CLK("i2c_omap.2",       "fck",                          &i2c2_fck,      CK_443X),
        CLK("i2c_omap.3",       "fck",                          &i2c3_fck,      CK_443X),
        CLK("i2c_omap.4",       "fck",                          &i2c4_fck,      CK_443X),
+       CLK(NULL,       "ipu_fck",                      &ipu_fck,       CK_443X),
+       CLK(NULL,       "iss_ctrlclk",                  &iss_ctrlclk,   CK_443X),
        CLK(NULL,       "iss_fck",                      &iss_fck,       CK_443X),
-       CLK(NULL,       "ivahd_ick",                    &ivahd_ick,     CK_443X),
-       CLK(NULL,       "keyboard_fck",                 &keyboard_fck,  CK_443X),
-       CLK(NULL,       "l3_instr_interconnect_ick",    &l3_instr_interconnect_ick,     CK_443X),
-       CLK(NULL,       "l3_interconnect_3_ick",        &l3_interconnect_3_ick, CK_443X),
+       CLK(NULL,       "iva_fck",                      &iva_fck,       CK_443X),
+       CLK(NULL,       "kbd_fck",                      &kbd_fck,       CK_443X),
+       CLK(NULL,       "l3_instr_ick",                 &l3_instr_ick,  CK_443X),
+       CLK(NULL,       "l3_main_3_ick",                &l3_main_3_ick, CK_443X),
        CLK(NULL,       "mcasp_sync_mux_ck",            &mcasp_sync_mux_ck,     CK_443X),
        CLK(NULL,       "mcasp_fck",                    &mcasp_fck,     CK_443X),
        CLK(NULL,       "mcbsp1_sync_mux_ck",           &mcbsp1_sync_mux_ck,    CK_443X),
@@ -2607,6 +2893,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("omap-mcbsp.3",     "fck",                          &mcbsp3_fck,    CK_443X),
        CLK(NULL,       "mcbsp4_sync_mux_ck",           &mcbsp4_sync_mux_ck,    CK_443X),
        CLK("omap-mcbsp.4",     "fck",                          &mcbsp4_fck,    CK_443X),
+       CLK(NULL,       "mcpdm_fck",                    &mcpdm_fck,     CK_443X),
        CLK("omap2_mcspi.1",    "fck",                          &mcspi1_fck,    CK_443X),
        CLK("omap2_mcspi.2",    "fck",                          &mcspi2_fck,    CK_443X),
        CLK("omap2_mcspi.3",    "fck",                          &mcspi3_fck,    CK_443X),
@@ -2616,43 +2903,66 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("mmci-omap-hs.2",   "fck",                          &mmc3_fck,      CK_443X),
        CLK("mmci-omap-hs.3",   "fck",                          &mmc4_fck,      CK_443X),
        CLK("mmci-omap-hs.4",   "fck",                          &mmc5_fck,      CK_443X),
-       CLK(NULL,       "ocp_wp1_ick",                  &ocp_wp1_ick,   CK_443X),
-       CLK(NULL,       "pdm_fck",                      &pdm_fck,       CK_443X),
-       CLK(NULL,       "pkaeip29_fck",                 &pkaeip29_fck,  CK_443X),
+       CLK(NULL,       "ocp2scp_usb_phy_phy_48m",      &ocp2scp_usb_phy_phy_48m,       CK_443X),
+       CLK(NULL,       "ocp2scp_usb_phy_ick",          &ocp2scp_usb_phy_ick,   CK_443X),
+       CLK(NULL,       "ocp_wp_noc_ick",               &ocp_wp_noc_ick,        CK_443X),
        CLK("omap_rng", "ick",                          &rng_ick,       CK_443X),
-       CLK(NULL,       "sha2md51_fck",                 &sha2md51_fck,  CK_443X),
-       CLK(NULL,       "sl2_ick",                      &sl2_ick,       CK_443X),
+       CLK(NULL,       "sha2md5_fck",                  &sha2md5_fck,   CK_443X),
+       CLK(NULL,       "sl2if_ick",                    &sl2if_ick,     CK_443X),
+       CLK(NULL,       "slimbus1_fclk_1",              &slimbus1_fclk_1,       CK_443X),
+       CLK(NULL,       "slimbus1_fclk_0",              &slimbus1_fclk_0,       CK_443X),
+       CLK(NULL,       "slimbus1_fclk_2",              &slimbus1_fclk_2,       CK_443X),
+       CLK(NULL,       "slimbus1_slimbus_clk",         &slimbus1_slimbus_clk,  CK_443X),
        CLK(NULL,       "slimbus1_fck",                 &slimbus1_fck,  CK_443X),
+       CLK(NULL,       "slimbus2_fclk_1",              &slimbus2_fclk_1,       CK_443X),
+       CLK(NULL,       "slimbus2_fclk_0",              &slimbus2_fclk_0,       CK_443X),
+       CLK(NULL,       "slimbus2_slimbus_clk",         &slimbus2_slimbus_clk,  CK_443X),
        CLK(NULL,       "slimbus2_fck",                 &slimbus2_fck,  CK_443X),
-       CLK(NULL,       "sr_core_fck",                  &sr_core_fck,   CK_443X),
-       CLK(NULL,       "sr_iva_fck",                   &sr_iva_fck,    CK_443X),
-       CLK(NULL,       "sr_mpu_fck",                   &sr_mpu_fck,    CK_443X),
-       CLK(NULL,       "tesla_ick",                    &tesla_ick,     CK_443X),
+       CLK(NULL,       "smartreflex_core_fck",         &smartreflex_core_fck,  CK_443X),
+       CLK(NULL,       "smartreflex_iva_fck",          &smartreflex_iva_fck,   CK_443X),
+       CLK(NULL,       "smartreflex_mpu_fck",          &smartreflex_mpu_fck,   CK_443X),
+       CLK(NULL,       "gpt1_fck",                     &timer1_fck,    CK_443X),
+       CLK(NULL,       "gpt10_fck",                    &timer10_fck,   CK_443X),
+       CLK(NULL,       "gpt11_fck",                    &timer11_fck,   CK_443X),
+       CLK(NULL,       "gpt2_fck",                     &timer2_fck,    CK_443X),
+       CLK(NULL,       "gpt3_fck",                     &timer3_fck,    CK_443X),
+       CLK(NULL,       "gpt4_fck",                     &timer4_fck,    CK_443X),
+       CLK(NULL,       "gpt5_fck",                     &timer5_fck,    CK_443X),
+       CLK(NULL,       "gpt6_fck",                     &timer6_fck,    CK_443X),
+       CLK(NULL,       "gpt7_fck",                     &timer7_fck,    CK_443X),
+       CLK(NULL,       "gpt8_fck",                     &timer8_fck,    CK_443X),
+       CLK(NULL,       "gpt9_fck",                     &timer9_fck,    CK_443X),
        CLK(NULL,       "uart1_fck",                    &uart1_fck,     CK_443X),
        CLK(NULL,       "uart2_fck",                    &uart2_fck,     CK_443X),
        CLK(NULL,       "uart3_fck",                    &uart3_fck,     CK_443X),
        CLK(NULL,       "uart4_fck",                    &uart4_fck,     CK_443X),
-       CLK(NULL,       "unipro1_fck",                  &unipro1_fck,   CK_443X),
-       CLK(NULL,       "usb_host_fck",                 &usb_host_fck,  CK_443X),
        CLK(NULL,       "usb_host_fs_fck",              &usb_host_fs_fck,       CK_443X),
-       CLK("musb_hdrc",        "ick",                          &usb_otg_ick,   CK_443X),
-       CLK(NULL,       "usb_tll_ick",                  &usb_tll_ick,   CK_443X),
-       CLK(NULL,       "usbphyocp2scp_ick",            &usbphyocp2scp_ick,     CK_443X),
+       CLK(NULL,       "usb_host_hs_utmi_p3_clk",      &usb_host_hs_utmi_p3_clk,       CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic60m_p1_clk",   &usb_host_hs_hsic60m_p1_clk,    CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic60m_p2_clk",   &usb_host_hs_hsic60m_p2_clk,    CK_443X),
+       CLK(NULL,       "utmi_p1_gfclk",                &utmi_p1_gfclk, CK_443X),
+       CLK(NULL,       "usb_host_hs_utmi_p1_clk",      &usb_host_hs_utmi_p1_clk,       CK_443X),
+       CLK(NULL,       "utmi_p2_gfclk",                &utmi_p2_gfclk, CK_443X),
+       CLK(NULL,       "usb_host_hs_utmi_p2_clk",      &usb_host_hs_utmi_p2_clk,       CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic480m_p1_clk",  &usb_host_hs_hsic480m_p1_clk,   CK_443X),
+       CLK(NULL,       "usb_host_hs_hsic480m_p2_clk",  &usb_host_hs_hsic480m_p2_clk,   CK_443X),
+       CLK(NULL,       "usb_host_hs_func48mclk",       &usb_host_hs_func48mclk,        CK_443X),
+       CLK(NULL,       "usb_host_hs_fck",              &usb_host_hs_fck,       CK_443X),
+       CLK(NULL,       "otg_60m_gfclk",                &otg_60m_gfclk, CK_443X),
+       CLK(NULL,       "usb_otg_hs_xclk",              &usb_otg_hs_xclk,       CK_443X),
+       CLK("musb_hdrc",        "ick",                          &usb_otg_hs_ick,        CK_443X),
+       CLK(NULL,       "usb_phy_cm_clk32k",            &usb_phy_cm_clk32k,     CK_443X),
+       CLK(NULL,       "usb_tll_hs_usb_ch2_clk",       &usb_tll_hs_usb_ch2_clk,        CK_443X),
+       CLK(NULL,       "usb_tll_hs_usb_ch0_clk",       &usb_tll_hs_usb_ch0_clk,        CK_443X),
+       CLK(NULL,       "usb_tll_hs_usb_ch1_clk",       &usb_tll_hs_usb_ch1_clk,        CK_443X),
+       CLK(NULL,       "usb_tll_hs_ick",               &usb_tll_hs_ick,        CK_443X),
+       CLK(NULL,       "usim_ck",                      &usim_ck,       CK_443X),
+       CLK(NULL,       "usim_fclk",                    &usim_fclk,     CK_443X),
        CLK(NULL,       "usim_fck",                     &usim_fck,      CK_443X),
-       CLK("omap_wdt", "fck",                          &wdt2_fck,      CK_443X),
-       CLK(NULL,       "wdt3_fck",                     &wdt3_fck,      CK_443X),
-       CLK(NULL,       "otg_60m_gfclk_ck",             &otg_60m_gfclk_ck,      CK_443X),
+       CLK("omap_wdt", "fck",                          &wd_timer2_fck, CK_443X),
+       CLK(NULL,       "wd_timer3_fck",                &wd_timer3_fck, CK_443X),
        CLK(NULL,       "stm_clk_div_ck",               &stm_clk_div_ck,        CK_443X),
        CLK(NULL,       "trace_clk_div_ck",             &trace_clk_div_ck,      CK_443X),
-       CLK(NULL,       "usim_fclk",                    &usim_fclk,     CK_443X),
-       CLK(NULL,       "utmi_p1_gfclk_ck",             &utmi_p1_gfclk_ck,      CK_443X),
-       CLK(NULL,       "utmi_p2_gfclk_ck",             &utmi_p2_gfclk_ck,      CK_443X),
-       CLK(NULL,       "gpio1_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio2_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio3_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio4_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio5_dbck",                   &dummy_ck,      CK_443X),
-       CLK(NULL,       "gpio6_dbck",                   &dummy_ck,      CK_443X),
        CLK(NULL,       "gpmc_ck",                      &dummy_ck,      CK_443X),
        CLK(NULL,       "gpt1_ick",                     &dummy_ck,      CK_443X),
        CLK(NULL,       "gpt2_ick",                     &dummy_ck,      CK_443X),
@@ -2669,19 +2979,19 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("i2c_omap.2",       "ick",                          &dummy_ck,      CK_443X),
        CLK("i2c_omap.3",       "ick",                          &dummy_ck,      CK_443X),
        CLK("i2c_omap.4",       "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.0",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.1",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.2",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.3",   "ick",                          &dummy_ck,      CK_443X),
+       CLK("mmci-omap-hs.4",   "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.1",     "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.2",     "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.3",     "ick",                          &dummy_ck,      CK_443X),
        CLK("omap-mcbsp.4",     "ick",                          &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.1",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.2",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.3",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("omap2_mcspi.4",    "ick",                  &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.0",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.1",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.2",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.3",   "ick",          &dummy_ck,      CK_443X),
-       CLK("mmci-omap-hs.4",   "ick",          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.1",    "ick",                          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.2",    "ick",                          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.3",    "ick",                          &dummy_ck,      CK_443X),
+       CLK("omap2_mcspi.4",    "ick",                          &dummy_ck,      CK_443X),
        CLK(NULL,       "uart1_ick",                    &dummy_ck,      CK_443X),
        CLK(NULL,       "uart2_ick",                    &dummy_ck,      CK_443X),
        CLK(NULL,       "uart3_ick",                    &dummy_ck,      CK_443X),
index 5d80cb8..6fb61b1 100644 (file)
@@ -258,97 +258,6 @@ static void _omap2_clkdm_set_hwsup(struct clockdomain *clkdm, int enable)
 
 }
 
-/**
- * _init_wkdep_usecount - initialize wkdep usecounts to match hardware
- * @clkdm: clockdomain to initialize wkdep usecounts
- *
- * Initialize the wakeup dependency usecount variables for clockdomain @clkdm.
- * If a wakeup dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software wakeup dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_wkdep_usecount(struct clockdomain *clkdm)
-{
-       u32 v;
-       struct clkdm_dep *cd;
-
-       if (!clkdm->wkdep_srcs)
-               return;
-
-       for (cd = clkdm->wkdep_srcs; cd->clkdm_name; cd++) {
-               if (!omap_chip_is(cd->omap_chip))
-                       continue;
-
-               if (!cd->clkdm && cd->clkdm_name)
-                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-               if (!cd->clkdm) {
-                       WARN(!cd->clkdm, "clockdomain: %s: wkdep clkdm %s not "
-                            "found\n", clkdm->name, cd->clkdm_name);
-                       continue;
-               }
-
-               v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-                                           PM_WKDEP,
-                                           (1 << cd->clkdm->dep_bit));
-
-               if (v)
-                       pr_debug("clockdomain: %s: wakeup dependency already "
-                                "set to wake up when %s wakes\n",
-                                clkdm->name, cd->clkdm->name);
-
-               atomic_set(&cd->wkdep_usecount, (v) ? 1 : 0);
-       }
-}
-
-/**
- * _init_sleepdep_usecount - initialize sleepdep usecounts to match hardware
- * @clkdm: clockdomain to initialize sleepdep usecounts
- *
- * Initialize the sleep dependency usecount variables for clockdomain @clkdm.
- * If a sleep dependency is present in the hardware, the usecount will be
- * set to 1; otherwise, it will be set to 0.  Software should clear all
- * software sleep dependencies prior to calling this function if it wishes
- * to ensure that all usecounts start at 0.  No return value.
- */
-static void _init_sleepdep_usecount(struct clockdomain *clkdm)
-{
-       u32 v;
-       struct clkdm_dep *cd;
-
-       if (!cpu_is_omap34xx())
-               return;
-
-       if (!clkdm->sleepdep_srcs)
-               return;
-
-       for (cd = clkdm->sleepdep_srcs; cd->clkdm_name; cd++) {
-               if (!omap_chip_is(cd->omap_chip))
-                       continue;
-
-               if (!cd->clkdm && cd->clkdm_name)
-                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-               if (!cd->clkdm) {
-                       WARN(!cd->clkdm, "clockdomain: %s: sleepdep clkdm %s "
-                            "not found\n", clkdm->name, cd->clkdm_name);
-                       continue;
-               }
-
-               v = prm_read_mod_bits_shift(clkdm->pwrdm.ptr->prcm_offs,
-                                           OMAP3430_CM_SLEEPDEP,
-                                           (1 << cd->clkdm->dep_bit));
-
-               if (v)
-                       pr_debug("clockdomain: %s: sleep dependency already "
-                                "set to prevent from idling until %s "
-                                "idles\n", clkdm->name, cd->clkdm->name);
-
-               atomic_set(&cd->sleepdep_usecount, (v) ? 1 : 0);
-       }
-};
-
 /* Public functions */
 
 /**
@@ -379,12 +288,17 @@ void clkdm_init(struct clockdomain **clkdms,
                        _autodep_lookup(autodep);
 
        /*
-        * Ensure that the *dep_usecount registers reflect the current
-        * state of the PRCM.
+        * Put all clockdomains into software-supervised mode; PM code
+        * should later enable hardware-supervised mode as appropriate
         */
        list_for_each_entry(clkdm, &clkdm_list, node) {
-               _init_wkdep_usecount(clkdm);
-               _init_sleepdep_usecount(clkdm);
+               if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+                       omap2_clkdm_wakeup(clkdm);
+               else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
+                       omap2_clkdm_deny_idle(clkdm);
+
+               clkdm_clear_all_wkdeps(clkdm);
+               clkdm_clear_all_sleepdeps(clkdm);
        }
 }
 
@@ -592,6 +506,9 @@ int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
                if (!omap_chip_is(cd->omap_chip))
                        continue;
 
+               if (!cd->clkdm && cd->clkdm_name)
+                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
                /* PRM accesses are slow, so minimize them */
                mask |= 1 << cd->clkdm->dep_bit;
                atomic_set(&cd->wkdep_usecount, 0);
@@ -752,6 +669,9 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
                if (!omap_chip_is(cd->omap_chip))
                        continue;
 
+               if (!cd->clkdm && cd->clkdm_name)
+                       cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
                /* PRM accesses are slow, so minimize them */
                mask |= 1 << cd->clkdm->dep_bit;
                atomic_set(&cd->sleepdep_usecount, 0);
index fe82b79..4f959a7 100644 (file)
 #define OMAP3430_ST_MCBSP2_MASK                                (1 << 0)
 
 /* CM_AUTOIDLE_PER */
+#define OMAP3630_AUTO_UART4_MASK                       (1 << 18)
+#define OMAP3630_AUTO_UART4_SHIFT                      18
 #define OMAP3430_AUTO_GPIO6_MASK                       (1 << 17)
 #define OMAP3430_AUTO_GPIO6_SHIFT                      17
 #define OMAP3430_AUTO_GPIO5_MASK                       (1 << 16)
index ac8458e..0b72be4 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * OMAP44xx Clock Management register bits
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
  * Rajendra Nayak (rnayak@ti.com)
 #include "cm.h"
 
 
-/* Used by CM_L3_1_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
+/*
+ * Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP,
+ * CM_TESLA_DYNAMICDEP
+ */
 #define OMAP4430_ABE_DYNDEP_SHIFT                              3
-#define OMAP4430_ABE_DYNDEP_MASK                               BITFIELD(3, 3)
+#define OMAP4430_ABE_DYNDEP_MASK                               (1 << 3)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ABE_STATDEP_SHIFT                             3
-#define OMAP4430_ABE_STATDEP_MASK                              BITFIELD(3, 3)
+#define OMAP4430_ABE_STATDEP_MASK                              (1 << 3)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_ALWONCORE_DYNDEP_SHIFT                                16
-#define OMAP4430_ALWONCORE_DYNDEP_MASK                         BITFIELD(16, 16)
+#define OMAP4430_ALWONCORE_DYNDEP_MASK                         (1 << 16)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_ALWONCORE_STATDEP_SHIFT                       16
-#define OMAP4430_ALWONCORE_STATDEP_MASK                                BITFIELD(16, 16)
+#define OMAP4430_ALWONCORE_STATDEP_MASK                                (1 << 16)
 
 /*
- * Used by CM_AUTOIDLE_DPLL_PER, CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB,
- * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
- * CM_AUTOIDLE_DPLL_DDRPHY, CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU
+ * Used by CM_AUTOIDLE_DPLL_ABE, CM_AUTOIDLE_DPLL_CORE,
+ * CM_AUTOIDLE_DPLL_CORE_RESTORE, CM_AUTOIDLE_DPLL_DDRPHY,
+ * CM_AUTOIDLE_DPLL_IVA, CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER,
+ * CM_AUTOIDLE_DPLL_UNIPRO, CM_AUTOIDLE_DPLL_USB
  */
 #define OMAP4430_AUTO_DPLL_MODE_SHIFT                          0
-#define OMAP4430_AUTO_DPLL_MODE_MASK                           BITFIELD(0, 2)
+#define OMAP4430_AUTO_DPLL_MODE_MASK                           (0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_CEFUSE_DYNDEP_SHIFT                           17
-#define OMAP4430_CEFUSE_DYNDEP_MASK                            BITFIELD(17, 17)
+#define OMAP4430_CEFUSE_DYNDEP_MASK                            (1 << 17)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_TESLA_STATICDEP */
 #define OMAP4430_CEFUSE_STATDEP_SHIFT                          17
-#define OMAP4430_CEFUSE_STATDEP_MASK                           BITFIELD(17, 17)
+#define OMAP4430_CEFUSE_STATDEP_MASK                           (1 << 17)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_SHIFT               13
-#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK                        BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ABE_24M_GFCLK_MASK                        (1 << 13)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_SHIFT           12
-#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK            BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ABE_ALWON_32K_CLK_MASK            (1 << 12)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_LP_CLK_SHIFT                  9
-#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK                   BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_ABE_LP_CLK_MASK                   (1 << 9)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_SYSCLK_SHIFT                  11
-#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK                   BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_ABE_SYSCLK_MASK                   (1 << 11)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ABE_X2_CLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_ABE_X2_CLK_MASK                   (1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_SHIFT               11
-#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK                        BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_ASYNC_DLL_CLK_MASK                        (1 << 11)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_SHIFT              12
-#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK               BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY1_CLK_MASK               (1 << 12)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_SHIFT              13
-#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK               BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_ASYNC_PHY2_CLK_MASK               (1 << 13)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_SHIFT           9
-#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK            BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CAM_PHY_CTRL_GCLK_MASK            (1 << 9)
+
+/* Used by CM_ALWON_CLKSTCTRL */
+#define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_SHIFT                12
+#define OMAP4430_CLKACTIVITY_CORE_ALWON_32K_GFCLK_MASK         (1 << 12)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_SHIFT           9
-#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK            BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CORE_DPLL_EMU_CLK_MASK            (1 << 9)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT          9
-#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK           BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK           (1 << 9)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DLL_CLK_SHIFT                     9
-#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK                      BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DLL_CLK_MASK                      (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT10_GFCLK_SHIFT                 9
-#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK                  BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DMT10_GFCLK_MASK                  (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT11_GFCLK_SHIFT                 10
-#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK                  BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DMT11_GFCLK_MASK                  (1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT2_GFCLK_SHIFT                  11
-#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK                   BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_DMT2_GFCLK_MASK                   (1 << 11)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT3_GFCLK_SHIFT                  12
-#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK                   BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_DMT3_GFCLK_MASK                   (1 << 12)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT4_GFCLK_SHIFT                  13
-#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK                   BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_DMT4_GFCLK_MASK                   (1 << 13)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_DMT9_GFCLK_SHIFT                  14
-#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK                   BITFIELD(14, 14)
+#define OMAP4430_CLKACTIVITY_DMT9_GFCLK_MASK                   (1 << 14)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_SHIFT           10
-#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK            BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DSS_ALWON_SYS_CLK_MASK            (1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DSS_FCLK_SHIFT                    9
-#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK                     BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_DSS_FCLK_MASK                     (1 << 9)
 
 /* Used by CM_DUCATI_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_DUCATI_GCLK_SHIFT                 8
-#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK                  BITFIELD(8, 8)
-
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
-#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_SHIFT              10
-#define OMAP4430_CLKACTIVITY_EMAC_50MHZ_CLK_MASK               BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_DUCATI_GCLK_MASK                  (1 << 8)
 
 /* Used by CM_EMU_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_SHIFT                 8
-#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK                  BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_EMU_SYS_CLK_MASK                  (1 << 8)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FDIF_GFCLK_SHIFT                  10
-#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK                   BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_FDIF_GFCLK_MASK                   (1 << 10)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_SHIFT              15
-#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK               BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_FUNC_12M_GFCLK_MASK               (1 << 15)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_SHIFT              10
-#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK               BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_FUNC_24M_GFCLK_MASK               (1 << 10)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_SHIFT                11
-#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK         BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_HDMI_PHY_48MHZ_GFCLK_MASK         (1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_SHIFT          20
-#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK           BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_480M_GFCLK_MASK           (1 << 20)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_SHIFT               26
-#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK                        BITFIELD(26, 26)
+#define OMAP4430_CLKACTIVITY_HSIC_P1_GFCLK_MASK                        (1 << 26)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_SHIFT          21
-#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK           BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_480M_GFCLK_MASK           (1 << 21)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_SHIFT               27
-#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK                        BITFIELD(27, 27)
-
-/* Used by CM_L3INIT_CLKSTCTRL */
-#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_SHIFT              31
-#define OMAP4430_CLKACTIVITY_INIT_32K_GFCLK_MASK               BITFIELD(31, 31)
+#define OMAP4430_CLKACTIVITY_HSIC_P2_GFCLK_MASK                        (1 << 27)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_SHIFT             13
-#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK              BITFIELD(13, 13)
+#define OMAP4430_CLKACTIVITY_INIT_48MC_GFCLK_MASK              (1 << 13)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_SHIFT              12
-#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK               BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_INIT_48M_GFCLK_MASK               (1 << 12)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_SHIFT           28
-#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK            BITFIELD(28, 28)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P1_GFCLK_MASK            (1 << 28)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_SHIFT           29
-#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK            BITFIELD(29, 29)
+#define OMAP4430_CLKACTIVITY_INIT_60M_P2_GFCLK_MASK            (1 << 29)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_SHIFT              11
-#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK               BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_INIT_96M_GFCLK_MASK               (1 << 11)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_SHIFT              16
-#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK               BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_INIT_HSI_GFCLK_MASK               (1 << 16)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_SHIFT           17
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK            BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC1_GFCLK_MASK            (1 << 17)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_SHIFT           18
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK            BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC2_GFCLK_MASK            (1 << 18)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_SHIFT           19
-#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK            BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_INIT_HSMMC6_GFCLK_MASK            (1 << 19)
 
 /* Used by CM_CAM_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_ISS_GCLK_SHIFT                    8
-#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK                     BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_ISS_GCLK_MASK                     (1 << 8)
 
 /* Used by CM_IVAHD_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_SHIFT              8
-#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK               BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_IVAHD_ROOT_CLK_MASK               (1 << 8)
 
-/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
-#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_SHIFT       14
-#define OMAP4430_CLKACTIVITY_L3INIT_DPLL_ALWON_CLK_MASK                BITFIELD(14, 14)
+/* Used by CM_D2D_CLKSTCTRL */
+#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_SHIFT              10
+#define OMAP4430_CLKACTIVITY_L3X2_D2D_GICLK_MASK               (1 << 10)
 
 /* Used by CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_1_GICLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_1_GICLK_MASK                   (1 << 8)
 
 /* Used by CM_L3_2_CLKSTCTRL, CM_L3_2_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_2_GICLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_2_GICLK_MASK                   (1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_D2D_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_SDMA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_DMA_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_DSS_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_DSS_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_SHIFT               8
-#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK                        BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_EMIF_GICLK_MASK                        (1 << 8)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_GFX_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_SHIFT               8
-#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK                        BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_INIT_GICLK_MASK                        (1 << 8)
 
 /* Used by CM_L3INSTR_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_SHIFT              8
-#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK               BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_INSTR_GICLK_MASK               (1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_SHIFT             8
-#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK              BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L3_SECURE_GICLK_MASK              (1 << 8)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_AO_ICLK_SHIFT                  8
-#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK                   BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_AO_ICLK_MASK                   (1 << 8)
 
 /* Used by CM_CEFUSE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT             8
-#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK              BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_CEFUSE_GICLK_MASK              (1 << 8)
 
 /* Used by CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_CFG_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_D2D_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_SHIFT                        9
-#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK                 BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_D2D_GICLK_MASK                 (1 << 9)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_SHIFT               9
-#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_INIT_GICLK_MASK                        (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_L4_PER_GICLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_L4_PER_GICLK_MASK                 (1 << 8)
 
 /* Used by CM_L4SEC_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_SHIFT             9
-#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK              BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_L4_SECURE_GICLK_MASK              (1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_SHIFT               12
-#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK                        BITFIELD(12, 12)
+#define OMAP4430_CLKACTIVITY_L4_WKUP_GICLK_MASK                        (1 << 12)
 
 /* Used by CM_MPU_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_SHIFT                        8
-#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK                 BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_MPU_DPLL_CLK_MASK                 (1 << 8)
 
 /* Used by CM1_ABE_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_SHIFT               9
-#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_OCP_ABE_GICLK_MASK                        (1 << 9)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_SHIFT              16
-#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK               BITFIELD(16, 16)
+#define OMAP4430_CLKACTIVITY_PER_24MC_GFCLK_MASK               (1 << 16)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_SHIFT               17
-#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK                        BITFIELD(17, 17)
+#define OMAP4430_CLKACTIVITY_PER_32K_GFCLK_MASK                        (1 << 17)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_SHIFT               18
-#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK                        BITFIELD(18, 18)
+#define OMAP4430_CLKACTIVITY_PER_48M_GFCLK_MASK                        (1 << 18)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_SHIFT               19
-#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK                        BITFIELD(19, 19)
+#define OMAP4430_CLKACTIVITY_PER_96M_GFCLK_MASK                        (1 << 19)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_SHIFT           25
-#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK            BITFIELD(25, 25)
-
-/* Used by CM_EMU_CLKSTCTRL */
-#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_SHIFT            10
-#define OMAP4430_CLKACTIVITY_PER_DPLL_EMU_CLK_MASK             BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_PER_ABE_24M_GFCLK_MASK            (1 << 25)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_SHIFT            20
-#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK             BITFIELD(20, 20)
+#define OMAP4430_CLKACTIVITY_PER_MCASP2_GFCLK_MASK             (1 << 20)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_SHIFT            21
-#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK             BITFIELD(21, 21)
+#define OMAP4430_CLKACTIVITY_PER_MCASP3_GFCLK_MASK             (1 << 21)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_SHIFT            22
-#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK             BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_PER_MCBSP4_GFCLK_MASK             (1 << 22)
 
 /* Used by CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_SHIFT               24
-#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK                        BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_PER_SYS_GFCLK_MASK                        (1 << 24)
 
 /* Used by CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_SHIFT                        10
-#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK                 BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_PHY_ROOT_CLK_MASK                 (1 << 10)
 
 /* Used by CM_GFX_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SGX_GFCLK_SHIFT                   9
-#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK                    BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_SGX_GFCLK_MASK                    (1 << 9)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_SHIFT              11
-#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK               BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_SR_CORE_SYSCLK_MASK               (1 << 11)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_SHIFT               10
-#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK                        BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_SR_IVA_SYSCLK_MASK                        (1 << 10)
 
 /* Used by CM_ALWON_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_SHIFT               9
-#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_CLKACTIVITY_SR_MPU_SYSCLK_MASK                        (1 << 9)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_SYS_CLK_SHIFT                     8
-#define OMAP4430_CLKACTIVITY_SYS_CLK_MASK                      BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_SYS_CLK_MASK                      (1 << 8)
 
 /* Used by CM_TESLA_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_SHIFT              8
-#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK               BITFIELD(8, 8)
+#define OMAP4430_CLKACTIVITY_TESLA_ROOT_CLK_MASK               (1 << 8)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_SHIFT               22
-#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK                        BITFIELD(22, 22)
+#define OMAP4430_CLKACTIVITY_TLL_CH0_GFCLK_MASK                        (1 << 22)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_SHIFT               23
-#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK                        BITFIELD(23, 23)
+#define OMAP4430_CLKACTIVITY_TLL_CH1_GFCLK_MASK                        (1 << 23)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_SHIFT               24
-#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK                        BITFIELD(24, 24)
+#define OMAP4430_CLKACTIVITY_TLL_CH2_GFCLK_MASK                        (1 << 24)
+
+/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_SHIFT             10
+#define OMAP4430_CLKACTIVITY_UNIPRO_DPLL_CLK_MASK              (1 << 10)
+
+/* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
+#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_SHIFT                        14
+#define OMAP4430_CLKACTIVITY_USB_DPLL_CLK_MASK                 (1 << 14)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_SHIFT             15
-#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK              BITFIELD(15, 15)
+#define OMAP4430_CLKACTIVITY_USB_DPLL_HS_CLK_MASK              (1 << 15)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_USIM_GFCLK_SHIFT                  10
-#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK                   BITFIELD(10, 10)
+#define OMAP4430_CLKACTIVITY_USIM_GFCLK_MASK                   (1 << 10)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_SHIFT               30
-#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK                        BITFIELD(30, 30)
+#define OMAP4430_CLKACTIVITY_UTMI_P3_GFCLK_MASK                        (1 << 30)
 
 /* Used by CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE */
 #define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_SHIFT             25
-#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK              BITFIELD(25, 25)
+#define OMAP4430_CLKACTIVITY_UTMI_ROOT_GFCLK_MASK              (1 << 25)
 
 /* Used by CM_WKUP_CLKSTCTRL */
 #define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_SHIFT              11
-#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK               BITFIELD(11, 11)
+#define OMAP4430_CLKACTIVITY_WKUP_32K_GFCLK_MASK               (1 << 11)
 
 /*
- * Used by CM_WKUP_TIMER1_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
+ * Used by CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL,
+ * CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL,
+ * CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
  * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
  * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
  * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL, CM_L3INIT_MMC6_CLKCTRL,
- * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
- * CM1_ABE_TIMER8_CLKCTRL
+ * CM_WKUP_TIMER1_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SHIFT                                  24
-#define OMAP4430_CLKSEL_MASK                                   BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_MASK                                   (1 << 24)
 
 /*
  * Renamed from CLKSEL Used by CM_ABE_DSS_SYS_CLKSEL, CM_ABE_PLL_REF_CLKSEL,
- * CM_DPLL_SYS_REF_CLKSEL, CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT,
- * CM_CLKSEL_USB_60MHZ
+ * CM_L4_WKUP_CLKSEL, CM_CLKSEL_DUCATI_ISS_ROOT, CM_CLKSEL_USB_60MHZ
  */
 #define OMAP4430_CLKSEL_0_0_SHIFT                              0
-#define OMAP4430_CLKSEL_0_0_MASK                               BITFIELD(0, 0)
+#define OMAP4430_CLKSEL_0_0_MASK                               (1 << 0)
 
 /* Renamed from CLKSEL Used by CM_BYPCLK_DPLL_IVA, CM_BYPCLK_DPLL_MPU */
 #define OMAP4430_CLKSEL_0_1_SHIFT                              0
-#define OMAP4430_CLKSEL_0_1_MASK                               BITFIELD(0, 1)
+#define OMAP4430_CLKSEL_0_1_MASK                               (0x3 << 0)
 
 /* Renamed from CLKSEL Used by CM_L3INIT_HSI_CLKCTRL */
 #define OMAP4430_CLKSEL_24_25_SHIFT                            24
-#define OMAP4430_CLKSEL_24_25_MASK                             BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_24_25_MASK                             (0x3 << 24)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_CLKSEL_60M_SHIFT                              24
-#define OMAP4430_CLKSEL_60M_MASK                               BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_60M_MASK                               (1 << 24)
 
 /* Used by CM1_ABE_AESS_CLKCTRL */
 #define OMAP4430_CLKSEL_AESS_FCLK_SHIFT                                24
-#define OMAP4430_CLKSEL_AESS_FCLK_MASK                         BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_AESS_FCLK_MASK                         (1 << 24)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_CORE_SHIFT                             0
-#define OMAP4430_CLKSEL_CORE_MASK                              BITFIELD(0, 0)
+#define OMAP4430_CLKSEL_CORE_MASK                              (1 << 0)
 
-/* Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2 */
+/*
+ * Renamed from CLKSEL_CORE Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
+ * CM_SHADOW_FREQ_CONFIG2
+ */
 #define OMAP4430_CLKSEL_CORE_1_1_SHIFT                         1
-#define OMAP4430_CLKSEL_CORE_1_1_MASK                          BITFIELD(1, 1)
+#define OMAP4430_CLKSEL_CORE_1_1_MASK                          (1 << 1)
 
 /* Used by CM_WKUP_USIM_CLKCTRL */
 #define OMAP4430_CLKSEL_DIV_SHIFT                              24
-#define OMAP4430_CLKSEL_DIV_MASK                               BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_DIV_MASK                               (1 << 24)
 
 /* Used by CM_CAM_FDIF_CLKCTRL */
 #define OMAP4430_CLKSEL_FCLK_SHIFT                             24
-#define OMAP4430_CLKSEL_FCLK_MASK                              BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_FCLK_MASK                              (0x3 << 24)
 
 /* Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT                  25
-#define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK                   BITFIELD(25, 25)
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_MASK                   (1 << 25)
 
 /*
  * Renamed from CLKSEL_INTERNAL_SOURCE Used by CM1_ABE_DMIC_CLKCTRL,
  * CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_SHIFT     26
-#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK      BITFIELD(26, 27)
+#define OMAP4430_CLKSEL_INTERNAL_SOURCE_CM1_ABE_DMIC_MASK      (0x3 << 26)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_L3_SHIFT                               4
-#define OMAP4430_CLKSEL_L3_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_CLKSEL_L3_MASK                                        (1 << 4)
 
-/* Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2 */
+/*
+ * Renamed from CLKSEL_L3 Used by CM_SHADOW_FREQ_CONFIG2_RESTORE,
+ * CM_SHADOW_FREQ_CONFIG2
+ */
 #define OMAP4430_CLKSEL_L3_SHADOW_SHIFT                                2
-#define OMAP4430_CLKSEL_L3_SHADOW_MASK                         BITFIELD(2, 2)
+#define OMAP4430_CLKSEL_L3_SHADOW_MASK                         (1 << 2)
 
-/* Used by CM_CLKSEL_CORE_RESTORE, CM_CLKSEL_CORE */
+/* Used by CM_CLKSEL_CORE, CM_CLKSEL_CORE_RESTORE */
 #define OMAP4430_CLKSEL_L4_SHIFT                               8
-#define OMAP4430_CLKSEL_L4_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_CLKSEL_L4_MASK                                        (1 << 8)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_CLKSEL_OPP_SHIFT                              0
-#define OMAP4430_CLKSEL_OPP_MASK                               BITFIELD(0, 1)
-
-/* Used by CM_GFX_GFX_CLKCTRL */
-#define OMAP4430_CLKSEL_PER_192M_SHIFT                         25
-#define OMAP4430_CLKSEL_PER_192M_MASK                          BITFIELD(25, 26)
+#define OMAP4430_CLKSEL_OPP_MASK                               (0x3 << 0)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_STM_CLK_SHIFT                      27
-#define OMAP4430_CLKSEL_PMD_STM_CLK_MASK                       BITFIELD(27, 29)
+#define OMAP4430_CLKSEL_PMD_STM_CLK_MASK                       (0x7 << 27)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_CLKSEL_PMD_TRACE_CLK_SHIFT                    24
-#define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK                     BITFIELD(24, 26)
+#define OMAP4430_CLKSEL_PMD_TRACE_CLK_MASK                     (0x7 << 24)
 
 /* Used by CM_GFX_GFX_CLKCTRL */
 #define OMAP4430_CLKSEL_SGX_FCLK_SHIFT                         24
-#define OMAP4430_CLKSEL_SGX_FCLK_MASK                          BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_SGX_FCLK_MASK                          (1 << 24)
 
 /*
  * Used by CM1_ABE_DMIC_CLKCTRL, CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL,
  * CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL
  */
 #define OMAP4430_CLKSEL_SOURCE_SHIFT                           24
-#define OMAP4430_CLKSEL_SOURCE_MASK                            BITFIELD(24, 25)
+#define OMAP4430_CLKSEL_SOURCE_MASK                            (0x3 << 24)
 
 /* Renamed from CLKSEL_SOURCE Used by CM_L4PER_MCBSP4_CLKCTRL */
 #define OMAP4430_CLKSEL_SOURCE_24_24_SHIFT                     24
-#define OMAP4430_CLKSEL_SOURCE_24_24_MASK                      BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_SOURCE_24_24_MASK                      (1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_CLKSEL_UTMI_P1_SHIFT                          24
-#define OMAP4430_CLKSEL_UTMI_P1_MASK                           BITFIELD(24, 24)
+#define OMAP4430_CLKSEL_UTMI_P1_MASK                           (1 << 24)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_CLKSEL_UTMI_P2_SHIFT                          25
-#define OMAP4430_CLKSEL_UTMI_P2_MASK                           BITFIELD(25, 25)
+#define OMAP4430_CLKSEL_UTMI_P2_MASK                           (1 << 25)
 
 /*
- * Used by CM_WKUP_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_D2D_CLKSTCTRL,
- * CM_DUCATI_CLKSTCTRL, CM_L3INSTR_CLKSTCTRL, CM_L3_1_CLKSTCTRL,
- * CM_L3_2_CLKSTCTRL, CM_L4CFG_CLKSTCTRL, CM_MEMIF_CLKSTCTRL,
- * CM_SDMA_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_L4PER_CLKSTCTRL, CM_L4SEC_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL, CM_CAM_CLKSTCTRL, CM_CEFUSE_CLKSTCTRL,
- * CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3_1_CLKSTCTRL_RESTORE,
- * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL_RESTORE,
- * CM_L4PER_CLKSTCTRL_RESTORE, CM_MEMIF_CLKSTCTRL_RESTORE, CM_ALWON_CLKSTCTRL,
- * CM_IVAHD_CLKSTCTRL, CM_DSS_CLKSTCTRL, CM_MPU_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
- * CM1_ABE_CLKSTCTRL, CM_MPU_CLKSTCTRL_RESTORE
+ * Used by CM1_ABE_CLKSTCTRL, CM_ALWON_CLKSTCTRL, CM_CAM_CLKSTCTRL,
+ * CM_CEFUSE_CLKSTCTRL, CM_D2D_CLKSTCTRL, CM_DSS_CLKSTCTRL,
+ * CM_DUCATI_CLKSTCTRL, CM_EMU_CLKSTCTRL, CM_GFX_CLKSTCTRL, CM_IVAHD_CLKSTCTRL,
+ * CM_L3INIT_CLKSTCTRL, CM_L3INIT_CLKSTCTRL_RESTORE, CM_L3INSTR_CLKSTCTRL,
+ * CM_L3_1_CLKSTCTRL, CM_L3_1_CLKSTCTRL_RESTORE, CM_L3_2_CLKSTCTRL,
+ * CM_L3_2_CLKSTCTRL_RESTORE, CM_L4CFG_CLKSTCTRL, CM_L4CFG_CLKSTCTRL_RESTORE,
+ * CM_L4PER_CLKSTCTRL, CM_L4PER_CLKSTCTRL_RESTORE, CM_L4SEC_CLKSTCTRL,
+ * CM_MEMIF_CLKSTCTRL, CM_MEMIF_CLKSTCTRL_RESTORE, CM_MPU_CLKSTCTRL,
+ * CM_MPU_CLKSTCTRL_RESTORE, CM_SDMA_CLKSTCTRL, CM_TESLA_CLKSTCTRL,
+ * CM_WKUP_CLKSTCTRL
  */
 #define OMAP4430_CLKTRCTRL_SHIFT                               0
-#define OMAP4430_CLKTRCTRL_MASK                                        BITFIELD(0, 1)
+#define OMAP4430_CLKTRCTRL_MASK                                        (0x3 << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_DIV_SHIFT                       0
-#define OMAP4430_CORE_DPLL_EMU_DIV_MASK                                BITFIELD(0, 6)
+#define OMAP4430_CORE_DPLL_EMU_DIV_MASK                                (0x7f << 0)
 
 /* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_CORE_DPLL_EMU_MULT_SHIFT                      8
-#define OMAP4430_CORE_DPLL_EMU_MULT_MASK                       BITFIELD(8, 18)
+#define OMAP4430_CORE_DPLL_EMU_MULT_MASK                       (0x7ff << 8)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_CUSTOM_SHIFT                                  6
+#define OMAP4430_CUSTOM_MASK                                   (0x3 << 6)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_D2D_DYNDEP_SHIFT                              18
-#define OMAP4430_D2D_DYNDEP_MASK                               BITFIELD(18, 18)
+#define OMAP4430_D2D_DYNDEP_MASK                               (1 << 18)
 
 /* Used by CM_MPU_STATICDEP */
 #define OMAP4430_D2D_STATDEP_SHIFT                             18
-#define OMAP4430_D2D_STATDEP_MASK                              BITFIELD(18, 18)
+#define OMAP4430_D2D_STATDEP_MASK                              (1 << 18)
 
 /*
- * Used by CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
- * CM_SSC_DELTAMSTEP_DPLL_USB, CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE,
- * CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
- * CM_SSC_DELTAMSTEP_DPLL_DDRPHY, CM_SSC_DELTAMSTEP_DPLL_IVA,
- * CM_SSC_DELTAMSTEP_DPLL_MPU
+ * Used by CM_SSC_DELTAMSTEP_DPLL_ABE, CM_SSC_DELTAMSTEP_DPLL_CORE,
+ * CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE, CM_SSC_DELTAMSTEP_DPLL_DDRPHY,
+ * CM_SSC_DELTAMSTEP_DPLL_IVA, CM_SSC_DELTAMSTEP_DPLL_MPU,
+ * CM_SSC_DELTAMSTEP_DPLL_PER, CM_SSC_DELTAMSTEP_DPLL_UNIPRO,
+ * CM_SSC_DELTAMSTEP_DPLL_USB
  */
 #define OMAP4430_DELTAMSTEP_SHIFT                              0
-#define OMAP4430_DELTAMSTEP_MASK                               BITFIELD(0, 19)
+#define OMAP4430_DELTAMSTEP_MASK                               (0xfffff << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DLL_OVERRIDE_SHIFT                            2
-#define OMAP4430_DLL_OVERRIDE_MASK                             BITFIELD(2, 2)
+#define OMAP4430_DLL_OVERRIDE_MASK                             (1 << 2)
 
 /* Renamed from DLL_OVERRIDE Used by CM_DLL_CTRL */
 #define OMAP4430_DLL_OVERRIDE_0_0_SHIFT                                0
-#define OMAP4430_DLL_OVERRIDE_0_0_MASK                         BITFIELD(0, 0)
+#define OMAP4430_DLL_OVERRIDE_0_0_MASK                         (1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DLL_RESET_SHIFT                               3
-#define OMAP4430_DLL_RESET_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_DLL_RESET_MASK                                        (1 << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO, CM_CLKSEL_DPLL_USB,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
+ * CM_CLKSEL_DPLL_USB
  */
 #define OMAP4430_DPLL_BYP_CLKSEL_SHIFT                         23
-#define OMAP4430_DPLL_BYP_CLKSEL_MASK                          BITFIELD(23, 23)
+#define OMAP4430_DPLL_BYP_CLKSEL_MASK                          (1 << 23)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT                        8
-#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK                 BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKDCOLDO_GATE_CTRL_MASK                 (1 << 8)
 
-/* Used by CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_CORE */
+/* Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_CORE_RESTORE */
 #define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_SHIFT                   20
-#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK                    BITFIELD(20, 20)
+#define OMAP4430_DPLL_CLKOUTHIF_CLKSEL_MASK                    (1 << 20)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_DIV_SHIFT                      0
-#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK                       BITFIELD(0, 4)
+#define OMAP4430_DPLL_CLKOUTHIF_DIV_MASK                       (0x1f << 0)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_SHIFT                 5
-#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK                  BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUTHIF_DIVCHACK_MASK                  (1 << 5)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT                        8
-#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK                 BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_MASK                 (1 << 8)
 
-/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */
+/* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_SHIFT                 10
-#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK                  BITFIELD(10, 10)
+#define OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK                  (1 << 10)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIV_SHIFT                         0
-#define OMAP4430_DPLL_CLKOUT_DIV_MASK                          BITFIELD(0, 4)
+#define OMAP4430_DPLL_CLKOUT_DIV_MASK                          (0x1f << 0)
 
 /* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIV_0_6_SHIFT                     0
-#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK                      BITFIELD(0, 6)
+#define OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK                      (0x7f << 0)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO,
- * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
- * CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_SHIFT                    5
-#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK                     BITFIELD(5, 5)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_MASK                     (1 << 5)
 
 /* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_USB */
 #define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_SHIFT             7
-#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK              BITFIELD(7, 7)
+#define OMAP4430_DPLL_CLKOUT_DIVCHACK_M2_USB_MASK              (1 << 7)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE,
- * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
- * CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_DPLL_CLKOUT_GATE_CTRL_SHIFT                   8
-#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK                    BITFIELD(8, 8)
+#define OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK                    (1 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DPLL_CORE_DPLL_EN_SHIFT                       8
-#define OMAP4430_DPLL_CORE_DPLL_EN_MASK                                BITFIELD(8, 10)
+#define OMAP4430_DPLL_CORE_DPLL_EN_MASK                                (0x7 << 8)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_DPLL_CORE_M2_DIV_SHIFT                                11
-#define OMAP4430_DPLL_CORE_M2_DIV_MASK                         BITFIELD(11, 15)
+#define OMAP4430_DPLL_CORE_M2_DIV_MASK                         (0x1f << 11)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2 */
+/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
 #define OMAP4430_DPLL_CORE_M5_DIV_SHIFT                                3
-#define OMAP4430_DPLL_CORE_M5_DIV_MASK                         BITFIELD(3, 7)
-
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
-#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_SHIFT                        1
-#define OMAP4430_DPLL_CORE_SYS_REF_CLKSEL_MASK                 BITFIELD(1, 1)
+#define OMAP4430_DPLL_CORE_M5_DIV_MASK                         (0x1f << 3)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_DIV_SHIFT                                        0
-#define OMAP4430_DPLL_DIV_MASK                                 BITFIELD(0, 6)
+#define OMAP4430_DPLL_DIV_MASK                                 (0x7f << 0)
 
 /* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_DIV_0_7_SHIFT                            0
-#define OMAP4430_DPLL_DIV_0_7_MASK                             BITFIELD(0, 7)
+#define OMAP4430_DPLL_DIV_0_7_MASK                             (0xff << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
  */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_SHIFT                      8
-#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK                       BITFIELD(8, 8)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_MASK                       (1 << 8)
 
 /* Renamed from DPLL_DRIFTGUARD_EN Used by CM_CLKMODE_DPLL_UNIPRO */
 #define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_SHIFT                  3
-#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK                   BITFIELD(3, 3)
+#define OMAP4430_DPLL_DRIFTGUARD_EN_3_3_MASK                   (1 << 3)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_EN_SHIFT                                 0
-#define OMAP4430_DPLL_EN_MASK                                  BITFIELD(0, 2)
+#define OMAP4430_DPLL_EN_MASK                                  (0x7 << 0)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_LPMODE_EN_SHIFT                          10
-#define OMAP4430_DPLL_LPMODE_EN_MASK                           BITFIELD(10, 10)
+#define OMAP4430_DPLL_LPMODE_EN_MASK                           (1 << 10)
 
 /*
- * Used by CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO,
- * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
- * CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA, CM_CLKSEL_DPLL_MPU
+ * Used by CM_CLKSEL_DPLL_ABE, CM_CLKSEL_DPLL_CORE,
+ * CM_CLKSEL_DPLL_CORE_RESTORE, CM_CLKSEL_DPLL_DDRPHY, CM_CLKSEL_DPLL_IVA,
+ * CM_CLKSEL_DPLL_MPU, CM_CLKSEL_DPLL_PER, CM_CLKSEL_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_MULT_SHIFT                               8
-#define OMAP4430_DPLL_MULT_MASK                                        BITFIELD(8, 18)
+#define OMAP4430_DPLL_MULT_MASK                                        (0x7ff << 8)
 
 /* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_MULT_USB_SHIFT                           8
-#define OMAP4430_DPLL_MULT_USB_MASK                            BITFIELD(8, 19)
+#define OMAP4430_DPLL_MULT_USB_MASK                            (0xfff << 8)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO
  */
 #define OMAP4430_DPLL_REGM4XEN_SHIFT                           11
-#define OMAP4430_DPLL_REGM4XEN_MASK                            BITFIELD(11, 11)
+#define OMAP4430_DPLL_REGM4XEN_MASK                            (1 << 11)
 
 /* Used by CM_CLKSEL_DPLL_USB */
 #define OMAP4430_DPLL_SD_DIV_SHIFT                             24
-#define OMAP4430_DPLL_SD_DIV_MASK                              BITFIELD(24, 31)
+#define OMAP4430_DPLL_SD_DIV_MASK                              (0xff << 24)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_ACK_SHIFT                            13
-#define OMAP4430_DPLL_SSC_ACK_MASK                             BITFIELD(13, 13)
+#define OMAP4430_DPLL_SSC_ACK_MASK                             (1 << 13)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_DOWNSPREAD_SHIFT                     14
-#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK                      BITFIELD(14, 14)
+#define OMAP4430_DPLL_SSC_DOWNSPREAD_MASK                      (1 << 14)
 
 /*
- * Used by CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO, CM_CLKMODE_DPLL_USB,
- * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
- * CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA, CM_CLKMODE_DPLL_MPU
+ * Used by CM_CLKMODE_DPLL_ABE, CM_CLKMODE_DPLL_CORE,
+ * CM_CLKMODE_DPLL_CORE_RESTORE, CM_CLKMODE_DPLL_DDRPHY, CM_CLKMODE_DPLL_IVA,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER, CM_CLKMODE_DPLL_UNIPRO,
+ * CM_CLKMODE_DPLL_USB
  */
 #define OMAP4430_DPLL_SSC_EN_SHIFT                             12
-#define OMAP4430_DPLL_SSC_EN_MASK                              BITFIELD(12, 12)
+#define OMAP4430_DPLL_SSC_EN_MASK                              (1 << 12)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_DSS_DYNDEP_SHIFT                              8
-#define OMAP4430_DSS_DYNDEP_MASK                               BITFIELD(8, 8)
+#define OMAP4430_DSS_DYNDEP_MASK                               (1 << 8)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE
  */
 #define OMAP4430_DSS_STATDEP_SHIFT                             8
-#define OMAP4430_DSS_STATDEP_MASK                              BITFIELD(8, 8)
+#define OMAP4430_DSS_STATDEP_MASK                              (1 << 8)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_DUCATI_DYNDEP_SHIFT                           0
-#define OMAP4430_DUCATI_DYNDEP_MASK                            BITFIELD(0, 0)
+#define OMAP4430_DUCATI_DYNDEP_MASK                            (1 << 0)
 
-/* Used by CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP */
+/* Used by CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE */
 #define OMAP4430_DUCATI_STATDEP_SHIFT                          0
-#define OMAP4430_DUCATI_STATDEP_MASK                           BITFIELD(0, 0)
+#define OMAP4430_DUCATI_STATDEP_MASK                           (1 << 0)
 
-/* Used by CM_SHADOW_FREQ_CONFIG1_RESTORE, CM_SHADOW_FREQ_CONFIG1 */
+/* Used by CM_SHADOW_FREQ_CONFIG1, CM_SHADOW_FREQ_CONFIG1_RESTORE */
 #define OMAP4430_FREQ_UPDATE_SHIFT                             0
-#define OMAP4430_FREQ_UPDATE_MASK                              BITFIELD(0, 0)
+#define OMAP4430_FREQ_UPDATE_MASK                              (1 << 0)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_FUNC_SHIFT                                    16
+#define OMAP4430_FUNC_MASK                                     (0xfff << 16)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_GFX_DYNDEP_SHIFT                              10
-#define OMAP4430_GFX_DYNDEP_MASK                               BITFIELD(10, 10)
+#define OMAP4430_GFX_DYNDEP_MASK                               (1 << 10)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_GFX_STATDEP_SHIFT                             10
-#define OMAP4430_GFX_STATDEP_MASK                              BITFIELD(10, 10)
+#define OMAP4430_GFX_STATDEP_MASK                              (1 << 10)
 
-/* Used by CM_SHADOW_FREQ_CONFIG2 */
+/* Used by CM_SHADOW_FREQ_CONFIG2, CM_SHADOW_FREQ_CONFIG2_RESTORE */
 #define OMAP4430_GPMC_FREQ_UPDATE_SHIFT                                0
-#define OMAP4430_GPMC_FREQ_UPDATE_MASK                         BITFIELD(0, 0)
+#define OMAP4430_GPMC_FREQ_UPDATE_MASK                         (1 << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT1_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK                   BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT1_PWDN_MASK                   (1 << 12)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT2_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK                   BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT2_PWDN_MASK                   (1 << 12)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT3_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK                   BITFIELD(12, 12)
+#define OMAP4430_HSDIVIDER_CLKOUT3_PWDN_MASK                   (1 << 12)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIV_SHIFT                   0
-#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK                    BITFIELD(0, 4)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK                    (0x1f << 0)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_SHIFT              5
-#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK               BITFIELD(5, 5)
+#define OMAP4430_HSDIVIDER_CLKOUT4_DIVCHACK_MASK               (1 << 5)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_SHIFT             8
-#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK              BITFIELD(8, 8)
+#define OMAP4430_HSDIVIDER_CLKOUT4_GATE_CTRL_MASK              (1 << 8)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_SHIFT                  12
-#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK                   BITFIELD(12, 12)
-
-/*
- * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL,
- * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL,
- * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL,
- * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL,
- * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL,
- * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
- * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
- * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
- * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
- * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
- * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
- * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL,
- * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL,
- * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL,
- * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
- * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL,
- * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL,
- * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL,
- * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL,
- * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL,
- * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL,
- * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+#define OMAP4430_HSDIVIDER_CLKOUT4_PWDN_MASK                   (1 << 12)
+
+/*
+ * Used by CM1_ABE_AESS_CLKCTRL, CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL,
+ * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
+ * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
+ * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
+ * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
+ * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
+ * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL,
- * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL,
- * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL,
- * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL,
- * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL,
- * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL,
- * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
+ * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
+ * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
+ * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
+ * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
+ * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
+ * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
+ * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
+ * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
+ * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
+ * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
+ * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
+ * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
+ * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_IDLEST_SHIFT                                  16
-#define OMAP4430_IDLEST_MASK                                   BITFIELD(16, 17)
+#define OMAP4430_IDLEST_MASK                                   (0x3 << 16)
 
-/* Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP */
+/*
+ * Used by CM_DUCATI_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
+ * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_ISS_DYNDEP_SHIFT                              9
-#define OMAP4430_ISS_DYNDEP_MASK                               BITFIELD(9, 9)
+#define OMAP4430_ISS_DYNDEP_MASK                               (1 << 9)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_ISS_STATDEP_SHIFT                             9
-#define OMAP4430_ISS_STATDEP_MASK                              BITFIELD(9, 9)
+#define OMAP4430_ISS_STATDEP_MASK                              (1 << 9)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_TESLA_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_TESLA_DYNAMICDEP */
 #define OMAP4430_IVAHD_DYNDEP_SHIFT                            2
-#define OMAP4430_IVAHD_DYNDEP_MASK                             BITFIELD(2, 2)
+#define OMAP4430_IVAHD_DYNDEP_MASK                             (1 << 2)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_DSS_STATICDEP, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_IVAHD_STATDEP_SHIFT                           2
-#define OMAP4430_IVAHD_STATDEP_MASK                            BITFIELD(2, 2)
+#define OMAP4430_IVAHD_STATDEP_MASK                            (1 << 2)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP, CM_L4PER_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_L3INIT_DYNDEP_SHIFT                           7
-#define OMAP4430_L3INIT_DYNDEP_MASK                            BITFIELD(7, 7)
+#define OMAP4430_L3INIT_DYNDEP_MASK                            (1 << 7)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_MPU_STATICDEP, CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
+ * CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3INIT_STATDEP_SHIFT                          7
-#define OMAP4430_L3INIT_STATDEP_MASK                           BITFIELD(7, 7)
+#define OMAP4430_L3INIT_STATDEP_MASK                           (1 << 7)
 
 /*
- * Used by CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_L3INIT_DYNAMICDEP,
- * CM_DSS_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * Used by CM_DSS_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_2_DYNAMICDEP,
+ * CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_L3_1_DYNDEP_SHIFT                             5
-#define OMAP4430_L3_1_DYNDEP_MASK                              BITFIELD(5, 5)
+#define OMAP4430_L3_1_DYNDEP_MASK                              (1 << 5)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_1_STATDEP_SHIFT                            5
-#define OMAP4430_L3_1_STATDEP_MASK                             BITFIELD(5, 5)
+#define OMAP4430_L3_1_STATDEP_MASK                             (1 << 5)
 
 /*
- * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP, CM_SDMA_DYNAMICDEP,
- * CM_GFX_DYNAMICDEP, CM_L4SEC_DYNAMICDEP, CM_L3INIT_DYNAMICDEP,
- * CM_CAM_DYNAMICDEP, CM_IVAHD_DYNAMICDEP
+ * Used by CM_CAM_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE,
+ * CM_DUCATI_DYNAMICDEP, CM_EMU_DYNAMICDEP, CM_GFX_DYNAMICDEP,
+ * CM_IVAHD_DYNAMICDEP, CM_L3INIT_DYNAMICDEP, CM_L3_1_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4SEC_DYNAMICDEP, CM_SDMA_DYNAMICDEP
  */
 #define OMAP4430_L3_2_DYNDEP_SHIFT                             6
-#define OMAP4430_L3_2_DYNDEP_MASK                              BITFIELD(6, 6)
+#define OMAP4430_L3_2_DYNDEP_MASK                              (1 << 6)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L3_2_STATDEP_SHIFT                            6
-#define OMAP4430_L3_2_STATDEP_MASK                             BITFIELD(6, 6)
+#define OMAP4430_L3_2_STATDEP_MASK                             (1 << 6)
 
-/* Used by CM_L3_1_DYNAMICDEP */
+/* Used by CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE */
 #define OMAP4430_L4CFG_DYNDEP_SHIFT                            12
-#define OMAP4430_L4CFG_DYNDEP_MASK                             BITFIELD(12, 12)
+#define OMAP4430_L4CFG_DYNDEP_MASK                             (1 << 12)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP,
- * CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_MPU_STATICDEP, CM_SDMA_STATICDEP,
+ * CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4CFG_STATDEP_SHIFT                           12
-#define OMAP4430_L4CFG_STATDEP_MASK                            BITFIELD(12, 12)
+#define OMAP4430_L4CFG_STATDEP_MASK                            (1 << 12)
 
-/* Used by CM_L3_2_DYNAMICDEP */
+/* Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE */
 #define OMAP4430_L4PER_DYNDEP_SHIFT                            13
-#define OMAP4430_L4PER_DYNDEP_MASK                             BITFIELD(13, 13)
+#define OMAP4430_L4PER_DYNDEP_MASK                             (1 << 13)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_SDMA_STATICDEP_RESTORE,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE, CM_DUCATI_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4PER_STATDEP_SHIFT                           13
-#define OMAP4430_L4PER_STATDEP_MASK                            BITFIELD(13, 13)
+#define OMAP4430_L4PER_STATDEP_MASK                            (1 << 13)
 
-/* Used by CM_L3_2_DYNAMICDEP, CM_L4PER_DYNAMICDEP */
+/*
+ * Used by CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP_RESTORE
+ */
 #define OMAP4430_L4SEC_DYNDEP_SHIFT                            14
-#define OMAP4430_L4SEC_DYNDEP_MASK                             BITFIELD(14, 14)
+#define OMAP4430_L4SEC_DYNDEP_MASK                             (1 << 14)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE
  */
 #define OMAP4430_L4SEC_STATDEP_SHIFT                           14
-#define OMAP4430_L4SEC_STATDEP_MASK                            BITFIELD(14, 14)
+#define OMAP4430_L4SEC_STATDEP_MASK                            (1 << 14)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_L4WKUP_DYNDEP_SHIFT                           15
-#define OMAP4430_L4WKUP_DYNDEP_MASK                            BITFIELD(15, 15)
+#define OMAP4430_L4WKUP_DYNDEP_MASK                            (1 << 15)
 
 /*
- * Used by CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP, CM_L3INIT_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_DUCATI_STATICDEP, CM_L3INIT_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_L4WKUP_STATDEP_SHIFT                          15
-#define OMAP4430_L4WKUP_STATDEP_MASK                           BITFIELD(15, 15)
+#define OMAP4430_L4WKUP_STATDEP_MASK                           (1 << 15)
 
 /*
- * Used by CM_D2D_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
- * CM_MPU_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_L3_1_DYNAMICDEP,
+ * CM_L3_1_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP
  */
 #define OMAP4430_MEMIF_DYNDEP_SHIFT                            4
-#define OMAP4430_MEMIF_DYNDEP_MASK                             BITFIELD(4, 4)
+#define OMAP4430_MEMIF_DYNDEP_MASK                             (1 << 4)
 
 /*
- * Used by CM_D2D_STATICDEP, CM_DUCATI_STATICDEP, CM_SDMA_STATICDEP,
- * CM_GFX_STATICDEP, CM_L4SEC_STATICDEP, CM_L3INIT_STATICDEP, CM_CAM_STATICDEP,
- * CM_SDMA_STATICDEP_RESTORE, CM_IVAHD_STATICDEP, CM_DSS_STATICDEP,
- * CM_MPU_STATICDEP, CM_TESLA_STATICDEP
+ * Used by CM_CAM_STATICDEP, CM_D2D_STATICDEP, CM_D2D_STATICDEP_RESTORE,
+ * CM_DSS_STATICDEP, CM_DUCATI_STATICDEP, CM_GFX_STATICDEP, CM_IVAHD_STATICDEP,
+ * CM_L3INIT_STATICDEP, CM_L4SEC_STATICDEP, CM_MPU_STATICDEP,
+ * CM_SDMA_STATICDEP, CM_SDMA_STATICDEP_RESTORE, CM_TESLA_STATICDEP
  */
 #define OMAP4430_MEMIF_STATDEP_SHIFT                           4
-#define OMAP4430_MEMIF_STATDEP_MASK                            BITFIELD(4, 4)
+#define OMAP4430_MEMIF_STATDEP_MASK                            (1 << 4)
 
 /*
- * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE,
- * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
- * CM_SSC_MODFREQDIV_DPLL_MPU
+ * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
+ * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
+ * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
+ * CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_EXPONENT_SHIFT                     8
-#define OMAP4430_MODFREQDIV_EXPONENT_MASK                      BITFIELD(8, 10)
+#define OMAP4430_MODFREQDIV_EXPONENT_MASK                      (0x7 << 8)
 
 /*
- * Used by CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
- * CM_SSC_MODFREQDIV_DPLL_USB, CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE,
- * CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
- * CM_SSC_MODFREQDIV_DPLL_DDRPHY, CM_SSC_MODFREQDIV_DPLL_IVA,
- * CM_SSC_MODFREQDIV_DPLL_MPU
+ * Used by CM_SSC_MODFREQDIV_DPLL_ABE, CM_SSC_MODFREQDIV_DPLL_CORE,
+ * CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE, CM_SSC_MODFREQDIV_DPLL_DDRPHY,
+ * CM_SSC_MODFREQDIV_DPLL_IVA, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER, CM_SSC_MODFREQDIV_DPLL_UNIPRO,
+ * CM_SSC_MODFREQDIV_DPLL_USB
  */
 #define OMAP4430_MODFREQDIV_MANTISSA_SHIFT                     0
-#define OMAP4430_MODFREQDIV_MANTISSA_MASK                      BITFIELD(0, 6)
-
-/*
- * Used by PRM_PRM_PROFILING_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL,
- * CM_WKUP_KEYBOARD_CLKCTRL, CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL,
- * CM_WKUP_SARRAM_CLKCTRL, CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL,
- * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL,
- * CM_WKUP_WDT2_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_MODEM_ICR_CLKCTRL,
- * CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
- * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL,
- * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL,
- * CM_L3_2_L3_2_CLKCTRL, CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL,
- * CM_L4CFG_L4_CFG_CLKCTRL, CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL,
- * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
- * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
- * CM_MEMIF_EMIF_H2_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4PER_ADC_CLKCTRL, CM_L4PER_DMTIMER10_CLKCTRL,
- * CM_L4PER_DMTIMER11_CLKCTRL, CM_L4PER_DMTIMER2_CLKCTRL,
- * CM_L4PER_DMTIMER3_CLKCTRL, CM_L4PER_DMTIMER4_CLKCTRL,
- * CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL,
- * CM_L4PER_HECC2_CLKCTRL, CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL,
- * CM_L4PER_I2C3_CLKCTRL, CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL,
- * CM_L4PER_L4PER_CLKCTRL, CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL,
- * CM_L4PER_MCBSP4_CLKCTRL, CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL,
- * CM_L4PER_MCSPI3_CLKCTRL, CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL,
- * CM_L4PER_MMCSD3_CLKCTRL, CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL,
- * CM_L4PER_MSPROHG_CLKCTRL, CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL,
- * CM_L4PER_UART2_CLKCTRL, CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL,
- * CM_L4SEC_AES1_CLKCTRL, CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL,
- * CM_L4SEC_DES3DES_CLKCTRL, CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL,
- * CM_L4SEC_SHA2MD51_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+#define OMAP4430_MODFREQDIV_MANTISSA_MASK                      (0x7f << 0)
+
+/*
+ * Used by CM1_ABE_AESS_CLKCTRL, CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL,
+ * CM1_ABE_MCASP_CLKCTRL, CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL,
+ * CM1_ABE_MCBSP3_CLKCTRL, CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL,
+ * CM1_ABE_TIMER5_CLKCTRL, CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL,
+ * CM1_ABE_TIMER8_CLKCTRL, CM1_ABE_WDT3_CLKCTRL, CM_ALWON_MDMINTC_CLKCTRL,
+ * CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL, CM_ALWON_SR_MPU_CLKCTRL,
+ * CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
+ * CM_CM1_PROFILING_CLKCTRL, CM_CM1_PROFILING_CLKCTRL_RESTORE,
+ * CM_CM2_PROFILING_CLKCTRL, CM_CM2_PROFILING_CLKCTRL_RESTORE,
+ * CM_D2D_MODEM_ICR_CLKCTRL, CM_D2D_SAD2D_CLKCTRL, CM_D2D_SAD2D_FW_CLKCTRL,
+ * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_DUCATI_DUCATI_CLKCTRL,
+ * CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL,
+ * CM_IVAHD_SL2_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
  * CM_L3INIT_USBPHYOCP2SCP_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL,
- * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
- * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE,
- * CM_L3INSTR_L3_3_CLKCTRL_RESTORE, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
- * CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
- * CM_ALWON_MDMINTC_CLKCTRL, CM_ALWON_SR_CORE_CLKCTRL, CM_ALWON_SR_IVA_CLKCTRL,
- * CM_ALWON_SR_MPU_CLKCTRL, CM_IVAHD_IVAHD_CLKCTRL, CM_IVAHD_SL2_CLKCTRL,
- * CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL, CM_CM2_PROFILING_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL,
- * CM1_ABE_DMIC_CLKCTRL, CM1_ABE_L4ABE_CLKCTRL, CM1_ABE_MCASP_CLKCTRL,
- * CM1_ABE_MCBSP1_CLKCTRL, CM1_ABE_MCBSP2_CLKCTRL, CM1_ABE_MCBSP3_CLKCTRL,
- * CM1_ABE_PDM_CLKCTRL, CM1_ABE_SLIMBUS_CLKCTRL, CM1_ABE_TIMER5_CLKCTRL,
- * CM1_ABE_TIMER6_CLKCTRL, CM1_ABE_TIMER7_CLKCTRL, CM1_ABE_TIMER8_CLKCTRL,
- * CM1_ABE_WDT3_CLKCTRL, CM_CM1_PROFILING_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_HOST_FS_CLKCTRL,
+ * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
+ * CM_L3INIT_USB_TLL_CLKCTRL_RESTORE, CM_L3INIT_XHPI_CLKCTRL,
+ * CM_L3INSTR_L3_3_CLKCTRL, CM_L3INSTR_L3_3_CLKCTRL_RESTORE,
+ * CM_L3INSTR_L3_INSTR_CLKCTRL, CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE,
+ * CM_L3INSTR_OCP_WP1_CLKCTRL, CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE,
+ * CM_L3_1_L3_1_CLKCTRL, CM_L3_2_GPMC_CLKCTRL, CM_L3_2_L3_2_CLKCTRL,
+ * CM_L3_2_OCMC_RAM_CLKCTRL, CM_L4CFG_HW_SEM_CLKCTRL, CM_L4CFG_L4_CFG_CLKCTRL,
+ * CM_L4CFG_MAILBOX_CLKCTRL, CM_L4CFG_SAR_ROM_CLKCTRL, CM_L4PER_ADC_CLKCTRL,
+ * CM_L4PER_DMTIMER10_CLKCTRL, CM_L4PER_DMTIMER11_CLKCTRL,
+ * CM_L4PER_DMTIMER2_CLKCTRL, CM_L4PER_DMTIMER3_CLKCTRL,
+ * CM_L4PER_DMTIMER4_CLKCTRL, CM_L4PER_DMTIMER9_CLKCTRL, CM_L4PER_ELM_CLKCTRL,
+ * CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE,
+ * CM_L4PER_HDQ1W_CLKCTRL, CM_L4PER_HECC1_CLKCTRL, CM_L4PER_HECC2_CLKCTRL,
+ * CM_L4PER_I2C1_CLKCTRL, CM_L4PER_I2C2_CLKCTRL, CM_L4PER_I2C3_CLKCTRL,
+ * CM_L4PER_I2C4_CLKCTRL, CM_L4PER_I2C5_CLKCTRL, CM_L4PER_L4PER_CLKCTRL,
+ * CM_L4PER_MCASP2_CLKCTRL, CM_L4PER_MCASP3_CLKCTRL, CM_L4PER_MCBSP4_CLKCTRL,
+ * CM_L4PER_MCSPI1_CLKCTRL, CM_L4PER_MCSPI2_CLKCTRL, CM_L4PER_MCSPI3_CLKCTRL,
+ * CM_L4PER_MCSPI4_CLKCTRL, CM_L4PER_MGATE_CLKCTRL, CM_L4PER_MMCSD3_CLKCTRL,
+ * CM_L4PER_MMCSD4_CLKCTRL, CM_L4PER_MMCSD5_CLKCTRL, CM_L4PER_MSPROHG_CLKCTRL,
+ * CM_L4PER_SLIMBUS2_CLKCTRL, CM_L4PER_UART1_CLKCTRL, CM_L4PER_UART2_CLKCTRL,
+ * CM_L4PER_UART3_CLKCTRL, CM_L4PER_UART4_CLKCTRL, CM_L4SEC_AES1_CLKCTRL,
+ * CM_L4SEC_AES2_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L4SEC_DES3DES_CLKCTRL,
+ * CM_L4SEC_PKAEIP29_CLKCTRL, CM_L4SEC_RNG_CLKCTRL, CM_L4SEC_SHA2MD51_CLKCTRL,
+ * CM_MEMIF_DMM_CLKCTRL, CM_MEMIF_EMIF_1_CLKCTRL, CM_MEMIF_EMIF_2_CLKCTRL,
+ * CM_MEMIF_EMIF_FW_CLKCTRL, CM_MEMIF_EMIF_H1_CLKCTRL,
+ * CM_MEMIF_EMIF_H2_CLKCTRL, CM_MPU_MPU_CLKCTRL, CM_SDMA_SDMA_CLKCTRL,
+ * CM_TESLA_TESLA_CLKCTRL, CM_WKUP_GPIO1_CLKCTRL, CM_WKUP_KEYBOARD_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_RTC_CLKCTRL, CM_WKUP_SARRAM_CLKCTRL,
+ * CM_WKUP_SYNCTIMER_CLKCTRL, CM_WKUP_TIMER12_CLKCTRL, CM_WKUP_TIMER1_CLKCTRL,
+ * CM_WKUP_USIM_CLKCTRL, CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WDT2_CLKCTRL
  */
 #define OMAP4430_MODULEMODE_SHIFT                              0
-#define OMAP4430_MODULEMODE_MASK                               BITFIELD(0, 1)
+#define OMAP4430_MODULEMODE_MASK                               (0x3 << 0)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_48MHZ_CLK_SHIFT                     9
-#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK                      BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_48MHZ_CLK_MASK                      (1 << 9)
 
 /* Used by CM_WKUP_BANDGAP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT                      8
-#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK                       BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_BGAP_32K_MASK                       (1 << 8)
 
-/* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */
-#define OMAP4430_OPTFCLKEN_CLK32K_SHIFT                                9
-#define OMAP4430_OPTFCLKEN_CLK32K_MASK                         BITFIELD(9, 9)
+/* Used by CM_ALWON_USBPHY_CLKCTRL */
+#define OMAP4430_OPTFCLKEN_CLK32K_SHIFT                                8
+#define OMAP4430_OPTFCLKEN_CLK32K_MASK                         (1 << 8)
 
 /* Used by CM_CAM_ISS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT                       8
-#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK                                BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_CTRLCLK_MASK                                (1 << 8)
 
 /*
- * Used by CM_WKUP_GPIO1_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL,
- * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL,
- * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO3_CLKCTRL_RESTORE, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
- * CM_L4PER_GPIO5_CLKCTRL_RESTORE, CM_L4PER_GPIO6_CLKCTRL_RESTORE
+ * Used by CM_L4PER_GPIO2_CLKCTRL, CM_L4PER_GPIO2_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO3_CLKCTRL, CM_L4PER_GPIO3_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO4_CLKCTRL, CM_L4PER_GPIO4_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO5_CLKCTRL, CM_L4PER_GPIO5_CLKCTRL_RESTORE,
+ * CM_L4PER_GPIO6_CLKCTRL, CM_L4PER_GPIO6_CLKCTRL_RESTORE, CM_WKUP_GPIO1_CLKCTRL
  */
 #define OMAP4430_OPTFCLKEN_DBCLK_SHIFT                         8
-#define OMAP4430_OPTFCLKEN_DBCLK_MASK                          BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DBCLK_MASK                          (1 << 8)
 
 /* Used by CM_MEMIF_DLL_CLKCTRL, CM_MEMIF_DLL_H_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DLL_CLK_SHIFT                       8
-#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK                                BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DLL_CLK_MASK                                (1 << 8)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_DSSCLK_SHIFT                                8
-#define OMAP4430_OPTFCLKEN_DSSCLK_MASK                         BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_DSSCLK_MASK                         (1 << 8)
+
+/* Used by CM_WKUP_USIM_CLKCTRL */
+#define OMAP4430_OPTFCLKEN_FCLK_SHIFT                          8
+#define OMAP4430_OPTFCLKEN_FCLK_MASK                           (1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK0_SHIFT                         8
-#define OMAP4430_OPTFCLKEN_FCLK0_MASK                          BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_FCLK0_MASK                          (1 << 8)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK1_SHIFT                         9
-#define OMAP4430_OPTFCLKEN_FCLK1_MASK                          BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_FCLK1_MASK                          (1 << 9)
 
 /* Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_FCLK2_SHIFT                         10
-#define OMAP4430_OPTFCLKEN_FCLK2_MASK                          BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_FCLK2_MASK                          (1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_FUNC48MCLK_SHIFT                    15
-#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK                     BITFIELD(15, 15)
+#define OMAP4430_OPTFCLKEN_FUNC48MCLK_MASK                     (1 << 15)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_SHIFT               13
-#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK                        BITFIELD(13, 13)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P1_CLK_MASK                        (1 << 13)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_SHIFT               14
-#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK                        BITFIELD(14, 14)
+#define OMAP4430_OPTFCLKEN_HSIC480M_P2_CLK_MASK                        (1 << 14)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_SHIFT                        11
-#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK                 BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P1_CLK_MASK                 (1 << 11)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_SHIFT                        12
-#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK                 BITFIELD(12, 12)
+#define OMAP4430_OPTFCLKEN_HSIC60M_P2_CLK_MASK                 (1 << 12)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_SHIFT                 8
-#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK                  BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_PER24MC_GFCLK_MASK                  (1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT               9
-#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK                        BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_MASK                        (1 << 9)
 
 /* Used by CM_L3INIT_USBPHYOCP2SCP_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_PHY_48M_SHIFT                       8
-#define OMAP4430_OPTFCLKEN_PHY_48M_MASK                                BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_PHY_48M_MASK                                (1 << 8)
 
 /* Used by CM_L4PER_SLIMBUS2_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT                   10
-#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK                    BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_MASK                    (1 << 10)
 
 /* Renamed from OPTFCLKEN_SLIMBUS_CLK Used by CM1_ABE_SLIMBUS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT             11
-#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK              BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_MASK              (1 << 11)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_SYS_CLK_SHIFT                       10
-#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK                                BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_SYS_CLK_MASK                                (1 << 10)
 
 /* Used by CM_DSS_DSS_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TV_CLK_SHIFT                                11
-#define OMAP4430_OPTFCLKEN_TV_CLK_MASK                         BITFIELD(11, 11)
+#define OMAP4430_OPTFCLKEN_TV_CLK_MASK                         (1 << 11)
 
 /* Used by CM_L3INIT_UNIPRO1_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_TXPHYCLK_SHIFT                      8
-#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK                       BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_TXPHYCLK_MASK                       (1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH0_CLK_SHIFT                   8
-#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK                    BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_USB_CH0_CLK_MASK                    (1 << 8)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH1_CLK_SHIFT                   9
-#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK                    BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_USB_CH1_CLK_MASK                    (1 << 9)
 
 /* Used by CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_USB_CH2_CLK_SHIFT                   10
-#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK                    BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_USB_CH2_CLK_MASK                    (1 << 10)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_SHIFT                   8
-#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK                    BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_UTMI_P1_CLK_MASK                    (1 << 8)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_SHIFT                   9
-#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK                    BITFIELD(9, 9)
+#define OMAP4430_OPTFCLKEN_UTMI_P2_CLK_MASK                    (1 << 9)
 
 /* Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE */
 #define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_SHIFT                   10
-#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK                    BITFIELD(10, 10)
+#define OMAP4430_OPTFCLKEN_UTMI_P3_CLK_MASK                    (1 << 10)
 
 /* Used by CM_L3INIT_USB_OTG_CLKCTRL */
 #define OMAP4430_OPTFCLKEN_XCLK_SHIFT                          8
-#define OMAP4430_OPTFCLKEN_XCLK_MASK                           BITFIELD(8, 8)
+#define OMAP4430_OPTFCLKEN_XCLK_MASK                           (1 << 8)
 
-/* Used by CM_EMU_OVERRIDE_DPLL_PER, CM_EMU_OVERRIDE_DPLL_CORE */
+/* Used by CM_EMU_OVERRIDE_DPLL_CORE */
 #define OMAP4430_OVERRIDE_ENABLE_SHIFT                         19
-#define OMAP4430_OVERRIDE_ENABLE_MASK                          BITFIELD(19, 19)
+#define OMAP4430_OVERRIDE_ENABLE_MASK                          (1 << 19)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_PAD_CLKS_GATE_SHIFT                           8
-#define OMAP4430_PAD_CLKS_GATE_MASK                            BITFIELD(8, 8)
+#define OMAP4430_PAD_CLKS_GATE_MASK                            (1 << 8)
 
 /* Used by CM_CORE_DVFS_CURRENT, CM_IVA_DVFS_CURRENT */
 #define OMAP4430_PERF_CURRENT_SHIFT                            0
-#define OMAP4430_PERF_CURRENT_MASK                             BITFIELD(0, 7)
+#define OMAP4430_PERF_CURRENT_MASK                             (0xff << 0)
 
 /*
  * Used by CM_CORE_DVFS_PERF1, CM_CORE_DVFS_PERF2, CM_CORE_DVFS_PERF3,
  * CM_IVA_DVFS_PERF_TESLA
  */
 #define OMAP4430_PERF_REQ_SHIFT                                        0
-#define OMAP4430_PERF_REQ_MASK                                 BITFIELD(0, 7)
-
-/* Used by CM_EMU_OVERRIDE_DPLL_PER */
-#define OMAP4430_PER_DPLL_EMU_DIV_SHIFT                                0
-#define OMAP4430_PER_DPLL_EMU_DIV_MASK                         BITFIELD(0, 6)
-
-/* Used by CM_EMU_OVERRIDE_DPLL_PER */
-#define OMAP4430_PER_DPLL_EMU_MULT_SHIFT                       8
-#define OMAP4430_PER_DPLL_EMU_MULT_MASK                                BITFIELD(8, 18)
+#define OMAP4430_PERF_REQ_MASK                                 (0xff << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE1_COMPLETED_SHIFT                                0
-#define OMAP4430_PHASE1_COMPLETED_MASK                         BITFIELD(0, 0)
+#define OMAP4430_PHASE1_COMPLETED_MASK                         (1 << 0)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2A_COMPLETED_SHIFT                       1
-#define OMAP4430_PHASE2A_COMPLETED_MASK                                BITFIELD(1, 1)
+#define OMAP4430_PHASE2A_COMPLETED_MASK                                (1 << 1)
 
 /* Used by CM_RESTORE_ST */
 #define OMAP4430_PHASE2B_COMPLETED_SHIFT                       2
-#define OMAP4430_PHASE2B_COMPLETED_MASK                                BITFIELD(2, 2)
+#define OMAP4430_PHASE2B_COMPLETED_MASK                                (1 << 2)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_STM_MUX_CTRL_SHIFT                                20
-#define OMAP4430_PMD_STM_MUX_CTRL_MASK                         BITFIELD(20, 21)
+#define OMAP4430_PMD_STM_MUX_CTRL_MASK                         (0x3 << 20)
 
 /* Used by CM_EMU_DEBUGSS_CLKCTRL */
 #define OMAP4430_PMD_TRACE_MUX_CTRL_SHIFT                      22
-#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK                       BITFIELD(22, 23)
+#define OMAP4430_PMD_TRACE_MUX_CTRL_MASK                       (0x3 << 22)
 
-/* Used by CM_DYN_DEP_PRESCAL */
+/* Used by CM_DYN_DEP_PRESCAL, CM_DYN_DEP_PRESCAL_RESTORE */
 #define OMAP4430_PRESCAL_SHIFT                                 0
-#define OMAP4430_PRESCAL_MASK                                  BITFIELD(0, 5)
+#define OMAP4430_PRESCAL_MASK                                  (0x3f << 0)
 
-/* Used by REVISION_CM2, REVISION_CM1 */
-#define OMAP4430_REV_SHIFT                                     0
-#define OMAP4430_REV_MASK                                      BITFIELD(0, 7)
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_R_RTL_SHIFT                                   11
+#define OMAP4430_R_RTL_MASK                                    (0x1f << 11)
 
 /*
- * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL_RESTORE, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
+ * Used by CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_TLL_CLKCTRL, CM_L3INIT_USB_TLL_CLKCTRL_RESTORE
  */
 #define OMAP4430_SAR_MODE_SHIFT                                        4
-#define OMAP4430_SAR_MODE_MASK                                 BITFIELD(4, 4)
+#define OMAP4430_SAR_MODE_MASK                                 (1 << 4)
 
 /* Used by CM_SCALE_FCLK */
 #define OMAP4430_SCALE_FCLK_SHIFT                              0
-#define OMAP4430_SCALE_FCLK_MASK                               BITFIELD(0, 0)
+#define OMAP4430_SCALE_FCLK_MASK                               (1 << 0)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_SCHEME_SHIFT                                  30
+#define OMAP4430_SCHEME_MASK                                   (0x3 << 30)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_SDMA_DYNDEP_SHIFT                             11
-#define OMAP4430_SDMA_DYNDEP_MASK                              BITFIELD(11, 11)
+#define OMAP4430_SDMA_DYNDEP_MASK                              (1 << 11)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_SDMA_STATDEP_SHIFT                            11
-#define OMAP4430_SDMA_STATDEP_MASK                             BITFIELD(11, 11)
+#define OMAP4430_SDMA_STATDEP_MASK                             (1 << 11)
 
 /* Used by CM_CLKSEL_ABE */
 #define OMAP4430_SLIMBUS_CLK_GATE_SHIFT                                10
-#define OMAP4430_SLIMBUS_CLK_GATE_MASK                         BITFIELD(10, 10)
+#define OMAP4430_SLIMBUS_CLK_GATE_MASK                         (1 << 10)
 
 /*
- * Used by CM_EMU_DEBUGSS_CLKCTRL, CM_D2D_SAD2D_CLKCTRL,
- * CM_DUCATI_DUCATI_CLKCTRL, CM_SDMA_SDMA_CLKCTRL, CM_GFX_GFX_CLKCTRL,
- * CM_L4SEC_CRYPTODMA_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
+ * Used by CM1_ABE_AESS_CLKCTRL, CM_CAM_FDIF_CLKCTRL, CM_CAM_ISS_CLKCTRL,
+ * CM_D2D_SAD2D_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL,
+ * CM_DUCATI_DUCATI_CLKCTRL, CM_EMU_DEBUGSS_CLKCTRL, CM_GFX_GFX_CLKCTRL,
+ * CM_IVAHD_IVAHD_CLKCTRL, CM_L3INIT_CCPTX_CLKCTRL, CM_L3INIT_EMAC_CLKCTRL,
  * CM_L3INIT_HSI_CLKCTRL, CM_L3INIT_MMC1_CLKCTRL, CM_L3INIT_MMC2_CLKCTRL,
  * CM_L3INIT_MMC6_CLKCTRL, CM_L3INIT_P1500_CLKCTRL, CM_L3INIT_PCIESS_CLKCTRL,
  * CM_L3INIT_SATA_CLKCTRL, CM_L3INIT_TPPSS_CLKCTRL, CM_L3INIT_UNIPRO1_CLKCTRL,
- * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_FS_CLKCTRL,
- * CM_L3INIT_USB_OTG_CLKCTRL, CM_L3INIT_XHPI_CLKCTRL, CM_CAM_FDIF_CLKCTRL,
- * CM_CAM_ISS_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
- * CM_IVAHD_IVAHD_CLKCTRL, CM_DSS_DEISS_CLKCTRL, CM_DSS_DSS_CLKCTRL,
- * CM_MPU_MPU_CLKCTRL, CM_TESLA_TESLA_CLKCTRL, CM1_ABE_AESS_CLKCTRL
+ * CM_L3INIT_USB_HOST_CLKCTRL, CM_L3INIT_USB_HOST_CLKCTRL_RESTORE,
+ * CM_L3INIT_USB_HOST_FS_CLKCTRL, CM_L3INIT_USB_OTG_CLKCTRL,
+ * CM_L3INIT_XHPI_CLKCTRL, CM_L4SEC_CRYPTODMA_CLKCTRL, CM_MPU_MPU_CLKCTRL,
+ * CM_SDMA_SDMA_CLKCTRL, CM_TESLA_TESLA_CLKCTRL
  */
 #define OMAP4430_STBYST_SHIFT                                  18
-#define OMAP4430_STBYST_MASK                                   BITFIELD(18, 18)
+#define OMAP4430_STBYST_MASK                                   (1 << 18)
 
 /*
- * Used by CM_IDLEST_DPLL_PER, CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB,
- * CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
- * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU
+ * Used by CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
+ * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER,
+ * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLK_SHIFT                             0
-#define OMAP4430_ST_DPLL_CLK_MASK                              BITFIELD(0, 0)
+#define OMAP4430_ST_DPLL_CLK_MASK                              (1 << 0)
 
 /* Used by CM_CLKDCOLDO_DPLL_USB */
 #define OMAP4430_ST_DPLL_CLKDCOLDO_SHIFT                       9
-#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK                                BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKDCOLDO_MASK                                (1 << 9)
 
 /*
- * Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB, CM_DIV_M2_DPLL_CORE_RESTORE,
- * CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE, CM_DIV_M2_DPLL_DDRPHY,
- * CM_DIV_M2_DPLL_MPU
+ * Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_CORE,
+ * CM_DIV_M2_DPLL_CORE_RESTORE, CM_DIV_M2_DPLL_DDRPHY, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_USB
  */
 #define OMAP4430_ST_DPLL_CLKOUT_SHIFT                          9
-#define OMAP4430_ST_DPLL_CLKOUT_MASK                           BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKOUT_MASK                           (1 << 9)
 
 /*
- * Used by CM_DIV_M3_DPLL_PER, CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_ABE,
- * CM_DIV_M3_DPLL_CORE
+ * Used by CM_DIV_M3_DPLL_ABE, CM_DIV_M3_DPLL_CORE,
+ * CM_DIV_M3_DPLL_CORE_RESTORE, CM_DIV_M3_DPLL_PER
  */
 #define OMAP4430_ST_DPLL_CLKOUTHIF_SHIFT                       9
-#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK                                BITFIELD(9, 9)
+#define OMAP4430_ST_DPLL_CLKOUTHIF_MASK                                (1 << 9)
 
-/* Used by CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO, CM_DIV_M2_DPLL_ABE */
+/* Used by CM_DIV_M2_DPLL_ABE, CM_DIV_M2_DPLL_PER, CM_DIV_M2_DPLL_UNIPRO */
 #define OMAP4430_ST_DPLL_CLKOUTX2_SHIFT                                11
-#define OMAP4430_ST_DPLL_CLKOUTX2_MASK                         BITFIELD(11, 11)
+#define OMAP4430_ST_DPLL_CLKOUTX2_MASK                         (1 << 11)
 
 /*
- * Used by CM_DIV_M4_DPLL_PER, CM_DIV_M4_DPLL_CORE_RESTORE,
- * CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA
+ * Used by CM_DIV_M4_DPLL_CORE, CM_DIV_M4_DPLL_CORE_RESTORE,
+ * CM_DIV_M4_DPLL_DDRPHY, CM_DIV_M4_DPLL_IVA, CM_DIV_M4_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT1_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT1_MASK                     (1 << 9)
 
 /*
- * Used by CM_DIV_M5_DPLL_PER, CM_DIV_M5_DPLL_CORE_RESTORE,
- * CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA
+ * Used by CM_DIV_M5_DPLL_CORE, CM_DIV_M5_DPLL_CORE_RESTORE,
+ * CM_DIV_M5_DPLL_DDRPHY, CM_DIV_M5_DPLL_IVA, CM_DIV_M5_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT2_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT2_MASK                     (1 << 9)
 
 /*
- * Used by CM_DIV_M6_DPLL_PER, CM_DIV_M6_DPLL_CORE_RESTORE,
- * CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_DDRPHY
+ * Used by CM_DIV_M6_DPLL_CORE, CM_DIV_M6_DPLL_CORE_RESTORE,
+ * CM_DIV_M6_DPLL_DDRPHY, CM_DIV_M6_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT3_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT3_MASK                     (1 << 9)
 
 /*
- * Used by CM_DIV_M7_DPLL_PER, CM_DIV_M7_DPLL_CORE_RESTORE,
- * CM_DIV_M7_DPLL_CORE
+ * Used by CM_DIV_M7_DPLL_CORE, CM_DIV_M7_DPLL_CORE_RESTORE,
+ * CM_DIV_M7_DPLL_PER
  */
 #define OMAP4430_ST_HSDIVIDER_CLKOUT4_SHIFT                    9
-#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK                     BITFIELD(9, 9)
+#define OMAP4430_ST_HSDIVIDER_CLKOUT4_MASK                     (1 << 9)
+
+/*
+ * Used by CM_IDLEST_DPLL_ABE, CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDRPHY,
+ * CM_IDLEST_DPLL_IVA, CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER,
+ * CM_IDLEST_DPLL_UNIPRO, CM_IDLEST_DPLL_USB
+ */
+#define OMAP4430_ST_MN_BYPASS_SHIFT                            8
+#define OMAP4430_ST_MN_BYPASS_MASK                             (1 << 8)
 
 /* Used by CM_SYS_CLKSEL */
 #define OMAP4430_SYS_CLKSEL_SHIFT                              0
-#define OMAP4430_SYS_CLKSEL_MASK                               BITFIELD(0, 2)
+#define OMAP4430_SYS_CLKSEL_MASK                               (0x7 << 0)
 
-/* Used by CM_L4CFG_DYNAMICDEP */
+/* Used by CM_L4CFG_DYNAMICDEP, CM_L4CFG_DYNAMICDEP_RESTORE */
 #define OMAP4430_TESLA_DYNDEP_SHIFT                            1
-#define OMAP4430_TESLA_DYNDEP_MASK                             BITFIELD(1, 1)
+#define OMAP4430_TESLA_DYNDEP_MASK                             (1 << 1)
 
 /* Used by CM_DUCATI_STATICDEP, CM_MPU_STATICDEP */
 #define OMAP4430_TESLA_STATDEP_SHIFT                           1
-#define OMAP4430_TESLA_STATDEP_MASK                            BITFIELD(1, 1)
+#define OMAP4430_TESLA_STATDEP_MASK                            (1 << 1)
 
 /*
- * Used by CM_EMU_DYNAMICDEP, CM_D2D_DYNAMICDEP, CM_DUCATI_DYNAMICDEP,
- * CM_L3_1_DYNAMICDEP, CM_L3_2_DYNAMICDEP, CM_L4CFG_DYNAMICDEP,
- * CM_L4PER_DYNAMICDEP, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
+ * Used by CM_D2D_DYNAMICDEP, CM_D2D_DYNAMICDEP_RESTORE, CM_DUCATI_DYNAMICDEP,
+ * CM_EMU_DYNAMICDEP, CM_L3_1_DYNAMICDEP, CM_L3_1_DYNAMICDEP_RESTORE,
+ * CM_L3_2_DYNAMICDEP, CM_L3_2_DYNAMICDEP_RESTORE, CM_L4CFG_DYNAMICDEP,
+ * CM_L4CFG_DYNAMICDEP_RESTORE, CM_L4PER_DYNAMICDEP,
+ * CM_L4PER_DYNAMICDEP_RESTORE, CM_MPU_DYNAMICDEP, CM_TESLA_DYNAMICDEP
  */
 #define OMAP4430_WINDOWSIZE_SHIFT                              24
-#define OMAP4430_WINDOWSIZE_MASK                               BITFIELD(24, 27)
+#define OMAP4430_WINDOWSIZE_MASK                               (0xf << 24)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_X_MAJOR_SHIFT                                 8
+#define OMAP4430_X_MAJOR_MASK                                  (0x7 << 8)
+
+/* Used by REVISION_CM1, REVISION_CM2 */
+#define OMAP4430_Y_MINOR_SHIFT                                 0
+#define OMAP4430_Y_MINOR_MASK                                  (0x3f << 0)
 #endif
index 336d948..3c35a87 100644 (file)
 #define OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET              0x0088
 #define OMAP4430_CM1_ABE_WDT3_CLKCTRL                  OMAP44XX_CM1_REGADDR(OMAP4430_CM1_ABE_MOD, 0x0088)
 
+/* CM1.RESTORE_CM1 register offsets */
+#define OMAP4_CM_CLKSEL_CORE_RESTORE_OFFSET            0x0000
+#define OMAP4430_CM_CLKSEL_CORE_RESTORE                        OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0000)
+#define OMAP4_CM_DIV_M2_DPLL_CORE_RESTORE_OFFSET       0x0004
+#define OMAP4430_CM_DIV_M2_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0004)
+#define OMAP4_CM_DIV_M3_DPLL_CORE_RESTORE_OFFSET       0x0008
+#define OMAP4430_CM_DIV_M3_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0008)
+#define OMAP4_CM_DIV_M4_DPLL_CORE_RESTORE_OFFSET       0x000c
+#define OMAP4430_CM_DIV_M4_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x000c)
+#define OMAP4_CM_DIV_M5_DPLL_CORE_RESTORE_OFFSET       0x0010
+#define OMAP4430_CM_DIV_M5_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0010)
+#define OMAP4_CM_DIV_M6_DPLL_CORE_RESTORE_OFFSET       0x0014
+#define OMAP4430_CM_DIV_M6_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0014)
+#define OMAP4_CM_DIV_M7_DPLL_CORE_RESTORE_OFFSET       0x0018
+#define OMAP4430_CM_DIV_M7_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0018)
+#define OMAP4_CM_CLKSEL_DPLL_CORE_RESTORE_OFFSET       0x001c
+#define OMAP4430_CM_CLKSEL_DPLL_CORE_RESTORE           OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x001c)
+#define OMAP4_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE_OFFSET       0x0020
+#define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_CORE_RESTORE   OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0020)
+#define OMAP4_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE_OFFSET       0x0024
+#define OMAP4430_CM_SSC_MODFREQDIV_DPLL_CORE_RESTORE   OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0024)
+#define OMAP4_CM_CLKMODE_DPLL_CORE_RESTORE_OFFSET      0x0028
+#define OMAP4430_CM_CLKMODE_DPLL_CORE_RESTORE          OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0028)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG2_RESTORE_OFFSET    0x002c
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG2_RESTORE                OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x002c)
+#define OMAP4_CM_SHADOW_FREQ_CONFIG1_RESTORE_OFFSET    0x0030
+#define OMAP4430_CM_SHADOW_FREQ_CONFIG1_RESTORE                OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0030)
+#define OMAP4_CM_AUTOIDLE_DPLL_CORE_RESTORE_OFFSET     0x0034
+#define OMAP4430_CM_AUTOIDLE_DPLL_CORE_RESTORE         OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0034)
+#define OMAP4_CM_MPU_CLKSTCTRL_RESTORE_OFFSET          0x0038
+#define OMAP4430_CM_MPU_CLKSTCTRL_RESTORE              OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0038)
+#define OMAP4_CM_CM1_PROFILING_CLKCTRL_RESTORE_OFFSET  0x003c
+#define OMAP4430_CM_CM1_PROFILING_CLKCTRL_RESTORE      OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x003c)
+#define OMAP4_CM_DYN_DEP_PRESCAL_RESTORE_OFFSET                0x0040
+#define OMAP4430_CM_DYN_DEP_PRESCAL_RESTORE            OMAP44XX_CM1_REGADDR(OMAP4430_CM1_RESTORE_MOD, 0x0040)
+
 /* CM2 */
 
 /* CM2.OCP_SOCKET_CM2 register offsets */
 #define OMAP4430_CM_SSC_DELTAMSTEP_DPLL_PER            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0068)
 #define OMAP4_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET                0x006c
 #define OMAP4430_CM_SSC_MODFREQDIV_DPLL_PER            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x006c)
-#define OMAP4_CM_EMU_OVERRIDE_DPLL_PER_OFFSET          0x0070
-#define OMAP4430_CM_EMU_OVERRIDE_DPLL_PER              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0070)
 #define OMAP4_CM_CLKMODE_DPLL_USB_OFFSET               0x0080
 #define OMAP4430_CM_CLKMODE_DPLL_USB                   OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CKGEN_MOD, 0x0080)
 #define OMAP4_CM_IDLEST_DPLL_USB_OFFSET                        0x0084
 #define OMAP4430_CM_ALWON_SR_IVA_CLKCTRL               OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0030)
 #define OMAP4_CM_ALWON_SR_CORE_CLKCTRL_OFFSET          0x0038
 #define OMAP4430_CM_ALWON_SR_CORE_CLKCTRL              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0038)
+#define OMAP4_CM_ALWON_USBPHY_CLKCTRL_OFFSET           0x0040
+#define OMAP4430_CM_ALWON_USBPHY_CLKCTRL               OMAP44XX_CM2_REGADDR(OMAP4430_CM2_ALWAYS_ON_MOD, 0x0040)
 
 /* CM2.CORE_CM2 register offsets */
 #define OMAP4_CM_L3_1_CLKSTCTRL_OFFSET                 0x0000
 #define OMAP4430_CM_CEFUSE_CLKSTCTRL                   OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0000)
 #define OMAP4_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET          0x0020
 #define OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_CEFUSE_MOD, 0x0020)
+
+/* CM2.RESTORE_CM2 register offsets */
+#define OMAP4_CM_L3_1_CLKSTCTRL_RESTORE_OFFSET         0x0000
+#define OMAP4430_CM_L3_1_CLKSTCTRL_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0000)
+#define OMAP4_CM_L3_2_CLKSTCTRL_RESTORE_OFFSET         0x0004
+#define OMAP4430_CM_L3_2_CLKSTCTRL_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0004)
+#define OMAP4_CM_L4CFG_CLKSTCTRL_RESTORE_OFFSET                0x0008
+#define OMAP4430_CM_L4CFG_CLKSTCTRL_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0008)
+#define OMAP4_CM_MEMIF_CLKSTCTRL_RESTORE_OFFSET                0x000c
+#define OMAP4430_CM_MEMIF_CLKSTCTRL_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x000c)
+#define OMAP4_CM_L4PER_CLKSTCTRL_RESTORE_OFFSET                0x0010
+#define OMAP4430_CM_L4PER_CLKSTCTRL_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0010)
+#define OMAP4_CM_L3INIT_CLKSTCTRL_RESTORE_OFFSET       0x0014
+#define OMAP4430_CM_L3INIT_CLKSTCTRL_RESTORE           OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0014)
+#define OMAP4_CM_L3INSTR_L3_3_CLKCTRL_RESTORE_OFFSET   0x0018
+#define OMAP4430_CM_L3INSTR_L3_3_CLKCTRL_RESTORE       OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0018)
+#define OMAP4_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE_OFFSET       0x001c
+#define OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL_RESTORE   OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x001c)
+#define OMAP4_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE_OFFSET        0x0020
+#define OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL_RESTORE    OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0020)
+#define OMAP4_CM_CM2_PROFILING_CLKCTRL_RESTORE_OFFSET  0x0024
+#define OMAP4430_CM_CM2_PROFILING_CLKCTRL_RESTORE      OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0024)
+#define OMAP4_CM_D2D_STATICDEP_RESTORE_OFFSET          0x0028
+#define OMAP4430_CM_D2D_STATICDEP_RESTORE              OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0028)
+#define OMAP4_CM_L3_1_DYNAMICDEP_RESTORE_OFFSET                0x002c
+#define OMAP4430_CM_L3_1_DYNAMICDEP_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x002c)
+#define OMAP4_CM_L3_2_DYNAMICDEP_RESTORE_OFFSET                0x0030
+#define OMAP4430_CM_L3_2_DYNAMICDEP_RESTORE            OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0030)
+#define OMAP4_CM_D2D_DYNAMICDEP_RESTORE_OFFSET         0x0034
+#define OMAP4430_CM_D2D_DYNAMICDEP_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0034)
+#define OMAP4_CM_L4CFG_DYNAMICDEP_RESTORE_OFFSET       0x0038
+#define OMAP4430_CM_L4CFG_DYNAMICDEP_RESTORE           OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0038)
+#define OMAP4_CM_L4PER_DYNAMICDEP_RESTORE_OFFSET       0x003c
+#define OMAP4430_CM_L4PER_DYNAMICDEP_RESTORE           OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x003c)
+#define OMAP4_CM_L4PER_GPIO2_CLKCTRL_RESTORE_OFFSET    0x0040
+#define OMAP4430_CM_L4PER_GPIO2_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0040)
+#define OMAP4_CM_L4PER_GPIO3_CLKCTRL_RESTORE_OFFSET    0x0044
+#define OMAP4430_CM_L4PER_GPIO3_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0044)
+#define OMAP4_CM_L4PER_GPIO4_CLKCTRL_RESTORE_OFFSET    0x0048
+#define OMAP4430_CM_L4PER_GPIO4_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0048)
+#define OMAP4_CM_L4PER_GPIO5_CLKCTRL_RESTORE_OFFSET    0x004c
+#define OMAP4430_CM_L4PER_GPIO5_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x004c)
+#define OMAP4_CM_L4PER_GPIO6_CLKCTRL_RESTORE_OFFSET    0x0050
+#define OMAP4430_CM_L4PER_GPIO6_CLKCTRL_RESTORE                OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0050)
+#define OMAP4_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE_OFFSET        0x0054
+#define OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL_RESTORE    OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0054)
+#define OMAP4_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE_OFFSET 0x0058
+#define OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL_RESTORE     OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x0058)
+#define OMAP4_CM_SDMA_STATICDEP_RESTORE_OFFSET         0x005c
+#define OMAP4430_CM_SDMA_STATICDEP_RESTORE             OMAP44XX_CM2_REGADDR(OMAP4430_CM2_RESTORE_MOD, 0x005c)
 #endif
index b101091..f8a660a 100644 (file)
@@ -43,7 +43,6 @@
  *                 using separate functional clock
  *   0x3 disabled: Module is disabled and cannot be accessed
  *
- * TODO: Need to handle module accessible in idle state
  */
 int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
 {
@@ -52,9 +51,11 @@ int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg)
        if (!clkctrl_reg)
                return 0;
 
-       omap_test_timeout(((__raw_readl(clkctrl_reg) &
-                           OMAP4430_IDLEST_MASK) == 0),
-                         MAX_MODULE_READY_TIME, i);
+       omap_test_timeout((
+               ((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) == 0) ||
+                (((__raw_readl(clkctrl_reg) & OMAP4430_IDLEST_MASK) >>
+                 OMAP4430_IDLEST_SHIFT) == 0x2)),
+               MAX_MODULE_READY_TIME, i);
 
        return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
 }
diff --git a/arch/arm/mach-omap2/common.c b/arch/arm/mach-omap2/common.c
new file mode 100644 (file)
index 0000000..778929f
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * linux/arch/arm/mach-omap2/common.c
+ *
+ * Code common to all OMAP2+ machines.
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2010 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+#include <plat/board.h>
+#include <plat/mux.h>
+
+#include <plat/clock.h>
+
+#include "sdrc.h"
+#include "control.h"
+
+/* Global address base setup code */
+
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+
+static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
+{
+       omap2_set_globals_tap(omap2_globals);
+       omap2_set_globals_sdrc(omap2_globals);
+       omap2_set_globals_control(omap2_globals);
+       omap2_set_globals_prcm(omap2_globals);
+}
+
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2420)
+
+static struct omap_globals omap242x_globals = {
+       .class  = OMAP242X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x48014000),
+       .sdrc   = OMAP2420_SDRC_BASE,
+       .sms    = OMAP2420_SMS_BASE,
+       .ctrl   = OMAP242X_CTRL_BASE,
+       .prm    = OMAP2420_PRM_BASE,
+       .cm     = OMAP2420_CM_BASE,
+       .uart1_phys     = OMAP2_UART1_BASE,
+       .uart2_phys     = OMAP2_UART2_BASE,
+       .uart3_phys     = OMAP2_UART3_BASE,
+};
+
+void __init omap2_set_globals_242x(void)
+{
+       __omap2_set_globals(&omap242x_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2430)
+
+static struct omap_globals omap243x_globals = {
+       .class  = OMAP243X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x4900a000),
+       .sdrc   = OMAP243X_SDRC_BASE,
+       .sms    = OMAP243X_SMS_BASE,
+       .ctrl   = OMAP243X_CTRL_BASE,
+       .prm    = OMAP2430_PRM_BASE,
+       .cm     = OMAP2430_CM_BASE,
+       .uart1_phys     = OMAP2_UART1_BASE,
+       .uart2_phys     = OMAP2_UART2_BASE,
+       .uart3_phys     = OMAP2_UART3_BASE,
+};
+
+void __init omap2_set_globals_243x(void)
+{
+       __omap2_set_globals(&omap243x_globals);
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP3)
+
+static struct omap_globals omap3_globals = {
+       .class  = OMAP343X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(0x4830A000),
+       .sdrc   = OMAP343X_SDRC_BASE,
+       .sms    = OMAP343X_SMS_BASE,
+       .ctrl   = OMAP343X_CTRL_BASE,
+       .prm    = OMAP3430_PRM_BASE,
+       .cm     = OMAP3430_CM_BASE,
+       .uart1_phys     = OMAP3_UART1_BASE,
+       .uart2_phys     = OMAP3_UART2_BASE,
+       .uart3_phys     = OMAP3_UART3_BASE,
+       .uart4_phys     = OMAP3_UART4_BASE,     /* Only on 3630 */
+};
+
+void __init omap2_set_globals_3xxx(void)
+{
+       __omap2_set_globals(&omap3_globals);
+}
+
+void __init omap3_map_io(void)
+{
+       omap2_set_globals_3xxx();
+       omap34xx_map_common_io();
+}
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4)
+static struct omap_globals omap4_globals = {
+       .class  = OMAP443X_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
+       .ctrl   = OMAP443X_SCM_BASE,
+       .ctrl_pad       = OMAP443X_CTRL_BASE,
+       .prm    = OMAP4430_PRM_BASE,
+       .cm     = OMAP4430_CM_BASE,
+       .cm2    = OMAP4430_CM2_BASE,
+       .uart1_phys     = OMAP4_UART1_BASE,
+       .uart2_phys     = OMAP4_UART2_BASE,
+       .uart3_phys     = OMAP4_UART3_BASE,
+       .uart4_phys     = OMAP4_UART4_BASE,
+};
+
+void __init omap2_set_globals_443x(void)
+{
+       omap2_set_globals_tap(&omap4_globals);
+       omap2_set_globals_control(&omap4_globals);
+       omap2_set_globals_prcm(&omap4_globals);
+}
+#endif
+
index a8d20ee..1fa3294 100644 (file)
 #include <linux/io.h>
 
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/sdrc.h>
+
 #include "cm-regbits-34xx.h"
 #include "prm-regbits-34xx.h"
 #include "cm.h"
 #include "prm.h"
 #include "sdrc.h"
+#include "pm.h"
+#include "control.h"
 
 static void __iomem *omap2_ctrl_base;
+static void __iomem *omap4_ctrl_pad_base;
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 struct omap3_scratchpad {
@@ -137,6 +140,7 @@ static struct omap3_control_regs control_context;
 #endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
 
 #define OMAP_CTRL_REGADDR(reg)         (omap2_ctrl_base + (reg))
+#define OMAP4_CTRL_PAD_REGADDR(reg)    (omap4_ctrl_pad_base + (reg))
 
 void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
 {
@@ -145,6 +149,12 @@ void __init omap2_set_globals_control(struct omap_globals *omap2_globals)
                omap2_ctrl_base = ioremap(omap2_globals->ctrl, SZ_4K);
                WARN_ON(!omap2_ctrl_base);
        }
+
+       /* Static mapping, never released */
+       if (omap2_globals->ctrl_pad) {
+               omap4_ctrl_pad_base = ioremap(omap2_globals->ctrl_pad, SZ_4K);
+               WARN_ON(!omap4_ctrl_pad_base);
+       }
 }
 
 void __iomem *omap_ctrl_base_get(void)
@@ -182,6 +192,23 @@ void omap_ctrl_writel(u32 val, u16 offset)
        __raw_writel(val, OMAP_CTRL_REGADDR(offset));
 }
 
+/*
+ * On OMAP4 control pad are not addressable from control
+ * core base. So the common omap_ctrl_read/write APIs breaks
+ * Hence export separate APIs to manage the omap4 pad control
+ * registers. This APIs will work only for OMAP4
+ */
+
+u32 omap4_ctrl_pad_readl(u16 offset)
+{
+       return __raw_readl(OMAP4_CTRL_PAD_REGADDR(offset));
+}
+
+void omap4_ctrl_pad_writel(u32 val, u16 offset)
+{
+       __raw_writel(val, OMAP4_CTRL_PAD_REGADDR(offset));
+}
+
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 /*
  * Clears the scratchpad contents in case of cold boot-
@@ -190,7 +217,7 @@ void omap_ctrl_writel(u32 val, u16 offset)
 void omap3_clear_scratchpad_contents(void)
 {
        u32 max_offset = OMAP343X_SCRATCHPAD_ROM_OFFSET;
-       u32 *v_addr;
+       void __iomem *v_addr;
        u32 offset = 0;
        v_addr = OMAP2_L4_IO_ADDRESS(OMAP343X_SCRATCHPAD_ROM);
        if (prm_read_mod_reg(OMAP3430_GR_MOD, OMAP3_PRM_RSTST_OFFSET) &
@@ -206,7 +233,7 @@ void omap3_clear_scratchpad_contents(void)
 /* Populate the scratchpad structure with restore structure */
 void omap3_save_scratchpad_contents(void)
 {
-       void * __iomem scratchpad_address;
+       void  __iomem *scratchpad_address;
        u32 arm_context_addr;
        struct omap3_scratchpad scratchpad_contents;
        struct omap3_scratchpad_prcm_block prcm_block_contents;
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
new file mode 100644 (file)
index 0000000..b6c6b7c
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * arch/arm/mach-omap2/control.h
+ *
+ * OMAP2/3/4 System Control Module definitions
+ *
+ * Copyright (C) 2007-2010 Texas Instruments, Inc.
+ * Copyright (C) 2007-2008, 2010 Nokia Corporation
+ *
+ * Written by Paul Walmsley
+ *
+ * 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.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CONTROL_H
+#define __ARCH_ARM_MACH_OMAP2_CONTROL_H
+
+#include <mach/io.h>
+#include <mach/ctrl_module_core_44xx.h>
+#include <mach/ctrl_module_wkup_44xx.h>
+#include <mach/ctrl_module_pad_core_44xx.h>
+#include <mach/ctrl_module_pad_wkup_44xx.h>
+
+#ifndef __ASSEMBLY__
+#define OMAP242X_CTRL_REGADDR(reg)                                     \
+               OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
+#define OMAP243X_CTRL_REGADDR(reg)                                     \
+               OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
+#define OMAP343X_CTRL_REGADDR(reg)                                     \
+               OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+#else
+#define OMAP242X_CTRL_REGADDR(reg)                                     \
+               OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
+#define OMAP243X_CTRL_REGADDR(reg)                                     \
+               OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
+#define OMAP343X_CTRL_REGADDR(reg)                                     \
+               OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+#endif /* __ASSEMBLY__ */
+
+/*
+ * As elsewhere, the "OMAP2_" prefix indicates that the macro is valid for
+ * OMAP24XX and OMAP34XX.
+ */
+
+/* Control submodule offsets */
+
+#define OMAP2_CONTROL_INTERFACE                0x000
+#define OMAP2_CONTROL_PADCONFS         0x030
+#define OMAP2_CONTROL_GENERAL          0x270
+#define OMAP343X_CONTROL_MEM_WKUP      0x600
+#define OMAP343X_CONTROL_PADCONFS_WKUP 0xa00
+#define OMAP343X_CONTROL_GENERAL_WKUP  0xa60
+
+/* Control register offsets - read/write with omap_ctrl_{read,write}{bwl}() */
+
+#define OMAP2_CONTROL_SYSCONFIG                (OMAP2_CONTROL_INTERFACE + 0x10)
+
+/* CONTROL_GENERAL register offsets common to OMAP2 & 3 */
+#define OMAP2_CONTROL_DEVCONF0         (OMAP2_CONTROL_GENERAL + 0x0004)
+#define OMAP2_CONTROL_MSUSPENDMUX_0    (OMAP2_CONTROL_GENERAL + 0x0020)
+#define OMAP2_CONTROL_MSUSPENDMUX_1    (OMAP2_CONTROL_GENERAL + 0x0024)
+#define OMAP2_CONTROL_MSUSPENDMUX_2    (OMAP2_CONTROL_GENERAL + 0x0028)
+#define OMAP2_CONTROL_MSUSPENDMUX_3    (OMAP2_CONTROL_GENERAL + 0x002c)
+#define OMAP2_CONTROL_MSUSPENDMUX_4    (OMAP2_CONTROL_GENERAL + 0x0030)
+#define OMAP2_CONTROL_MSUSPENDMUX_5    (OMAP2_CONTROL_GENERAL + 0x0034)
+#define OMAP2_CONTROL_SEC_CTRL         (OMAP2_CONTROL_GENERAL + 0x0040)
+#define OMAP2_CONTROL_RPUB_KEY_H_0     (OMAP2_CONTROL_GENERAL + 0x0090)
+#define OMAP2_CONTROL_RPUB_KEY_H_1     (OMAP2_CONTROL_GENERAL + 0x0094)
+#define OMAP2_CONTROL_RPUB_KEY_H_2     (OMAP2_CONTROL_GENERAL + 0x0098)
+#define OMAP2_CONTROL_RPUB_KEY_H_3     (OMAP2_CONTROL_GENERAL + 0x009c)
+
+/* 242x-only CONTROL_GENERAL register offsets */
+#define OMAP242X_CONTROL_DEVCONF       OMAP2_CONTROL_DEVCONF0 /* match TRM */
+#define OMAP242X_CONTROL_OCM_RAM_PERM  (OMAP2_CONTROL_GENERAL + 0x0068)
+
+/* 243x-only CONTROL_GENERAL register offsets */
+/* CONTROL_IVA2_BOOT{ADDR,MOD} are at the same place on 343x - noted below */
+#define OMAP243X_CONTROL_DEVCONF1      (OMAP2_CONTROL_GENERAL + 0x0078)
+#define OMAP243X_CONTROL_CSIRXFE       (OMAP2_CONTROL_GENERAL + 0x007c)
+#define OMAP243X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
+#define OMAP243X_CONTROL_IVA2_BOOTMOD  (OMAP2_CONTROL_GENERAL + 0x0194)
+#define OMAP243X_CONTROL_IVA2_GEMCFG   (OMAP2_CONTROL_GENERAL + 0x0198)
+#define OMAP243X_CONTROL_PBIAS_LITE    (OMAP2_CONTROL_GENERAL + 0x0230)
+
+/* 24xx-only CONTROL_GENERAL register offsets */
+#define OMAP24XX_CONTROL_DEBOBS                (OMAP2_CONTROL_GENERAL + 0x0000)
+#define OMAP24XX_CONTROL_EMU_SUPPORT   (OMAP2_CONTROL_GENERAL + 0x0008)
+#define OMAP24XX_CONTROL_SEC_TEST      (OMAP2_CONTROL_GENERAL + 0x0044)
+#define OMAP24XX_CONTROL_PSA_CTRL      (OMAP2_CONTROL_GENERAL + 0x0048)
+#define OMAP24XX_CONTROL_PSA_CMD       (OMAP2_CONTROL_GENERAL + 0x004c)
+#define OMAP24XX_CONTROL_PSA_VALUE     (OMAP2_CONTROL_GENERAL + 0x0050)
+#define OMAP24XX_CONTROL_SEC_EMU       (OMAP2_CONTROL_GENERAL + 0x0060)
+#define OMAP24XX_CONTROL_SEC_TAP       (OMAP2_CONTROL_GENERAL + 0x0064)
+#define OMAP24XX_CONTROL_OCM_PUB_RAM_ADD       (OMAP2_CONTROL_GENERAL + 0x006c)
+#define OMAP24XX_CONTROL_EXT_SEC_RAM_START_ADD (OMAP2_CONTROL_GENERAL + 0x0070)
+#define OMAP24XX_CONTROL_EXT_SEC_RAM_STOP_ADD  (OMAP2_CONTROL_GENERAL + 0x0074)
+#define OMAP24XX_CONTROL_SEC_STATUS            (OMAP2_CONTROL_GENERAL + 0x0080)
+#define OMAP24XX_CONTROL_SEC_ERR_STATUS                (OMAP2_CONTROL_GENERAL + 0x0084)
+#define OMAP24XX_CONTROL_STATUS                        (OMAP2_CONTROL_GENERAL + 0x0088)
+#define OMAP24XX_CONTROL_GENERAL_PURPOSE_STATUS        (OMAP2_CONTROL_GENERAL + 0x008c)
+#define OMAP24XX_CONTROL_RAND_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00a0)
+#define OMAP24XX_CONTROL_RAND_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00a4)
+#define OMAP24XX_CONTROL_RAND_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00a8)
+#define OMAP24XX_CONTROL_RAND_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00ac)
+#define OMAP24XX_CONTROL_CUST_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00b0)
+#define OMAP24XX_CONTROL_CUST_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00b4)
+#define OMAP24XX_CONTROL_TEST_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00c0)
+#define OMAP24XX_CONTROL_TEST_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00c4)
+#define OMAP24XX_CONTROL_TEST_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00c8)
+#define OMAP24XX_CONTROL_TEST_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00cc)
+#define OMAP24XX_CONTROL_TEST_KEY_4    (OMAP2_CONTROL_GENERAL + 0x00d0)
+#define OMAP24XX_CONTROL_TEST_KEY_5    (OMAP2_CONTROL_GENERAL + 0x00d4)
+#define OMAP24XX_CONTROL_TEST_KEY_6    (OMAP2_CONTROL_GENERAL + 0x00d8)
+#define OMAP24XX_CONTROL_TEST_KEY_7    (OMAP2_CONTROL_GENERAL + 0x00dc)
+#define OMAP24XX_CONTROL_TEST_KEY_8    (OMAP2_CONTROL_GENERAL + 0x00e0)
+#define OMAP24XX_CONTROL_TEST_KEY_9    (OMAP2_CONTROL_GENERAL + 0x00e4)
+
+#define OMAP343X_CONTROL_PADCONF_SYSNIRQ (OMAP2_CONTROL_INTERFACE + 0x01b0)
+
+/* 34xx-only CONTROL_GENERAL register offsets */
+#define OMAP343X_CONTROL_PADCONF_OFF   (OMAP2_CONTROL_GENERAL + 0x0000)
+#define OMAP343X_CONTROL_MEM_DFTRW0    (OMAP2_CONTROL_GENERAL + 0x0008)
+#define OMAP343X_CONTROL_MEM_DFTRW1    (OMAP2_CONTROL_GENERAL + 0x000c)
+#define OMAP343X_CONTROL_DEVCONF1      (OMAP2_CONTROL_GENERAL + 0x0068)
+#define OMAP343X_CONTROL_CSIRXFE               (OMAP2_CONTROL_GENERAL + 0x006c)
+#define OMAP343X_CONTROL_SEC_STATUS            (OMAP2_CONTROL_GENERAL + 0x0070)
+#define OMAP343X_CONTROL_SEC_ERR_STATUS                (OMAP2_CONTROL_GENERAL + 0x0074)
+#define OMAP343X_CONTROL_SEC_ERR_STATUS_DEBUG  (OMAP2_CONTROL_GENERAL + 0x0078)
+#define OMAP343X_CONTROL_STATUS                        (OMAP2_CONTROL_GENERAL + 0x0080)
+#define OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS        (OMAP2_CONTROL_GENERAL + 0x0084)
+#define OMAP343X_CONTROL_RPUB_KEY_H_4  (OMAP2_CONTROL_GENERAL + 0x00a0)
+#define OMAP343X_CONTROL_RAND_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00a8)
+#define OMAP343X_CONTROL_RAND_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00ac)
+#define OMAP343X_CONTROL_RAND_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00b0)
+#define OMAP343X_CONTROL_RAND_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00b4)
+#define OMAP343X_CONTROL_TEST_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00c8)
+#define OMAP343X_CONTROL_TEST_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00cc)
+#define OMAP343X_CONTROL_TEST_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00d0)
+#define OMAP343X_CONTROL_TEST_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00d4)
+#define OMAP343X_CONTROL_TEST_KEY_4    (OMAP2_CONTROL_GENERAL + 0x00d8)
+#define OMAP343X_CONTROL_TEST_KEY_5    (OMAP2_CONTROL_GENERAL + 0x00dc)
+#define OMAP343X_CONTROL_TEST_KEY_6    (OMAP2_CONTROL_GENERAL + 0x00e0)
+#define OMAP343X_CONTROL_TEST_KEY_7    (OMAP2_CONTROL_GENERAL + 0x00e4)
+#define OMAP343X_CONTROL_TEST_KEY_8    (OMAP2_CONTROL_GENERAL + 0x00e8)
+#define OMAP343X_CONTROL_TEST_KEY_9    (OMAP2_CONTROL_GENERAL + 0x00ec)
+#define OMAP343X_CONTROL_TEST_KEY_10   (OMAP2_CONTROL_GENERAL + 0x00f0)
+#define OMAP343X_CONTROL_TEST_KEY_11   (OMAP2_CONTROL_GENERAL + 0x00f4)
+#define OMAP343X_CONTROL_TEST_KEY_12   (OMAP2_CONTROL_GENERAL + 0x00f8)
+#define OMAP343X_CONTROL_TEST_KEY_13   (OMAP2_CONTROL_GENERAL + 0x00fc)
+#define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
+#define OMAP343X_CONTROL_IVA2_BOOTMOD  (OMAP2_CONTROL_GENERAL + 0x0194)
+#define OMAP343X_CONTROL_DEBOBS(i)     (OMAP2_CONTROL_GENERAL + 0x01B0 \
+                                       + ((i) >> 1) * 4 + (!((i) & 1)) * 2)
+#define OMAP343X_CONTROL_PROG_IO0      (OMAP2_CONTROL_GENERAL + 0x01D4)
+#define OMAP343X_CONTROL_PROG_IO1      (OMAP2_CONTROL_GENERAL + 0x01D8)
+#define OMAP343X_CONTROL_DSS_DPLL_SPREADING    (OMAP2_CONTROL_GENERAL + 0x01E0)
+#define OMAP343X_CONTROL_CORE_DPLL_SPREADING   (OMAP2_CONTROL_GENERAL + 0x01E4)
+#define OMAP343X_CONTROL_PER_DPLL_SPREADING    (OMAP2_CONTROL_GENERAL + 0x01E8)
+#define OMAP343X_CONTROL_USBHOST_DPLL_SPREADING        (OMAP2_CONTROL_GENERAL + 0x01EC)
+#define OMAP343X_CONTROL_PBIAS_LITE    (OMAP2_CONTROL_GENERAL + 0x02B0)
+#define OMAP343X_CONTROL_TEMP_SENSOR   (OMAP2_CONTROL_GENERAL + 0x02B4)
+#define OMAP343X_CONTROL_SRAMLDO4      (OMAP2_CONTROL_GENERAL + 0x02B8)
+#define OMAP343X_CONTROL_SRAMLDO5      (OMAP2_CONTROL_GENERAL + 0x02C0)
+#define OMAP343X_CONTROL_CSI           (OMAP2_CONTROL_GENERAL + 0x02C4)
+
+/* AM35XX only CONTROL_GENERAL register offsets */
+#define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
+#define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
+#define AM35XX_CONTROL_DEVCONF3         (OMAP2_CONTROL_GENERAL + 0x0314)
+#define AM35XX_CONTROL_CBA_PRIORITY     (OMAP2_CONTROL_GENERAL + 0x0320)
+#define AM35XX_CONTROL_LVL_INTR_CLEAR   (OMAP2_CONTROL_GENERAL + 0x0324)
+#define AM35XX_CONTROL_IP_SW_RESET      (OMAP2_CONTROL_GENERAL + 0x0328)
+#define AM35XX_CONTROL_IPSS_CLK_CTRL    (OMAP2_CONTROL_GENERAL + 0x032C)
+
+/* 34xx PADCONF register offsets */
+#define OMAP343X_PADCONF_ETK(i)                (OMAP2_CONTROL_PADCONFS + 0x5a8 + \
+                                               (i)*2)
+#define OMAP343X_PADCONF_ETK_CLK       OMAP343X_PADCONF_ETK(0)
+#define OMAP343X_PADCONF_ETK_CTL       OMAP343X_PADCONF_ETK(1)
+#define OMAP343X_PADCONF_ETK_D0                OMAP343X_PADCONF_ETK(2)
+#define OMAP343X_PADCONF_ETK_D1                OMAP343X_PADCONF_ETK(3)
+#define OMAP343X_PADCONF_ETK_D2                OMAP343X_PADCONF_ETK(4)
+#define OMAP343X_PADCONF_ETK_D3                OMAP343X_PADCONF_ETK(5)
+#define OMAP343X_PADCONF_ETK_D4                OMAP343X_PADCONF_ETK(6)
+#define OMAP343X_PADCONF_ETK_D5                OMAP343X_PADCONF_ETK(7)
+#define OMAP343X_PADCONF_ETK_D6                OMAP343X_PADCONF_ETK(8)
+#define OMAP343X_PADCONF_ETK_D7                OMAP343X_PADCONF_ETK(9)
+#define OMAP343X_PADCONF_ETK_D8                OMAP343X_PADCONF_ETK(10)
+#define OMAP343X_PADCONF_ETK_D9                OMAP343X_PADCONF_ETK(11)
+#define OMAP343X_PADCONF_ETK_D10       OMAP343X_PADCONF_ETK(12)
+#define OMAP343X_PADCONF_ETK_D11       OMAP343X_PADCONF_ETK(13)
+#define OMAP343X_PADCONF_ETK_D12       OMAP343X_PADCONF_ETK(14)
+#define OMAP343X_PADCONF_ETK_D13       OMAP343X_PADCONF_ETK(15)
+#define OMAP343X_PADCONF_ETK_D14       OMAP343X_PADCONF_ETK(16)
+#define OMAP343X_PADCONF_ETK_D15       OMAP343X_PADCONF_ETK(17)
+
+/* 34xx GENERAL_WKUP regist offsets */
+#define OMAP343X_CONTROL_WKUP_DEBOBSMUX(i) (OMAP343X_CONTROL_GENERAL_WKUP + \
+                                               0x008 + (i))
+#define OMAP343X_CONTROL_WKUP_DEBOBS0 (OMAP343X_CONTROL_GENERAL_WKUP + 0x008)
+#define OMAP343X_CONTROL_WKUP_DEBOBS1 (OMAP343X_CONTROL_GENERAL_WKUP + 0x00C)
+#define OMAP343X_CONTROL_WKUP_DEBOBS2 (OMAP343X_CONTROL_GENERAL_WKUP + 0x010)
+#define OMAP343X_CONTROL_WKUP_DEBOBS3 (OMAP343X_CONTROL_GENERAL_WKUP + 0x014)
+#define OMAP343X_CONTROL_WKUP_DEBOBS4 (OMAP343X_CONTROL_GENERAL_WKUP + 0x018)
+
+/* 34xx D2D idle-related pins, handled by PM core */
+#define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
+#define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
+
+/*
+ * REVISIT: This list of registers is not comprehensive - there are more
+ * that should be added.
+ */
+
+/*
+ * Control module register bit defines - these should eventually go into
+ * their own regbits file.  Some of these will be complicated, depending
+ * on the device type (general-purpose, emulator, test, secure, bad, other)
+ * and the security mode (secure, non-secure, don't care)
+ */
+/* CONTROL_DEVCONF0 bits */
+#define OMAP2_MMCSDIO1ADPCLKISEL       (1 << 24) /* MMC1 loop back clock */
+#define OMAP24XX_USBSTANDBYCTRL                (1 << 15)
+#define OMAP2_MCBSP2_CLKS_MASK         (1 << 6)
+#define OMAP2_MCBSP1_FSR_MASK          (1 << 4)
+#define OMAP2_MCBSP1_CLKR_MASK         (1 << 3)
+#define OMAP2_MCBSP1_CLKS_MASK         (1 << 2)
+
+/* CONTROL_DEVCONF1 bits */
+#define OMAP243X_MMC1_ACTIVE_OVERWRITE (1 << 31)
+#define OMAP2_MMCSDIO2ADPCLKISEL       (1 << 6) /* MMC2 loop back clock */
+#define OMAP2_MCBSP5_CLKS_MASK         (1 << 4) /* > 242x */
+#define OMAP2_MCBSP4_CLKS_MASK         (1 << 2) /* > 242x */
+#define OMAP2_MCBSP3_CLKS_MASK         (1 << 0) /* > 242x */
+
+/* CONTROL_STATUS bits */
+#define OMAP2_DEVICETYPE_MASK          (0x7 << 8)
+#define OMAP2_SYSBOOT_5_MASK           (1 << 5)
+#define OMAP2_SYSBOOT_4_MASK           (1 << 4)
+#define OMAP2_SYSBOOT_3_MASK           (1 << 3)
+#define OMAP2_SYSBOOT_2_MASK           (1 << 2)
+#define OMAP2_SYSBOOT_1_MASK           (1 << 1)
+#define OMAP2_SYSBOOT_0_MASK           (1 << 0)
+
+/* CONTROL_PBIAS_LITE bits */
+#define OMAP343X_PBIASLITESUPPLY_HIGH1 (1 << 15)
+#define OMAP343X_PBIASLITEVMODEERROR1  (1 << 11)
+#define OMAP343X_PBIASSPEEDCTRL1       (1 << 10)
+#define OMAP343X_PBIASLITEPWRDNZ1      (1 << 9)
+#define OMAP343X_PBIASLITEVMODE1       (1 << 8)
+#define OMAP343X_PBIASLITESUPPLY_HIGH0 (1 << 7)
+#define OMAP343X_PBIASLITEVMODEERROR0  (1 << 3)
+#define OMAP2_PBIASSPEEDCTRL0          (1 << 2)
+#define OMAP2_PBIASLITEPWRDNZ0         (1 << 1)
+#define OMAP2_PBIASLITEVMODE0          (1 << 0)
+
+/* CONTROL_PROG_IO1 bits */
+#define OMAP3630_PRG_SDMMC1_SPEEDCTRL  (1 << 20)
+
+/* CONTROL_IVA2_BOOTMOD bits */
+#define OMAP3_IVA2_BOOTMOD_SHIFT       0
+#define OMAP3_IVA2_BOOTMOD_MASK                (0xf << 0)
+#define OMAP3_IVA2_BOOTMOD_IDLE                (0x1 << 0)
+
+/* CONTROL_PADCONF_X bits */
+#define OMAP3_PADCONF_WAKEUPEVENT0     (1 << 15)
+#define OMAP3_PADCONF_WAKEUPENABLE0    (1 << 14)
+
+#define OMAP343X_SCRATCHPAD_ROM                (OMAP343X_CTRL_BASE + 0x860)
+#define OMAP343X_SCRATCHPAD            (OMAP343X_CTRL_BASE + 0x910)
+#define OMAP343X_SCRATCHPAD_ROM_OFFSET 0x19C
+
+/* AM35XX_CONTROL_IPSS_CLK_CTRL bits */
+#define AM35XX_USBOTG_VBUSP_CLK_SHIFT   0
+#define AM35XX_CPGMAC_VBUSP_CLK_SHIFT   1
+#define AM35XX_VPFE_VBUSP_CLK_SHIFT     2
+#define AM35XX_HECC_VBUSP_CLK_SHIFT     3
+#define AM35XX_USBOTG_FCLK_SHIFT        8
+#define AM35XX_CPGMAC_FCLK_SHIFT        9
+#define AM35XX_VPFE_FCLK_SHIFT          10
+
+/*AM35XX CONTROL_LVL_INTR_CLEAR bits*/
+#define AM35XX_CPGMAC_C0_MISC_PULSE_CLR        BIT(0)
+#define AM35XX_CPGMAC_C0_RX_PULSE_CLR  BIT(1)
+#define AM35XX_CPGMAC_C0_RX_THRESH_CLR BIT(2)
+#define AM35XX_CPGMAC_C0_TX_PULSE_CLR  BIT(3)
+#define AM35XX_USBOTGSS_INT_CLR                BIT(4)
+#define AM35XX_VPFE_CCDC_VD0_INT_CLR   BIT(5)
+#define AM35XX_VPFE_CCDC_VD1_INT_CLR   BIT(6)
+#define AM35XX_VPFE_CCDC_VD2_INT_CLR   BIT(7)
+
+/*AM35XX CONTROL_IP_SW_RESET bits*/
+#define AM35XX_USBOTGSS_SW_RST         BIT(0)
+#define AM35XX_CPGMACSS_SW_RST         BIT(1)
+#define AM35XX_VPFE_VBUSP_SW_RST       BIT(2)
+#define AM35XX_HECC_SW_RST             BIT(3)
+#define AM35XX_VPFE_PCLK_SW_RST                BIT(4)
+
+/*
+ * CONTROL OMAP STATUS register to identify OMAP3 features
+ */
+#define OMAP3_CONTROL_OMAP_STATUS      0x044c
+
+#define OMAP3_SGX_SHIFT                        13
+#define OMAP3_SGX_MASK                 (3 << OMAP3_SGX_SHIFT)
+#define                FEAT_SGX_FULL           0
+#define                FEAT_SGX_HALF           1
+#define                FEAT_SGX_NONE           2
+
+#define OMAP3_IVA_SHIFT                        12
+#define OMAP3_IVA_MASK                 (1 << OMAP3_SGX_SHIFT)
+#define                FEAT_IVA                0
+#define                FEAT_IVA_NONE           1
+
+#define OMAP3_L2CACHE_SHIFT            10
+#define OMAP3_L2CACHE_MASK             (3 << OMAP3_L2CACHE_SHIFT)
+#define                FEAT_L2CACHE_NONE       0
+#define                FEAT_L2CACHE_64KB       1
+#define                FEAT_L2CACHE_128KB      2
+#define                FEAT_L2CACHE_256KB      3
+
+#define OMAP3_ISP_SHIFT                        5
+#define OMAP3_ISP_MASK                 (1 << OMAP3_ISP_SHIFT)
+#define                FEAT_ISP                0
+#define                FEAT_ISP_NONE           1
+
+#define OMAP3_NEON_SHIFT               4
+#define OMAP3_NEON_MASK                        (1 << OMAP3_NEON_SHIFT)
+#define                FEAT_NEON               0
+#define                FEAT_NEON_NONE          1
+
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_ARCH_OMAP2PLUS
+extern void __iomem *omap_ctrl_base_get(void);
+extern u8 omap_ctrl_readb(u16 offset);
+extern u16 omap_ctrl_readw(u16 offset);
+extern u32 omap_ctrl_readl(u16 offset);
+extern u32 omap4_ctrl_pad_readl(u16 offset);
+extern void omap_ctrl_writeb(u8 val, u16 offset);
+extern void omap_ctrl_writew(u16 val, u16 offset);
+extern void omap_ctrl_writel(u32 val, u16 offset);
+extern void omap4_ctrl_pad_writel(u32 val, u16 offset);
+
+extern void omap3_save_scratchpad_contents(void);
+extern void omap3_clear_scratchpad_contents(void);
+extern u32 *get_restore_pointer(void);
+extern u32 *get_es3_restore_pointer(void);
+extern u32 omap3_arm_context[128];
+extern void omap3_control_save_context(void);
+extern void omap3_control_restore_context(void);
+
+#else
+#define omap_ctrl_base_get()           0
+#define omap_ctrl_readb(x)             0
+#define omap_ctrl_readw(x)             0
+#define omap_ctrl_readl(x)             0
+#define omap4_ctrl_pad_readl(x)                0
+#define omap_ctrl_writeb(x, y)         WARN_ON(1)
+#define omap_ctrl_writew(x, y)         WARN_ON(1)
+#define omap_ctrl_writel(x, y)         WARN_ON(1)
+#define omap4_ctrl_pad_writel(x, y)    WARN_ON(1)
+#endif
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ARCH_ARM_MACH_OMAP2_CONTROL_H */
+
index 3d3d035..0d50b45 100644 (file)
 #include <plat/irqs.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
-#include <plat/control.h>
 #include <plat/serial.h>
 
 #include "pm.h"
+#include "control.h"
 
 #ifdef CONFIG_CPU_IDLE
 
@@ -60,7 +60,8 @@ struct omap3_processor_cx {
 
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
 struct omap3_processor_cx current_cx_state;
-struct powerdomain *mpu_pd, *core_pd;
+struct powerdomain *mpu_pd, *core_pd, *per_pd;
+struct powerdomain *cam_pd;
 
 /*
  * The latencies/thresholds for various C states have
@@ -233,14 +234,60 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
                               struct cpuidle_state *state)
 {
        struct cpuidle_state *new_state = next_valid_state(dev, state);
+       u32 core_next_state, per_next_state = 0, per_saved_state = 0;
+       u32 cam_state;
+       struct omap3_processor_cx *cx;
+       int ret;
 
        if ((state->flags & CPUIDLE_FLAG_CHECK_BM) && omap3_idle_bm_check()) {
                BUG_ON(!dev->safe_state);
                new_state = dev->safe_state;
+               goto select_state;
        }
 
+       cx = cpuidle_get_statedata(state);
+       core_next_state = cx->core_state;
+
+       /*
+        * FIXME: we currently manage device-specific idle states
+        *        for PER and CORE in combination with CPU-specific
+        *        idle states.  This is wrong, and device-specific
+        *        idle managment needs to be separated out into 
+        *        its own code.
+        */
+
+       /*
+        * Prevent idle completely if CAM is active.
+        * CAM does not have wakeup capability in OMAP3.
+        */
+       cam_state = pwrdm_read_pwrst(cam_pd);
+       if (cam_state == PWRDM_POWER_ON) {
+               new_state = dev->safe_state;
+               goto select_state;
+       }
+
+       /*
+        * Prevent PER off if CORE is not in retention or off as this
+        * would disable PER wakeups completely.
+        */
+       per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
+       if ((per_next_state == PWRDM_POWER_OFF) &&
+           (core_next_state > PWRDM_POWER_RET))
+               per_next_state = PWRDM_POWER_RET;
+
+       /* Are we changing PER target state? */
+       if (per_next_state != per_saved_state)
+               pwrdm_set_next_pwrst(per_pd, per_next_state);
+
+select_state:
        dev->last_state = new_state;
-       return omap3_enter_idle(dev, new_state);
+       ret = omap3_enter_idle(dev, new_state);
+
+       /* Restore original PER state if it was modified */
+       if (per_next_state != per_saved_state)
+               pwrdm_set_next_pwrst(per_pd, per_saved_state);
+
+       return ret;
 }
 
 DEFINE_PER_CPU(struct cpuidle_device, omap3_idle_dev);
@@ -328,7 +375,8 @@ void omap_init_power_states(void)
                        cpuidle_params_table[OMAP3_STATE_C2].threshold;
        omap3_power_states[OMAP3_STATE_C2].mpu_state = PWRDM_POWER_ON;
        omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
-       omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID;
+       omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
+                               CPUIDLE_FLAG_CHECK_BM;
 
        /* C3 . MPU CSWR + Core inactive */
        omap3_power_states[OMAP3_STATE_C3].valid =
@@ -426,6 +474,8 @@ int __init omap3_idle_init(void)
 
        mpu_pd = pwrdm_lookup("mpu_pwrdm");
        core_pd = pwrdm_lookup("core_pwrdm");
+       per_pd = pwrdm_lookup("per_pwrdm");
+       cam_pd = pwrdm_lookup("cam_pwrdm");
 
        omap_init_power_states();
        cpuidle_register_driver(&omap3_idle_driver);
index c5cf1ba..5a0c148 100644 (file)
@@ -9,12 +9,12 @@
  * (at your option) any later version.
  */
 
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/err.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
 
-#include <plat/control.h>
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/mcbsp.h>
 #include <mach/gpio.h>
 #include <plat/mmc.h>
 #include <plat/dma.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "mux.h"
+#include "control.h"
 
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
@@ -538,7 +540,7 @@ static inline void omap_init_sham(void) { }
 
 #if defined(CONFIG_CRYPTO_DEV_OMAP_AES) || defined(CONFIG_CRYPTO_DEV_OMAP_AES_MODULE)
 
-#ifdef CONFIG_ARCH_OMAP24XX
+#ifdef CONFIG_ARCH_OMAP2
 static struct resource omap2_aes_resources[] = {
        {
                .start  = OMAP24XX_SEC_AES_BASE,
@@ -560,7 +562,7 @@ static int omap2_aes_resources_sz = ARRAY_SIZE(omap2_aes_resources);
 #define omap2_aes_resources_sz         0
 #endif
 
-#ifdef CONFIG_ARCH_OMAP34XX
+#ifdef CONFIG_ARCH_OMAP3
 static struct resource omap3_aes_resources[] = {
        {
                .start  = OMAP34XX_SEC_AES_BASE,
@@ -732,7 +734,7 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                omap_mux_init_signal("sdmmc_dat0", 0);
                omap_mux_init_signal("sdmmc_dat_dir0", 0);
                omap_mux_init_signal("sdmmc_cmd_dir", 0);
-               if (mmc_controller->slots[0].wires == 4) {
+               if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
                        omap_mux_init_signal("sdmmc_dat1", 0);
                        omap_mux_init_signal("sdmmc_dat2", 0);
                        omap_mux_init_signal("sdmmc_dat3", 0);
@@ -760,8 +762,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                OMAP_PIN_INPUT_PULLUP);
                        omap_mux_init_signal("sdmmc1_dat0",
                                OMAP_PIN_INPUT_PULLUP);
-                       if (mmc_controller->slots[0].wires == 4 ||
-                               mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                               (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
                                omap_mux_init_signal("sdmmc1_dat1",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc1_dat2",
@@ -769,7 +771,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                omap_mux_init_signal("sdmmc1_dat3",
                                        OMAP_PIN_INPUT_PULLUP);
                        }
-                       if (mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                                               MMC_CAP_8_BIT_DATA) {
                                omap_mux_init_signal("sdmmc1_dat4",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc1_dat5",
@@ -793,8 +796,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                         * For 8 wire configurations, Lines DAT4, 5, 6 and 7 need to be muxed
                         * in the board-*.c files
                         */
-                       if (mmc_controller->slots[0].wires == 4 ||
-                               mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                               (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
                                omap_mux_init_signal("sdmmc2_dat1",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc2_dat2",
@@ -802,7 +805,8 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
                                omap_mux_init_signal("sdmmc2_dat3",
                                        OMAP_PIN_INPUT_PULLUP);
                        }
-                       if (mmc_controller->slots[0].wires == 8) {
+                       if (mmc_controller->slots[0].caps &
+                                                       MMC_CAP_8_BIT_DATA) {
                                omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
                                        OMAP_PIN_INPUT_PULLUP);
                                omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
@@ -853,13 +857,13 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                case 3:
                        if (!cpu_is_omap44xx())
                                return;
-                       base = OMAP4_MMC4_BASE + OMAP4_MMC_REG_OFFSET;
+                       base = OMAP4_MMC4_BASE;
                        irq = OMAP44XX_IRQ_MMC4;
                        break;
                case 4:
                        if (!cpu_is_omap44xx())
                                return;
-                       base = OMAP4_MMC5_BASE + OMAP4_MMC_REG_OFFSET;
+                       base = OMAP4_MMC5_BASE;
                        irq = OMAP44XX_IRQ_MMC5;
                        break;
                default:
@@ -870,10 +874,8 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
                        size = OMAP2420_MMC_SIZE;
                        name = "mmci-omap";
                } else if (cpu_is_omap44xx()) {
-                       if (i < 3) {
-                               base += OMAP4_MMC_REG_OFFSET;
+                       if (i < 3)
                                irq += OMAP44XX_IRQ_GIC_START;
-                       }
                        size = OMAP4_HSMMC_SIZE;
                        name = "mmci-omap-hs";
                } else {
@@ -949,11 +951,72 @@ static inline void omap_init_vout(void) {}
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * Inorder to avoid any assumptions from bootloader regarding WDT
+ * settings, WDT module is reset during init. This enables the watchdog
+ * timer. Hence it is required to disable the watchdog after the WDT reset
+ * during init. Otherwise the system would reboot as per the default
+ * watchdog timer registers settings.
+ */
+#define OMAP_WDT_WPS   (0x34)
+#define OMAP_WDT_SPR   (0x48)
+
+static int omap2_disable_wdt(struct omap_hwmod *oh, void *unused)
+{
+       void __iomem *base;
+       int ret;
+
+       if (!oh) {
+               pr_err("%s: Could not look up wdtimer_hwmod\n", __func__);
+               return -EINVAL;
+       }
+
+       base = omap_hwmod_get_mpu_rt_va(oh);
+       if (!base) {
+               pr_err("%s: Could not get the base address for %s\n",
+                               oh->name, __func__);
+               return -EINVAL;
+       }
+
+       /* Enable the clocks before accessing the WDT registers */
+       ret = omap_hwmod_enable(oh);
+       if (ret) {
+               pr_err("%s: Could not enable clocks for %s\n",
+                               oh->name, __func__);
+               return ret;
+       }
+
+       /* sequence required to disable watchdog */
+       __raw_writel(0xAAAA, base + OMAP_WDT_SPR);
+       while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+               cpu_relax();
+
+       __raw_writel(0x5555, base + OMAP_WDT_SPR);
+       while (__raw_readl(base + OMAP_WDT_WPS) & 0x10)
+               cpu_relax();
+
+       ret = omap_hwmod_idle(oh);
+       if (ret)
+               pr_err("%s: Could not disable clocks for %s\n",
+                               oh->name, __func__);
+
+       return ret;
+}
+
+static void __init omap_disable_wdt(void)
+{
+       if (cpu_class_is_omap2())
+               omap_hwmod_for_each_by_class("wd_timer",
+                                               omap2_disable_wdt, NULL);
+       return;
+}
+
 static int __init omap2_init_devices(void)
 {
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
         */
+       omap_disable_wdt();
        omap_hsmmc_reset();
        omap_init_audio();
        omap_init_camera();
@@ -969,3 +1032,39 @@ static int __init omap2_init_devices(void)
        return 0;
 }
 arch_initcall(omap2_init_devices);
+
+#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
+struct omap_device_pm_latency omap_wdt_latency[] = {
+       [0] = {
+               .deactivate_func = omap_device_idle_hwmods,
+               .activate_func   = omap_device_enable_hwmods,
+               .flags           = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
+};
+
+static int __init omap_init_wdt(void)
+{
+       int id = -1;
+       struct omap_device *od;
+       struct omap_hwmod *oh;
+       char *oh_name = "wd_timer2";
+       char *dev_name = "omap_wdt";
+
+       if (!cpu_class_is_omap2())
+               return 0;
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("Could not look up wd_timer%d hwmod\n", id);
+               return -EINVAL;
+       }
+
+       od = omap_device_build(dev_name, id, oh, NULL, 0,
+                               omap_wdt_latency,
+                               ARRAY_SIZE(omap_wdt_latency), 0);
+       WARN(IS_ERR(od), "Cant build omap_device for %s:%s.\n",
+                               dev_name, oh->name);
+       return 0;
+}
+subsys_initcall(omap_init_wdt);
+#endif
diff --git a/arch/arm/mach-omap2/gpmc-smsc911x.c b/arch/arm/mach-omap2/gpmc-smsc911x.c
new file mode 100644 (file)
index 0000000..703f150
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * linux/arch/arm/mach-omap2/gpmc-smsc911x.c
+ *
+ * Copyright (C) 2009 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Modified from linux/arch/arm/mach-omap2/gpmc-smc91x.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/smsc911x.h>
+
+#include <plat/board.h>
+#include <plat/gpmc.h>
+#include <plat/gpmc-smsc911x.h>
+
+static struct omap_smsc911x_platform_data *gpmc_cfg;
+
+static struct resource gpmc_smsc911x_resources[] = {
+       [0] = {
+               .flags          = IORESOURCE_MEM,
+       },
+       [1] = {
+               .flags          = IORESOURCE_IRQ,
+       },
+};
+
+static struct smsc911x_platform_config gpmc_smsc911x_config = {
+       .phy_interface  = PHY_INTERFACE_MODE_MII,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type       = SMSC911X_IRQ_TYPE_OPEN_DRAIN,
+       .flags          = SMSC911X_USE_16BIT,
+};
+
+static struct platform_device gpmc_smsc911x_device = {
+       .name           = "smsc911x",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(gpmc_smsc911x_resources),
+       .resource       = gpmc_smsc911x_resources,
+       .dev            = {
+               .platform_data = &gpmc_smsc911x_config,
+       },
+};
+
+/*
+ * Initialize smsc911x device connected to the GPMC. Note that we
+ * assume that pin multiplexing is done in the board-*.c file,
+ * or in the bootloader.
+ */
+void __init gpmc_smsc911x_init(struct omap_smsc911x_platform_data *board_data)
+{
+       unsigned long cs_mem_base;
+       int ret;
+
+       gpmc_cfg = board_data;
+
+       if (gpmc_cs_request(gpmc_cfg->cs, SZ_16M, &cs_mem_base) < 0) {
+               printk(KERN_ERR "Failed to request GPMC mem for smsc911x\n");
+               return;
+       }
+
+       gpmc_smsc911x_resources[0].start = cs_mem_base + 0x0;
+       gpmc_smsc911x_resources[0].end = cs_mem_base + 0xff;
+
+       if (gpio_request(gpmc_cfg->gpio_irq, "smsc911x irq") < 0) {
+               printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n",
+                               gpmc_cfg->gpio_irq);
+               goto free1;
+       }
+
+       gpio_direction_input(gpmc_cfg->gpio_irq);
+       gpmc_smsc911x_resources[1].start = gpio_to_irq(gpmc_cfg->gpio_irq);
+       gpmc_smsc911x_resources[1].flags |=
+                                       (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
+
+       if (gpio_is_valid(gpmc_cfg->gpio_reset)) {
+               ret = gpio_request(gpmc_cfg->gpio_reset, "smsc911x reset");
+               if (ret) {
+                       printk(KERN_ERR "Failed to request GPIO%d for smsc911x reset\n",
+                                       gpmc_cfg->gpio_reset);
+                       goto free2;
+               }
+
+               gpio_direction_output(gpmc_cfg->gpio_reset, 1);
+               gpio_set_value(gpmc_cfg->gpio_reset, 0);
+               msleep(100);
+               gpio_set_value(gpmc_cfg->gpio_reset, 1);
+       }
+
+       if (platform_device_register(&gpmc_smsc911x_device) < 0) {
+               printk(KERN_ERR "Unable to register smsc911x device\n");
+               gpio_free(gpmc_cfg->gpio_reset);
+               goto free2;
+       }
+
+       return;
+
+free2:
+       gpio_free(gpmc_cfg->gpio_irq);
+free1:
+       gpmc_cs_free(gpmc_cfg->cs);
+
+       printk(KERN_ERR "Could not initialize smsc911x\n");
+}
index c8f647b..34272e4 100644 (file)
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <mach/hardware.h>
-#include <plat/control.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
 
 #include "hsmmc.h"
+#include "control.h"
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 
@@ -135,10 +135,11 @@ static void omap4_hsmmc1_before_set_reg(struct device *dev, int slot,
         *
         * FIXME handle VMMC1A as needed ...
         */
-       reg = omap_ctrl_readl(control_pbias_offset);
-       reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
-                                       OMAP4_USBC1_ICUSB_PWRDNZ);
-       omap_ctrl_writel(reg, control_pbias_offset);
+       reg = omap4_ctrl_pad_readl(control_pbias_offset);
+       reg &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+               OMAP4_MMC1_PWRDNZ_MASK |
+               OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+       omap4_ctrl_pad_writel(reg, control_pbias_offset);
 }
 
 static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
@@ -147,30 +148,33 @@ static void omap4_hsmmc1_after_set_reg(struct device *dev, int slot,
        u32 reg;
 
        if (power_on) {
-               reg = omap_ctrl_readl(control_pbias_offset);
-               reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ;
+               reg = omap4_ctrl_pad_readl(control_pbias_offset);
+               reg |= OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK;
                if ((1 << vdd) <= MMC_VDD_165_195)
-                       reg &= ~OMAP4_MMC1_PBIASLITE_VMODE;
+                       reg &= ~OMAP4_MMC1_PBIASLITE_VMODE_MASK;
                else
-                       reg |= OMAP4_MMC1_PBIASLITE_VMODE;
-               reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ |
-                                               OMAP4_USBC1_ICUSB_PWRDNZ);
-               omap_ctrl_writel(reg, control_pbias_offset);
+                       reg |= OMAP4_MMC1_PBIASLITE_VMODE_MASK;
+               reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+                       OMAP4_MMC1_PWRDNZ_MASK |
+                       OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+               omap4_ctrl_pad_writel(reg, control_pbias_offset);
                /* 4 microsec delay for comparator to generate an error*/
                udelay(4);
-               reg = omap_ctrl_readl(control_pbias_offset);
-               if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR) {
+               reg = omap4_ctrl_pad_readl(control_pbias_offset);
+               if (reg & OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK) {
                        pr_err("Pbias Voltage is not same as LDO\n");
                        /* Caution : On VMODE_ERROR Power Down MMC IO */
-                       reg &= ~(OMAP4_MMC1_PWRDNZ | OMAP4_USBC1_ICUSB_PWRDNZ);
-                       omap_ctrl_writel(reg, control_pbias_offset);
+                       reg &= ~(OMAP4_MMC1_PWRDNZ_MASK |
+                               OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+                       omap4_ctrl_pad_writel(reg, control_pbias_offset);
                }
        } else {
-               reg = omap_ctrl_readl(control_pbias_offset);
-                reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ |
-                       OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PWRDNZ |
-                       OMAP4_USBC1_ICUSB_PWRDNZ);
-               omap_ctrl_writel(reg, control_pbias_offset);
+               reg = omap4_ctrl_pad_readl(control_pbias_offset);
+               reg |= (OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK |
+                       OMAP4_MMC1_PWRDNZ_MASK |
+                       OMAP4_MMC1_PBIASLITE_VMODE_MASK |
+                       OMAP4_USBC1_ICUSB_PWRDNZ_MASK);
+               omap4_ctrl_pad_writel(reg, control_pbias_offset);
        }
 }
 
@@ -218,17 +222,18 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                        control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
                }
        } else {
-               control_pbias_offset = OMAP44XX_CONTROL_PBIAS_LITE;
-               control_mmc1 = OMAP44XX_CONTROL_MMC1;
-               reg = omap_ctrl_readl(control_mmc1);
-               reg |= (OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0 |
-                       OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1);
-               reg &= ~(OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2 |
-                       OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3);
-               reg |= (OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL |
-                       OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL |
-                       OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL);
-               omap_ctrl_writel(reg, control_mmc1);
+               control_pbias_offset =
+                       OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
+               control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
+               reg = omap4_ctrl_pad_readl(control_mmc1);
+               reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
+                       OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
+               reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
+                       OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
+               reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+                       OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
+                       OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
+               omap4_ctrl_pad_writel(reg, control_mmc1);
        }
 
        for (c = controllers; c->mmc; c++) {
@@ -258,9 +263,13 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                                "mmc%islot%i", c->mmc, 1);
                mmc->slots[0].name = hc->name;
                mmc->nr_slots = 1;
-               mmc->slots[0].wires = c->wires;
+               mmc->slots[0].caps = c->caps;
                mmc->slots[0].internal_clock = !c->ext_clock;
                mmc->dma_mask = 0xffffffff;
+               if (cpu_is_omap44xx())
+                       mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
+               else
+                       mmc->reg_offset = 0;
 
                mmc->get_context_loss_count = hsmmc_get_context_loss;
 
@@ -298,6 +307,9 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                else
                        mmc->slots[0].features |= HSMMC_HAS_PBIAS;
 
+               if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
+                       mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+
                switch (c->mmc) {
                case 1:
                        if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
@@ -316,16 +328,20 @@ void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
                        }
 
                        /* Omap3630 HSMMC1 supports only 4-bit */
-                       if (cpu_is_omap3630() && c->wires > 4) {
-                               c->wires = 4;
-                               mmc->slots[0].wires = c->wires;
+                       if (cpu_is_omap3630() &&
+                                       (c->caps & MMC_CAP_8_BIT_DATA)) {
+                               c->caps &= ~MMC_CAP_8_BIT_DATA;
+                               c->caps |= MMC_CAP_4_BIT_DATA;
+                               mmc->slots[0].caps = c->caps;
                        }
                        break;
                case 2:
                        if (c->ext_clock)
                                c->transceiver = 1;
-                       if (c->transceiver && c->wires > 4)
-                               c->wires = 4;
+                       if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) {
+                               c->caps &= ~MMC_CAP_8_BIT_DATA;
+                               c->caps |= MMC_CAP_4_BIT_DATA;
+                       }
                        /* FALLTHROUGH */
                case 3:
                        if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
index 0f8a2e6..f119348 100644 (file)
@@ -10,7 +10,8 @@ struct mmc_card;
 
 struct omap2_hsmmc_info {
        u8      mmc;            /* controller 1/2/3 */
-       u8      wires;          /* 1/4/8 wires */
+       u32     caps;           /* 4/8 wires and any additional host
+                                * capabilities OR'd (ref. linux/mmc/host.h) */
        bool    transceiver;    /* MMC-2 option */
        bool    ext_clock;      /* use external pin for input clock */
        bool    cover_only;     /* No card detect - just cover switch */
index 9a879f9..5f9086c 100644 (file)
 #include <asm/cputype.h>
 
 #include <plat/common.h>
-#include <plat/control.h>
 #include <plat/cpu.h>
 
 #include <mach/id.h>
 
+#include "control.h"
+
 static struct omap_chip_id omap_chip;
 static unsigned int omap_revision;
 
@@ -60,7 +61,7 @@ int omap_type(void)
        } else if (cpu_is_omap34xx()) {
                val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
        } else if (cpu_is_omap44xx()) {
-               val = omap_ctrl_readl(OMAP44XX_CONTROL_STATUS);
+               val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STATUS);
        } else {
                pr_err("Cannot detect omap type!\n");
                goto out;
@@ -298,7 +299,6 @@ static void __init omap4_check_revision(void)
        u32 idcode;
        u16 hawkeye;
        u8 rev;
-       char *rev_name = "ES1.0";
 
        /*
         * The IC rev detection is done with hawkeye and rev.
@@ -309,14 +309,39 @@ static void __init omap4_check_revision(void)
        hawkeye = (idcode >> 12) & 0xffff;
        rev = (idcode >> 28) & 0xff;
 
-       if ((hawkeye == 0xb852) && (rev == 0x0)) {
-               omap_revision = OMAP4430_REV_ES1_0;
-               omap_chip.oc |= CHIP_IS_OMAP4430ES1;
-               pr_info("OMAP%04x %s\n", omap_rev() >> 16, rev_name);
-               return;
+       /*
+        * Few initial ES2.0 samples IDCODE is same as ES1.0
+        * Use ARM register to detect the correct ES version
+        */
+       if (!rev) {
+               idcode = read_cpuid(CPUID_ID);
+               rev = (idcode & 0xf) - 1;
+       }
+
+       switch (hawkeye) {
+       case 0xb852:
+               switch (rev) {
+               case 0:
+                       omap_revision = OMAP4430_REV_ES1_0;
+                       omap_chip.oc |= CHIP_IS_OMAP4430ES1;
+                       break;
+               case 1:
+                       omap_revision = OMAP4430_REV_ES2_0;
+                       omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+                       break;
+               default:
+                       omap_revision = OMAP4430_REV_ES2_0;
+                       omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+       }
+       break;
+       default:
+               /* Unknown default to latest silicon rev as default*/
+               omap_revision = OMAP4430_REV_ES2_0;
+               omap_chip.oc |= CHIP_IS_OMAP4430ES2;
        }
 
-       pr_err("Unknown OMAP4 CPU id\n");
+       pr_info("OMAP%04x ES%d.0\n",
+                       omap_rev() >> 16, ((omap_rev() >> 12) & 0xf) + 1);
 }
 
 #define OMAP3_SHOW_FEATURE(feat)               \
@@ -361,30 +386,54 @@ static void __init omap3_cpuinfo(void)
                strcpy(cpu_name, "OMAP3503");
        }
 
-       switch (rev) {
-       case OMAP_REVBITS_00:
-               strcpy(cpu_rev, "1.0");
-               break;
-       case OMAP_REVBITS_01:
-               strcpy(cpu_rev, "1.1");
-               break;
-       case OMAP_REVBITS_02:
-               strcpy(cpu_rev, "1.2");
-               break;
-       case OMAP_REVBITS_10:
-               strcpy(cpu_rev, "2.0");
-               break;
-       case OMAP_REVBITS_20:
-               strcpy(cpu_rev, "2.1");
-               break;
-       case OMAP_REVBITS_30:
-               strcpy(cpu_rev, "3.0");
-               break;
-       case OMAP_REVBITS_40:
-       /* FALLTHROUGH */
-       default:
-               /* Use the latest known revision as default */
-               strcpy(cpu_rev, "3.1");
+       if (cpu_is_omap3630()) {
+               switch (rev) {
+               case OMAP_REVBITS_00:
+                       strcpy(cpu_rev, "1.0");
+                       break;
+               case OMAP_REVBITS_01:
+                       strcpy(cpu_rev, "1.1");
+                       break;
+               case OMAP_REVBITS_02:
+                       /* FALLTHROUGH */
+               default:
+                       /* Use the latest known revision as default */
+                       strcpy(cpu_rev, "1.2");
+               }
+       } else if (cpu_is_omap3505() || cpu_is_omap3517()) {
+               switch (rev) {
+               case OMAP_REVBITS_00:
+                       strcpy(cpu_rev, "1.0");
+                       break;
+               case OMAP_REVBITS_01:
+                       /* FALLTHROUGH */
+               default:
+                       /* Use the latest known revision as default */
+                       strcpy(cpu_rev, "1.1");
+               }
+       } else {
+               switch (rev) {
+               case OMAP_REVBITS_00:
+                       strcpy(cpu_rev, "1.0");
+                       break;
+               case OMAP_REVBITS_01:
+                       strcpy(cpu_rev, "2.0");
+                       break;
+               case OMAP_REVBITS_02:
+                       strcpy(cpu_rev, "2.1");
+                       break;
+               case OMAP_REVBITS_03:
+                       strcpy(cpu_rev, "3.0");
+                       break;
+               case OMAP_REVBITS_04:
+                       strcpy(cpu_rev, "3.1");
+                       break;
+               case OMAP_REVBITS_05:
+                       /* FALLTHROUGH */
+               default:
+                       /* Use the latest known revision as default */
+                       strcpy(cpu_rev, "3.1.2");
+               }
        }
 
        /* Print verbose information */
diff --git a/arch/arm/mach-omap2/include/mach/board-flash.h b/arch/arm/mach-omap2/include/mach/board-flash.h
deleted file mode 100644 (file)
index b2242ae..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  board-sdp.h
- *
- *  Information structures for SDP-specific board config data
- *
- *  Copyright (C) 2009 Nokia Corporation
- *  Copyright (C) 2009 Texas Instruments
- *
- * This 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/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <plat/gpmc.h>
-
-#define PDC_NOR                1
-#define PDC_NAND       2
-#define PDC_ONENAND    3
-#define DBG_MPDB       4
-
-struct flash_partitions {
-       struct mtd_partition *parts;
-       int nr_parts;
-};
-
-extern void board_flash_init(struct flash_partitions [],
-                               char chip_sel[][GPMC_CS_NUM]);
diff --git a/arch/arm/mach-omap2/include/mach/board-rx51.h b/arch/arm/mach-omap2/include/mach/board-rx51.h
new file mode 100644 (file)
index 0000000..b76f49e
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Defines for rx51 boards
+ */
+
+#ifndef _OMAP_BOARD_RX51_H
+#define _OMAP_BOARD_RX51_H
+
+extern void __init rx51_peripherals_init(void);
+extern void __init rx51_video_mem_init(void);
+
+#endif
index 80591fd..f93ca39 100644 (file)
@@ -1,12 +1,8 @@
 /*
  * Defines for zoom boards
  */
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-
 #define ZOOM_NAND_CS    0
 
-extern void __init board_nand_init(struct mtd_partition *, u8 nr_parts, u8 cs);
 extern int __init zoom_debugboard_init(void);
 extern void __init zoom_peripherals_init(void);
 
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
new file mode 100644 (file)
index 0000000..2f7ac70
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * OMAP44xx CTRL_MODULE_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_CORE                                 0x4a002000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_CORE_IP_REVISION                     0x0000
+#define OMAP4_CTRL_MODULE_CORE_IP_HWINFO                       0x0004
+#define OMAP4_CTRL_MODULE_CORE_IP_SYSCONFIG                    0x0010
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_0               0x0200
+#define OMAP4_CTRL_MODULE_CORE_ID_CODE                         0x0204
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_1               0x0208
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_2               0x020c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_DIE_ID_3               0x0210
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_0              0x0214
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_PROD_ID_1              0x0218
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_USB_CONF               0x021c
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_VDD_WKUP           0x0228
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_BGAP               0x0260
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_0             0x0264
+#define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1             0x0268
+#define OMAP4_CTRL_MODULE_CORE_STATUS                          0x02c4
+#define OMAP4_CTRL_MODULE_CORE_DEV_CONF                                0x0300
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL         0x0314
+#define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL         0x0318
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL                0x0320
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_MPU_VOLTAGE_CTRL                0x0324
+#define OMAP4_CTRL_MODULE_CORE_LDOSRAM_CORE_VOLTAGE_CTRL       0x0328
+#define OMAP4_CTRL_MODULE_CORE_TEMP_SENSOR                     0x032c
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_0               0x0330
+#define OMAP4_CTRL_MODULE_CORE_DPLL_NWELL_TRIM_1               0x0334
+#define OMAP4_CTRL_MODULE_CORE_USBOTGHS_CONTROL                        0x033c
+#define OMAP4_CTRL_MODULE_CORE_DSS_CONTROL                     0x0340
+#define OMAP4_CTRL_MODULE_CORE_HWOBS_CONTROL                   0x0350
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_FINAL_MUX_SEL            0x0400
+#define OMAP4_CTRL_MODULE_CORE_DEBOBS_MMR_MPU                  0x0408
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL0              0x042c
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL1              0x0430
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL2              0x0434
+#define OMAP4_CTRL_MODULE_CORE_CONF_SDMA_REQ_SEL3              0x0438
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL0                   0x0440
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL1                   0x0444
+#define OMAP4_CTRL_MODULE_CORE_CONF_CLK_SEL2                   0x0448
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_FREQLOCK_SEL          0x044c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_TINITZ_SEL            0x0450
+#define OMAP4_CTRL_MODULE_CORE_CONF_DPLL_PHASELOCK_SEL         0x0454
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_0            0x0480
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_1            0x0484
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_2            0x0488
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_3            0x048c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_4            0x0490
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_5            0x0494
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_6            0x0498
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_7            0x049c
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_8            0x04a0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_9            0x04a4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_10           0x04a8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_11           0x04ac
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_12           0x04b0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_13           0x04b4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_14           0x04b8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_15           0x04bc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_16           0x04c0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_17           0x04c4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_18           0x04c8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_19           0x04cc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_20           0x04d0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_21           0x04d4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_22           0x04d8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_23           0x04dc
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_24           0x04e0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_25           0x04e4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_26           0x04e8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_27           0x04ec
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_28           0x04f0
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_29           0x04f4
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_30           0x04f8
+#define OMAP4_CTRL_MODULE_CORE_CONF_DEBUG_SEL_TST_31           0x04fc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT                      30
+#define OMAP4_IP_REV_SCHEME_MASK                       (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                                16
+#define OMAP4_IP_REV_FUNC_MASK                         (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                         11
+#define OMAP4_IP_REV_RTL_MASK                          (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT                       8
+#define OMAP4_IP_REV_MAJOR_MASK                                (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT                      6
+#define OMAP4_IP_REV_CUSTOM_MASK                       (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT                       0
+#define OMAP4_IP_REV_MINOR_MASK                                (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                          0
+#define OMAP4_IP_HWINFO_MASK                           (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT              2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK               (0x3 << 2)
+
+/* STD_FUSE_DIE_ID_0 */
+#define OMAP4_STD_FUSE_DIE_ID_0_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_0_MASK                   (0xffffffff << 0)
+
+/* ID_CODE */
+#define OMAP4_STD_FUSE_IDCODE_SHIFT                    0
+#define OMAP4_STD_FUSE_IDCODE_MASK                     (0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_1 */
+#define OMAP4_STD_FUSE_DIE_ID_1_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_1_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_2 */
+#define OMAP4_STD_FUSE_DIE_ID_2_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_2_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_DIE_ID_3 */
+#define OMAP4_STD_FUSE_DIE_ID_3_SHIFT                  0
+#define OMAP4_STD_FUSE_DIE_ID_3_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_0 */
+#define OMAP4_STD_FUSE_PROD_ID_0_SHIFT                 0
+#define OMAP4_STD_FUSE_PROD_ID_0_MASK                  (0xffffffff << 0)
+
+/* STD_FUSE_PROD_ID_1 */
+#define OMAP4_STD_FUSE_PROD_ID_1_SHIFT                 0
+#define OMAP4_STD_FUSE_PROD_ID_1_MASK                  (0xffffffff << 0)
+
+/* STD_FUSE_USB_CONF */
+#define OMAP4_USB_PROD_ID_SHIFT                                16
+#define OMAP4_USB_PROD_ID_MASK                         (0xffff << 16)
+#define OMAP4_USB_VENDOR_ID_SHIFT                      0
+#define OMAP4_USB_VENDOR_ID_MASK                       (0xffff << 0)
+
+/* STD_FUSE_OPP_VDD_WKUP */
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_SHIFT              0
+#define OMAP4_STD_FUSE_OPP_VDD_WKUP_MASK               (0xffffffff << 0)
+
+/* STD_FUSE_OPP_BGAP */
+#define OMAP4_STD_FUSE_OPP_BGAP_SHIFT                  0
+#define OMAP4_STD_FUSE_OPP_BGAP_MASK                   (0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_0 */
+#define OMAP4_STD_FUSE_OPP_DPLL_0_SHIFT                        0
+#define OMAP4_STD_FUSE_OPP_DPLL_0_MASK                 (0xffffffff << 0)
+
+/* STD_FUSE_OPP_DPLL_1 */
+#define OMAP4_STD_FUSE_OPP_DPLL_1_SHIFT                        0
+#define OMAP4_STD_FUSE_OPP_DPLL_1_MASK                 (0xffffffff << 0)
+
+/* STATUS */
+#define OMAP4_ATTILA_CONF_SHIFT                                11
+#define OMAP4_ATTILA_CONF_MASK                         (0x3 << 11)
+#define OMAP4_DEVICE_TYPE_SHIFT                                8
+#define OMAP4_DEVICE_TYPE_MASK                         (0x7 << 8)
+#define OMAP4_SYS_BOOT_SHIFT                           0
+#define OMAP4_SYS_BOOT_MASK                            (0xff << 0)
+
+/* DEV_CONF */
+#define OMAP4_DEV_CONF_SHIFT                           1
+#define OMAP4_DEV_CONF_MASK                            (0x7fffffff << 1)
+#define OMAP4_USBPHY_PD_SHIFT                          0
+#define OMAP4_USBPHY_PD_MASK                           (1 << 0)
+
+/* LDOVBB_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_SHIFT             26
+#define OMAP4_LDOVBBIVA_RBB_MUX_CTRL_MASK              (1 << 26)
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_SHIFT              21
+#define OMAP4_LDOVBBIVA_RBB_VSET_IN_MASK               (0x1f << 21)
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_SHIFT             16
+#define OMAP4_LDOVBBIVA_RBB_VSET_OUT_MASK              (0x1f << 16)
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_SHIFT             10
+#define OMAP4_LDOVBBIVA_FBB_MUX_CTRL_MASK              (1 << 10)
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_SHIFT              5
+#define OMAP4_LDOVBBIVA_FBB_VSET_IN_MASK               (0x1f << 5)
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_SHIFT             0
+#define OMAP4_LDOVBBIVA_FBB_VSET_OUT_MASK              (0x1f << 0)
+
+/* LDOVBB_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_SHIFT             26
+#define OMAP4_LDOVBBMPU_RBB_MUX_CTRL_MASK              (1 << 26)
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_SHIFT              21
+#define OMAP4_LDOVBBMPU_RBB_VSET_IN_MASK               (0x1f << 21)
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_SHIFT             16
+#define OMAP4_LDOVBBMPU_RBB_VSET_OUT_MASK              (0x1f << 16)
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_SHIFT             10
+#define OMAP4_LDOVBBMPU_FBB_MUX_CTRL_MASK              (1 << 10)
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_SHIFT              5
+#define OMAP4_LDOVBBMPU_FBB_VSET_IN_MASK               (0x1f << 5)
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_SHIFT             0
+#define OMAP4_LDOVBBMPU_FBB_VSET_OUT_MASK              (0x1f << 0)
+
+/* LDOSRAM_IVA_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_SHIFT                26
+#define OMAP4_LDOSRAMIVA_RETMODE_MUX_CTRL_MASK         (1 << 26)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_SHIFT         21
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_IN_MASK          (0x1f << 21)
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_SHIFT                16
+#define OMAP4_LDOSRAMIVA_RETMODE_VSET_OUT_MASK         (0x1f << 16)
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_SHIFT                10
+#define OMAP4_LDOSRAMIVA_ACTMODE_MUX_CTRL_MASK         (1 << 10)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_SHIFT         5
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_IN_MASK          (0x1f << 5)
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_SHIFT                0
+#define OMAP4_LDOSRAMIVA_ACTMODE_VSET_OUT_MASK         (0x1f << 0)
+
+/* LDOSRAM_MPU_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_SHIFT                26
+#define OMAP4_LDOSRAMMPU_RETMODE_MUX_CTRL_MASK         (1 << 26)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_SHIFT         21
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_IN_MASK          (0x1f << 21)
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_SHIFT                16
+#define OMAP4_LDOSRAMMPU_RETMODE_VSET_OUT_MASK         (0x1f << 16)
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_SHIFT                10
+#define OMAP4_LDOSRAMMPU_ACTMODE_MUX_CTRL_MASK         (1 << 10)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_SHIFT         5
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_IN_MASK          (0x1f << 5)
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_SHIFT                0
+#define OMAP4_LDOSRAMMPU_ACTMODE_VSET_OUT_MASK         (0x1f << 0)
+
+/* LDOSRAM_CORE_VOLTAGE_CTRL */
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_SHIFT       26
+#define OMAP4_LDOSRAMCORE_RETMODE_MUX_CTRL_MASK                (1 << 26)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_SHIFT                21
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_IN_MASK         (0x1f << 21)
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_SHIFT       16
+#define OMAP4_LDOSRAMCORE_RETMODE_VSET_OUT_MASK                (0x1f << 16)
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_SHIFT       10
+#define OMAP4_LDOSRAMCORE_ACTMODE_MUX_CTRL_MASK                (1 << 10)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_SHIFT                5
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_IN_MASK         (0x1f << 5)
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_SHIFT       0
+#define OMAP4_LDOSRAMCORE_ACTMODE_VSET_OUT_MASK                (0x1f << 0)
+
+/* TEMP_SENSOR */
+#define OMAP4_BGAP_TEMPSOFF_SHIFT                      12
+#define OMAP4_BGAP_TEMPSOFF_MASK                       (1 << 12)
+#define OMAP4_BGAP_TSHUT_SHIFT                         11
+#define OMAP4_BGAP_TSHUT_MASK                          (1 << 11)
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_SHIFT          10
+#define OMAP4_BGAP_TEMP_SENSOR_CONTCONV_MASK           (1 << 10)
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_SHIFT               9
+#define OMAP4_BGAP_TEMP_SENSOR_SOC_MASK                        (1 << 9)
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_SHIFT              8
+#define OMAP4_BGAP_TEMP_SENSOR_EOCZ_MASK               (1 << 8)
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_SHIFT             0
+#define OMAP4_BGAP_TEMP_SENSOR_DTEMP_MASK              (0xff << 0)
+
+/* DPLL_NWELL_TRIM_0 */
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_SHIFT       29
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MUX_CTRL_MASK                (1 << 29)
+#define OMAP4_DPLL_ABE_NWELL_TRIM_SHIFT                        24
+#define OMAP4_DPLL_ABE_NWELL_TRIM_MASK                 (0x1f << 24)
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_SHIFT       23
+#define OMAP4_DPLL_PER_NWELL_TRIM_MUX_CTRL_MASK                (1 << 23)
+#define OMAP4_DPLL_PER_NWELL_TRIM_SHIFT                        18
+#define OMAP4_DPLL_PER_NWELL_TRIM_MASK                 (0x1f << 18)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_SHIFT      17
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MUX_CTRL_MASK       (1 << 17)
+#define OMAP4_DPLL_CORE_NWELL_TRIM_SHIFT               12
+#define OMAP4_DPLL_CORE_NWELL_TRIM_MASK                        (0x1f << 12)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_SHIFT       11
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MUX_CTRL_MASK                (1 << 11)
+#define OMAP4_DPLL_IVA_NWELL_TRIM_SHIFT                        6
+#define OMAP4_DPLL_IVA_NWELL_TRIM_MASK                 (0x1f << 6)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_SHIFT       5
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MUX_CTRL_MASK                (1 << 5)
+#define OMAP4_DPLL_MPU_NWELL_TRIM_SHIFT                        0
+#define OMAP4_DPLL_MPU_NWELL_TRIM_MASK                 (0x1f << 0)
+
+/* DPLL_NWELL_TRIM_1 */
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_SHIFT    29
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MUX_CTRL_MASK     (1 << 29)
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_SHIFT             24
+#define OMAP4_DPLL_UNIPRO_NWELL_TRIM_MASK              (0x1f << 24)
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_SHIFT       23
+#define OMAP4_DPLL_USB_NWELL_TRIM_MUX_CTRL_MASK                (1 << 23)
+#define OMAP4_DPLL_USB_NWELL_TRIM_SHIFT                        18
+#define OMAP4_DPLL_USB_NWELL_TRIM_MASK                 (0x1f << 18)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_SHIFT      17
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MUX_CTRL_MASK       (1 << 17)
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_SHIFT               12
+#define OMAP4_DPLL_HDMI_NWELL_TRIM_MASK                        (0x1f << 12)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_SHIFT      11
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MUX_CTRL_MASK       (1 << 11)
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_SHIFT               6
+#define OMAP4_DPLL_DSI2_NWELL_TRIM_MASK                        (0x1f << 6)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_SHIFT      5
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MUX_CTRL_MASK       (1 << 5)
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_SHIFT               0
+#define OMAP4_DPLL_DSI1_NWELL_TRIM_MASK                        (0x1f << 0)
+
+/* USBOTGHS_CONTROL */
+#define OMAP4_DISCHRGVBUS_SHIFT                                8
+#define OMAP4_DISCHRGVBUS_MASK                         (1 << 8)
+#define OMAP4_CHRGVBUS_SHIFT                           7
+#define OMAP4_CHRGVBUS_MASK                            (1 << 7)
+#define OMAP4_DRVVBUS_SHIFT                            6
+#define OMAP4_DRVVBUS_MASK                             (1 << 6)
+#define OMAP4_IDPULLUP_SHIFT                           5
+#define OMAP4_IDPULLUP_MASK                            (1 << 5)
+#define OMAP4_IDDIG_SHIFT                              4
+#define OMAP4_IDDIG_MASK                               (1 << 4)
+#define OMAP4_SESSEND_SHIFT                            3
+#define OMAP4_SESSEND_MASK                             (1 << 3)
+#define OMAP4_VBUSVALID_SHIFT                          2
+#define OMAP4_VBUSVALID_MASK                           (1 << 2)
+#define OMAP4_BVALID_SHIFT                             1
+#define OMAP4_BVALID_MASK                              (1 << 1)
+#define OMAP4_AVALID_SHIFT                             0
+#define OMAP4_AVALID_MASK                              (1 << 0)
+
+/* DSS_CONTROL */
+#define OMAP4_DSS_MUX6_SELECT_SHIFT                    0
+#define OMAP4_DSS_MUX6_SELECT_MASK                     (1 << 0)
+
+/* HWOBS_CONTROL */
+#define OMAP4_HWOBS_CLKDIV_SEL_SHIFT                   3
+#define OMAP4_HWOBS_CLKDIV_SEL_MASK                    (0x1f << 3)
+#define OMAP4_HWOBS_ALL_ZERO_MODE_SHIFT                        2
+#define OMAP4_HWOBS_ALL_ZERO_MODE_MASK                 (1 << 2)
+#define OMAP4_HWOBS_ALL_ONE_MODE_SHIFT                 1
+#define OMAP4_HWOBS_ALL_ONE_MODE_MASK                  (1 << 1)
+#define OMAP4_HWOBS_MACRO_ENABLE_SHIFT                 0
+#define OMAP4_HWOBS_MACRO_ENABLE_MASK                  (1 << 0)
+
+/* DEBOBS_FINAL_MUX_SEL */
+#define OMAP4_SELECT_SHIFT                             0
+#define OMAP4_SELECT_MASK                              (0xffffffff << 0)
+
+/* DEBOBS_MMR_MPU */
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_SHIFT              0
+#define OMAP4_SELECT_DEBOBS_MMR_MPU_MASK               (0xf << 0)
+
+/* CONF_SDMA_REQ_SEL0 */
+#define OMAP4_MULT_SHIFT                               0
+#define OMAP4_MULT_MASK                                        (0x7f << 0)
+
+/* CONF_CLK_SEL0 */
+#define OMAP4_MULT_CONF_CLK_SEL0_SHIFT                 0
+#define OMAP4_MULT_CONF_CLK_SEL0_MASK                  (0x7 << 0)
+
+/* CONF_CLK_SEL1 */
+#define OMAP4_MULT_CONF_CLK_SEL1_SHIFT                 0
+#define OMAP4_MULT_CONF_CLK_SEL1_MASK                  (0x7 << 0)
+
+/* CONF_CLK_SEL2 */
+#define OMAP4_MULT_CONF_CLK_SEL2_SHIFT                 0
+#define OMAP4_MULT_CONF_CLK_SEL2_MASK                  (0x7 << 0)
+
+/* CONF_DPLL_FREQLOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_SHIFT                0
+#define OMAP4_MULT_CONF_DPLL_FREQLOCK_SEL_MASK         (0x7 << 0)
+
+/* CONF_DPLL_TINITZ_SEL */
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_SHIFT          0
+#define OMAP4_MULT_CONF_DPLL_TINITZ_SEL_MASK           (0x7 << 0)
+
+/* CONF_DPLL_PHASELOCK_SEL */
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_SHIFT       0
+#define OMAP4_MULT_CONF_DPLL_PHASELOCK_SEL_MASK                (0x7 << 0)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_MODE_SHIFT                               0
+#define OMAP4_MODE_MASK                                        (0xf << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_core_44xx.h
new file mode 100644 (file)
index 0000000..c88420d
--- /dev/null
@@ -0,0 +1,1409 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_CORE registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_CORE_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_CORE                             0x4a100000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_REVISION                 0x0000
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_HWINFO                   0x0004
+#define OMAP4_CTRL_MODULE_PAD_CORE_IP_SYSCONFIG                        0x0010
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_0       0x01d8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_1       0x01dc
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_2       0x01e0
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_3       0x01e4
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_4       0x01e8
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_5       0x01ec
+#define OMAP4_CTRL_MODULE_PAD_CORE_PADCONF_WAKEUPEVENT_6       0x01f0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_GLOBAL      0x05a0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PADCONF_MODE                0x05a4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_0  0x05a8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART1IO_PADCONF_1  0x05ac
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_0  0x05b0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART2IO_PADCONF_1  0x05b4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_0  0x05b8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_1  0x05bc
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SMART3IO_PADCONF_2  0x05c0
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC           0x05c4
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_SLIMBUS             0x05c8
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE           0x0600
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0               0x0604
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX           0x0608
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_AVDAC               0x060c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDMI_TX_PHY         0x0610
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC2                        0x0614
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_DSIPHY              0x0618
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP             0x061c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB2PHYCORE         0x0620
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_1               0x0624
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1                        0x0628
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HSI                 0x062c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USB                 0x0630
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_HDQ                 0x0634
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_0         0x0638
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_1         0x063c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_2         0x0640
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO1_3         0x0644
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_0         0x0648
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_1         0x064c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_2         0x0650
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_LPDDR2IO2_3         0x0654
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_BUS_HOLD            0x0658
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_C2C                 0x065c
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_RW       0x0660
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R                0x0664
+#define OMAP4_CTRL_MODULE_PAD_CORE_CORE_CONTROL_SPARE_R_C0     0x0668
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_1             0x0700
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_2             0x0704
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_3             0x0708
+#define OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_EFUSE_4             0x070c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT                              30
+#define OMAP4_IP_REV_SCHEME_MASK                               (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                                        16
+#define OMAP4_IP_REV_FUNC_MASK                                 (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                                 11
+#define OMAP4_IP_REV_RTL_MASK                                  (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT                               8
+#define OMAP4_IP_REV_MAJOR_MASK                                        (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT                              6
+#define OMAP4_IP_REV_CUSTOM_MASK                               (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT                               0
+#define OMAP4_IP_REV_MINOR_MASK                                        (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                                  0
+#define OMAP4_IP_HWINFO_MASK                                   (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT                      2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK                       (0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_SHIFT              31
+#define OMAP4_GPMC_CLK_DUPLICATEWAKEUPEVENT_MASK               (1 << 31)
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_SHIFT              30
+#define OMAP4_GPMC_NWP_DUPLICATEWAKEUPEVENT_MASK               (1 << 30)
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_SHIFT             29
+#define OMAP4_GPMC_NCS3_DUPLICATEWAKEUPEVENT_MASK              (1 << 29)
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_SHIFT             28
+#define OMAP4_GPMC_NCS2_DUPLICATEWAKEUPEVENT_MASK              (1 << 28)
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_SHIFT             27
+#define OMAP4_GPMC_NCS1_DUPLICATEWAKEUPEVENT_MASK              (1 << 27)
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_SHIFT             26
+#define OMAP4_GPMC_NCS0_DUPLICATEWAKEUPEVENT_MASK              (1 << 26)
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_SHIFT              25
+#define OMAP4_GPMC_A25_DUPLICATEWAKEUPEVENT_MASK               (1 << 25)
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_GPMC_A24_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_GPMC_A23_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_SHIFT              22
+#define OMAP4_GPMC_A22_DUPLICATEWAKEUPEVENT_MASK               (1 << 22)
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_SHIFT              21
+#define OMAP4_GPMC_A21_DUPLICATEWAKEUPEVENT_MASK               (1 << 21)
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_GPMC_A20_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_SHIFT              19
+#define OMAP4_GPMC_A19_DUPLICATEWAKEUPEVENT_MASK               (1 << 19)
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_SHIFT              18
+#define OMAP4_GPMC_A18_DUPLICATEWAKEUPEVENT_MASK               (1 << 18)
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_SHIFT              17
+#define OMAP4_GPMC_A17_DUPLICATEWAKEUPEVENT_MASK               (1 << 17)
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_SHIFT              16
+#define OMAP4_GPMC_A16_DUPLICATEWAKEUPEVENT_MASK               (1 << 16)
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_SHIFT             15
+#define OMAP4_GPMC_AD15_DUPLICATEWAKEUPEVENT_MASK              (1 << 15)
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_SHIFT             14
+#define OMAP4_GPMC_AD14_DUPLICATEWAKEUPEVENT_MASK              (1 << 14)
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_SHIFT             13
+#define OMAP4_GPMC_AD13_DUPLICATEWAKEUPEVENT_MASK              (1 << 13)
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_SHIFT             12
+#define OMAP4_GPMC_AD12_DUPLICATEWAKEUPEVENT_MASK              (1 << 12)
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_SHIFT             11
+#define OMAP4_GPMC_AD11_DUPLICATEWAKEUPEVENT_MASK              (1 << 11)
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_SHIFT             10
+#define OMAP4_GPMC_AD10_DUPLICATEWAKEUPEVENT_MASK              (1 << 10)
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_SHIFT              9
+#define OMAP4_GPMC_AD9_DUPLICATEWAKEUPEVENT_MASK               (1 << 9)
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_SHIFT              8
+#define OMAP4_GPMC_AD8_DUPLICATEWAKEUPEVENT_MASK               (1 << 8)
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_SHIFT              7
+#define OMAP4_GPMC_AD7_DUPLICATEWAKEUPEVENT_MASK               (1 << 7)
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_SHIFT              6
+#define OMAP4_GPMC_AD6_DUPLICATEWAKEUPEVENT_MASK               (1 << 6)
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_SHIFT              5
+#define OMAP4_GPMC_AD5_DUPLICATEWAKEUPEVENT_MASK               (1 << 5)
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_SHIFT              4
+#define OMAP4_GPMC_AD4_DUPLICATEWAKEUPEVENT_MASK               (1 << 4)
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_SHIFT              3
+#define OMAP4_GPMC_AD3_DUPLICATEWAKEUPEVENT_MASK               (1 << 3)
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_SHIFT              2
+#define OMAP4_GPMC_AD2_DUPLICATEWAKEUPEVENT_MASK               (1 << 2)
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_SHIFT              1
+#define OMAP4_GPMC_AD1_DUPLICATEWAKEUPEVENT_MASK               (1 << 1)
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_SHIFT              0
+#define OMAP4_GPMC_AD0_DUPLICATEWAKEUPEVENT_MASK               (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_1 */
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_SHIFT            31
+#define OMAP4_CAM_STROBE_DUPLICATEWAKEUPEVENT_MASK             (1 << 31)
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_SHIFT           30
+#define OMAP4_CAM_SHUTTER_DUPLICATEWAKEUPEVENT_MASK            (1 << 30)
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_SHIFT             29
+#define OMAP4_CSI22_DY1_DUPLICATEWAKEUPEVENT_MASK              (1 << 29)
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_SHIFT             28
+#define OMAP4_CSI22_DX1_DUPLICATEWAKEUPEVENT_MASK              (1 << 28)
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_SHIFT             27
+#define OMAP4_CSI22_DY0_DUPLICATEWAKEUPEVENT_MASK              (1 << 27)
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_SHIFT             26
+#define OMAP4_CSI22_DX0_DUPLICATEWAKEUPEVENT_MASK              (1 << 26)
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_SHIFT             25
+#define OMAP4_CSI21_DY4_DUPLICATEWAKEUPEVENT_MASK              (1 << 25)
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_SHIFT             24
+#define OMAP4_CSI21_DX4_DUPLICATEWAKEUPEVENT_MASK              (1 << 24)
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_SHIFT             23
+#define OMAP4_CSI21_DY3_DUPLICATEWAKEUPEVENT_MASK              (1 << 23)
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_SHIFT             22
+#define OMAP4_CSI21_DX3_DUPLICATEWAKEUPEVENT_MASK              (1 << 22)
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_SHIFT             21
+#define OMAP4_CSI21_DY2_DUPLICATEWAKEUPEVENT_MASK              (1 << 21)
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_SHIFT             20
+#define OMAP4_CSI21_DX2_DUPLICATEWAKEUPEVENT_MASK              (1 << 20)
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_SHIFT             19
+#define OMAP4_CSI21_DY1_DUPLICATEWAKEUPEVENT_MASK              (1 << 19)
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_SHIFT             18
+#define OMAP4_CSI21_DX1_DUPLICATEWAKEUPEVENT_MASK              (1 << 18)
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_SHIFT             17
+#define OMAP4_CSI21_DY0_DUPLICATEWAKEUPEVENT_MASK              (1 << 17)
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_SHIFT             16
+#define OMAP4_CSI21_DX0_DUPLICATEWAKEUPEVENT_MASK              (1 << 16)
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_SHIFT          15
+#define OMAP4_HDMI_DDC_SDA_DUPLICATEWAKEUPEVENT_MASK           (1 << 15)
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_SHIFT          14
+#define OMAP4_HDMI_DDC_SCL_DUPLICATEWAKEUPEVENT_MASK           (1 << 14)
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_SHIFT              13
+#define OMAP4_HDMI_CEC_DUPLICATEWAKEUPEVENT_MASK               (1 << 13)
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_SHIFT              12
+#define OMAP4_HDMI_HPD_DUPLICATEWAKEUPEVENT_MASK               (1 << 12)
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_SHIFT            11
+#define OMAP4_C2C_DATA15_DUPLICATEWAKEUPEVENT_MASK             (1 << 11)
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_SHIFT            10
+#define OMAP4_C2C_DATA14_DUPLICATEWAKEUPEVENT_MASK             (1 << 10)
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_SHIFT            9
+#define OMAP4_C2C_DATA13_DUPLICATEWAKEUPEVENT_MASK             (1 << 9)
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_SHIFT            8
+#define OMAP4_C2C_DATA12_DUPLICATEWAKEUPEVENT_MASK             (1 << 8)
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_SHIFT            7
+#define OMAP4_C2C_DATA11_DUPLICATEWAKEUPEVENT_MASK             (1 << 7)
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_SHIFT            6
+#define OMAP4_GPMC_WAIT1_DUPLICATEWAKEUPEVENT_MASK             (1 << 6)
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_SHIFT            5
+#define OMAP4_GPMC_WAIT0_DUPLICATEWAKEUPEVENT_MASK             (1 << 5)
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_SHIFT             4
+#define OMAP4_GPMC_NBE1_DUPLICATEWAKEUPEVENT_MASK              (1 << 4)
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_SHIFT         3
+#define OMAP4_GPMC_NBE0_CLE_DUPLICATEWAKEUPEVENT_MASK          (1 << 3)
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_SHIFT              2
+#define OMAP4_GPMC_NWE_DUPLICATEWAKEUPEVENT_MASK               (1 << 2)
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_SHIFT              1
+#define OMAP4_GPMC_NOE_DUPLICATEWAKEUPEVENT_MASK               (1 << 1)
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_SHIFT         0
+#define OMAP4_GPMC_NADV_ALE_DUPLICATEWAKEUPEVENT_MASK          (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_2 */
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_SHIFT       31
+#define OMAP4_ABE_MCBSP1_CLKX_DUPLICATEWAKEUPEVENT_MASK                (1 << 31)
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_SHIFT                30
+#define OMAP4_ABE_MCBSP2_FSX_DUPLICATEWAKEUPEVENT_MASK         (1 << 30)
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_SHIFT         29
+#define OMAP4_ABE_MCBSP2_DX_DUPLICATEWAKEUPEVENT_MASK          (1 << 29)
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_SHIFT         28
+#define OMAP4_ABE_MCBSP2_DR_DUPLICATEWAKEUPEVENT_MASK          (1 << 28)
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_SHIFT       27
+#define OMAP4_ABE_MCBSP2_CLKX_DUPLICATEWAKEUPEVENT_MASK                (1 << 27)
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_SHIFT           26
+#define OMAP4_SDMMC1_DAT7_DUPLICATEWAKEUPEVENT_MASK            (1 << 26)
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_SHIFT           25
+#define OMAP4_SDMMC1_DAT6_DUPLICATEWAKEUPEVENT_MASK            (1 << 25)
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_SHIFT           24
+#define OMAP4_SDMMC1_DAT5_DUPLICATEWAKEUPEVENT_MASK            (1 << 24)
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_SHIFT           23
+#define OMAP4_SDMMC1_DAT4_DUPLICATEWAKEUPEVENT_MASK            (1 << 23)
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_SHIFT           22
+#define OMAP4_SDMMC1_DAT3_DUPLICATEWAKEUPEVENT_MASK            (1 << 22)
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_SHIFT           21
+#define OMAP4_SDMMC1_DAT2_DUPLICATEWAKEUPEVENT_MASK            (1 << 21)
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_SHIFT           20
+#define OMAP4_SDMMC1_DAT1_DUPLICATEWAKEUPEVENT_MASK            (1 << 20)
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_SHIFT           19
+#define OMAP4_SDMMC1_DAT0_DUPLICATEWAKEUPEVENT_MASK            (1 << 19)
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_SHIFT            18
+#define OMAP4_SDMMC1_CMD_DUPLICATEWAKEUPEVENT_MASK             (1 << 18)
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_SHIFT            17
+#define OMAP4_SDMMC1_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 17)
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_SHIFT                16
+#define OMAP4_USBC1_ICUSB_DM_DUPLICATEWAKEUPEVENT_MASK         (1 << 16)
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_SHIFT                15
+#define OMAP4_USBC1_ICUSB_DP_DUPLICATEWAKEUPEVENT_MASK         (1 << 15)
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT     14
+#define OMAP4_USBB1_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK      (1 << 14)
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT       13
+#define OMAP4_USBB1_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 13)
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT    12
+#define OMAP4_USBB1_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK     (1 << 12)
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT    11
+#define OMAP4_USBB1_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK     (1 << 11)
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT    10
+#define OMAP4_USBB1_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK     (1 << 10)
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT    9
+#define OMAP4_USBB1_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK     (1 << 9)
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT    8
+#define OMAP4_USBB1_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK     (1 << 8)
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT    7
+#define OMAP4_USBB1_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK     (1 << 7)
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT    6
+#define OMAP4_USBB1_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK     (1 << 6)
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT    5
+#define OMAP4_USBB1_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK     (1 << 5)
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT     4
+#define OMAP4_USBB1_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK      (1 << 4)
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT     3
+#define OMAP4_USBB1_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK      (1 << 3)
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT     2
+#define OMAP4_USBB1_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK      (1 << 2)
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT     1
+#define OMAP4_USBB1_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK      (1 << 1)
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_SHIFT       0
+#define OMAP4_CAM_GLOBALRESET_DUPLICATEWAKEUPEVENT_MASK                (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_3 */
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_SHIFT            31
+#define OMAP4_MCSPI1_CS3_DUPLICATEWAKEUPEVENT_MASK             (1 << 31)
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_SHIFT            30
+#define OMAP4_MCSPI1_CS2_DUPLICATEWAKEUPEVENT_MASK             (1 << 30)
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_SHIFT            29
+#define OMAP4_MCSPI1_CS1_DUPLICATEWAKEUPEVENT_MASK             (1 << 29)
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_SHIFT            28
+#define OMAP4_MCSPI1_CS0_DUPLICATEWAKEUPEVENT_MASK             (1 << 28)
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_SHIFT           27
+#define OMAP4_MCSPI1_SIMO_DUPLICATEWAKEUPEVENT_MASK            (1 << 27)
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_SHIFT           26
+#define OMAP4_MCSPI1_SOMI_DUPLICATEWAKEUPEVENT_MASK            (1 << 26)
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_SHIFT            25
+#define OMAP4_MCSPI1_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 25)
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_I2C4_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_I2C4_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_SHIFT              22
+#define OMAP4_I2C3_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 22)
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_SHIFT              21
+#define OMAP4_I2C3_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 21)
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_I2C2_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_SHIFT              19
+#define OMAP4_I2C2_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 19)
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_SHIFT              18
+#define OMAP4_I2C1_SDA_DUPLICATEWAKEUPEVENT_MASK               (1 << 18)
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_SHIFT              17
+#define OMAP4_I2C1_SCL_DUPLICATEWAKEUPEVENT_MASK               (1 << 17)
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_SHIFT               16
+#define OMAP4_HDQ_SIO_DUPLICATEWAKEUPEVENT_MASK                        (1 << 16)
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_SHIFT              15
+#define OMAP4_UART2_TX_DUPLICATEWAKEUPEVENT_MASK               (1 << 15)
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_SHIFT              14
+#define OMAP4_UART2_RX_DUPLICATEWAKEUPEVENT_MASK               (1 << 14)
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_SHIFT             13
+#define OMAP4_UART2_RTS_DUPLICATEWAKEUPEVENT_MASK              (1 << 13)
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_SHIFT             12
+#define OMAP4_UART2_CTS_DUPLICATEWAKEUPEVENT_MASK              (1 << 12)
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_SHIFT         11
+#define OMAP4_ABE_DMIC_DIN3_DUPLICATEWAKEUPEVENT_MASK          (1 << 11)
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_SHIFT         10
+#define OMAP4_ABE_DMIC_DIN2_DUPLICATEWAKEUPEVENT_MASK          (1 << 10)
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_SHIFT         9
+#define OMAP4_ABE_DMIC_DIN1_DUPLICATEWAKEUPEVENT_MASK          (1 << 9)
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_SHIFT         8
+#define OMAP4_ABE_DMIC_CLK1_DUPLICATEWAKEUPEVENT_MASK          (1 << 8)
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_SHIFT              7
+#define OMAP4_ABE_CLKS_DUPLICATEWAKEUPEVENT_MASK               (1 << 7)
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_SHIFT                6
+#define OMAP4_ABE_PDM_LB_CLK_DUPLICATEWAKEUPEVENT_MASK         (1 << 6)
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_SHIFT         5
+#define OMAP4_ABE_PDM_FRAME_DUPLICATEWAKEUPEVENT_MASK          (1 << 5)
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_SHIFT       4
+#define OMAP4_ABE_PDM_DL_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 4)
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_SHIFT       3
+#define OMAP4_ABE_PDM_UL_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 3)
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_SHIFT                2
+#define OMAP4_ABE_MCBSP1_FSX_DUPLICATEWAKEUPEVENT_MASK         (1 << 2)
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_SHIFT         1
+#define OMAP4_ABE_MCBSP1_DX_DUPLICATEWAKEUPEVENT_MASK          (1 << 1)
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_SHIFT         0
+#define OMAP4_ABE_MCBSP1_DR_DUPLICATEWAKEUPEVENT_MASK          (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_4 */
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_SHIFT            31
+#define OMAP4_UNIPRO_TY0_DUPLICATEWAKEUPEVENT_MASK             (1 << 31)
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_SHIFT            30
+#define OMAP4_UNIPRO_TX0_DUPLICATEWAKEUPEVENT_MASK             (1 << 30)
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_SHIFT     29
+#define OMAP4_USBB2_HSIC_STROBE_DUPLICATEWAKEUPEVENT_MASK      (1 << 29)
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_SHIFT       28
+#define OMAP4_USBB2_HSIC_DATA_DUPLICATEWAKEUPEVENT_MASK                (1 << 28)
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_SHIFT    27
+#define OMAP4_USBB2_ULPITLL_DAT7_DUPLICATEWAKEUPEVENT_MASK     (1 << 27)
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_SHIFT    26
+#define OMAP4_USBB2_ULPITLL_DAT6_DUPLICATEWAKEUPEVENT_MASK     (1 << 26)
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_SHIFT    25
+#define OMAP4_USBB2_ULPITLL_DAT5_DUPLICATEWAKEUPEVENT_MASK     (1 << 25)
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_SHIFT    24
+#define OMAP4_USBB2_ULPITLL_DAT4_DUPLICATEWAKEUPEVENT_MASK     (1 << 24)
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_SHIFT    23
+#define OMAP4_USBB2_ULPITLL_DAT3_DUPLICATEWAKEUPEVENT_MASK     (1 << 23)
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_SHIFT    22
+#define OMAP4_USBB2_ULPITLL_DAT2_DUPLICATEWAKEUPEVENT_MASK     (1 << 22)
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_SHIFT    21
+#define OMAP4_USBB2_ULPITLL_DAT1_DUPLICATEWAKEUPEVENT_MASK     (1 << 21)
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_SHIFT    20
+#define OMAP4_USBB2_ULPITLL_DAT0_DUPLICATEWAKEUPEVENT_MASK     (1 << 20)
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_SHIFT     19
+#define OMAP4_USBB2_ULPITLL_NXT_DUPLICATEWAKEUPEVENT_MASK      (1 << 19)
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_SHIFT     18
+#define OMAP4_USBB2_ULPITLL_DIR_DUPLICATEWAKEUPEVENT_MASK      (1 << 18)
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_SHIFT     17
+#define OMAP4_USBB2_ULPITLL_STP_DUPLICATEWAKEUPEVENT_MASK      (1 << 17)
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_SHIFT     16
+#define OMAP4_USBB2_ULPITLL_CLK_DUPLICATEWAKEUPEVENT_MASK      (1 << 16)
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_SHIFT              15
+#define OMAP4_UART4_TX_DUPLICATEWAKEUPEVENT_MASK               (1 << 15)
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_SHIFT              14
+#define OMAP4_UART4_RX_DUPLICATEWAKEUPEVENT_MASK               (1 << 14)
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_SHIFT            13
+#define OMAP4_MCSPI4_CS0_DUPLICATEWAKEUPEVENT_MASK             (1 << 13)
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_SHIFT           12
+#define OMAP4_MCSPI4_SOMI_DUPLICATEWAKEUPEVENT_MASK            (1 << 12)
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_SHIFT           11
+#define OMAP4_MCSPI4_SIMO_DUPLICATEWAKEUPEVENT_MASK            (1 << 11)
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_SHIFT            10
+#define OMAP4_MCSPI4_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 10)
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_SHIFT           9
+#define OMAP4_SDMMC5_DAT3_DUPLICATEWAKEUPEVENT_MASK            (1 << 9)
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_SHIFT           8
+#define OMAP4_SDMMC5_DAT2_DUPLICATEWAKEUPEVENT_MASK            (1 << 8)
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_SHIFT           7
+#define OMAP4_SDMMC5_DAT1_DUPLICATEWAKEUPEVENT_MASK            (1 << 7)
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_SHIFT           6
+#define OMAP4_SDMMC5_DAT0_DUPLICATEWAKEUPEVENT_MASK            (1 << 6)
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_SHIFT            5
+#define OMAP4_SDMMC5_CMD_DUPLICATEWAKEUPEVENT_MASK             (1 << 5)
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_SHIFT            4
+#define OMAP4_SDMMC5_CLK_DUPLICATEWAKEUPEVENT_MASK             (1 << 4)
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_SHIFT         3
+#define OMAP4_UART3_TX_IRTX_DUPLICATEWAKEUPEVENT_MASK          (1 << 3)
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_SHIFT         2
+#define OMAP4_UART3_RX_IRRX_DUPLICATEWAKEUPEVENT_MASK          (1 << 2)
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_SHIFT          1
+#define OMAP4_UART3_RTS_SD_DUPLICATEWAKEUPEVENT_MASK           (1 << 1)
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_SHIFT                0
+#define OMAP4_UART3_CTS_RCTX_DUPLICATEWAKEUPEVENT_MASK         (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_5 */
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_SHIFT             31
+#define OMAP4_DPM_EMU11_DUPLICATEWAKEUPEVENT_MASK              (1 << 31)
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_SHIFT             30
+#define OMAP4_DPM_EMU10_DUPLICATEWAKEUPEVENT_MASK              (1 << 30)
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_SHIFT              29
+#define OMAP4_DPM_EMU9_DUPLICATEWAKEUPEVENT_MASK               (1 << 29)
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_SHIFT              28
+#define OMAP4_DPM_EMU8_DUPLICATEWAKEUPEVENT_MASK               (1 << 28)
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_SHIFT              27
+#define OMAP4_DPM_EMU7_DUPLICATEWAKEUPEVENT_MASK               (1 << 27)
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_SHIFT              26
+#define OMAP4_DPM_EMU6_DUPLICATEWAKEUPEVENT_MASK               (1 << 26)
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_SHIFT              25
+#define OMAP4_DPM_EMU5_DUPLICATEWAKEUPEVENT_MASK               (1 << 25)
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_DPM_EMU4_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_DPM_EMU3_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_SHIFT              22
+#define OMAP4_DPM_EMU2_DUPLICATEWAKEUPEVENT_MASK               (1 << 22)
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_SHIFT              21
+#define OMAP4_DPM_EMU1_DUPLICATEWAKEUPEVENT_MASK               (1 << 21)
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_DPM_EMU0_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_SHIFT             19
+#define OMAP4_SYS_BOOT5_DUPLICATEWAKEUPEVENT_MASK              (1 << 19)
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_SHIFT             18
+#define OMAP4_SYS_BOOT4_DUPLICATEWAKEUPEVENT_MASK              (1 << 18)
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_SHIFT             17
+#define OMAP4_SYS_BOOT3_DUPLICATEWAKEUPEVENT_MASK              (1 << 17)
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_SHIFT             16
+#define OMAP4_SYS_BOOT2_DUPLICATEWAKEUPEVENT_MASK              (1 << 16)
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_SHIFT             15
+#define OMAP4_SYS_BOOT1_DUPLICATEWAKEUPEVENT_MASK              (1 << 15)
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_SHIFT             14
+#define OMAP4_SYS_BOOT0_DUPLICATEWAKEUPEVENT_MASK              (1 << 14)
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_SHIFT             13
+#define OMAP4_SYS_NIRQ2_DUPLICATEWAKEUPEVENT_MASK              (1 << 13)
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_SHIFT             12
+#define OMAP4_SYS_NIRQ1_DUPLICATEWAKEUPEVENT_MASK              (1 << 12)
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_SHIFT         11
+#define OMAP4_FREF_CLK2_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 11)
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_SHIFT         10
+#define OMAP4_FREF_CLK1_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 10)
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_SHIFT            9
+#define OMAP4_UNIPRO_RY2_DUPLICATEWAKEUPEVENT_MASK             (1 << 9)
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_SHIFT            8
+#define OMAP4_UNIPRO_RX2_DUPLICATEWAKEUPEVENT_MASK             (1 << 8)
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_SHIFT            7
+#define OMAP4_UNIPRO_RY1_DUPLICATEWAKEUPEVENT_MASK             (1 << 7)
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_SHIFT            6
+#define OMAP4_UNIPRO_RX1_DUPLICATEWAKEUPEVENT_MASK             (1 << 6)
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_SHIFT            5
+#define OMAP4_UNIPRO_RY0_DUPLICATEWAKEUPEVENT_MASK             (1 << 5)
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_SHIFT            4
+#define OMAP4_UNIPRO_RX0_DUPLICATEWAKEUPEVENT_MASK             (1 << 4)
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_SHIFT            3
+#define OMAP4_UNIPRO_TY2_DUPLICATEWAKEUPEVENT_MASK             (1 << 3)
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_SHIFT            2
+#define OMAP4_UNIPRO_TX2_DUPLICATEWAKEUPEVENT_MASK             (1 << 2)
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_SHIFT            1
+#define OMAP4_UNIPRO_TY1_DUPLICATEWAKEUPEVENT_MASK             (1 << 1)
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_SHIFT            0
+#define OMAP4_UNIPRO_TX1_DUPLICATEWAKEUPEVENT_MASK             (1 << 0)
+
+/* PADCONF_WAKEUPEVENT_6 */
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_SHIFT             7
+#define OMAP4_DPM_EMU19_DUPLICATEWAKEUPEVENT_MASK              (1 << 7)
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_SHIFT             6
+#define OMAP4_DPM_EMU18_DUPLICATEWAKEUPEVENT_MASK              (1 << 6)
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_SHIFT             5
+#define OMAP4_DPM_EMU17_DUPLICATEWAKEUPEVENT_MASK              (1 << 5)
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_SHIFT             4
+#define OMAP4_DPM_EMU16_DUPLICATEWAKEUPEVENT_MASK              (1 << 4)
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_SHIFT             3
+#define OMAP4_DPM_EMU15_DUPLICATEWAKEUPEVENT_MASK              (1 << 3)
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_SHIFT             2
+#define OMAP4_DPM_EMU14_DUPLICATEWAKEUPEVENT_MASK              (1 << 2)
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_SHIFT             1
+#define OMAP4_DPM_EMU13_DUPLICATEWAKEUPEVENT_MASK              (1 << 1)
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_SHIFT             0
+#define OMAP4_DPM_EMU12_DUPLICATEWAKEUPEVENT_MASK              (1 << 0)
+
+/* CONTROL_PADCONF_GLOBAL */
+#define OMAP4_FORCE_OFFMODE_EN_SHIFT                           31
+#define OMAP4_FORCE_OFFMODE_EN_MASK                            (1 << 31)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_BANK0_SHIFT                              31
+#define OMAP4_VDDS_DV_BANK0_MASK                               (1 << 31)
+#define OMAP4_VDDS_DV_BANK1_SHIFT                              30
+#define OMAP4_VDDS_DV_BANK1_MASK                               (1 << 30)
+#define OMAP4_VDDS_DV_BANK3_SHIFT                              29
+#define OMAP4_VDDS_DV_BANK3_MASK                               (1 << 29)
+#define OMAP4_VDDS_DV_BANK4_SHIFT                              28
+#define OMAP4_VDDS_DV_BANK4_MASK                               (1 << 28)
+#define OMAP4_VDDS_DV_BANK5_SHIFT                              27
+#define OMAP4_VDDS_DV_BANK5_MASK                               (1 << 27)
+#define OMAP4_VDDS_DV_BANK6_SHIFT                              26
+#define OMAP4_VDDS_DV_BANK6_MASK                               (1 << 26)
+#define OMAP4_VDDS_DV_C2C_SHIFT                                        25
+#define OMAP4_VDDS_DV_C2C_MASK                                 (1 << 25)
+#define OMAP4_VDDS_DV_CAM_SHIFT                                        24
+#define OMAP4_VDDS_DV_CAM_MASK                                 (1 << 24)
+#define OMAP4_VDDS_DV_GPMC_SHIFT                               23
+#define OMAP4_VDDS_DV_GPMC_MASK                                        (1 << 23)
+#define OMAP4_VDDS_DV_SDMMC2_SHIFT                             22
+#define OMAP4_VDDS_DV_SDMMC2_MASK                              (1 << 22)
+
+/* CONTROL_SMART1IO_PADCONF_0 */
+#define OMAP4_ABE_DR0_SC_SHIFT                                 30
+#define OMAP4_ABE_DR0_SC_MASK                                  (0x3 << 30)
+#define OMAP4_CAM_DR0_SC_SHIFT                                 28
+#define OMAP4_CAM_DR0_SC_MASK                                  (0x3 << 28)
+#define OMAP4_FREF_DR2_SC_SHIFT                                        26
+#define OMAP4_FREF_DR2_SC_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR3_SC_SHIFT                                        24
+#define OMAP4_FREF_DR3_SC_MASK                                 (0x3 << 24)
+#define OMAP4_GPIO_DR8_SC_SHIFT                                        22
+#define OMAP4_GPIO_DR8_SC_MASK                                 (0x3 << 22)
+#define OMAP4_GPIO_DR9_SC_SHIFT                                        20
+#define OMAP4_GPIO_DR9_SC_MASK                                 (0x3 << 20)
+#define OMAP4_GPMC_DR2_SC_SHIFT                                        18
+#define OMAP4_GPMC_DR2_SC_MASK                                 (0x3 << 18)
+#define OMAP4_GPMC_DR3_SC_SHIFT                                        16
+#define OMAP4_GPMC_DR3_SC_MASK                                 (0x3 << 16)
+#define OMAP4_GPMC_DR6_SC_SHIFT                                        14
+#define OMAP4_GPMC_DR6_SC_MASK                                 (0x3 << 14)
+#define OMAP4_HDMI_DR0_SC_SHIFT                                        12
+#define OMAP4_HDMI_DR0_SC_MASK                                 (0x3 << 12)
+#define OMAP4_MCSPI1_DR0_SC_SHIFT                              10
+#define OMAP4_MCSPI1_DR0_SC_MASK                               (0x3 << 10)
+#define OMAP4_UART1_DR0_SC_SHIFT                               8
+#define OMAP4_UART1_DR0_SC_MASK                                        (0x3 << 8)
+#define OMAP4_UART3_DR0_SC_SHIFT                               6
+#define OMAP4_UART3_DR0_SC_MASK                                        (0x3 << 6)
+#define OMAP4_UART3_DR1_SC_SHIFT                               4
+#define OMAP4_UART3_DR1_SC_MASK                                        (0x3 << 4)
+#define OMAP4_UNIPRO_DR0_SC_SHIFT                              2
+#define OMAP4_UNIPRO_DR0_SC_MASK                               (0x3 << 2)
+#define OMAP4_UNIPRO_DR1_SC_SHIFT                              0
+#define OMAP4_UNIPRO_DR1_SC_MASK                               (0x3 << 0)
+
+/* CONTROL_SMART1IO_PADCONF_1 */
+#define OMAP4_ABE_DR0_LB_SHIFT                                 30
+#define OMAP4_ABE_DR0_LB_MASK                                  (0x3 << 30)
+#define OMAP4_CAM_DR0_LB_SHIFT                                 28
+#define OMAP4_CAM_DR0_LB_MASK                                  (0x3 << 28)
+#define OMAP4_FREF_DR2_LB_SHIFT                                        26
+#define OMAP4_FREF_DR2_LB_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR3_LB_SHIFT                                        24
+#define OMAP4_FREF_DR3_LB_MASK                                 (0x3 << 24)
+#define OMAP4_GPIO_DR8_LB_SHIFT                                        22
+#define OMAP4_GPIO_DR8_LB_MASK                                 (0x3 << 22)
+#define OMAP4_GPIO_DR9_LB_SHIFT                                        20
+#define OMAP4_GPIO_DR9_LB_MASK                                 (0x3 << 20)
+#define OMAP4_GPMC_DR2_LB_SHIFT                                        18
+#define OMAP4_GPMC_DR2_LB_MASK                                 (0x3 << 18)
+#define OMAP4_GPMC_DR3_LB_SHIFT                                        16
+#define OMAP4_GPMC_DR3_LB_MASK                                 (0x3 << 16)
+#define OMAP4_GPMC_DR6_LB_SHIFT                                        14
+#define OMAP4_GPMC_DR6_LB_MASK                                 (0x3 << 14)
+#define OMAP4_HDMI_DR0_LB_SHIFT                                        12
+#define OMAP4_HDMI_DR0_LB_MASK                                 (0x3 << 12)
+#define OMAP4_MCSPI1_DR0_LB_SHIFT                              10
+#define OMAP4_MCSPI1_DR0_LB_MASK                               (0x3 << 10)
+#define OMAP4_UART1_DR0_LB_SHIFT                               8
+#define OMAP4_UART1_DR0_LB_MASK                                        (0x3 << 8)
+#define OMAP4_UART3_DR0_LB_SHIFT                               6
+#define OMAP4_UART3_DR0_LB_MASK                                        (0x3 << 6)
+#define OMAP4_UART3_DR1_LB_SHIFT                               4
+#define OMAP4_UART3_DR1_LB_MASK                                        (0x3 << 4)
+#define OMAP4_UNIPRO_DR0_LB_SHIFT                              2
+#define OMAP4_UNIPRO_DR0_LB_MASK                               (0x3 << 2)
+#define OMAP4_UNIPRO_DR1_LB_SHIFT                              0
+#define OMAP4_UNIPRO_DR1_LB_MASK                               (0x3 << 0)
+
+/* CONTROL_SMART2IO_PADCONF_0 */
+#define OMAP4_C2C_DR0_LB_SHIFT                                 31
+#define OMAP4_C2C_DR0_LB_MASK                                  (1 << 31)
+#define OMAP4_DPM_DR1_LB_SHIFT                                 30
+#define OMAP4_DPM_DR1_LB_MASK                                  (1 << 30)
+#define OMAP4_DPM_DR2_LB_SHIFT                                 29
+#define OMAP4_DPM_DR2_LB_MASK                                  (1 << 29)
+#define OMAP4_DPM_DR3_LB_SHIFT                                 28
+#define OMAP4_DPM_DR3_LB_MASK                                  (1 << 28)
+#define OMAP4_GPIO_DR0_LB_SHIFT                                        27
+#define OMAP4_GPIO_DR0_LB_MASK                                 (1 << 27)
+#define OMAP4_GPIO_DR1_LB_SHIFT                                        26
+#define OMAP4_GPIO_DR1_LB_MASK                                 (1 << 26)
+#define OMAP4_GPIO_DR10_LB_SHIFT                               25
+#define OMAP4_GPIO_DR10_LB_MASK                                        (1 << 25)
+#define OMAP4_GPIO_DR2_LB_SHIFT                                        24
+#define OMAP4_GPIO_DR2_LB_MASK                                 (1 << 24)
+#define OMAP4_GPMC_DR0_LB_SHIFT                                        23
+#define OMAP4_GPMC_DR0_LB_MASK                                 (1 << 23)
+#define OMAP4_GPMC_DR1_LB_SHIFT                                        22
+#define OMAP4_GPMC_DR1_LB_MASK                                 (1 << 22)
+#define OMAP4_GPMC_DR4_LB_SHIFT                                        21
+#define OMAP4_GPMC_DR4_LB_MASK                                 (1 << 21)
+#define OMAP4_GPMC_DR5_LB_SHIFT                                        20
+#define OMAP4_GPMC_DR5_LB_MASK                                 (1 << 20)
+#define OMAP4_GPMC_DR7_LB_SHIFT                                        19
+#define OMAP4_GPMC_DR7_LB_MASK                                 (1 << 19)
+#define OMAP4_HSI2_DR0_LB_SHIFT                                        18
+#define OMAP4_HSI2_DR0_LB_MASK                                 (1 << 18)
+#define OMAP4_HSI2_DR1_LB_SHIFT                                        17
+#define OMAP4_HSI2_DR1_LB_MASK                                 (1 << 17)
+#define OMAP4_HSI2_DR2_LB_SHIFT                                        16
+#define OMAP4_HSI2_DR2_LB_MASK                                 (1 << 16)
+#define OMAP4_KPD_DR0_LB_SHIFT                                 15
+#define OMAP4_KPD_DR0_LB_MASK                                  (1 << 15)
+#define OMAP4_KPD_DR1_LB_SHIFT                                 14
+#define OMAP4_KPD_DR1_LB_MASK                                  (1 << 14)
+#define OMAP4_PDM_DR0_LB_SHIFT                                 13
+#define OMAP4_PDM_DR0_LB_MASK                                  (1 << 13)
+#define OMAP4_SDMMC2_DR0_LB_SHIFT                              12
+#define OMAP4_SDMMC2_DR0_LB_MASK                               (1 << 12)
+#define OMAP4_SDMMC3_DR0_LB_SHIFT                              11
+#define OMAP4_SDMMC3_DR0_LB_MASK                               (1 << 11)
+#define OMAP4_SDMMC4_DR0_LB_SHIFT                              10
+#define OMAP4_SDMMC4_DR0_LB_MASK                               (1 << 10)
+#define OMAP4_SDMMC4_DR1_LB_SHIFT                              9
+#define OMAP4_SDMMC4_DR1_LB_MASK                               (1 << 9)
+#define OMAP4_SPI3_DR0_LB_SHIFT                                        8
+#define OMAP4_SPI3_DR0_LB_MASK                                 (1 << 8)
+#define OMAP4_SPI3_DR1_LB_SHIFT                                        7
+#define OMAP4_SPI3_DR1_LB_MASK                                 (1 << 7)
+#define OMAP4_UART3_DR2_LB_SHIFT                               6
+#define OMAP4_UART3_DR2_LB_MASK                                        (1 << 6)
+#define OMAP4_UART3_DR3_LB_SHIFT                               5
+#define OMAP4_UART3_DR3_LB_MASK                                        (1 << 5)
+#define OMAP4_UART3_DR4_LB_SHIFT                               4
+#define OMAP4_UART3_DR4_LB_MASK                                        (1 << 4)
+#define OMAP4_UART3_DR5_LB_SHIFT                               3
+#define OMAP4_UART3_DR5_LB_MASK                                        (1 << 3)
+#define OMAP4_USBA0_DR1_LB_SHIFT                               2
+#define OMAP4_USBA0_DR1_LB_MASK                                        (1 << 2)
+#define OMAP4_USBA_DR2_LB_SHIFT                                        1
+#define OMAP4_USBA_DR2_LB_MASK                                 (1 << 1)
+
+/* CONTROL_SMART2IO_PADCONF_1 */
+#define OMAP4_USBB1_DR0_LB_SHIFT                               31
+#define OMAP4_USBB1_DR0_LB_MASK                                        (1 << 31)
+#define OMAP4_USBB2_DR0_LB_SHIFT                               30
+#define OMAP4_USBB2_DR0_LB_MASK                                        (1 << 30)
+#define OMAP4_USBA0_DR0_LB_SHIFT                               29
+#define OMAP4_USBA0_DR0_LB_MASK                                        (1 << 29)
+
+/* CONTROL_SMART3IO_PADCONF_0 */
+#define OMAP4_DMIC_DR0_MB_SHIFT                                        30
+#define OMAP4_DMIC_DR0_MB_MASK                                 (0x3 << 30)
+#define OMAP4_GPIO_DR3_MB_SHIFT                                        28
+#define OMAP4_GPIO_DR3_MB_MASK                                 (0x3 << 28)
+#define OMAP4_GPIO_DR4_MB_SHIFT                                        26
+#define OMAP4_GPIO_DR4_MB_MASK                                 (0x3 << 26)
+#define OMAP4_GPIO_DR5_MB_SHIFT                                        24
+#define OMAP4_GPIO_DR5_MB_MASK                                 (0x3 << 24)
+#define OMAP4_GPIO_DR6_MB_SHIFT                                        22
+#define OMAP4_GPIO_DR6_MB_MASK                                 (0x3 << 22)
+#define OMAP4_HSI_DR1_MB_SHIFT                                 20
+#define OMAP4_HSI_DR1_MB_MASK                                  (0x3 << 20)
+#define OMAP4_HSI_DR2_MB_SHIFT                                 18
+#define OMAP4_HSI_DR2_MB_MASK                                  (0x3 << 18)
+#define OMAP4_HSI_DR3_MB_SHIFT                                 16
+#define OMAP4_HSI_DR3_MB_MASK                                  (0x3 << 16)
+#define OMAP4_MCBSP2_DR0_MB_SHIFT                              14
+#define OMAP4_MCBSP2_DR0_MB_MASK                               (0x3 << 14)
+#define OMAP4_MCSPI4_DR0_MB_SHIFT                              12
+#define OMAP4_MCSPI4_DR0_MB_MASK                               (0x3 << 12)
+#define OMAP4_MCSPI4_DR1_MB_SHIFT                              10
+#define OMAP4_MCSPI4_DR1_MB_MASK                               (0x3 << 10)
+#define OMAP4_SDMMC3_DR0_MB_SHIFT                              8
+#define OMAP4_SDMMC3_DR0_MB_MASK                               (0x3 << 8)
+#define OMAP4_SPI2_DR0_MB_SHIFT                                        0
+#define OMAP4_SPI2_DR0_MB_MASK                                 (0x3 << 0)
+
+/* CONTROL_SMART3IO_PADCONF_1 */
+#define OMAP4_SPI2_DR1_MB_SHIFT                                        30
+#define OMAP4_SPI2_DR1_MB_MASK                                 (0x3 << 30)
+#define OMAP4_SPI2_DR2_MB_SHIFT                                        28
+#define OMAP4_SPI2_DR2_MB_MASK                                 (0x3 << 28)
+#define OMAP4_UART2_DR0_MB_SHIFT                               26
+#define OMAP4_UART2_DR0_MB_MASK                                        (0x3 << 26)
+#define OMAP4_UART2_DR1_MB_SHIFT                               24
+#define OMAP4_UART2_DR1_MB_MASK                                        (0x3 << 24)
+#define OMAP4_UART4_DR0_MB_SHIFT                               22
+#define OMAP4_UART4_DR0_MB_MASK                                        (0x3 << 22)
+#define OMAP4_HSI_DR0_MB_SHIFT                                 20
+#define OMAP4_HSI_DR0_MB_MASK                                  (0x3 << 20)
+
+/* CONTROL_SMART3IO_PADCONF_2 */
+#define OMAP4_DMIC_DR0_LB_SHIFT                                        31
+#define OMAP4_DMIC_DR0_LB_MASK                                 (1 << 31)
+#define OMAP4_GPIO_DR3_LB_SHIFT                                        30
+#define OMAP4_GPIO_DR3_LB_MASK                                 (1 << 30)
+#define OMAP4_GPIO_DR4_LB_SHIFT                                        29
+#define OMAP4_GPIO_DR4_LB_MASK                                 (1 << 29)
+#define OMAP4_GPIO_DR5_LB_SHIFT                                        28
+#define OMAP4_GPIO_DR5_LB_MASK                                 (1 << 28)
+#define OMAP4_GPIO_DR6_LB_SHIFT                                        27
+#define OMAP4_GPIO_DR6_LB_MASK                                 (1 << 27)
+#define OMAP4_HSI_DR1_LB_SHIFT                                 26
+#define OMAP4_HSI_DR1_LB_MASK                                  (1 << 26)
+#define OMAP4_HSI_DR2_LB_SHIFT                                 25
+#define OMAP4_HSI_DR2_LB_MASK                                  (1 << 25)
+#define OMAP4_HSI_DR3_LB_SHIFT                                 24
+#define OMAP4_HSI_DR3_LB_MASK                                  (1 << 24)
+#define OMAP4_MCBSP2_DR0_LB_SHIFT                              23
+#define OMAP4_MCBSP2_DR0_LB_MASK                               (1 << 23)
+#define OMAP4_MCSPI4_DR0_LB_SHIFT                              22
+#define OMAP4_MCSPI4_DR0_LB_MASK                               (1 << 22)
+#define OMAP4_MCSPI4_DR1_LB_SHIFT                              21
+#define OMAP4_MCSPI4_DR1_LB_MASK                               (1 << 21)
+#define OMAP4_SLIMBUS2_DR0_LB_SHIFT                            18
+#define OMAP4_SLIMBUS2_DR0_LB_MASK                             (1 << 18)
+#define OMAP4_SPI2_DR0_LB_SHIFT                                        16
+#define OMAP4_SPI2_DR0_LB_MASK                                 (1 << 16)
+#define OMAP4_SPI2_DR1_LB_SHIFT                                        15
+#define OMAP4_SPI2_DR1_LB_MASK                                 (1 << 15)
+#define OMAP4_SPI2_DR2_LB_SHIFT                                        14
+#define OMAP4_SPI2_DR2_LB_MASK                                 (1 << 14)
+#define OMAP4_UART2_DR0_LB_SHIFT                               13
+#define OMAP4_UART2_DR0_LB_MASK                                        (1 << 13)
+#define OMAP4_UART2_DR1_LB_SHIFT                               12
+#define OMAP4_UART2_DR1_LB_MASK                                        (1 << 12)
+#define OMAP4_UART4_DR0_LB_SHIFT                               11
+#define OMAP4_UART4_DR0_LB_MASK                                        (1 << 11)
+#define OMAP4_HSI_DR0_LB_SHIFT                                 10
+#define OMAP4_HSI_DR0_LB_MASK                                  (1 << 10)
+
+/* CONTROL_USBB_HSIC */
+#define OMAP4_USBB2_DR1_SR_SHIFT                               30
+#define OMAP4_USBB2_DR1_SR_MASK                                        (0x3 << 30)
+#define OMAP4_USBB2_DR1_I_SHIFT                                        27
+#define OMAP4_USBB2_DR1_I_MASK                                 (0x7 << 27)
+#define OMAP4_USBB1_DR1_SR_SHIFT                               25
+#define OMAP4_USBB1_DR1_SR_MASK                                        (0x3 << 25)
+#define OMAP4_USBB1_DR1_I_SHIFT                                        22
+#define OMAP4_USBB1_DR1_I_MASK                                 (0x7 << 22)
+#define OMAP4_USBB1_HSIC_DATA_WD_SHIFT                         20
+#define OMAP4_USBB1_HSIC_DATA_WD_MASK                          (0x3 << 20)
+#define OMAP4_USBB1_HSIC_STROBE_WD_SHIFT                       18
+#define OMAP4_USBB1_HSIC_STROBE_WD_MASK                                (0x3 << 18)
+#define OMAP4_USBB2_HSIC_DATA_WD_SHIFT                         16
+#define OMAP4_USBB2_HSIC_DATA_WD_MASK                          (0x3 << 16)
+#define OMAP4_USBB2_HSIC_STROBE_WD_SHIFT                       14
+#define OMAP4_USBB2_HSIC_STROBE_WD_MASK                                (0x3 << 14)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT          13
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_ENABLE_MASK           (1 << 13)
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_SHIFT                 11
+#define OMAP4_USBB1_HSIC_DATA_OFFMODE_WD_MASK                  (0x3 << 11)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT                10
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK         (1 << 10)
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_SHIFT               8
+#define OMAP4_USBB1_HSIC_STROBE_OFFMODE_WD_MASK                        (0x3 << 8)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_SHIFT          7
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_ENABLE_MASK           (1 << 7)
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_SHIFT                 5
+#define OMAP4_USBB2_HSIC_DATA_OFFMODE_WD_MASK                  (0x3 << 5)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_SHIFT                4
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_ENABLE_MASK         (1 << 4)
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_SHIFT               2
+#define OMAP4_USBB2_HSIC_STROBE_OFFMODE_WD_MASK                        (0x3 << 2)
+
+/* CONTROL_SLIMBUS */
+#define OMAP4_SLIMBUS1_DR0_MB_SHIFT                            30
+#define OMAP4_SLIMBUS1_DR0_MB_MASK                             (0x3 << 30)
+#define OMAP4_SLIMBUS1_DR1_MB_SHIFT                            28
+#define OMAP4_SLIMBUS1_DR1_MB_MASK                             (0x3 << 28)
+#define OMAP4_SLIMBUS2_DR0_MB_SHIFT                            26
+#define OMAP4_SLIMBUS2_DR0_MB_MASK                             (0x3 << 26)
+#define OMAP4_SLIMBUS2_DR1_MB_SHIFT                            24
+#define OMAP4_SLIMBUS2_DR1_MB_MASK                             (0x3 << 24)
+#define OMAP4_SLIMBUS2_DR2_MB_SHIFT                            22
+#define OMAP4_SLIMBUS2_DR2_MB_MASK                             (0x3 << 22)
+#define OMAP4_SLIMBUS2_DR3_MB_SHIFT                            20
+#define OMAP4_SLIMBUS2_DR3_MB_MASK                             (0x3 << 20)
+#define OMAP4_SLIMBUS1_DR0_LB_SHIFT                            19
+#define OMAP4_SLIMBUS1_DR0_LB_MASK                             (1 << 19)
+#define OMAP4_SLIMBUS2_DR1_LB_SHIFT                            18
+#define OMAP4_SLIMBUS2_DR1_LB_MASK                             (1 << 18)
+
+/* CONTROL_PBIASLITE */
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_SHIFT                    31
+#define OMAP4_USIM_PBIASLITE_HIZ_MODE_MASK                     (1 << 31)
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_SHIFT               30
+#define OMAP4_USIM_PBIASLITE_SUPPLY_HI_OUT_MASK                        (1 << 30)
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_SHIFT                 29
+#define OMAP4_USIM_PBIASLITE_VMODE_ERROR_MASK                  (1 << 29)
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_SHIFT                      28
+#define OMAP4_USIM_PBIASLITE_PWRDNZ_MASK                       (1 << 28)
+#define OMAP4_USIM_PBIASLITE_VMODE_SHIFT                       27
+#define OMAP4_USIM_PBIASLITE_VMODE_MASK                                (1 << 27)
+#define OMAP4_MMC1_PWRDNZ_SHIFT                                        26
+#define OMAP4_MMC1_PWRDNZ_MASK                                 (1 << 26)
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_SHIFT                    25
+#define OMAP4_MMC1_PBIASLITE_HIZ_MODE_MASK                     (1 << 25)
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_SHIFT               24
+#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT_MASK                        (1 << 24)
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_SHIFT                 23
+#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR_MASK                  (1 << 23)
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_SHIFT                      22
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ_MASK                       (1 << 22)
+#define OMAP4_MMC1_PBIASLITE_VMODE_SHIFT                       21
+#define OMAP4_MMC1_PBIASLITE_VMODE_MASK                                (1 << 21)
+#define OMAP4_USBC1_ICUSB_PWRDNZ_SHIFT                         20
+#define OMAP4_USBC1_ICUSB_PWRDNZ_MASK                          (1 << 20)
+
+/* CONTROL_I2C_0 */
+#define OMAP4_I2C4_SDA_GLFENB_SHIFT                            31
+#define OMAP4_I2C4_SDA_GLFENB_MASK                             (1 << 31)
+#define OMAP4_I2C4_SDA_LOAD_BITS_SHIFT                         29
+#define OMAP4_I2C4_SDA_LOAD_BITS_MASK                          (0x3 << 29)
+#define OMAP4_I2C4_SDA_PULLUPRESX_SHIFT                                28
+#define OMAP4_I2C4_SDA_PULLUPRESX_MASK                         (1 << 28)
+#define OMAP4_I2C3_SDA_GLFENB_SHIFT                            27
+#define OMAP4_I2C3_SDA_GLFENB_MASK                             (1 << 27)
+#define OMAP4_I2C3_SDA_LOAD_BITS_SHIFT                         25
+#define OMAP4_I2C3_SDA_LOAD_BITS_MASK                          (0x3 << 25)
+#define OMAP4_I2C3_SDA_PULLUPRESX_SHIFT                                24
+#define OMAP4_I2C3_SDA_PULLUPRESX_MASK                         (1 << 24)
+#define OMAP4_I2C2_SDA_GLFENB_SHIFT                            23
+#define OMAP4_I2C2_SDA_GLFENB_MASK                             (1 << 23)
+#define OMAP4_I2C2_SDA_LOAD_BITS_SHIFT                         21
+#define OMAP4_I2C2_SDA_LOAD_BITS_MASK                          (0x3 << 21)
+#define OMAP4_I2C2_SDA_PULLUPRESX_SHIFT                                20
+#define OMAP4_I2C2_SDA_PULLUPRESX_MASK                         (1 << 20)
+#define OMAP4_I2C1_SDA_GLFENB_SHIFT                            19
+#define OMAP4_I2C1_SDA_GLFENB_MASK                             (1 << 19)
+#define OMAP4_I2C1_SDA_LOAD_BITS_SHIFT                         17
+#define OMAP4_I2C1_SDA_LOAD_BITS_MASK                          (0x3 << 17)
+#define OMAP4_I2C1_SDA_PULLUPRESX_SHIFT                                16
+#define OMAP4_I2C1_SDA_PULLUPRESX_MASK                         (1 << 16)
+#define OMAP4_I2C4_SCL_GLFENB_SHIFT                            15
+#define OMAP4_I2C4_SCL_GLFENB_MASK                             (1 << 15)
+#define OMAP4_I2C4_SCL_LOAD_BITS_SHIFT                         13
+#define OMAP4_I2C4_SCL_LOAD_BITS_MASK                          (0x3 << 13)
+#define OMAP4_I2C4_SCL_PULLUPRESX_SHIFT                                12
+#define OMAP4_I2C4_SCL_PULLUPRESX_MASK                         (1 << 12)
+#define OMAP4_I2C3_SCL_GLFENB_SHIFT                            11
+#define OMAP4_I2C3_SCL_GLFENB_MASK                             (1 << 11)
+#define OMAP4_I2C3_SCL_LOAD_BITS_SHIFT                         9
+#define OMAP4_I2C3_SCL_LOAD_BITS_MASK                          (0x3 << 9)
+#define OMAP4_I2C3_SCL_PULLUPRESX_SHIFT                                8
+#define OMAP4_I2C3_SCL_PULLUPRESX_MASK                         (1 << 8)
+#define OMAP4_I2C2_SCL_GLFENB_SHIFT                            7
+#define OMAP4_I2C2_SCL_GLFENB_MASK                             (1 << 7)
+#define OMAP4_I2C2_SCL_LOAD_BITS_SHIFT                         5
+#define OMAP4_I2C2_SCL_LOAD_BITS_MASK                          (0x3 << 5)
+#define OMAP4_I2C2_SCL_PULLUPRESX_SHIFT                                4
+#define OMAP4_I2C2_SCL_PULLUPRESX_MASK                         (1 << 4)
+#define OMAP4_I2C1_SCL_GLFENB_SHIFT                            3
+#define OMAP4_I2C1_SCL_GLFENB_MASK                             (1 << 3)
+#define OMAP4_I2C1_SCL_LOAD_BITS_SHIFT                         1
+#define OMAP4_I2C1_SCL_LOAD_BITS_MASK                          (0x3 << 1)
+#define OMAP4_I2C1_SCL_PULLUPRESX_SHIFT                                0
+#define OMAP4_I2C1_SCL_PULLUPRESX_MASK                         (1 << 0)
+
+/* CONTROL_CAMERA_RX */
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_SHIFT                  31
+#define OMAP4_CAMERARX_UNIPRO_CTRLCLKEN_MASK                   (1 << 31)
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_SHIFT                  29
+#define OMAP4_CAMERARX_CSI22_LANEENABLE_MASK                   (0x3 << 29)
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_SHIFT                  24
+#define OMAP4_CAMERARX_CSI21_LANEENABLE_MASK                   (0x1f << 24)
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_SHIFT                    22
+#define OMAP4_CAMERARX_UNIPRO_CAMMODE_MASK                     (0x3 << 22)
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_SHIFT                   21
+#define OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK                    (1 << 21)
+#define OMAP4_CAMERARX_CSI22_CAMMODE_SHIFT                     19
+#define OMAP4_CAMERARX_CSI22_CAMMODE_MASK                      (0x3 << 19)
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_SHIFT                   18
+#define OMAP4_CAMERARX_CSI21_CTRLCLKEN_MASK                    (1 << 18)
+#define OMAP4_CAMERARX_CSI21_CAMMODE_SHIFT                     16
+#define OMAP4_CAMERARX_CSI21_CAMMODE_MASK                      (0x3 << 16)
+
+/* CONTROL_AVDAC */
+#define OMAP4_AVDAC_ACEN_SHIFT                                 31
+#define OMAP4_AVDAC_ACEN_MASK                                  (1 << 31)
+#define OMAP4_AVDAC_TVOUTBYPASS_SHIFT                          30
+#define OMAP4_AVDAC_TVOUTBYPASS_MASK                           (1 << 30)
+#define OMAP4_AVDAC_INPUTINV_SHIFT                             29
+#define OMAP4_AVDAC_INPUTINV_MASK                              (1 << 29)
+#define OMAP4_AVDAC_CTL_SHIFT                                  13
+#define OMAP4_AVDAC_CTL_MASK                                   (0xffff << 13)
+#define OMAP4_AVDAC_CTL_WR_ACK_SHIFT                           12
+#define OMAP4_AVDAC_CTL_WR_ACK_MASK                            (1 << 12)
+
+/* CONTROL_HDMI_TX_PHY */
+#define OMAP4_HDMITXPHY_PADORDER_SHIFT                         31
+#define OMAP4_HDMITXPHY_PADORDER_MASK                          (1 << 31)
+#define OMAP4_HDMITXPHY_TXVALID_SHIFT                          30
+#define OMAP4_HDMITXPHY_TXVALID_MASK                           (1 << 30)
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_SHIFT                      29
+#define OMAP4_HDMITXPHY_ENBYPASSCLK_MASK                       (1 << 29)
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_SHIFT                     28
+#define OMAP4_HDMITXPHY_PD_PULLUPDET_MASK                      (1 << 28)
+
+/* CONTROL_MMC2 */
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_SHIFT                      31
+#define OMAP4_MMC2_FEEDBACK_CLK_SEL_MASK                       (1 << 31)
+
+/* CONTROL_DSIPHY */
+#define OMAP4_DSI2_LANEENABLE_SHIFT                            29
+#define OMAP4_DSI2_LANEENABLE_MASK                             (0x7 << 29)
+#define OMAP4_DSI1_LANEENABLE_SHIFT                            24
+#define OMAP4_DSI1_LANEENABLE_MASK                             (0x1f << 24)
+#define OMAP4_DSI1_PIPD_SHIFT                                  19
+#define OMAP4_DSI1_PIPD_MASK                                   (0x1f << 19)
+#define OMAP4_DSI2_PIPD_SHIFT                                  14
+#define OMAP4_DSI2_PIPD_MASK                                   (0x1f << 14)
+
+/* CONTROL_MCBSPLP */
+#define OMAP4_ALBCTRLRX_FSX_SHIFT                              31
+#define OMAP4_ALBCTRLRX_FSX_MASK                               (1 << 31)
+#define OMAP4_ALBCTRLRX_CLKX_SHIFT                             30
+#define OMAP4_ALBCTRLRX_CLKX_MASK                              (1 << 30)
+#define OMAP4_ABE_MCBSP1_DR_EN_SHIFT                           29
+#define OMAP4_ABE_MCBSP1_DR_EN_MASK                            (1 << 29)
+
+/* CONTROL_USB2PHYCORE */
+#define OMAP4_USB2PHY_AUTORESUME_EN_SHIFT                      31
+#define OMAP4_USB2PHY_AUTORESUME_EN_MASK                       (1 << 31)
+#define OMAP4_USB2PHY_DISCHGDET_SHIFT                          30
+#define OMAP4_USB2PHY_DISCHGDET_MASK                           (1 << 30)
+#define OMAP4_USB2PHY_GPIOMODE_SHIFT                           29
+#define OMAP4_USB2PHY_GPIOMODE_MASK                            (1 << 29)
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_SHIFT                    28
+#define OMAP4_USB2PHY_CHG_DET_EXT_CTL_MASK                     (1 << 28)
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_SHIFT                   27
+#define OMAP4_USB2PHY_RDM_PD_CHGDET_EN_MASK                    (1 << 27)
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_SHIFT                   26
+#define OMAP4_USB2PHY_RDP_PU_CHGDET_EN_MASK                    (1 << 26)
+#define OMAP4_USB2PHY_CHG_VSRC_EN_SHIFT                                25
+#define OMAP4_USB2PHY_CHG_VSRC_EN_MASK                         (1 << 25)
+#define OMAP4_USB2PHY_CHG_ISINK_EN_SHIFT                       24
+#define OMAP4_USB2PHY_CHG_ISINK_EN_MASK                                (1 << 24)
+#define OMAP4_USB2PHY_CHG_DET_STATUS_SHIFT                     21
+#define OMAP4_USB2PHY_CHG_DET_STATUS_MASK                      (0x7 << 21)
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_SHIFT                    20
+#define OMAP4_USB2PHY_CHG_DET_DM_COMP_MASK                     (1 << 20)
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_SHIFT                    19
+#define OMAP4_USB2PHY_CHG_DET_DP_COMP_MASK                     (1 << 19)
+#define OMAP4_USB2PHY_DATADET_SHIFT                            18
+#define OMAP4_USB2PHY_DATADET_MASK                             (1 << 18)
+#define OMAP4_USB2PHY_SINKONDP_SHIFT                           17
+#define OMAP4_USB2PHY_SINKONDP_MASK                            (1 << 17)
+#define OMAP4_USB2PHY_SRCONDM_SHIFT                            16
+#define OMAP4_USB2PHY_SRCONDM_MASK                             (1 << 16)
+#define OMAP4_USB2PHY_RESTARTCHGDET_SHIFT                      15
+#define OMAP4_USB2PHY_RESTARTCHGDET_MASK                       (1 << 15)
+#define OMAP4_USB2PHY_CHGDETDONE_SHIFT                         14
+#define OMAP4_USB2PHY_CHGDETDONE_MASK                          (1 << 14)
+#define OMAP4_USB2PHY_CHGDETECTED_SHIFT                                13
+#define OMAP4_USB2PHY_CHGDETECTED_MASK                         (1 << 13)
+#define OMAP4_USB2PHY_MCPCPUEN_SHIFT                           12
+#define OMAP4_USB2PHY_MCPCPUEN_MASK                            (1 << 12)
+#define OMAP4_USB2PHY_MCPCMODEEN_SHIFT                         11
+#define OMAP4_USB2PHY_MCPCMODEEN_MASK                          (1 << 11)
+#define OMAP4_USB2PHY_RESETDONEMCLK_SHIFT                      10
+#define OMAP4_USB2PHY_RESETDONEMCLK_MASK                       (1 << 10)
+#define OMAP4_USB2PHY_UTMIRESETDONE_SHIFT                      9
+#define OMAP4_USB2PHY_UTMIRESETDONE_MASK                       (1 << 9)
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_SHIFT                   8
+#define OMAP4_USB2PHY_TXBITSTUFFENABLE_MASK                    (1 << 8)
+#define OMAP4_USB2PHY_DATAPOLARITYN_SHIFT                      7
+#define OMAP4_USB2PHY_DATAPOLARITYN_MASK                       (1 << 7)
+#define OMAP4_USBDPLL_FREQLOCK_SHIFT                           6
+#define OMAP4_USBDPLL_FREQLOCK_MASK                            (1 << 6)
+#define OMAP4_USB2PHY_RESETDONETCLK_SHIFT                      5
+#define OMAP4_USB2PHY_RESETDONETCLK_MASK                       (1 << 5)
+
+/* CONTROL_I2C_1 */
+#define OMAP4_HDMI_DDC_SDA_GLFENB_SHIFT                                31
+#define OMAP4_HDMI_DDC_SDA_GLFENB_MASK                         (1 << 31)
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_SHIFT                     29
+#define OMAP4_HDMI_DDC_SDA_LOAD_BITS_MASK                      (0x3 << 29)
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_SHIFT                    28
+#define OMAP4_HDMI_DDC_SDA_PULLUPRESX_MASK                     (1 << 28)
+#define OMAP4_HDMI_DDC_SCL_GLFENB_SHIFT                                27
+#define OMAP4_HDMI_DDC_SCL_GLFENB_MASK                         (1 << 27)
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_SHIFT                     25
+#define OMAP4_HDMI_DDC_SCL_LOAD_BITS_MASK                      (0x3 << 25)
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_SHIFT                    24
+#define OMAP4_HDMI_DDC_SCL_PULLUPRESX_MASK                     (1 << 24)
+#define OMAP4_HDMI_DDC_SDA_HSMODE_SHIFT                                23
+#define OMAP4_HDMI_DDC_SDA_HSMODE_MASK                         (1 << 23)
+#define OMAP4_HDMI_DDC_SDA_NMODE_SHIFT                         22
+#define OMAP4_HDMI_DDC_SDA_NMODE_MASK                          (1 << 22)
+#define OMAP4_HDMI_DDC_SCL_HSMODE_SHIFT                                21
+#define OMAP4_HDMI_DDC_SCL_HSMODE_MASK                         (1 << 21)
+#define OMAP4_HDMI_DDC_SCL_NMODE_SHIFT                         20
+#define OMAP4_HDMI_DDC_SCL_NMODE_MASK                          (1 << 20)
+
+/* CONTROL_MMC1 */
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_SHIFT                     31
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK                      (1 << 31)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_SHIFT                     30
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK                      (1 << 30)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_SHIFT                     29
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK                      (1 << 29)
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_SHIFT                     28
+#define OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK                      (1 << 28)
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_SHIFT                       27
+#define OMAP4_SDMMC1_DR0_SPEEDCTRL_MASK                                (1 << 27)
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_SHIFT                       26
+#define OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK                                (1 << 26)
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_SHIFT                       25
+#define OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK                                (1 << 25)
+#define OMAP4_USBC1_DR0_SPEEDCTRL_SHIFT                                24
+#define OMAP4_USBC1_DR0_SPEEDCTRL_MASK                         (1 << 24)
+#define OMAP4_USB_FD_CDEN_SHIFT                                        23
+#define OMAP4_USB_FD_CDEN_MASK                                 (1 << 23)
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_SHIFT                       22
+#define OMAP4_USBC1_ICUSB_DP_PDDIS_MASK                                (1 << 22)
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_SHIFT                       21
+#define OMAP4_USBC1_ICUSB_DM_PDDIS_MASK                                (1 << 21)
+
+/* CONTROL_HSI */
+#define OMAP4_HSI1_CALLOOP_SEL_SHIFT                           31
+#define OMAP4_HSI1_CALLOOP_SEL_MASK                            (1 << 31)
+#define OMAP4_HSI1_CALMUX_SEL_SHIFT                            30
+#define OMAP4_HSI1_CALMUX_SEL_MASK                             (1 << 30)
+#define OMAP4_HSI2_CALLOOP_SEL_SHIFT                           29
+#define OMAP4_HSI2_CALLOOP_SEL_MASK                            (1 << 29)
+#define OMAP4_HSI2_CALMUX_SEL_SHIFT                            28
+#define OMAP4_HSI2_CALMUX_SEL_MASK                             (1 << 28)
+
+/* CONTROL_USB */
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_SHIFT          31
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT0_AUTO_EN_MASK           (1 << 31)
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_SHIFT          30
+#define OMAP4_CARKIT_USBA0_ULPIPHY_DAT1_AUTO_EN_MASK           (1 << 30)
+
+/* CONTROL_HDQ */
+#define OMAP4_HDQ_SIO_PWRDNZ_SHIFT                             31
+#define OMAP4_HDQ_SIO_PWRDNZ_MASK                              (1 << 31)
+
+/* CONTROL_LPDDR2IO1_0 */
+#define OMAP4_LPDDR2IO1_GR4_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO1_GR4_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR4_I_SHIFT                            27
+#define OMAP4_LPDDR2IO1_GR4_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR4_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO1_GR4_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR3_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO1_GR3_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR3_I_SHIFT                            19
+#define OMAP4_LPDDR2IO1_GR3_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR3_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO1_GR3_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR2_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO1_GR2_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR2_I_SHIFT                            11
+#define OMAP4_LPDDR2IO1_GR2_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR2_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO1_GR2_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR1_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO1_GR1_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR1_I_SHIFT                            3
+#define OMAP4_LPDDR2IO1_GR1_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR1_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO1_GR1_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_1 */
+#define OMAP4_LPDDR2IO1_GR8_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO1_GR8_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR8_I_SHIFT                            27
+#define OMAP4_LPDDR2IO1_GR8_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR8_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO1_GR8_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR7_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO1_GR7_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR7_I_SHIFT                            19
+#define OMAP4_LPDDR2IO1_GR7_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR7_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO1_GR7_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR6_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO1_GR6_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR6_I_SHIFT                            11
+#define OMAP4_LPDDR2IO1_GR6_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR6_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO1_GR6_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO1_GR5_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO1_GR5_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO1_GR5_I_SHIFT                            3
+#define OMAP4_LPDDR2IO1_GR5_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO1_GR5_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO1_GR5_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO1_2 */
+#define OMAP4_LPDDR2IO1_GR11_SR_SHIFT                          30
+#define OMAP4_LPDDR2IO1_GR11_SR_MASK                           (0x3 << 30)
+#define OMAP4_LPDDR2IO1_GR11_I_SHIFT                           27
+#define OMAP4_LPDDR2IO1_GR11_I_MASK                            (0x7 << 27)
+#define OMAP4_LPDDR2IO1_GR11_WD_SHIFT                          25
+#define OMAP4_LPDDR2IO1_GR11_WD_MASK                           (0x3 << 25)
+#define OMAP4_LPDDR2IO1_GR10_SR_SHIFT                          22
+#define OMAP4_LPDDR2IO1_GR10_SR_MASK                           (0x3 << 22)
+#define OMAP4_LPDDR2IO1_GR10_I_SHIFT                           19
+#define OMAP4_LPDDR2IO1_GR10_I_MASK                            (0x7 << 19)
+#define OMAP4_LPDDR2IO1_GR10_WD_SHIFT                          17
+#define OMAP4_LPDDR2IO1_GR10_WD_MASK                           (0x3 << 17)
+#define OMAP4_LPDDR2IO1_GR9_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO1_GR9_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO1_GR9_I_SHIFT                            11
+#define OMAP4_LPDDR2IO1_GR9_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO1_GR9_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO1_GR9_WD_MASK                            (0x3 << 9)
+
+/* CONTROL_LPDDR2IO1_3 */
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_SHIFT                      31
+#define OMAP4_LPDDR21_VREF_CA_CCAP0_MASK                       (1 << 31)
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_SHIFT                      30
+#define OMAP4_LPDDR21_VREF_CA_CCAP1_MASK                       (1 << 30)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_SHIFT                  29
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP0_MASK                   (1 << 29)
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_SHIFT                  28
+#define OMAP4_LPDDR21_VREF_CA_INT_CCAP1_MASK                   (1 << 28)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_SHIFT                   27
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP0_MASK                    (1 << 27)
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_SHIFT                   26
+#define OMAP4_LPDDR21_VREF_CA_INT_TAP1_MASK                    (1 << 26)
+#define OMAP4_LPDDR21_VREF_CA_TAP0_SHIFT                       25
+#define OMAP4_LPDDR21_VREF_CA_TAP0_MASK                                (1 << 25)
+#define OMAP4_LPDDR21_VREF_CA_TAP1_SHIFT                       24
+#define OMAP4_LPDDR21_VREF_CA_TAP1_MASK                                (1 << 24)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_SHIFT                 23
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP0_MASK                  (1 << 23)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_SHIFT                 22
+#define OMAP4_LPDDR21_VREF_DQ0_INT_CCAP1_MASK                  (1 << 22)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_SHIFT                  21
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP0_MASK                   (1 << 21)
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_SHIFT                  20
+#define OMAP4_LPDDR21_VREF_DQ0_INT_TAP1_MASK                   (1 << 20)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_SHIFT                 19
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP0_MASK                  (1 << 19)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_SHIFT                 18
+#define OMAP4_LPDDR21_VREF_DQ1_INT_CCAP1_MASK                  (1 << 18)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_SHIFT                  17
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP0_MASK                   (1 << 17)
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_SHIFT                  16
+#define OMAP4_LPDDR21_VREF_DQ1_INT_TAP1_MASK                   (1 << 16)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_SHIFT                      15
+#define OMAP4_LPDDR21_VREF_DQ_CCAP0_MASK                       (1 << 15)
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_SHIFT                      14
+#define OMAP4_LPDDR21_VREF_DQ_CCAP1_MASK                       (1 << 14)
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_SHIFT                       13
+#define OMAP4_LPDDR21_VREF_DQ_TAP0_MASK                                (1 << 13)
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_SHIFT                       12
+#define OMAP4_LPDDR21_VREF_DQ_TAP1_MASK                                (1 << 12)
+
+/* CONTROL_LPDDR2IO2_0 */
+#define OMAP4_LPDDR2IO2_GR4_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO2_GR4_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR4_I_SHIFT                            27
+#define OMAP4_LPDDR2IO2_GR4_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR4_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO2_GR4_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR3_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO2_GR3_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR3_I_SHIFT                            19
+#define OMAP4_LPDDR2IO2_GR3_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR3_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO2_GR3_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR2_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO2_GR2_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR2_I_SHIFT                            11
+#define OMAP4_LPDDR2IO2_GR2_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR2_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO2_GR2_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR1_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO2_GR1_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR1_I_SHIFT                            3
+#define OMAP4_LPDDR2IO2_GR1_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR1_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO2_GR1_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_1 */
+#define OMAP4_LPDDR2IO2_GR8_SR_SHIFT                           30
+#define OMAP4_LPDDR2IO2_GR8_SR_MASK                            (0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR8_I_SHIFT                            27
+#define OMAP4_LPDDR2IO2_GR8_I_MASK                             (0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR8_WD_SHIFT                           25
+#define OMAP4_LPDDR2IO2_GR8_WD_MASK                            (0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR7_SR_SHIFT                           22
+#define OMAP4_LPDDR2IO2_GR7_SR_MASK                            (0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR7_I_SHIFT                            19
+#define OMAP4_LPDDR2IO2_GR7_I_MASK                             (0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR7_WD_SHIFT                           17
+#define OMAP4_LPDDR2IO2_GR7_WD_MASK                            (0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR6_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO2_GR6_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR6_I_SHIFT                            11
+#define OMAP4_LPDDR2IO2_GR6_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR6_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO2_GR6_WD_MASK                            (0x3 << 9)
+#define OMAP4_LPDDR2IO2_GR5_SR_SHIFT                           6
+#define OMAP4_LPDDR2IO2_GR5_SR_MASK                            (0x3 << 6)
+#define OMAP4_LPDDR2IO2_GR5_I_SHIFT                            3
+#define OMAP4_LPDDR2IO2_GR5_I_MASK                             (0x7 << 3)
+#define OMAP4_LPDDR2IO2_GR5_WD_SHIFT                           1
+#define OMAP4_LPDDR2IO2_GR5_WD_MASK                            (0x3 << 1)
+
+/* CONTROL_LPDDR2IO2_2 */
+#define OMAP4_LPDDR2IO2_GR11_SR_SHIFT                          30
+#define OMAP4_LPDDR2IO2_GR11_SR_MASK                           (0x3 << 30)
+#define OMAP4_LPDDR2IO2_GR11_I_SHIFT                           27
+#define OMAP4_LPDDR2IO2_GR11_I_MASK                            (0x7 << 27)
+#define OMAP4_LPDDR2IO2_GR11_WD_SHIFT                          25
+#define OMAP4_LPDDR2IO2_GR11_WD_MASK                           (0x3 << 25)
+#define OMAP4_LPDDR2IO2_GR10_SR_SHIFT                          22
+#define OMAP4_LPDDR2IO2_GR10_SR_MASK                           (0x3 << 22)
+#define OMAP4_LPDDR2IO2_GR10_I_SHIFT                           19
+#define OMAP4_LPDDR2IO2_GR10_I_MASK                            (0x7 << 19)
+#define OMAP4_LPDDR2IO2_GR10_WD_SHIFT                          17
+#define OMAP4_LPDDR2IO2_GR10_WD_MASK                           (0x3 << 17)
+#define OMAP4_LPDDR2IO2_GR9_SR_SHIFT                           14
+#define OMAP4_LPDDR2IO2_GR9_SR_MASK                            (0x3 << 14)
+#define OMAP4_LPDDR2IO2_GR9_I_SHIFT                            11
+#define OMAP4_LPDDR2IO2_GR9_I_MASK                             (0x7 << 11)
+#define OMAP4_LPDDR2IO2_GR9_WD_SHIFT                           9
+#define OMAP4_LPDDR2IO2_GR9_WD_MASK                            (0x3 << 9)
+
+/* CONTROL_LPDDR2IO2_3 */
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_SHIFT                      31
+#define OMAP4_LPDDR22_VREF_CA_CCAP0_MASK                       (1 << 31)
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_SHIFT                      30
+#define OMAP4_LPDDR22_VREF_CA_CCAP1_MASK                       (1 << 30)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_SHIFT                  29
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP0_MASK                   (1 << 29)
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_SHIFT                  28
+#define OMAP4_LPDDR22_VREF_CA_INT_CCAP1_MASK                   (1 << 28)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_SHIFT                   27
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP0_MASK                    (1 << 27)
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_SHIFT                   26
+#define OMAP4_LPDDR22_VREF_CA_INT_TAP1_MASK                    (1 << 26)
+#define OMAP4_LPDDR22_VREF_CA_TAP0_SHIFT                       25
+#define OMAP4_LPDDR22_VREF_CA_TAP0_MASK                                (1 << 25)
+#define OMAP4_LPDDR22_VREF_CA_TAP1_SHIFT                       24
+#define OMAP4_LPDDR22_VREF_CA_TAP1_MASK                                (1 << 24)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_SHIFT                 23
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP0_MASK                  (1 << 23)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_SHIFT                 22
+#define OMAP4_LPDDR22_VREF_DQ0_INT_CCAP1_MASK                  (1 << 22)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_SHIFT                  21
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP0_MASK                   (1 << 21)
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_SHIFT                  20
+#define OMAP4_LPDDR22_VREF_DQ0_INT_TAP1_MASK                   (1 << 20)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_SHIFT                 19
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP0_MASK                  (1 << 19)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_SHIFT                 18
+#define OMAP4_LPDDR22_VREF_DQ1_INT_CCAP1_MASK                  (1 << 18)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_SHIFT                  17
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP0_MASK                   (1 << 17)
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_SHIFT                  16
+#define OMAP4_LPDDR22_VREF_DQ1_INT_TAP1_MASK                   (1 << 16)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_SHIFT                      15
+#define OMAP4_LPDDR22_VREF_DQ_CCAP0_MASK                       (1 << 15)
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_SHIFT                      14
+#define OMAP4_LPDDR22_VREF_DQ_CCAP1_MASK                       (1 << 14)
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_SHIFT                       13
+#define OMAP4_LPDDR22_VREF_DQ_TAP0_MASK                                (1 << 13)
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_SHIFT                       12
+#define OMAP4_LPDDR22_VREF_DQ_TAP1_MASK                                (1 << 12)
+
+/* CONTROL_BUS_HOLD */
+#define OMAP4_ABE_DMIC_DIN3_EN_SHIFT                           31
+#define OMAP4_ABE_DMIC_DIN3_EN_MASK                            (1 << 31)
+#define OMAP4_MCSPI1_CS3_EN_SHIFT                              30
+#define OMAP4_MCSPI1_CS3_EN_MASK                               (1 << 30)
+
+/* CONTROL_C2C */
+#define OMAP4_MIRROR_MODE_EN_SHIFT                             31
+#define OMAP4_MIRROR_MODE_EN_MASK                              (1 << 31)
+#define OMAP4_C2C_SPARE_SHIFT                                  24
+#define OMAP4_C2C_SPARE_MASK                                   (0x7f << 24)
+
+/* CORE_CONTROL_SPARE_RW */
+#define OMAP4_CORE_CONTROL_SPARE_RW_SHIFT                      0
+#define OMAP4_CORE_CONTROL_SPARE_RW_MASK                       (0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R */
+#define OMAP4_CORE_CONTROL_SPARE_R_SHIFT                       0
+#define OMAP4_CORE_CONTROL_SPARE_R_MASK                                (0xffffffff << 0)
+
+/* CORE_CONTROL_SPARE_R_C0 */
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_SHIFT                    31
+#define OMAP4_CORE_CONTROL_SPARE_R_C0_MASK                     (1 << 31)
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_SHIFT                    30
+#define OMAP4_CORE_CONTROL_SPARE_R_C1_MASK                     (1 << 30)
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_SHIFT                    29
+#define OMAP4_CORE_CONTROL_SPARE_R_C2_MASK                     (1 << 29)
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_SHIFT                    28
+#define OMAP4_CORE_CONTROL_SPARE_R_C3_MASK                     (1 << 28)
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_SHIFT                    27
+#define OMAP4_CORE_CONTROL_SPARE_R_C4_MASK                     (1 << 27)
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_SHIFT                    26
+#define OMAP4_CORE_CONTROL_SPARE_R_C5_MASK                     (1 << 26)
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_SHIFT                    25
+#define OMAP4_CORE_CONTROL_SPARE_R_C6_MASK                     (1 << 25)
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_SHIFT                    24
+#define OMAP4_CORE_CONTROL_SPARE_R_C7_MASK                     (1 << 24)
+
+/* CONTROL_EFUSE_1 */
+#define OMAP4_AVDAC_TRIM_BYTE3_SHIFT                           24
+#define OMAP4_AVDAC_TRIM_BYTE3_MASK                            (0x7f << 24)
+#define OMAP4_AVDAC_TRIM_BYTE2_SHIFT                           16
+#define OMAP4_AVDAC_TRIM_BYTE2_MASK                            (0xff << 16)
+#define OMAP4_AVDAC_TRIM_BYTE1_SHIFT                           8
+#define OMAP4_AVDAC_TRIM_BYTE1_MASK                            (0xff << 8)
+#define OMAP4_AVDAC_TRIM_BYTE0_SHIFT                           0
+#define OMAP4_AVDAC_TRIM_BYTE0_MASK                            (0xff << 0)
+
+/* CONTROL_EFUSE_2 */
+#define OMAP4_EFUSE_SMART2TEST_P0_SHIFT                                31
+#define OMAP4_EFUSE_SMART2TEST_P0_MASK                         (1 << 31)
+#define OMAP4_EFUSE_SMART2TEST_P1_SHIFT                                30
+#define OMAP4_EFUSE_SMART2TEST_P1_MASK                         (1 << 30)
+#define OMAP4_EFUSE_SMART2TEST_P2_SHIFT                                29
+#define OMAP4_EFUSE_SMART2TEST_P2_MASK                         (1 << 29)
+#define OMAP4_EFUSE_SMART2TEST_P3_SHIFT                                28
+#define OMAP4_EFUSE_SMART2TEST_P3_MASK                         (1 << 28)
+#define OMAP4_EFUSE_SMART2TEST_N0_SHIFT                                27
+#define OMAP4_EFUSE_SMART2TEST_N0_MASK                         (1 << 27)
+#define OMAP4_EFUSE_SMART2TEST_N1_SHIFT                                26
+#define OMAP4_EFUSE_SMART2TEST_N1_MASK                         (1 << 26)
+#define OMAP4_EFUSE_SMART2TEST_N2_SHIFT                                25
+#define OMAP4_EFUSE_SMART2TEST_N2_MASK                         (1 << 25)
+#define OMAP4_EFUSE_SMART2TEST_N3_SHIFT                                24
+#define OMAP4_EFUSE_SMART2TEST_N3_MASK                         (1 << 24)
+#define OMAP4_LPDDR2_PTV_N1_SHIFT                              23
+#define OMAP4_LPDDR2_PTV_N1_MASK                               (1 << 23)
+#define OMAP4_LPDDR2_PTV_N2_SHIFT                              22
+#define OMAP4_LPDDR2_PTV_N2_MASK                               (1 << 22)
+#define OMAP4_LPDDR2_PTV_N3_SHIFT                              21
+#define OMAP4_LPDDR2_PTV_N3_MASK                               (1 << 21)
+#define OMAP4_LPDDR2_PTV_N4_SHIFT                              20
+#define OMAP4_LPDDR2_PTV_N4_MASK                               (1 << 20)
+#define OMAP4_LPDDR2_PTV_N5_SHIFT                              19
+#define OMAP4_LPDDR2_PTV_N5_MASK                               (1 << 19)
+#define OMAP4_LPDDR2_PTV_P1_SHIFT                              18
+#define OMAP4_LPDDR2_PTV_P1_MASK                               (1 << 18)
+#define OMAP4_LPDDR2_PTV_P2_SHIFT                              17
+#define OMAP4_LPDDR2_PTV_P2_MASK                               (1 << 17)
+#define OMAP4_LPDDR2_PTV_P3_SHIFT                              16
+#define OMAP4_LPDDR2_PTV_P3_MASK                               (1 << 16)
+#define OMAP4_LPDDR2_PTV_P4_SHIFT                              15
+#define OMAP4_LPDDR2_PTV_P4_MASK                               (1 << 15)
+#define OMAP4_LPDDR2_PTV_P5_SHIFT                              14
+#define OMAP4_LPDDR2_PTV_P5_MASK                               (1 << 14)
+
+/* CONTROL_EFUSE_3 */
+#define OMAP4_STD_FUSE_SPARE_1_SHIFT                           24
+#define OMAP4_STD_FUSE_SPARE_1_MASK                            (0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_2_SHIFT                           16
+#define OMAP4_STD_FUSE_SPARE_2_MASK                            (0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_3_SHIFT                           8
+#define OMAP4_STD_FUSE_SPARE_3_MASK                            (0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_4_SHIFT                           0
+#define OMAP4_STD_FUSE_SPARE_4_MASK                            (0xff << 0)
+
+/* CONTROL_EFUSE_4 */
+#define OMAP4_STD_FUSE_SPARE_5_SHIFT                           24
+#define OMAP4_STD_FUSE_SPARE_5_MASK                            (0xff << 24)
+#define OMAP4_STD_FUSE_SPARE_6_SHIFT                           16
+#define OMAP4_STD_FUSE_SPARE_6_MASK                            (0xff << 16)
+#define OMAP4_STD_FUSE_SPARE_7_SHIFT                           8
+#define OMAP4_STD_FUSE_SPARE_7_MASK                            (0xff << 8)
+#define OMAP4_STD_FUSE_SPARE_8_SHIFT                           0
+#define OMAP4_STD_FUSE_SPARE_8_MASK                            (0xff << 0)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_pad_wkup_44xx.h
new file mode 100644 (file)
index 0000000..17c9b37
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * OMAP44xx CTRL_MODULE_PAD_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_PAD_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_PAD_WKUP                                     0x4a31e000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_REVISION                         0x0000
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_HWINFO                           0x0004
+#define OMAP4_CTRL_MODULE_PAD_WKUP_IP_SYSCONFIG                                0x0010
+#define OMAP4_CTRL_MODULE_PAD_WKUP_PADCONF_WAKEUPEVENT_0               0x007c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_0      0x05a0
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SMART1NOPMIO_PADCONF_1      0x05a4
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_PADCONF_MODE                        0x05a8
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_XTAL_OSCILLATOR             0x05ac
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_USIMIO                      0x0600
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_I2C_2                       0x0604
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_JTAG                                0x0608
+#define OMAP4_CTRL_MODULE_PAD_WKUP_CONTROL_SYS                         0x060c
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_RW               0x0614
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R                        0x0618
+#define OMAP4_CTRL_MODULE_PAD_WKUP_WKUP_CONTROL_SPARE_R_C0             0x061c
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT                              30
+#define OMAP4_IP_REV_SCHEME_MASK                               (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                                        16
+#define OMAP4_IP_REV_FUNC_MASK                                 (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                                 11
+#define OMAP4_IP_REV_RTL_MASK                                  (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT                               8
+#define OMAP4_IP_REV_MAJOR_MASK                                        (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT                              6
+#define OMAP4_IP_REV_CUSTOM_MASK                               (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT                               0
+#define OMAP4_IP_REV_MINOR_MASK                                        (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                                  0
+#define OMAP4_IP_HWINFO_MASK                                   (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT                      2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK                       (0x3 << 2)
+
+/* PADCONF_WAKEUPEVENT_0 */
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_SHIFT              24
+#define OMAP4_JTAG_TDO_DUPLICATEWAKEUPEVENT_MASK               (1 << 24)
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_SHIFT              23
+#define OMAP4_JTAG_TDI_DUPLICATEWAKEUPEVENT_MASK               (1 << 23)
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_SHIFT         22
+#define OMAP4_JTAG_TMS_TMSC_DUPLICATEWAKEUPEVENT_MASK          (1 << 22)
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_SHIFT             21
+#define OMAP4_JTAG_RTCK_DUPLICATEWAKEUPEVENT_MASK              (1 << 21)
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_SHIFT              20
+#define OMAP4_JTAG_TCK_DUPLICATEWAKEUPEVENT_MASK               (1 << 20)
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_SHIFT            19
+#define OMAP4_JTAG_NTRST_DUPLICATEWAKEUPEVENT_MASK             (1 << 19)
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_SHIFT             18
+#define OMAP4_SYS_BOOT7_DUPLICATEWAKEUPEVENT_MASK              (1 << 18)
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_SHIFT             17
+#define OMAP4_SYS_BOOT6_DUPLICATEWAKEUPEVENT_MASK              (1 << 17)
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_SHIFT   16
+#define OMAP4_SYS_PWRON_RESET_OUT_DUPLICATEWAKEUPEVENT_MASK    (1 << 16)
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_SHIFT           15
+#define OMAP4_SYS_PWR_REQ_DUPLICATEWAKEUPEVENT_MASK            (1 << 15)
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_SHIFT          14
+#define OMAP4_SYS_NRESWARM_DUPLICATEWAKEUPEVENT_MASK           (1 << 14)
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_SHIFT               13
+#define OMAP4_SYS_32K_DUPLICATEWAKEUPEVENT_MASK                        (1 << 13)
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_SHIFT         12
+#define OMAP4_FREF_CLK4_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 12)
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_SHIFT         11
+#define OMAP4_FREF_CLK4_REQ_DUPLICATEWAKEUPEVENT_MASK          (1 << 11)
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_SHIFT         10
+#define OMAP4_FREF_CLK3_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 10)
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_SHIFT         9
+#define OMAP4_FREF_CLK3_REQ_DUPLICATEWAKEUPEVENT_MASK          (1 << 9)
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_SHIFT         8
+#define OMAP4_FREF_CLK0_OUT_DUPLICATEWAKEUPEVENT_MASK          (1 << 8)
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_SHIFT                7
+#define OMAP4_FREF_CLK_IOREQ_DUPLICATEWAKEUPEVENT_MASK         (1 << 7)
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_SHIFT                        6
+#define OMAP4_SR_SDA_DUPLICATEWAKEUPEVENT_MASK                 (1 << 6)
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_SHIFT                        5
+#define OMAP4_SR_SCL_DUPLICATEWAKEUPEVENT_MASK                 (1 << 5)
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_SHIFT           4
+#define OMAP4_SIM_PWRCTRL_DUPLICATEWAKEUPEVENT_MASK            (1 << 4)
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_SHIFT                        3
+#define OMAP4_SIM_CD_DUPLICATEWAKEUPEVENT_MASK                 (1 << 3)
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_SHIFT             2
+#define OMAP4_SIM_RESET_DUPLICATEWAKEUPEVENT_MASK              (1 << 2)
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_SHIFT               1
+#define OMAP4_SIM_CLK_DUPLICATEWAKEUPEVENT_MASK                        (1 << 1)
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_SHIFT                        0
+#define OMAP4_SIM_IO_DUPLICATEWAKEUPEVENT_MASK                 (1 << 0)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_0 */
+#define OMAP4_FREF_DR0_SC_SHIFT                                        30
+#define OMAP4_FREF_DR0_SC_MASK                                 (0x3 << 30)
+#define OMAP4_FREF_DR1_SC_SHIFT                                        28
+#define OMAP4_FREF_DR1_SC_MASK                                 (0x3 << 28)
+#define OMAP4_FREF_DR4_SC_SHIFT                                        26
+#define OMAP4_FREF_DR4_SC_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR5_SC_SHIFT                                        24
+#define OMAP4_FREF_DR5_SC_MASK                                 (0x3 << 24)
+#define OMAP4_FREF_DR6_SC_SHIFT                                        22
+#define OMAP4_FREF_DR6_SC_MASK                                 (0x3 << 22)
+#define OMAP4_FREF_DR7_SC_SHIFT                                        20
+#define OMAP4_FREF_DR7_SC_MASK                                 (0x3 << 20)
+#define OMAP4_GPIO_DR7_SC_SHIFT                                        18
+#define OMAP4_GPIO_DR7_SC_MASK                                 (0x3 << 18)
+#define OMAP4_DPM_DR0_SC_SHIFT                                 14
+#define OMAP4_DPM_DR0_SC_MASK                                  (0x3 << 14)
+#define OMAP4_SIM_DR0_SC_SHIFT                                 12
+#define OMAP4_SIM_DR0_SC_MASK                                  (0x3 << 12)
+
+/* CONTROL_SMART1NOPMIO_PADCONF_1 */
+#define OMAP4_FREF_DR0_LB_SHIFT                                        30
+#define OMAP4_FREF_DR0_LB_MASK                                 (0x3 << 30)
+#define OMAP4_FREF_DR1_LB_SHIFT                                        28
+#define OMAP4_FREF_DR1_LB_MASK                                 (0x3 << 28)
+#define OMAP4_FREF_DR4_LB_SHIFT                                        26
+#define OMAP4_FREF_DR4_LB_MASK                                 (0x3 << 26)
+#define OMAP4_FREF_DR5_LB_SHIFT                                        24
+#define OMAP4_FREF_DR5_LB_MASK                                 (0x3 << 24)
+#define OMAP4_FREF_DR6_LB_SHIFT                                        22
+#define OMAP4_FREF_DR6_LB_MASK                                 (0x3 << 22)
+#define OMAP4_FREF_DR7_LB_SHIFT                                        20
+#define OMAP4_FREF_DR7_LB_MASK                                 (0x3 << 20)
+#define OMAP4_GPIO_DR7_LB_SHIFT                                        18
+#define OMAP4_GPIO_DR7_LB_MASK                                 (0x3 << 18)
+#define OMAP4_DPM_DR0_LB_SHIFT                                 14
+#define OMAP4_DPM_DR0_LB_MASK                                  (0x3 << 14)
+#define OMAP4_SIM_DR0_LB_SHIFT                                 12
+#define OMAP4_SIM_DR0_LB_MASK                                  (0x3 << 12)
+
+/* CONTROL_PADCONF_MODE */
+#define OMAP4_VDDS_DV_FREF_SHIFT                               31
+#define OMAP4_VDDS_DV_FREF_MASK                                        (1 << 31)
+#define OMAP4_VDDS_DV_BANK2_SHIFT                              30
+#define OMAP4_VDDS_DV_BANK2_MASK                               (1 << 30)
+
+/* CONTROL_XTAL_OSCILLATOR */
+#define OMAP4_OSCILLATOR_BOOST_SHIFT                           31
+#define OMAP4_OSCILLATOR_BOOST_MASK                            (1 << 31)
+#define OMAP4_OSCILLATOR_OS_OUT_SHIFT                          30
+#define OMAP4_OSCILLATOR_OS_OUT_MASK                           (1 << 30)
+
+/* CONTROL_USIMIO */
+#define OMAP4_PAD_USIM_CLK_LOW_SHIFT                           31
+#define OMAP4_PAD_USIM_CLK_LOW_MASK                            (1 << 31)
+#define OMAP4_PAD_USIM_RST_LOW_SHIFT                           29
+#define OMAP4_PAD_USIM_RST_LOW_MASK                            (1 << 29)
+#define OMAP4_USIM_PWRDNZ_SHIFT                                        28
+#define OMAP4_USIM_PWRDNZ_MASK                                 (1 << 28)
+
+/* CONTROL_I2C_2 */
+#define OMAP4_SR_SDA_GLFENB_SHIFT                              31
+#define OMAP4_SR_SDA_GLFENB_MASK                               (1 << 31)
+#define OMAP4_SR_SDA_LOAD_BITS_SHIFT                           29
+#define OMAP4_SR_SDA_LOAD_BITS_MASK                            (0x3 << 29)
+#define OMAP4_SR_SDA_PULLUPRESX_SHIFT                          28
+#define OMAP4_SR_SDA_PULLUPRESX_MASK                           (1 << 28)
+#define OMAP4_SR_SCL_GLFENB_SHIFT                              27
+#define OMAP4_SR_SCL_GLFENB_MASK                               (1 << 27)
+#define OMAP4_SR_SCL_LOAD_BITS_SHIFT                           25
+#define OMAP4_SR_SCL_LOAD_BITS_MASK                            (0x3 << 25)
+#define OMAP4_SR_SCL_PULLUPRESX_SHIFT                          24
+#define OMAP4_SR_SCL_PULLUPRESX_MASK                           (1 << 24)
+
+/* CONTROL_JTAG */
+#define OMAP4_JTAG_NTRST_EN_SHIFT                              31
+#define OMAP4_JTAG_NTRST_EN_MASK                               (1 << 31)
+#define OMAP4_JTAG_TCK_EN_SHIFT                                        30
+#define OMAP4_JTAG_TCK_EN_MASK                                 (1 << 30)
+#define OMAP4_JTAG_RTCK_EN_SHIFT                               29
+#define OMAP4_JTAG_RTCK_EN_MASK                                        (1 << 29)
+#define OMAP4_JTAG_TDI_EN_SHIFT                                        28
+#define OMAP4_JTAG_TDI_EN_MASK                                 (1 << 28)
+#define OMAP4_JTAG_TDO_EN_SHIFT                                        27
+#define OMAP4_JTAG_TDO_EN_MASK                                 (1 << 27)
+
+/* CONTROL_SYS */
+#define OMAP4_SYS_NRESWARM_PIPU_SHIFT                          31
+#define OMAP4_SYS_NRESWARM_PIPU_MASK                           (1 << 31)
+
+/* WKUP_CONTROL_SPARE_RW */
+#define OMAP4_WKUP_CONTROL_SPARE_RW_SHIFT                      0
+#define OMAP4_WKUP_CONTROL_SPARE_RW_MASK                       (0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R */
+#define OMAP4_WKUP_CONTROL_SPARE_R_SHIFT                       0
+#define OMAP4_WKUP_CONTROL_SPARE_R_MASK                                (0xffffffff << 0)
+
+/* WKUP_CONTROL_SPARE_R_C0 */
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_SHIFT                    31
+#define OMAP4_WKUP_CONTROL_SPARE_R_C0_MASK                     (1 << 31)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_SHIFT                    30
+#define OMAP4_WKUP_CONTROL_SPARE_R_C1_MASK                     (1 << 30)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_SHIFT                    29
+#define OMAP4_WKUP_CONTROL_SPARE_R_C2_MASK                     (1 << 29)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_SHIFT                    28
+#define OMAP4_WKUP_CONTROL_SPARE_R_C3_MASK                     (1 << 28)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_SHIFT                    27
+#define OMAP4_WKUP_CONTROL_SPARE_R_C4_MASK                     (1 << 27)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_SHIFT                    26
+#define OMAP4_WKUP_CONTROL_SPARE_R_C5_MASK                     (1 << 26)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_SHIFT                    25
+#define OMAP4_WKUP_CONTROL_SPARE_R_C6_MASK                     (1 << 25)
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_SHIFT                    24
+#define OMAP4_WKUP_CONTROL_SPARE_R_C7_MASK                     (1 << 24)
+
+#endif
diff --git a/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h b/arch/arm/mach-omap2/include/mach/ctrl_module_wkup_44xx.h
new file mode 100644 (file)
index 0000000..a0af9ba
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * OMAP44xx CTRL_MODULE_WKUP registers and bitfields
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ *
+ * Benoit Cousson (b-cousson@ti.com)
+ * Santosh Shilimkar (santosh.shilimkar@ti.com)
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
+#define __ARCH_ARM_MACH_OMAP2_CTRL_MODULE_WKUP_44XX_H
+
+
+/* Base address */
+#define OMAP4_CTRL_MODULE_WKUP                         0x4a30c000
+
+/* Registers offset */
+#define OMAP4_CTRL_MODULE_WKUP_IP_REVISION             0x0000
+#define OMAP4_CTRL_MODULE_WKUP_IP_HWINFO               0x0004
+#define OMAP4_CTRL_MODULE_WKUP_IP_SYSCONFIG            0x0010
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_0    0x0460
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_1    0x0464
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_2    0x0468
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_3    0x046c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_4    0x0470
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_5    0x0474
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_6    0x0478
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_7    0x047c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_8    0x0480
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_9    0x0484
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_10   0x0488
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_11   0x048c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_12   0x0490
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_13   0x0494
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_14   0x0498
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_15   0x049c
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_16   0x04a0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_17   0x04a4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_18   0x04a8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_19   0x04ac
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_20   0x04b0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_21   0x04b4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_22   0x04b8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_23   0x04bc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_24   0x04c0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_25   0x04c4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_26   0x04c8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_27   0x04cc
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_28   0x04d0
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_29   0x04d4
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_30   0x04d8
+#define OMAP4_CTRL_MODULE_WKUP_CONF_DEBUG_SEL_TST_31   0x04dc
+
+/* Registers shifts and masks */
+
+/* IP_REVISION */
+#define OMAP4_IP_REV_SCHEME_SHIFT              30
+#define OMAP4_IP_REV_SCHEME_MASK               (0x3 << 30)
+#define OMAP4_IP_REV_FUNC_SHIFT                        16
+#define OMAP4_IP_REV_FUNC_MASK                 (0xfff << 16)
+#define OMAP4_IP_REV_RTL_SHIFT                 11
+#define OMAP4_IP_REV_RTL_MASK                  (0x1f << 11)
+#define OMAP4_IP_REV_MAJOR_SHIFT               8
+#define OMAP4_IP_REV_MAJOR_MASK                        (0x7 << 8)
+#define OMAP4_IP_REV_CUSTOM_SHIFT              6
+#define OMAP4_IP_REV_CUSTOM_MASK               (0x3 << 6)
+#define OMAP4_IP_REV_MINOR_SHIFT               0
+#define OMAP4_IP_REV_MINOR_MASK                        (0x3f << 0)
+
+/* IP_HWINFO */
+#define OMAP4_IP_HWINFO_SHIFT                  0
+#define OMAP4_IP_HWINFO_MASK                   (0xffffffff << 0)
+
+/* IP_SYSCONFIG */
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_SHIFT      2
+#define OMAP4_IP_SYSCONFIG_IDLEMODE_MASK       (0x3 << 2)
+
+/* CONF_DEBUG_SEL_TST_0 */
+#define OMAP4_WKUP_MODE_SHIFT                  0
+#define OMAP4_WKUP_MODE_MASK                           (1 << 0)
+
+#endif
index b9ea70b..40562dd 100644 (file)
@@ -36,6 +36,7 @@
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
+#include "io.h"
 
 #include <plat/omap-pm.h>
 #include <plat/powerdomain.h>
@@ -323,6 +324,9 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
                omap2430_hwmod_init();
        else if (cpu_is_omap34xx())
                omap3xxx_hwmod_init();
+       else if (cpu_is_omap44xx())
+               omap44xx_hwmod_init();
+
        /* The OPP tables have to be registered before a clk init */
        omap_pm_if_early_init(mpu_opps, dsp_opps, l3_opps);
 
@@ -342,9 +346,7 @@ void __init omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
 #ifndef CONFIG_PM_RUNTIME
        skip_setup_idle = 1;
 #endif
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())   /* FIXME: OMAP4 */
-               omap_hwmod_late_init(skip_setup_idle);
-
+       omap_hwmod_late_init(skip_setup_idle);
        if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
                omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
                _omap2_init_reprogram_sdrc();
diff --git a/arch/arm/mach-omap2/io.h b/arch/arm/mach-omap2/io.h
new file mode 100644 (file)
index 0000000..fd230c6
--- /dev/null
@@ -0,0 +1,7 @@
+
+#ifndef __MACH_OMAP2_IO_H__
+#define __MACH_OMAP2_IO_H__
+
+extern int __init omap_sram_init(void);
+
+#endif /*  __MACH_OMAP2_IO_H__ */
index 26aeef5..32eeabe 100644 (file)
@@ -47,7 +47,6 @@ static struct omap_irq_bank {
 } __attribute__ ((aligned(4))) irq_banks[] = {
        {
                /* MPU INTC */
-               .base_reg       = 0,
                .nr_irqs        = 96,
        },
 };
index 42dbfa4..40ddeca 100644 (file)
@@ -181,7 +181,7 @@ static int omap2_mbox_fifo_full(struct omap_mbox *mbox)
 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 
        l = mbox_read_reg(p->irqenable);
@@ -192,7 +192,7 @@ static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
 static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 l, bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
        l = mbox_read_reg(p->irqdisable);
        l &= ~bit;
@@ -202,7 +202,7 @@ static void omap2_mbox_disable_irq(struct omap_mbox *mbox,
 static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
 
        mbox_write_reg(bit, p->irqstatus);
@@ -214,7 +214,7 @@ static void omap2_mbox_ack_irq(struct omap_mbox *mbox,
 static int omap2_mbox_is_irq(struct omap_mbox *mbox,
                omap_mbox_type_t irq)
 {
-       struct omap_mbox2_priv *p = (struct omap_mbox2_priv *)mbox->priv;
+       struct omap_mbox2_priv *p = mbox->priv;
        u32 bit = (irq == IRQ_TX) ? p->notfull_bit : p->newmsg_bit;
        u32 enable = mbox_read_reg(p->irqenable);
        u32 status = mbox_read_reg(p->irqstatus);
index 467aae2..f9c9df5 100644 (file)
 #include <plat/cpu.h>
 #include <plat/mcbsp.h>
 
-#include "mux.h"
+#include "control.h"
 
-static void omap2_mcbsp2_mux_setup(void)
+
+/* McBSP internal signal muxing functions */
+
+void omap2_mcbsp1_mux_clkr_src(u8 mux)
 {
-       omap_mux_init_signal("eac_ac_sclk.mcbsp2_clkx", OMAP_PULL_ENA);
-       omap_mux_init_signal("eac_ac_fs.mcbsp2_fsx", OMAP_PULL_ENA);
-       omap_mux_init_signal("eac_ac_din.mcbsp2_dr", OMAP_PULL_ENA);
-       omap_mux_init_signal("eac_ac_dout.mcbsp2_dx", OMAP_PULL_ENA);
-       omap_mux_init_gpio(117, OMAP_PULL_ENA);
-       /*
-        * TODO: Need to add MUX settings for OMAP 2430 SDP
-        */
+       u32 v;
+
+       v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+       if (mux == CLKR_SRC_CLKR)
+               v &= ~OMAP2_MCBSP1_CLKR_MASK;
+       else if (mux == CLKR_SRC_CLKX)
+               v |= OMAP2_MCBSP1_CLKR_MASK;
+       omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
 }
+EXPORT_SYMBOL(omap2_mcbsp1_mux_clkr_src);
 
-static void omap2_mcbsp_request(unsigned int id)
+void omap2_mcbsp1_mux_fsr_src(u8 mux)
 {
-       if (cpu_is_omap2420() && (id == OMAP_MCBSP2))
-               omap2_mcbsp2_mux_setup();
+       u32 v;
+
+       v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+       if (mux == FSR_SRC_FSR)
+               v &= ~OMAP2_MCBSP1_FSR_MASK;
+       else if (mux == FSR_SRC_FSX)
+               v |= OMAP2_MCBSP1_FSR_MASK;
+       omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
 }
+EXPORT_SYMBOL(omap2_mcbsp1_mux_fsr_src);
 
-static struct omap_mcbsp_ops omap2_mcbsp_ops = {
-       .request        = omap2_mcbsp_request,
-};
+/* McBSP CLKS source switching function */
+
+int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+{
+       struct omap_mcbsp *mcbsp;
+       struct clk *fck_src;
+       char *fck_src_name;
+       int r;
+
+       if (!omap_mcbsp_check_valid_id(id)) {
+               pr_err("%s: Invalid id (%d)\n", __func__, id + 1);
+               return -EINVAL;
+       }
+       mcbsp = id_to_mcbsp_ptr(id);
+
+       if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+               fck_src_name = "pad_fck";
+       else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+               fck_src_name = "prcm_fck";
+       else
+               return -EINVAL;
+
+       fck_src = clk_get(mcbsp->dev, fck_src_name);
+       if (IS_ERR_OR_NULL(fck_src)) {
+               pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks",
+                      fck_src_name);
+               return -EINVAL;
+       }
+
+       clk_disable(mcbsp->fclk);
+
+       r = clk_set_parent(mcbsp->fclk, fck_src);
+       if (IS_ERR_VALUE(r)) {
+               pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n",
+                      "clks", fck_src_name);
+               clk_put(fck_src);
+               return -EINVAL;
+       }
+
+       clk_enable(mcbsp->fclk);
+
+       clk_put(fck_src);
+
+       return 0;
+}
+EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
+
+
+/* Platform data */
 
 #ifdef CONFIG_ARCH_OMAP2420
 static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
@@ -55,7 +112,6 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP24XX_MCBSP2_BASE,
@@ -63,7 +119,6 @@ static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
 };
 #define OMAP2420_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2420_mcbsp_pdata)
@@ -82,7 +137,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP24XX_MCBSP2_BASE,
@@ -90,7 +144,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP2430_MCBSP3_BASE,
@@ -98,7 +151,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
                .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP2430_MCBSP4_BASE,
@@ -106,7 +158,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
                .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP2430_MCBSP5_BASE,
@@ -114,7 +165,6 @@ static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
                .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
        },
 };
 #define OMAP2430_MCBSP_PDATA_SZ                ARRAY_SIZE(omap2430_mcbsp_pdata)
@@ -133,7 +183,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP1_TX,
                .rx_irq         = INT_24XX_MCBSP1_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP1_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
        {
@@ -143,7 +192,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP2_TX,
                .rx_irq         = INT_24XX_MCBSP2_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP2_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x500, /* The FIFO has 1024 + 256 locations */
        },
        {
@@ -153,7 +201,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP3_TX,
                .rx_irq         = INT_24XX_MCBSP3_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP3_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
        {
@@ -162,7 +209,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP4_TX,
                .rx_irq         = INT_24XX_MCBSP4_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP4_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
        {
@@ -171,7 +217,6 @@ static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
                .dma_tx_sync    = OMAP24XX_DMA_MCBSP5_TX,
                .rx_irq         = INT_24XX_MCBSP5_IRQ_RX,
                .tx_irq         = INT_24XX_MCBSP5_IRQ_TX,
-               .ops            = &omap2_mcbsp_ops,
                .buffer_size    = 0x80, /* The FIFO has 128 locations */
        },
 };
@@ -189,28 +234,24 @@ static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP1_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP1_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP1,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP44XX_MCBSP2_BASE,
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP2_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP2_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP2,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP44XX_MCBSP3_BASE,
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP3_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP3_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP3,
-               .ops            = &omap2_mcbsp_ops,
        },
        {
                .phys_base      = OMAP44XX_MCBSP4_BASE,
                .dma_rx_sync    = OMAP44XX_DMA_MCBSP4_RX,
                .dma_tx_sync    = OMAP44XX_DMA_MCBSP4_TX,
                .tx_irq         = OMAP44XX_IRQ_MCBSP4,
-               .ops            = &omap2_mcbsp_ops,
        },
 };
 #define OMAP44XX_MCBSP_PDATA_SZ                ARRAY_SIZE(omap44xx_mcbsp_pdata)
index ab403b2..074536a 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  */
-#include <linux/module.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/slab.h>
 #include <linux/ctype.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
@@ -36,8 +35,7 @@
 
 #include <asm/system.h>
 
-#include <plat/control.h>
-
+#include "control.h"
 #include "mux.h"
 
 #define OMAP_MUX_BASE_OFFSET           0x30    /* Offset from CTRL_BASE */
@@ -87,7 +85,7 @@ static char *omap_mux_options;
 int __init omap_mux_init_gpio(int gpio, int val)
 {
        struct omap_mux_entry *e;
-       struct omap_mux *gpio_mux;
+       struct omap_mux *gpio_mux = NULL;
        u16 old_mode;
        u16 mux_mode;
        int found = 0;
@@ -127,17 +125,16 @@ int __init omap_mux_init_gpio(int gpio, int val)
        return 0;
 }
 
-int __init omap_mux_init_signal(char *muxname, int val)
+int __init omap_mux_init_signal(const char *muxname, int val)
 {
        struct omap_mux_entry *e;
-       char *m0_name = NULL, *mode_name = NULL;
-       int found = 0;
+       const char *mode_name;
+       int found = 0, mode0_len = 0;
 
        mode_name = strchr(muxname, '.');
        if (mode_name) {
-               *mode_name = '\0';
+               mode0_len = strlen(muxname) - strlen(mode_name);
                mode_name++;
-               m0_name = muxname;
        } else {
                mode_name = muxname;
        }
@@ -147,9 +144,11 @@ int __init omap_mux_init_signal(char *muxname, int val)
                char *m0_entry = m->muxnames[0];
                int i;
 
-               if (m0_name && strcmp(m0_name, m0_entry))
+               /* First check for full name in mode0.muxmode format */
+               if (mode0_len && strncmp(muxname, m0_entry, mode0_len))
                        continue;
 
+               /* Then check for muxmode only */
                for (i = 0; i < OMAP_MUX_NR_MODES; i++) {
                        char *mode_cur = m->muxnames[i];
 
index a8e040c..350c04f 100644 (file)
@@ -120,7 +120,7 @@ int omap_mux_init_gpio(int gpio, int val);
  * @muxname:           Mux name in mode0_name.signal_name format
  * @val:               Options for the mux register value
  */
-int omap_mux_init_signal(char *muxname, int val);
+int omap_mux_init_signal(const char *muxname, int val);
 
 #else
 
index fdb04a7..414af54 100644 (file)
@@ -507,7 +507,7 @@ static struct omap_mux __initdata omap2420_muxmodes[] = {
  * Balls for 447-pin POP package
  */
 #ifdef CONFIG_DEBUG_FS
-struct omap_ball __initdata omap2420_pop_ball[] = {
+static struct omap_ball __initdata omap2420_pop_ball[] = {
        _OMAP2420_BALLENTRY(CAM_D0, "y4", NULL),
        _OMAP2420_BALLENTRY(CAM_D1, "y3", NULL),
        _OMAP2420_BALLENTRY(CAM_D2, "u7", NULL),
index 7dcaaa8..84d2c5a 100644 (file)
@@ -586,7 +586,7 @@ static struct omap_mux __initdata omap2430_muxmodes[] = {
  * 447-pin s-PBGA Package, 0.00mm Ball Pitch (Bottom)
  */
 #ifdef CONFIG_DEBUG_FS
-struct omap_ball __initdata omap2430_pop_ball[] = {
+static struct omap_ball __initdata omap2430_pop_ball[] = {
        _OMAP2430_BALLENTRY(CAM_D0, "t8", NULL),
        _OMAP2430_BALLENTRY(CAM_D1, "t4", NULL),
        _OMAP2430_BALLENTRY(CAM_D10, "r4", NULL),
index f64d7ee..574e54e 100644 (file)
@@ -931,7 +931,7 @@ struct omap_ball __initdata omap3_cbc_ball[] = {
  * Signals different on CUS package compared to superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CUS)
-struct omap_mux __initdata omap3_cus_subset[] = {
+static struct omap_mux __initdata omap3_cus_subset[] = {
        _OMAP3_MUXENTRY(CAM_D10, 109,
                "cam_d10", NULL, NULL, NULL,
                "gpio_109", NULL, NULL, "safe_mode"),
@@ -1077,7 +1077,7 @@ struct omap_mux __initdata omap3_cus_subset[] = {
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)               \
                && defined(CONFIG_OMAP_PACKAGE_CUS)
-struct omap_ball __initdata omap3_cus_ball[] = {
+static struct omap_ball __initdata omap3_cus_ball[] = {
        _OMAP3_BALLENTRY(CAM_D0, "ab18", NULL),
        _OMAP3_BALLENTRY(CAM_D1, "ac18", NULL),
        _OMAP3_BALLENTRY(CAM_D10, "f21", NULL),
@@ -1269,7 +1269,7 @@ struct omap_ball __initdata omap3_cus_ball[] = {
  * Signals different on CBB package comapared to superset
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBB)
-struct omap_mux __initdata omap3_cbb_subset[] = {
+static struct omap_mux __initdata omap3_cbb_subset[] = {
        _OMAP3_MUXENTRY(CAM_D10, 109,
                "cam_d10", NULL, NULL, NULL,
                "gpio_109", NULL, NULL, "safe_mode"),
@@ -1390,7 +1390,7 @@ struct omap_mux __initdata omap3_cbb_subset[] = {
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)               \
                && defined(CONFIG_OMAP_PACKAGE_CBB)
-struct omap_ball __initdata omap3_cbb_ball[] = {
+static struct omap_ball __initdata omap3_cbb_ball[] = {
        _OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
        _OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
        _OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
@@ -1600,7 +1600,7 @@ struct omap_ball __initdata omap3_cbb_ball[] = {
  * Signals different on 36XX CBP package comapared to 34XX CBC package
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_OMAP_PACKAGE_CBP)
-struct omap_mux __initdata omap36xx_cbp_subset[] = {
+static struct omap_mux __initdata omap36xx_cbp_subset[] = {
        _OMAP3_MUXENTRY(CAM_D0, 99,
                "cam_d0", NULL, "csi2_dx2", NULL,
                "gpio_99", NULL, NULL, "safe_mode"),
@@ -1818,7 +1818,7 @@ struct omap_mux __initdata omap36xx_cbp_subset[] = {
  */
 #if defined(CONFIG_OMAP_MUX) && defined(CONFIG_DEBUG_FS)               \
                && defined (CONFIG_OMAP_PACKAGE_CBP)
-struct omap_ball __initdata omap36xx_cbp_ball[] = {
+static struct omap_ball __initdata omap36xx_cbp_ball[] = {
        _OMAP3_BALLENTRY(CAM_D0, "ag17", NULL),
        _OMAP3_BALLENTRY(CAM_D1, "ah17", NULL),
        _OMAP3_BALLENTRY(CAM_D10, "b25", NULL),
index 13dc979..923f9f5 100644 (file)
@@ -61,10 +61,14 @@ static int __init omap_l2_cache_init(void)
        omap_smc1(0x102, 0x1);
 
        /*
-        * 32KB way size, 16-way associativity,
-        * parity disabled
+        * 16-way associativity, parity disabled
+        * Way size - 32KB (es1.0)
+        * Way size - 64KB (es2.0 +)
         */
-       l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
+       if (omap_rev() == OMAP4430_REV_ES1_0)
+               l2x0_init(l2cache_base, 0x0e050000, 0xc0000fff);
+       else
+               l2x0_init(l2cache_base, 0x0e070000, 0xc0000fff);
 
        return 0;
 }
index cb911d7..5a30658 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * This code manages "OMAP modules" (on-chip devices) and their
- * integration with Linux device driver and bus code.
- *
- * References:
+ * Introduction
+ * ------------
+ * One way to view an OMAP SoC is as a collection of largely unrelated
+ * IP blocks connected by interconnects.  The IP blocks include
+ * devices such as ARM processors, audio serial interfaces, UARTs,
+ * etc.  Some of these devices, like the DSP, are created by TI;
+ * others, like the SGX, largely originate from external vendors.  In
+ * TI's documentation, on-chip devices are referred to as "OMAP
+ * modules."  Some of these IP blocks are identical across several
+ * OMAP versions.  Others are revised frequently.
+ *
+ * These OMAP modules are tied together by various interconnects.
+ * Most of the address and data flow between modules is via OCP-based
+ * interconnects such as the L3 and L4 buses; but there are other
+ * interconnects that distribute the hardware clock tree, handle idle
+ * and reset signaling, supply power, and connect the modules to
+ * various pads or balls on the OMAP package.
+ *
+ * OMAP hwmod provides a consistent way to describe the on-chip
+ * hardware blocks and their integration into the rest of the chip.
+ * This description can be automatically generated from the TI
+ * hardware database.  OMAP hwmod provides a standard, consistent API
+ * to reset, enable, idle, and disable these hardware blocks.  And
+ * hwmod provides a way for other core code, such as the Linux device
+ * code or the OMAP power management and address space mapping code,
+ * to query the hardware database.
+ *
+ * Using hwmod
+ * -----------
+ * Drivers won't call hwmod functions directly.  That is done by the
+ * omap_device code, and in rare occasions, by custom integration code
+ * in arch/arm/ *omap*.  The omap_device code includes functions to
+ * build a struct platform_device using omap_hwmod data, and that is
+ * currently how hwmod data is communicated to drivers and to the
+ * Linux driver model.  Most drivers will call omap_hwmod functions only
+ * indirectly, via pm_runtime*() functions.
+ *
+ * From a layering perspective, here is where the OMAP hwmod code
+ * fits into the kernel software stack:
+ *
+ *            +-------------------------------+
+ *            |      Device driver code       |
+ *            |      (e.g., drivers/)         |
+ *            +-------------------------------+
+ *            |      Linux driver model       |
+ *            |     (platform_device /        |
+ *            |  platform_driver data/code)   |
+ *            +-------------------------------+
+ *            | OMAP core-driver integration  |
+ *            |(arch/arm/mach-omap2/devices.c)|
+ *            +-------------------------------+
+ *            |      omap_device code         |
+ *            | (../plat-omap/omap_device.c)  |
+ *            +-------------------------------+
+ *   ---->    |    omap_hwmod code/data       |    <-----
+ *            | (../mach-omap2/omap_hwmod*)   |
+ *            +-------------------------------+
+ *            | OMAP clock/PRCM/register fns  |
+ *            | (__raw_{read,write}l, clk*)   |
+ *            +-------------------------------+
+ *
+ * Device drivers should not contain any OMAP-specific code or data in
+ * them.  They should only contain code to operate the IP block that
+ * the driver is responsible for.  This is because these IP blocks can
+ * also appear in other SoCs, either from TI (such as DaVinci) or from
+ * other manufacturers; and drivers should be reusable across other
+ * platforms.
+ *
+ * The OMAP hwmod code also will attempt to reset and idle all on-chip
+ * devices upon boot.  The goal here is for the kernel to be
+ * completely self-reliant and independent from bootloaders.  This is
+ * to ensure a repeatable configuration, both to ensure consistent
+ * runtime behavior, and to make it easier for others to reproduce
+ * bugs.
+ *
+ * OMAP module activity states
+ * ---------------------------
+ * The hwmod code considers modules to be in one of several activity
+ * states.  IP blocks start out in an UNKNOWN state, then once they
+ * are registered via the hwmod code, proceed to the REGISTERED state.
+ * Once their clock names are resolved to clock pointers, the module
+ * enters the CLKS_INITED state; and finally, once the module has been
+ * reset and the integration registers programmed, the INITIALIZED state
+ * is entered.  The hwmod code will then place the module into either
+ * the IDLE state to save power, or in the case of a critical system
+ * module, the ENABLED state.
+ *
+ * OMAP core integration code can then call omap_hwmod*() functions
+ * directly to move the module between the IDLE, ENABLED, and DISABLED
+ * states, as needed.  This is done during both the PM idle loop, and
+ * in the OMAP core integration code's implementation of the PM runtime
+ * functions.
+ *
+ * References
+ * ----------
+ * This is a partial list.
  * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
  * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
  * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
 #include <plat/powerdomain.h>
 #include <plat/clock.h>
 #include <plat/omap_hwmod.h>
+#include <plat/prcm.h>
 
 #include "cm.h"
+#include "prm.h"
 
-/* Maximum microseconds to wait for OMAP module to reset */
-#define MAX_MODULE_RESET_WAIT          10000
+/* Maximum microseconds to wait for OMAP module to softreset */
+#define MAX_MODULE_SOFTRESET_WAIT      10000
 
 /* Name of the OMAP hwmod for the MPU */
 #define MPU_INITIATOR_NAME             "mpu"
@@ -90,7 +184,7 @@ static int _update_sysc_cache(struct omap_hwmod *oh)
 
        /* XXX ensure module interface clock is up */
 
-       oh->_sysc_cache = omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
+       oh->_sysc_cache = omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
 
        if (!(oh->class->sysc->sysc_flags & SYSC_NO_CACHE))
                oh->_int_flags |= _HWMOD_SYSCONFIG_LOADED;
@@ -117,7 +211,7 @@ static void _write_sysconfig(u32 v, struct omap_hwmod *oh)
 
        if (oh->_sysc_cache != v) {
                oh->_sysc_cache = v;
-               omap_hwmod_writel(v, oh, oh->class->sysc->sysc_offs);
+               omap_hwmod_write(v, oh, oh->class->sysc->sysc_offs);
        }
 }
 
@@ -544,6 +638,36 @@ static int _disable_clocks(struct omap_hwmod *oh)
        return 0;
 }
 
+static void _enable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: enabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: enable %s:%s\n", oc->role,
+                                oc->_clk->name);
+                       clk_enable(oc->_clk);
+               }
+}
+
+static void _disable_optional_clocks(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int i;
+
+       pr_debug("omap_hwmod: %s: disabling optional clocks\n", oh->name);
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk) {
+                       pr_debug("omap_hwmod: disable %s:%s\n", oc->role,
+                                oc->_clk->name);
+                       clk_disable(oc->_clk);
+               }
+}
+
 /**
  * _find_mpu_port_index - find hwmod OCP slave port ID intended for MPU use
  * @oh: struct omap_hwmod *
@@ -622,7 +746,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
 }
 
 /**
- * _sysc_enable - try to bring a module out of idle via OCP_SYSCONFIG
+ * _enable_sysc - try to bring a module out of idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module out of slave
@@ -630,7 +754,7 @@ static void __iomem *_find_mpu_rt_base(struct omap_hwmod *oh, u8 index)
  * as SWSUP_MSUSPEND, force the module out of master standby;
  * otherwise, configure it for smart-standby.  No return value.
  */
-static void _sysc_enable(struct omap_hwmod *oh)
+static void _enable_sysc(struct omap_hwmod *oh)
 {
        u8 idlemode, sf;
        u32 v;
@@ -653,14 +777,6 @@ static void _sysc_enable(struct omap_hwmod *oh)
                _set_master_standbymode(oh, idlemode, &v);
        }
 
-       if (sf & SYSC_HAS_AUTOIDLE) {
-               idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
-                       0 : 1;
-               _set_module_autoidle(oh, idlemode, &v);
-       }
-
-       /* XXX OCP ENAWAKEUP bit? */
-
        /*
         * XXX The clock framework should handle this, by
         * calling into this code.  But this must wait until the
@@ -671,10 +787,25 @@ static void _sysc_enable(struct omap_hwmod *oh)
                _set_clockactivity(oh, oh->class->sysc->clockact, &v);
 
        _write_sysconfig(v, oh);
+
+       /* If slave is in SMARTIDLE, also enable wakeup */
+       if ((sf & SYSC_HAS_SIDLEMODE) && !(oh->flags & HWMOD_SWSUP_SIDLE))
+               _enable_wakeup(oh);
+
+       /*
+        * Set the autoidle bit only after setting the smartidle bit
+        * Setting this will not have any impact on the other modules.
+        */
+       if (sf & SYSC_HAS_AUTOIDLE) {
+               idlemode = (oh->flags & HWMOD_NO_OCP_AUTOIDLE) ?
+                       0 : 1;
+               _set_module_autoidle(oh, idlemode, &v);
+               _write_sysconfig(v, oh);
+       }
 }
 
 /**
- * _sysc_idle - try to put a module into idle via OCP_SYSCONFIG
+ * _idle_sysc - try to put a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * If module is marked as SWSUP_SIDLE, force the module into slave
@@ -682,7 +813,7 @@ static void _sysc_enable(struct omap_hwmod *oh)
  * as SWSUP_MSUSPEND, force the module into master standby; otherwise,
  * configure it for smart-standby.  No return value.
  */
-static void _sysc_idle(struct omap_hwmod *oh)
+static void _idle_sysc(struct omap_hwmod *oh)
 {
        u8 idlemode, sf;
        u32 v;
@@ -709,13 +840,13 @@ static void _sysc_idle(struct omap_hwmod *oh)
 }
 
 /**
- * _sysc_shutdown - force a module into idle via OCP_SYSCONFIG
+ * _shutdown_sysc - force a module into idle via OCP_SYSCONFIG
  * @oh: struct omap_hwmod *
  *
  * Force the module into slave idle and master suspend. No return
  * value.
  */
-static void _sysc_shutdown(struct omap_hwmod *oh)
+static void _shutdown_sysc(struct omap_hwmod *oh)
 {
        u32 v;
        u8 sf;
@@ -767,10 +898,10 @@ static struct omap_hwmod *_lookup(const char *name)
  * @data: not used; pass NULL
  *
  * Called by omap_hwmod_late_init() (after omap2_clk_init()).
- * Resolves all clock names embedded in the hwmod.  Must be called
- * with omap_hwmod_mutex held.  Returns -EINVAL if the omap_hwmod
- * has not yet been registered or if the clocks have already been
- * initialized, 0 on success, or a non-zero error on failure.
+ * Resolves all clock names embedded in the hwmod.  Returns -EINVAL if
+ * the omap_hwmod has not yet been registered or if the clocks have
+ * already been initialized, 0 on success, or a non-zero error on
+ * failure.
  */
 static int _init_clocks(struct omap_hwmod *oh, void *data)
 {
@@ -834,56 +965,202 @@ static int _wait_target_ready(struct omap_hwmod *oh)
 }
 
 /**
+ * _lookup_hardreset - return the register bit shift for this hwmod/reset line
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line in the context of this hwmod
+ *
+ * Return the bit position of the reset line that match the
+ * input name. Return -ENOENT if not found.
+ */
+static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int i;
+
+       for (i = 0; i < oh->rst_lines_cnt; i++) {
+               const char *rst_line = oh->rst_lines[i].name;
+               if (!strcmp(rst_line, name)) {
+                       u8 shift = oh->rst_lines[i].rst_shift;
+                       pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
+                                oh->name, rst_line, shift);
+
+                       return shift;
+               }
+       }
+
+       return -ENOENT;
+}
+
+/**
+ * _assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
+                                                 shift);
+       else if (cpu_is_omap44xx())
+               return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
+                                                 shift);
+       else
+               return -EINVAL;
+}
+
+/**
+ * _deassert_hardreset - deassert the HW reset line of submodules contained
+ * in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.
+ */
+static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+       int r;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+               r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
+                                                shift);
+       else if (cpu_is_omap44xx())
+               r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
+                                                shift);
+       else
+               return -EINVAL;
+
+       if (r == -EBUSY)
+               pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
+
+       return r;
+}
+
+/**
+ * _read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the state of the reset line.
+ */
+static int _read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       u8 shift;
+
+       if (!oh)
+               return -EINVAL;
+
+       shift = _lookup_hardreset(oh, name);
+       if (IS_ERR_VALUE(shift))
+               return shift;
+
+       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+               return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
+                                                      shift);
+       } else if (cpu_is_omap44xx()) {
+               return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
+                                                      shift);
+       } else {
+               return -EINVAL;
+       }
+}
+
+/**
  * _reset - reset an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Resets an omap_hwmod @oh via the OCP_SYSCONFIG bit.  hwmod must be
- * enabled for this to work.  Must be called with omap_hwmod_mutex
- * held.  Returns -EINVAL if the hwmod cannot be reset this way or if
- * the hwmod is in the wrong state, -ETIMEDOUT if the module did not
- * reset in time, or 0 upon success.
+ * enabled for this to work.  Returns -EINVAL if the hwmod cannot be
+ * reset this way or if the hwmod is in the wrong state, -ETIMEDOUT if
+ * the module did not reset in time, or 0 upon success.
+ *
+ * In OMAP3 a specific SYSSTATUS register is used to get the reset status.
+ * Starting in OMAP4, some IPs does not have SYSSTATUS register and instead
+ * use the SYSCONFIG softreset bit to provide the status.
+ *
+ * Note that some IP like McBSP does have a reset control but no reset status.
  */
 static int _reset(struct omap_hwmod *oh)
 {
-       u32 r, v;
+       u32 v;
        int c = 0;
+       int ret = 0;
 
        if (!oh->class->sysc ||
-           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET) ||
-           (oh->class->sysc->sysc_flags & SYSS_MISSING))
+           !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET))
                return -EINVAL;
 
        /* clocks must be on for this operation */
        if (oh->_state != _HWMOD_STATE_ENABLED) {
-               WARN(1, "omap_hwmod: %s: reset can only be entered from "
-                    "enabled state\n", oh->name);
+               pr_warning("omap_hwmod: %s: reset can only be entered from "
+                          "enabled state\n", oh->name);
                return -EINVAL;
        }
 
+       /* For some modules, all optionnal clocks need to be enabled as well */
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _enable_optional_clocks(oh);
+
        pr_debug("omap_hwmod: %s: resetting\n", oh->name);
 
        v = oh->_sysc_cache;
-       r = _set_softreset(oh, &v);
-       if (r)
-               return r;
+       ret = _set_softreset(oh, &v);
+       if (ret)
+               goto dis_opt_clks;
        _write_sysconfig(v, oh);
 
-       omap_test_timeout((omap_hwmod_readl(oh, oh->class->sysc->syss_offs) &
-                          SYSS_RESETDONE_MASK),
-                         MAX_MODULE_RESET_WAIT, c);
-
-       if (c == MAX_MODULE_RESET_WAIT)
-               WARN(1, "omap_hwmod: %s: failed to reset in %d usec\n",
-                    oh->name, MAX_MODULE_RESET_WAIT);
+       if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+               omap_test_timeout((omap_hwmod_read(oh,
+                                                   oh->class->sysc->syss_offs)
+                                  & SYSS_RESETDONE_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS)
+               omap_test_timeout(!(omap_hwmod_read(oh,
+                                                    oh->class->sysc->sysc_offs)
+                                  & SYSC_TYPE2_SOFTRESET_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT)
+               pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
+                          oh->name, MAX_MODULE_SOFTRESET_WAIT);
        else
-               pr_debug("omap_hwmod: %s: reset in %d usec\n", oh->name, c);
+               pr_debug("omap_hwmod: %s: softreset in %d usec\n", oh->name, c);
 
        /*
         * XXX add _HWMOD_STATE_WEDGED for modules that don't come back from
         * _wait_target_ready() or _reset()
         */
 
-       return (c == MAX_MODULE_RESET_WAIT) ? -ETIMEDOUT : 0;
+       ret = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+dis_opt_clks:
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _disable_optional_clocks(oh);
+
+       return ret;
 }
 
 /**
@@ -891,9 +1168,11 @@ static int _reset(struct omap_hwmod *oh)
  * @oh: struct omap_hwmod *
  *
  * Enables an omap_hwmod @oh such that the MPU can access the hwmod's
- * register target.  Must be called with omap_hwmod_mutex held.
- * Returns -EINVAL if the hwmod is in the wrong state or passes along
- * the return value of _wait_target_ready().
+ * register target.  (This function has a full name --
+ * _omap_hwmod_enable() rather than simply _enable() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or passes along the return value of
+ * _wait_target_ready().
  */
 int _omap_hwmod_enable(struct omap_hwmod *oh)
 {
@@ -909,6 +1188,15 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
 
        pr_debug("omap_hwmod: %s: enabling\n", oh->name);
 
+       /*
+        * If an IP contains only one HW reset line, then de-assert it in order
+        * to allow to enable the clocks. Otherwise the PRCM will return
+        * Intransition status, and the init will failed.
+        */
+       if ((oh->_state == _HWMOD_STATE_INITIALIZED ||
+            oh->_state == _HWMOD_STATE_DISABLED) && oh->rst_lines_cnt == 1)
+               _deassert_hardreset(oh, oh->rst_lines[0].name);
+
        /* XXX mux balls */
 
        _add_initiator_dep(oh, mpu_oh);
@@ -922,7 +1210,7 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
                if (oh->class->sysc) {
                        if (!(oh->_int_flags & _HWMOD_SYSCONFIG_LOADED))
                                _update_sysc_cache(oh);
-                       _sysc_enable(oh);
+                       _enable_sysc(oh);
                }
        } else {
                pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
@@ -933,12 +1221,14 @@ int _omap_hwmod_enable(struct omap_hwmod *oh)
 }
 
 /**
- * _idle - idle an omap_hwmod
+ * _omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Idles an omap_hwmod @oh.  This should be called once the hwmod has
- * no further work.  Returns -EINVAL if the hwmod is in the wrong
- * state or returns 0.
+ * no further work.  (This function has a full name --
+ * _omap_hwmod_idle() rather than simply _idle() -- because it is
+ * currently required by the pm34xx.c idle loop.)  Returns -EINVAL if
+ * the hwmod is in the wrong state or returns 0.
  */
 int _omap_hwmod_idle(struct omap_hwmod *oh)
 {
@@ -951,7 +1241,7 @@ int _omap_hwmod_idle(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: idling\n", oh->name);
 
        if (oh->class->sysc)
-               _sysc_idle(oh);
+               _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
        _disable_clocks(oh);
 
@@ -981,10 +1271,21 @@ static int _shutdown(struct omap_hwmod *oh)
        pr_debug("omap_hwmod: %s: disabling\n", oh->name);
 
        if (oh->class->sysc)
-               _sysc_shutdown(oh);
-       _del_initiator_dep(oh, mpu_oh);
-       /* XXX what about the other system initiators here? DMA, tesla, d2d */
-       _disable_clocks(oh);
+               _shutdown_sysc(oh);
+
+       /*
+        * If an IP contains only one HW reset line, then assert it
+        * before disabling the clocks and shutting down the IP.
+        */
+       if (oh->rst_lines_cnt == 1)
+               _assert_hardreset(oh, oh->rst_lines[0].name);
+
+       /* clocks and deps are already disabled in idle */
+       if (oh->_state == _HWMOD_STATE_ENABLED) {
+               _del_initiator_dep(oh, mpu_oh);
+               /* XXX what about the other system initiators here? dma, dsp */
+               _disable_clocks(oh);
+       }
        /* XXX Should this code also force-disable the optional clocks? */
 
        /* XXX mux any associated balls to safe mode */
@@ -1000,11 +1301,10 @@ static int _shutdown(struct omap_hwmod *oh)
  * @skip_setup_idle_p: do not idle hwmods at the end of the fn if 1
  *
  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  Must be called with omap_hwmod_mutex held.
- * @skip_setup_idle is intended to be used on a system that will not
- * call omap_hwmod_enable() to enable devices (e.g., a system without
- * PM runtime).  Returns -EINVAL if the hwmod is in the wrong state or
- * returns 0.
+ * OCP_SYSCONFIG register.  @skip_setup_idle is intended to be used on
+ * a system that will not call omap_hwmod_enable() to enable devices
+ * (e.g., a system without PM runtime).  Returns -EINVAL if the hwmod
+ * is in the wrong state or returns 0.
  */
 static int _setup(struct omap_hwmod *oh, void *data)
 {
@@ -1034,8 +1334,19 @@ static int _setup(struct omap_hwmod *oh, void *data)
                }
        }
 
+       mutex_init(&oh->_mutex);
        oh->_state = _HWMOD_STATE_INITIALIZED;
 
+       /*
+        * In the case of hwmod with hardreset that should not be
+        * de-assert at boot time, we have to keep the module
+        * initialized, because we cannot enable it properly with the
+        * reset asserted. Exit without warning because that behavior is
+        * expected.
+        */
+       if ((oh->flags & HWMOD_INIT_NO_RESET) && oh->rst_lines_cnt == 1)
+               return 0;
+
        r = _omap_hwmod_enable(oh);
        if (r) {
                pr_warning("omap_hwmod: %s: cannot be enabled (%d)\n",
@@ -1044,16 +1355,16 @@ static int _setup(struct omap_hwmod *oh, void *data)
        }
 
        if (!(oh->flags & HWMOD_INIT_NO_RESET)) {
+               _reset(oh);
+
                /*
-                * XXX Do the OCP_SYSCONFIG bits need to be
-                * reprogrammed after a reset?  If not, then this can
-                * be removed.  If they do, then probably the
-                * _omap_hwmod_enable() function should be split to avoid the
-                * rewrite of the OCP_SYSCONFIG register.
+                * OCP_SYSCONFIG bits need to be reprogrammed after a softreset.
+                * The _omap_hwmod_enable() function should be split to
+                * avoid the rewrite of the OCP_SYSCONFIG register.
                 */
                if (oh->class->sysc) {
                        _update_sysc_cache(oh);
-                       _sysc_enable(oh);
+                       _enable_sysc(oh);
                }
        }
 
@@ -1067,14 +1378,20 @@ static int _setup(struct omap_hwmod *oh, void *data)
 
 /* Public functions */
 
-u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs)
+u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
 {
-       return __raw_readl(oh->_mpu_rt_va + reg_offs);
+       if (oh->flags & HWMOD_16BIT_REG)
+               return __raw_readw(oh->_mpu_rt_va + reg_offs);
+       else
+               return __raw_readl(oh->_mpu_rt_va + reg_offs);
 }
 
-void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs)
+void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs)
 {
-       __raw_writel(v, oh->_mpu_rt_va + reg_offs);
+       if (oh->flags & HWMOD_16BIT_REG)
+               __raw_writew(v, oh->_mpu_rt_va + reg_offs);
+       else
+               __raw_writel(v, oh->_mpu_rt_va + reg_offs);
 }
 
 /**
@@ -1309,7 +1626,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh)
  * omap_hwmod_enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Enable an omap_hwomd @oh.  Intended to be called by omap_device_enable().
+ * Enable an omap_hwmod @oh.  Intended to be called by omap_device_enable().
  * Returns -EINVAL on error or passes along the return value from _enable().
  */
 int omap_hwmod_enable(struct omap_hwmod *oh)
@@ -1319,9 +1636,9 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        r = _omap_hwmod_enable(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return r;
 }
@@ -1331,7 +1648,7 @@ int omap_hwmod_enable(struct omap_hwmod *oh)
  * omap_hwmod_idle - idle an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Idle an omap_hwomd @oh.  Intended to be called by omap_device_idle().
+ * Idle an omap_hwmod @oh.  Intended to be called by omap_device_idle().
  * Returns -EINVAL on error or passes along the return value from _idle().
  */
 int omap_hwmod_idle(struct omap_hwmod *oh)
@@ -1339,9 +1656,9 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _omap_hwmod_idle(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1350,7 +1667,7 @@ int omap_hwmod_idle(struct omap_hwmod *oh)
  * omap_hwmod_shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
  *
- * Shutdown an omap_hwomd @oh.  Intended to be called by
+ * Shutdown an omap_hwmod @oh.  Intended to be called by
  * omap_device_shutdown().  Returns -EINVAL on error or passes along
  * the return value from _shutdown().
  */
@@ -1359,9 +1676,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
        if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _shutdown(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1374,9 +1691,9 @@ int omap_hwmod_shutdown(struct omap_hwmod *oh)
  */
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
 {
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _enable_clocks(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1389,9 +1706,9 @@ int omap_hwmod_enable_clocks(struct omap_hwmod *oh)
  */
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh)
 {
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _disable_clocks(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1421,7 +1738,7 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
         * Forces posted writes to complete on the OCP thread handling
         * register writes
         */
-       omap_hwmod_readl(oh, oh->class->sysc->sysc_offs);
+       omap_hwmod_read(oh, oh->class->sysc->sysc_offs);
 }
 
 /**
@@ -1430,20 +1747,18 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh)
  *
  * Under some conditions, a driver may wish to reset the entire device.
  * Called from omap_device code.  Returns -EINVAL on error or passes along
- * the return value from _reset()/_enable().
+ * the return value from _reset().
  */
 int omap_hwmod_reset(struct omap_hwmod *oh)
 {
        int r;
 
-       if (!oh || !(oh->_state & _HWMOD_STATE_ENABLED))
+       if (!oh)
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        r = _reset(oh);
-       if (!r)
-               r = _omap_hwmod_enable(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return r;
 }
@@ -1468,7 +1783,7 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh)
 {
        int ret, i;
 
-       ret = oh->mpu_irqs_cnt + oh->sdma_chs_cnt;
+       ret = oh->mpu_irqs_cnt + oh->sdma_reqs_cnt;
 
        for (i = 0; i < oh->slaves_cnt; i++)
                ret += oh->slaves[i]->addr_cnt;
@@ -1501,10 +1816,10 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
                r++;
        }
 
-       for (i = 0; i < oh->sdma_chs_cnt; i++) {
-               (res + r)->name = (oh->sdma_chs + i)->name;
-               (res + r)->start = (oh->sdma_chs + i)->dma_ch;
-               (res + r)->end = (oh->sdma_chs + i)->dma_ch;
+       for (i = 0; i < oh->sdma_reqs_cnt; i++) {
+               (res + r)->name = (oh->sdma_reqs + i)->name;
+               (res + r)->start = (oh->sdma_reqs + i)->dma_req;
+               (res + r)->end = (oh->sdma_reqs + i)->dma_req;
                (res + r)->flags = IORESOURCE_DMA;
                r++;
        }
@@ -1644,9 +1959,9 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
            !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _enable_wakeup(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
@@ -1669,14 +1984,92 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
            !(oh->class->sysc->sysc_flags & SYSC_HAS_ENAWAKEUP))
                return -EINVAL;
 
-       mutex_lock(&omap_hwmod_mutex);
+       mutex_lock(&oh->_mutex);
        _disable_wakeup(oh);
-       mutex_unlock(&omap_hwmod_mutex);
+       mutex_unlock(&oh->_mutex);
 
        return 0;
 }
 
 /**
+ * omap_hwmod_assert_hardreset - assert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to lookup and assert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _assert_hardreset().
+ */
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _assert_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+/**
+ * omap_hwmod_deassert_hardreset - deassert the HW reset line of submodules
+ * contained in the hwmod module.
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and deassert
+ *
+ * Some IP like dsp, ipu or iva contain processor that require
+ * an HW reset line to be assert / deassert in order to enable fully
+ * the IP.  Returns -EINVAL if @oh is null or if the operation is not
+ * yet supported on this OMAP; otherwise, passes along the return value
+ * from _deassert_hardreset().
+ */
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _deassert_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+/**
+ * omap_hwmod_read_hardreset - read the HW reset line state of submodules
+ * contained in the hwmod module
+ * @oh: struct omap_hwmod *
+ * @name: name of the reset line to look up and read
+ *
+ * Return the current state of the hwmod @oh's reset line named @name:
+ * returns -EINVAL upon parameter error or if this operation
+ * is unsupported on the current OMAP; otherwise, passes along the return
+ * value from _read_hardreset().
+ */
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name)
+{
+       int ret;
+
+       if (!oh)
+               return -EINVAL;
+
+       mutex_lock(&oh->_mutex);
+       ret = _read_hardreset(oh, name);
+       mutex_unlock(&oh->_mutex);
+
+       return ret;
+}
+
+
+/**
  * omap_hwmod_for_each_by_class - call @fn for each hwmod of class @classname
  * @classname: struct omap_hwmod_class name to search for
  * @fn: callback function pointer to call for each hwmod in class @classname
index 3cc768e..adf6e36 100644 (file)
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
 
 /*
  * OMAP2420 hardware module integration data
@@ -33,6 +35,7 @@ static struct omap_hwmod omap2420_mpu_hwmod;
 static struct omap_hwmod omap2420_iva_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
+static struct omap_hwmod omap2420_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -71,6 +74,9 @@ static struct omap_hwmod omap2420_l3_main_hwmod = {
 };
 
 static struct omap_hwmod omap2420_l4_wkup_hwmod;
+static struct omap_hwmod omap2420_uart1_hwmod;
+static struct omap_hwmod omap2420_uart2_hwmod;
+static struct omap_hwmod omap2420_uart3_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
@@ -79,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
        .user   = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap2420_uart1_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART1_BASE,
+               .pa_end         = OMAP2_UART1_BASE + SZ_8K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
+       .master         = &omap2420_l4_core_hwmod,
+       .slave          = &omap2420_uart1_hwmod,
+       .clk            = "uart1_ick",
+       .addr           = omap2420_uart1_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2420_uart1_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap2420_uart2_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART2_BASE,
+               .pa_end         = OMAP2_UART2_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
+       .master         = &omap2420_l4_core_hwmod,
+       .slave          = &omap2420_uart2_hwmod,
+       .clk            = "uart2_ick",
+       .addr           = omap2420_uart2_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2420_uart2_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap2420_uart3_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART3_BASE,
+               .pa_end         = OMAP2_UART3_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
+       .master         = &omap2420_l4_core_hwmod,
+       .slave          = &omap2420_uart3_hwmod,
+       .clk            = "uart3_ick",
+       .addr           = omap2420_uart3_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2420_uart3_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
        &omap2420_l3_main__l4_core,
@@ -87,6 +147,9 @@ static struct omap_hwmod_ocp_if *omap2420_l4_core_slaves[] = {
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l4_core_masters[] = {
        &omap2420_l4_core__l4_wkup,
+       &omap2_l4_core__uart1,
+       &omap2_l4_core__uart2,
+       &omap2_l4_core__uart3,
 };
 
 /* L4 CORE */
@@ -165,12 +228,206 @@ static struct omap_hwmod omap2420_iva_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x48022000,
+               .pa_end         = 0x4802207f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__wd_timer2 = {
+       .master         = &omap2420_l4_wkup_hwmod,
+       .slave          = &omap2420_wd_timer2_hwmod,
+       .clk            = "mpu_wdt_ick",
+       .addr           = omap2420_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap2420_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_wd_timer_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap2420_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap2420_wd_timer2_slaves[] = {
+       &omap2420_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap2420_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap2420_wd_timer_hwmod_class,
+       .main_clk       = "mpu_wdt_fck",
+       .prcm           = {
+               .omap2 = {
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+                       .module_offs = WKUP_MOD,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+               },
+       },
+       .slaves         = omap2420_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+       .rev_offs       = 0x50,
+       .sysc_offs      = 0x54,
+       .syss_offs      = 0x58,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+       .name = "uart",
+       .sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+       { .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart1_slaves[] = {
+       &omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2420_uart1_hwmod = {
+       .name           = "uart1",
+       .mpu_irqs       = uart1_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart1_mpu_irqs),
+       .sdma_reqs      = uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART1_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+               },
+       },
+       .slaves         = omap2420_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_uart1_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+       { .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart2_slaves[] = {
+       &omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2420_uart2_hwmod = {
+       .name           = "uart2",
+       .mpu_irqs       = uart2_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart2_mpu_irqs),
+       .sdma_reqs      = uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+               },
+       },
+       .slaves         = omap2420_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_uart2_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+       { .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2420_uart3_slaves[] = {
+       &omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2420_uart3_hwmod = {
+       .name           = "uart3",
+       .mpu_irqs       = uart3_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart3_mpu_irqs),
+       .sdma_reqs      = uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 2,
+                       .module_bit = OMAP24XX_EN_UART3_SHIFT,
+                       .idlest_reg_id = 2,
+                       .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+               },
+       },
+       .slaves         = omap2420_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2420_uart3_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
        &omap2420_l3_main_hwmod,
        &omap2420_l4_core_hwmod,
        &omap2420_l4_wkup_hwmod,
        &omap2420_mpu_hwmod,
        &omap2420_iva_hwmod,
+       &omap2420_wd_timer2_hwmod,
+       &omap2420_uart1_hwmod,
+       &omap2420_uart2_hwmod,
+       &omap2420_uart3_hwmod,
        NULL,
 };
 
index 4526628..12d939e 100644 (file)
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-24xx.h"
+#include "cm-regbits-24xx.h"
 
 /*
  * OMAP2430 hardware module integration data
@@ -33,6 +35,7 @@ static struct omap_hwmod omap2430_mpu_hwmod;
 static struct omap_hwmod omap2430_iva_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
+static struct omap_hwmod omap2430_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -71,6 +74,9 @@ static struct omap_hwmod omap2430_l3_main_hwmod = {
 };
 
 static struct omap_hwmod omap2430_l4_wkup_hwmod;
+static struct omap_hwmod omap2430_uart1_hwmod;
+static struct omap_hwmod omap2430_uart2_hwmod;
+static struct omap_hwmod omap2430_uart3_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
@@ -79,6 +85,60 @@ static struct omap_hwmod_ocp_if omap2430_l4_core__l4_wkup = {
        .user   = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap2430_uart1_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART1_BASE,
+               .pa_end         = OMAP2_UART1_BASE + SZ_8K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart1 = {
+       .master         = &omap2430_l4_core_hwmod,
+       .slave          = &omap2430_uart1_hwmod,
+       .clk            = "uart1_ick",
+       .addr           = omap2430_uart1_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2430_uart1_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap2430_uart2_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART2_BASE,
+               .pa_end         = OMAP2_UART2_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart2 = {
+       .master         = &omap2430_l4_core_hwmod,
+       .slave          = &omap2430_uart2_hwmod,
+       .clk            = "uart2_ick",
+       .addr           = omap2430_uart2_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2430_uart2_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap2430_uart3_addr_space[] = {
+       {
+               .pa_start       = OMAP2_UART3_BASE,
+               .pa_end         = OMAP2_UART3_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2_l4_core__uart3 = {
+       .master         = &omap2430_l4_core_hwmod,
+       .slave          = &omap2430_uart3_hwmod,
+       .clk            = "uart3_ick",
+       .addr           = omap2430_uart3_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap2430_uart3_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = {
        &omap2430_l3_main__l4_core,
@@ -104,6 +164,9 @@ static struct omap_hwmod omap2430_l4_core_hwmod = {
 /* Slave interfaces on the L4_WKUP interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_wkup_slaves[] = {
        &omap2430_l4_core__l4_wkup,
+       &omap2_l4_core__uart1,
+       &omap2_l4_core__uart2,
+       &omap2_l4_core__uart3,
 };
 
 /* Master interfaces on the L4_WKUP interconnect */
@@ -165,12 +228,206 @@ static struct omap_hwmod omap2430_iva_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x49016000,
+               .pa_end         = 0x4901607f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__wd_timer2 = {
+       .master         = &omap2430_l4_wkup_hwmod,
+       .slave          = &omap2430_wd_timer2_hwmod,
+       .clk            = "mpu_wdt_ick",
+       .addr           = omap2430_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap2430_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_wd_timer_sysc = {
+       .rev_offs       = 0x0,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap2430_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap2430_wd_timer2_slaves[] = {
+       &omap2430_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap2430_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap2430_wd_timer_hwmod_class,
+       .main_clk       = "mpu_wdt_fck",
+       .prcm           = {
+               .omap2 = {
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_MPU_WDT_SHIFT,
+                       .module_offs = WKUP_MOD,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_ST_MPU_WDT_SHIFT,
+               },
+       },
+       .slaves         = omap2430_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+       .rev_offs       = 0x50,
+       .sysc_offs      = 0x54,
+       .syss_offs      = 0x58,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+       .name = "uart",
+       .sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+       { .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart1_slaves[] = {
+       &omap2_l4_core__uart1,
+};
+
+static struct omap_hwmod omap2430_uart1_hwmod = {
+       .name           = "uart1",
+       .mpu_irqs       = uart1_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart1_mpu_irqs),
+       .sdma_reqs      = uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART1_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART1_SHIFT,
+               },
+       },
+       .slaves         = omap2430_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_uart1_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+       { .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart2_slaves[] = {
+       &omap2_l4_core__uart2,
+};
+
+static struct omap_hwmod omap2430_uart2_hwmod = {
+       .name           = "uart2",
+       .mpu_irqs       = uart2_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart2_mpu_irqs),
+       .sdma_reqs      = uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP24XX_EN_UART2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP24XX_EN_UART2_SHIFT,
+               },
+       },
+       .slaves         = omap2430_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_uart2_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+       { .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_uart3_slaves[] = {
+       &omap2_l4_core__uart3,
+};
+
+static struct omap_hwmod omap2430_uart3_hwmod = {
+       .name           = "uart3",
+       .mpu_irqs       = uart3_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart3_mpu_irqs),
+       .sdma_reqs      = uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 2,
+                       .module_bit = OMAP24XX_EN_UART3_SHIFT,
+                       .idlest_reg_id = 2,
+                       .idlest_idle_bit = OMAP24XX_EN_UART3_SHIFT,
+               },
+       },
+       .slaves         = omap2430_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap2430_uart3_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
        &omap2430_l3_main_hwmod,
        &omap2430_l4_core_hwmod,
        &omap2430_l4_wkup_hwmod,
        &omap2430_mpu_hwmod,
        &omap2430_iva_hwmod,
+       &omap2430_wd_timer2_hwmod,
+       &omap2430_uart1_hwmod,
+       &omap2430_uart2_hwmod,
+       &omap2430_uart3_hwmod,
        NULL,
 };
 
index 5d8eb58..cb97ecf 100644 (file)
 #include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/dma.h>
+#include <plat/serial.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-34xx.h"
+#include "cm-regbits-34xx.h"
 
 /*
  * OMAP3xxx hardware module integration data
@@ -36,6 +38,7 @@ static struct omap_hwmod omap3xxx_iva_hwmod;
 static struct omap_hwmod omap3xxx_l3_main_hwmod;
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
+static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
@@ -82,6 +85,10 @@ static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 };
 
 static struct omap_hwmod omap3xxx_l4_wkup_hwmod;
+static struct omap_hwmod omap3xxx_uart1_hwmod;
+static struct omap_hwmod omap3xxx_uart2_hwmod;
+static struct omap_hwmod omap3xxx_uart3_hwmod;
+static struct omap_hwmod omap3xxx_uart4_hwmod;
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
@@ -90,6 +97,78 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
        .user   = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> UART1 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART1_BASE,
+               .pa_end         = OMAP3_UART1_BASE + SZ_8K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart1 = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &omap3xxx_uart1_hwmod,
+       .clk            = "uart1_ick",
+       .addr           = omap3xxx_uart1_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart1_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> UART2 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart2_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART2_BASE,
+               .pa_end         = OMAP3_UART2_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_core__uart2 = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &omap3xxx_uart2_hwmod,
+       .clk            = "uart2_ick",
+       .addr           = omap3xxx_uart2_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart2_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART3 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart3_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART3_BASE,
+               .pa_end         = OMAP3_UART3_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_per__uart3 = {
+       .master         = &omap3xxx_l4_per_hwmod,
+       .slave          = &omap3xxx_uart3_hwmod,
+       .clk            = "uart3_ick",
+       .addr           = omap3xxx_uart3_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart3_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 PER -> UART4 interface */
+static struct omap_hwmod_addr_space omap3xxx_uart4_addr_space[] = {
+       {
+               .pa_start       = OMAP3_UART4_BASE,
+               .pa_end         = OMAP3_UART4_BASE + SZ_1K - 1,
+               .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3_l4_per__uart4 = {
+       .master         = &omap3xxx_l4_per_hwmod,
+       .slave          = &omap3xxx_uart4_hwmod,
+       .clk            = "uart4_ick",
+       .addr           = omap3xxx_uart4_addr_space,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_uart4_addr_space),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
        &omap3xxx_l3_main__l4_core,
@@ -98,6 +177,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = {
        &omap3xxx_l4_core__l4_wkup,
+       &omap3_l4_core__uart1,
+       &omap3_l4_core__uart2,
 };
 
 /* L4 CORE */
@@ -119,6 +200,8 @@ static struct omap_hwmod_ocp_if *omap3xxx_l4_per_slaves[] = {
 
 /* Master interfaces on the L4_PER interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = {
+       &omap3_l4_per__uart3,
+       &omap3_l4_per__uart4,
 };
 
 /* L4 PER */
@@ -197,6 +280,235 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
        .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x48314000,
+               .pa_end         = 0x4831407f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__wd_timer2 = {
+       .master         = &omap3xxx_l4_wkup_hwmod,
+       .slave          = &omap3xxx_wd_timer2_hwmod,
+       .clk            = "wdt2_ick",
+       .addr           = omap3xxx_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap3xxx_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_wd_timer_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap3xxx_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod_ocp_if *omap3xxx_wd_timer2_slaves[] = {
+       &omap3xxx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap3xxx_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap3xxx_wd_timer_hwmod_class,
+       .main_clk       = "wdt2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_WDT2_SHIFT,
+                       .module_offs = WKUP_MOD,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_ST_WDT2_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART common */
+
+static struct omap_hwmod_class_sysconfig uart_sysc = {
+       .rev_offs       = 0x50,
+       .sysc_offs      = 0x54,
+       .syss_offs      = 0x58,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+                          SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class uart_class = {
+       .name = "uart",
+       .sysc = &uart_sysc,
+};
+
+/* UART1 */
+
+static struct omap_hwmod_irq_info uart1_mpu_irqs[] = {
+       { .irq = INT_24XX_UART1_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart1_sdma_reqs[] = {
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART1_TX, },
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART1_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart1_slaves[] = {
+       &omap3_l4_core__uart1,
+};
+
+static struct omap_hwmod omap3xxx_uart1_hwmod = {
+       .name           = "uart1",
+       .mpu_irqs       = uart1_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart1_mpu_irqs),
+       .sdma_reqs      = uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_UART1_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_EN_UART1_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart1_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART2 */
+
+static struct omap_hwmod_irq_info uart2_mpu_irqs[] = {
+       { .irq = INT_24XX_UART2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart2_sdma_reqs[] = {
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART2_TX, },
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART2_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart2_slaves[] = {
+       &omap3_l4_core__uart2,
+};
+
+static struct omap_hwmod omap3xxx_uart2_hwmod = {
+       .name           = "uart2",
+       .mpu_irqs       = uart2_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart2_mpu_irqs),
+       .sdma_reqs      = uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = CORE_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_UART2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_EN_UART2_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart2_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART3 */
+
+static struct omap_hwmod_irq_info uart3_mpu_irqs[] = {
+       { .irq = INT_24XX_UART3_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart3_sdma_reqs[] = {
+       { .name = "tx", .dma_req = OMAP24XX_DMA_UART3_TX, },
+       { .name = "rx", .dma_req = OMAP24XX_DMA_UART3_RX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart3_slaves[] = {
+       &omap3_l4_per__uart3,
+};
+
+static struct omap_hwmod omap3xxx_uart3_hwmod = {
+       .name           = "uart3",
+       .mpu_irqs       = uart3_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart3_mpu_irqs),
+       .sdma_reqs      = uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = OMAP3430_PER_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_EN_UART3_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_EN_UART3_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart3_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* UART4 */
+
+static struct omap_hwmod_irq_info uart4_mpu_irqs[] = {
+       { .irq = INT_36XX_UART4_IRQ, },
+};
+
+static struct omap_hwmod_dma_info uart4_sdma_reqs[] = {
+       { .name = "rx", .dma_req = OMAP36XX_DMA_UART4_RX, },
+       { .name = "tx", .dma_req = OMAP36XX_DMA_UART4_TX, },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_uart4_slaves[] = {
+       &omap3_l4_per__uart4,
+};
+
+static struct omap_hwmod omap3xxx_uart4_hwmod = {
+       .name           = "uart4",
+       .mpu_irqs       = uart4_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(uart4_mpu_irqs),
+       .sdma_reqs      = uart4_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(uart4_sdma_reqs),
+       .main_clk       = "uart4_fck",
+       .prcm           = {
+               .omap2 = {
+                       .module_offs = OMAP3430_PER_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3630_EN_UART4_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3630_EN_UART4_SHIFT,
+               },
+       },
+       .slaves         = omap3xxx_uart4_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap3xxx_uart4_slaves),
+       .class          = &uart_class,
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_l3_main_hwmod,
        &omap3xxx_l4_core_hwmod,
@@ -204,6 +516,11 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
        &omap3xxx_l4_wkup_hwmod,
        &omap3xxx_mpu_hwmod,
        &omap3xxx_iva_hwmod,
+       &omap3xxx_wd_timer2_hwmod,
+       &omap3xxx_uart1_hwmod,
+       &omap3xxx_uart2_hwmod,
+       &omap3xxx_uart3_hwmod,
+       &omap3xxx_uart4_hwmod,
        NULL,
 };
 
@@ -211,5 +528,3 @@ int __init omap3xxx_hwmod_init(void)
 {
        return omap_hwmod_init(omap3xxx_hwmods);
 }
-
-
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
new file mode 100644 (file)
index 0000000..7274db4
--- /dev/null
@@ -0,0 +1,850 @@
+/*
+ * Hardware modules present on the OMAP44xx chips
+ *
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Paul Walmsley
+ * Benoit Cousson
+ *
+ * This file is automatically generated from the OMAP hardware databases.
+ * We respectfully ask that any modifications to this file be coordinated
+ * with the public linux-omap@vger.kernel.org mailing list and the
+ * authors above to ensure that the autogeneration scripts are kept
+ * up-to-date with the file contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/cpu.h>
+
+#include "omap_hwmod_common_data.h"
+
+#include "cm.h"
+#include "prm-regbits-44xx.h"
+
+/* Base offset for all OMAP4 interrupts external to MPUSS */
+#define OMAP44XX_IRQ_GIC_START 32
+
+/* Base offset for all OMAP4 dma requests */
+#define OMAP44XX_DMA_REQ_START  1
+
+/* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_dmm_hwmod;
+static struct omap_hwmod omap44xx_emif_fw_hwmod;
+static struct omap_hwmod omap44xx_l3_instr_hwmod;
+static struct omap_hwmod omap44xx_l3_main_1_hwmod;
+static struct omap_hwmod omap44xx_l3_main_2_hwmod;
+static struct omap_hwmod omap44xx_l3_main_3_hwmod;
+static struct omap_hwmod omap44xx_l4_abe_hwmod;
+static struct omap_hwmod omap44xx_l4_cfg_hwmod;
+static struct omap_hwmod omap44xx_l4_per_hwmod;
+static struct omap_hwmod omap44xx_l4_wkup_hwmod;
+static struct omap_hwmod omap44xx_mpu_hwmod;
+static struct omap_hwmod omap44xx_mpu_private_hwmod;
+
+/*
+ * Interconnects omap_hwmod structures
+ * hwmods that compose the global OMAP interconnect
+ */
+
+/*
+ * 'dmm' class
+ * instance(s): dmm
+ */
+static struct omap_hwmod_class omap44xx_dmm_hwmod_class = {
+       .name = "dmm",
+};
+
+/* dmm interface data */
+/* l3_main_1 -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__dmm = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_dmm_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> dmm */
+static struct omap_hwmod_ocp_if omap44xx_mpu__dmm = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_dmm_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dmm slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dmm_slaves[] = {
+       &omap44xx_l3_main_1__dmm,
+       &omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod_irq_info omap44xx_dmm_irqs[] = {
+       { .irq = 113 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod omap44xx_dmm_hwmod = {
+       .name           = "dmm",
+       .class          = &omap44xx_dmm_hwmod_class,
+       .slaves         = omap44xx_dmm_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_dmm_slaves),
+       .mpu_irqs       = omap44xx_dmm_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_dmm_irqs),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'emif_fw' class
+ * instance(s): emif_fw
+ */
+static struct omap_hwmod_class omap44xx_emif_fw_hwmod_class = {
+       .name = "emif_fw",
+};
+
+/* emif_fw interface data */
+/* dmm -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_dmm__emif_fw = {
+       .master         = &omap44xx_dmm_hwmod,
+       .slave          = &omap44xx_emif_fw_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> emif_fw */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__emif_fw = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_emif_fw_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* emif_fw slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_emif_fw_slaves[] = {
+       &omap44xx_dmm__emif_fw,
+       &omap44xx_l4_cfg__emif_fw,
+};
+
+static struct omap_hwmod omap44xx_emif_fw_hwmod = {
+       .name           = "emif_fw",
+       .class          = &omap44xx_emif_fw_hwmod_class,
+       .slaves         = omap44xx_emif_fw_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_emif_fw_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l3' class
+ * instance(s): l3_instr, l3_main_1, l3_main_2, l3_main_3
+ */
+static struct omap_hwmod_class omap44xx_l3_hwmod_class = {
+       .name = "l3",
+};
+
+/* l3_instr interface data */
+/* l3_main_3 -> l3_instr */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_3__l3_instr = {
+       .master         = &omap44xx_l3_main_3_hwmod,
+       .slave          = &omap44xx_l3_instr_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_instr slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_instr_slaves[] = {
+       &omap44xx_l3_main_3__l3_instr,
+};
+
+static struct omap_hwmod omap44xx_l3_instr_hwmod = {
+       .name           = "l3_instr",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_instr_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_instr_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_1 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_l3_main_1_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
+       &omap44xx_l3_main_2__l3_main_1,
+       &omap44xx_l4_cfg__l3_main_1,
+       &omap44xx_mpu__l3_main_1,
+};
+
+static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
+       .name           = "l3_main_1",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_1_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_2 interface data */
+/* l3_main_1 -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l3_main_2_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_2 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_2_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
+       &omap44xx_l3_main_1__l3_main_2,
+       &omap44xx_l4_cfg__l3_main_2,
+};
+
+static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
+       .name           = "l3_main_2",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l3_main_3 interface data */
+/* l3_main_1 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_2 -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_3 = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg -> l3_main_3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l3_main_3 = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l3_main_3_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l3_main_3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l3_main_3_slaves[] = {
+       &omap44xx_l3_main_1__l3_main_3,
+       &omap44xx_l3_main_2__l3_main_3,
+       &omap44xx_l4_cfg__l3_main_3,
+};
+
+static struct omap_hwmod omap44xx_l3_main_3_hwmod = {
+       .name           = "l3_main_3",
+       .class          = &omap44xx_l3_hwmod_class,
+       .slaves         = omap44xx_l3_main_3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l3_main_3_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'l4' class
+ * instance(s): l4_abe, l4_cfg, l4_per, l4_wkup
+ */
+static struct omap_hwmod_class omap44xx_l4_hwmod_class = {
+       .name = "l4",
+};
+
+/* l4_abe interface data */
+/* l3_main_1 -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_abe = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l4_abe_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_mpu__l4_abe = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_l4_abe_hwmod,
+       .clk            = "ocp_abe_iclk",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_abe slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
+       &omap44xx_l3_main_1__l4_abe,
+       &omap44xx_mpu__l4_abe,
+};
+
+static struct omap_hwmod omap44xx_l4_abe_hwmod = {
+       .name           = "l4_abe",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_abe_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_abe_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_cfg interface data */
+/* l3_main_1 -> l4_cfg */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l4_cfg = {
+       .master         = &omap44xx_l3_main_1_hwmod,
+       .slave          = &omap44xx_l4_cfg_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_cfg slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_cfg_slaves[] = {
+       &omap44xx_l3_main_1__l4_cfg,
+};
+
+static struct omap_hwmod omap44xx_l4_cfg_hwmod = {
+       .name           = "l4_cfg",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_cfg_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_cfg_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_per interface data */
+/* l3_main_2 -> l4_per */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l4_per = {
+       .master         = &omap44xx_l3_main_2_hwmod,
+       .slave          = &omap44xx_l4_per_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_per slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_per_slaves[] = {
+       &omap44xx_l3_main_2__l4_per,
+};
+
+static struct omap_hwmod omap44xx_l4_per_hwmod = {
+       .name           = "l4_per",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_per_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_per_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_wkup interface data */
+/* l4_cfg -> l4_wkup */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__l4_wkup = {
+       .master         = &omap44xx_l4_cfg_hwmod,
+       .slave          = &omap44xx_l4_wkup_hwmod,
+       .clk            = "l4_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4_wkup slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_l4_wkup_slaves[] = {
+       &omap44xx_l4_cfg__l4_wkup,
+};
+
+static struct omap_hwmod omap44xx_l4_wkup_hwmod = {
+       .name           = "l4_wkup",
+       .class          = &omap44xx_l4_hwmod_class,
+       .slaves         = omap44xx_l4_wkup_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_l4_wkup_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu_bus' class
+ * instance(s): mpu_private
+ */
+static struct omap_hwmod_class omap44xx_mpu_bus_hwmod_class = {
+       .name = "mpu_bus",
+};
+
+/* mpu_private interface data */
+/* mpu -> mpu_private */
+static struct omap_hwmod_ocp_if omap44xx_mpu__mpu_private = {
+       .master         = &omap44xx_mpu_hwmod,
+       .slave          = &omap44xx_mpu_private_hwmod,
+       .clk            = "l3_div_ck",
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mpu_private slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_private_slaves[] = {
+       &omap44xx_mpu__mpu_private,
+};
+
+static struct omap_hwmod omap44xx_mpu_private_hwmod = {
+       .name           = "mpu_private",
+       .class          = &omap44xx_mpu_bus_hwmod_class,
+       .slaves         = omap44xx_mpu_private_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_mpu_private_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mpu' class
+ * mpu sub-system
+ */
+
+static struct omap_hwmod_class omap44xx_mpu_hwmod_class = {
+       .name = "mpu",
+};
+
+/* mpu */
+static struct omap_hwmod_irq_info omap44xx_mpu_irqs[] = {
+       { .name = "pl310", .irq = 0 + OMAP44XX_IRQ_GIC_START },
+       { .name = "cti0", .irq = 1 + OMAP44XX_IRQ_GIC_START },
+       { .name = "cti1", .irq = 2 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* mpu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mpu_masters[] = {
+       &omap44xx_mpu__l3_main_1,
+       &omap44xx_mpu__l4_abe,
+       &omap44xx_mpu__dmm,
+};
+
+static struct omap_hwmod omap44xx_mpu_hwmod = {
+       .name           = "mpu",
+       .class          = &omap44xx_mpu_hwmod_class,
+       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+       .mpu_irqs       = omap44xx_mpu_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_mpu_irqs),
+       .main_clk       = "dpll_mpu_m2_ck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_MPU_MPU_CLKCTRL,
+               },
+       },
+       .masters        = omap44xx_mpu_masters,
+       .masters_cnt    = ARRAY_SIZE(omap44xx_mpu_masters),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'wd_timer' class
+ * 32-bit watchdog upward counter that generates a pulse on the reset pin on
+ * overflow condition
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_wd_timer_sysc = {
+       .rev_offs       = 0x0000,
+       .sysc_offs      = 0x0010,
+       .syss_offs      = 0x0014,
+       .sysc_flags     = (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
+                          SYSC_HAS_SOFTRESET),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+/*
+ * 'uart' class
+ * universal asynchronous receiver/transmitter (uart)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_uart_sysc = {
+       .rev_offs       = 0x0050,
+       .sysc_offs      = 0x0054,
+       .syss_offs      = 0x0058,
+       .sysc_flags     = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+                          SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_wd_timer_hwmod_class = {
+       .name = "wd_timer",
+       .sysc = &omap44xx_wd_timer_sysc,
+};
+
+/* wd_timer2 */
+static struct omap_hwmod omap44xx_wd_timer2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer2_irqs[] = {
+       { .irq = 80 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer2_addrs[] = {
+       {
+               .pa_start       = 0x4a314000,
+               .pa_end         = 0x4a31407f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_class omap44xx_uart_hwmod_class = {
+       .name = "uart",
+       .sysc = &omap44xx_uart_sysc,
+};
+
+/* uart1 */
+static struct omap_hwmod omap44xx_uart1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart1_irqs[] = {
+       { .irq = 72 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart1_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 48 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 49 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart1_addrs[] = {
+       {
+               .pa_start       = 0x4806a000,
+               .pa_end         = 0x4806a0ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_per -> uart1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart1 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart1_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart1_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart1_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart1_slaves[] = {
+       &omap44xx_l4_per__uart1,
+};
+
+static struct omap_hwmod omap44xx_uart1_hwmod = {
+       .name           = "uart1",
+       .class          = &omap44xx_uart_hwmod_class,
+       .mpu_irqs       = omap44xx_uart1_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart1_irqs),
+       .sdma_reqs      = omap44xx_uart1_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart1_sdma_reqs),
+       .main_clk       = "uart1_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART1_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart1_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart1_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart2 */
+static struct omap_hwmod omap44xx_uart2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart2_irqs[] = {
+       { .irq = 73 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart2_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 50 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 51 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart2_addrs[] = {
+       {
+               .pa_start       = 0x4806c000,
+               .pa_end         = 0x4806c0ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_wkup -> wd_timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__wd_timer2 = {
+       .master         = &omap44xx_l4_wkup_hwmod,
+       .slave          = &omap44xx_wd_timer2_hwmod,
+       .clk            = "l4_wkup_clk_mux_ck",
+       .addr           = omap44xx_wd_timer2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_wd_timer2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* wd_timer2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer2_slaves[] = {
+       &omap44xx_l4_wkup__wd_timer2,
+};
+
+static struct omap_hwmod omap44xx_wd_timer2_hwmod = {
+       .name           = "wd_timer2",
+       .class          = &omap44xx_wd_timer_hwmod_class,
+       .mpu_irqs       = omap44xx_wd_timer2_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_wd_timer2_irqs),
+       .main_clk       = "wd_timer2_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_WKUP_WDT2_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_wd_timer2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_wd_timer2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* wd_timer3 */
+static struct omap_hwmod omap44xx_wd_timer3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_wd_timer3_irqs[] = {
+       { .irq = 36 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_addrs[] = {
+       {
+               .pa_start       = 0x40130000,
+               .pa_end         = 0x4013007f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_per -> uart2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart2 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart2_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart2_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart2_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart2_slaves[] = {
+       &omap44xx_l4_per__uart2,
+};
+
+static struct omap_hwmod omap44xx_uart2_hwmod = {
+       .name           = "uart2",
+       .class          = &omap44xx_uart_hwmod_class,
+       .mpu_irqs       = omap44xx_uart2_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart2_irqs),
+       .sdma_reqs      = omap44xx_uart2_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart2_sdma_reqs),
+       .main_clk       = "uart2_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART2_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart2_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart2_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart3 */
+static struct omap_hwmod omap44xx_uart3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart3_irqs[] = {
+       { .irq = 74 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart3_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 52 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 53 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart3_addrs[] = {
+       {
+               .pa_start       = 0x48020000,
+               .pa_end         = 0x480200ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_abe -> wd_timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3 = {
+       .master         = &omap44xx_l4_abe_hwmod,
+       .slave          = &omap44xx_wd_timer3_hwmod,
+       .clk            = "ocp_abe_iclk",
+       .addr           = omap44xx_wd_timer3_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_wd_timer3_addrs),
+       .user           = OCP_USER_MPU,
+};
+
+/* l4_abe -> wd_timer3 (dma) */
+static struct omap_hwmod_addr_space omap44xx_wd_timer3_dma_addrs[] = {
+       {
+               .pa_start       = 0x49030000,
+               .pa_end         = 0x4903007f,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+/* l4_per -> uart3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart3 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart3_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart3_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart3_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart3_slaves[] = {
+       &omap44xx_l4_per__uart3,
+};
+
+static struct omap_hwmod omap44xx_uart3_hwmod = {
+       .name           = "uart3",
+       .class          = &omap44xx_uart_hwmod_class,
+       .flags          = (HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET),
+       .mpu_irqs       = omap44xx_uart3_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart3_irqs),
+       .sdma_reqs      = omap44xx_uart3_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart3_sdma_reqs),
+       .main_clk       = "uart3_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART3_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart3_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* uart4 */
+static struct omap_hwmod omap44xx_uart4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_uart4_irqs[] = {
+       { .irq = 70 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_uart4_sdma_reqs[] = {
+       { .name = "tx", .dma_req = 54 + OMAP44XX_DMA_REQ_START },
+       { .name = "rx", .dma_req = 55 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_uart4_addrs[] = {
+       {
+               .pa_start       = 0x4806e000,
+               .pa_end         = 0x4806e0ff,
+               .flags          = ADDR_TYPE_RT
+       },
+};
+
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__wd_timer3_dma = {
+       .master         = &omap44xx_l4_abe_hwmod,
+       .slave          = &omap44xx_wd_timer3_hwmod,
+       .clk            = "ocp_abe_iclk",
+       .addr           = omap44xx_wd_timer3_dma_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_wd_timer3_dma_addrs),
+       .user           = OCP_USER_SDMA,
+};
+
+/* wd_timer3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_wd_timer3_slaves[] = {
+       &omap44xx_l4_abe__wd_timer3,
+       &omap44xx_l4_abe__wd_timer3_dma,
+};
+
+static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
+       .name           = "wd_timer3",
+       .class          = &omap44xx_wd_timer_hwmod_class,
+       .mpu_irqs       = omap44xx_wd_timer3_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_wd_timer3_irqs),
+       .main_clk       = "wd_timer3_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM1_ABE_WDT3_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_wd_timer3_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_wd_timer3_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* l4_per -> uart4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__uart4 = {
+       .master         = &omap44xx_l4_per_hwmod,
+       .slave          = &omap44xx_uart4_hwmod,
+       .clk            = "l4_div_ck",
+       .addr           = omap44xx_uart4_addrs,
+       .addr_cnt       = ARRAY_SIZE(omap44xx_uart4_addrs),
+       .user           = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* uart4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_uart4_slaves[] = {
+       &omap44xx_l4_per__uart4,
+};
+
+static struct omap_hwmod omap44xx_uart4_hwmod = {
+       .name           = "uart4",
+       .class          = &omap44xx_uart_hwmod_class,
+       .mpu_irqs       = omap44xx_uart4_irqs,
+       .mpu_irqs_cnt   = ARRAY_SIZE(omap44xx_uart4_irqs),
+       .sdma_reqs      = omap44xx_uart4_sdma_reqs,
+       .sdma_reqs_cnt  = ARRAY_SIZE(omap44xx_uart4_sdma_reqs),
+       .main_clk       = "uart4_fck",
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_reg = OMAP4430_CM_L4PER_UART4_CLKCTRL,
+               },
+       },
+       .slaves         = omap44xx_uart4_slaves,
+       .slaves_cnt     = ARRAY_SIZE(omap44xx_uart4_slaves),
+       .omap_chip      = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
+       /* dmm class */
+       &omap44xx_dmm_hwmod,
+       /* emif_fw class */
+       &omap44xx_emif_fw_hwmod,
+       /* l3 class */
+       &omap44xx_l3_instr_hwmod,
+       &omap44xx_l3_main_1_hwmod,
+       &omap44xx_l3_main_2_hwmod,
+       &omap44xx_l3_main_3_hwmod,
+       /* l4 class */
+       &omap44xx_l4_abe_hwmod,
+       &omap44xx_l4_cfg_hwmod,
+       &omap44xx_l4_per_hwmod,
+       &omap44xx_l4_wkup_hwmod,
+       /* mpu_bus class */
+       &omap44xx_mpu_private_hwmod,
+
+       /* mpu class */
+       &omap44xx_mpu_hwmod,
+       /* wd_timer class */
+       &omap44xx_wd_timer2_hwmod,
+       &omap44xx_wd_timer3_hwmod,
+
+       /* uart class */
+       &omap44xx_uart1_hwmod,
+       &omap44xx_uart2_hwmod,
+       &omap44xx_uart3_hwmod,
+       &omap44xx_uart4_hwmod,
+       NULL,
+};
+
+int __init omap44xx_hwmod_init(void)
+{
+       return omap_hwmod_init(omap44xx_hwmods);
+}
+
index 723b44e..5e81517 100644 (file)
 #include <plat/board.h>
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
+#include <plat/dmtimer.h>
 
 #include "prm.h"
 #include "cm.h"
 #include "pm.h"
 
 int omap2_pm_debug;
+u32 enable_off_mode;
+u32 sleep_while_idle;
+u32 wakeup_timer_seconds;
+u32 wakeup_timer_milliseconds;
 
 #define DUMP_PRM_MOD_REG(mod, reg)    \
        regs[reg_count].name = #mod "." #reg; \
@@ -162,7 +167,7 @@ void omap2_pm_dump(int mode, int resume, unsigned int us)
 
 static void pm_dbg_regset_store(u32 *ptr);
 
-struct dentry *pm_dbg_dir;
+static struct dentry *pm_dbg_dir;
 
 static int pm_dbg_init_done;
 
@@ -349,6 +354,23 @@ void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
        pwrdm->timer = t;
 }
 
+void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
+{
+       u32 tick_rate, cycles;
+
+       if (!seconds && !milliseconds)
+               return;
+
+       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
+       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
+       omap_dm_timer_stop(gptimer_wakeup);
+       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
+
+       pr_info("PM: Resume timer in %u.%03u secs"
+               " (%d ticks at %d ticks/sec.)\n",
+               seconds, milliseconds, cycles, tick_rate);
+}
+
 static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
 {
        struct seq_file *s = (struct seq_file *)user;
@@ -494,8 +516,10 @@ int pm_dbg_regset_init(int reg_set)
 
 static int pwrdm_suspend_get(void *data, u64 *val)
 {
-       int ret;
-       ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
+       int ret = -EINVAL;
+
+       if (cpu_is_omap34xx())
+               ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
        *val = ret;
 
        if (ret >= 0)
@@ -505,7 +529,10 @@ static int pwrdm_suspend_get(void *data, u64 *val)
 
 static int pwrdm_suspend_set(void *data, u64 val)
 {
-       return omap3_pm_set_suspend_state((struct powerdomain *)data, (int)val);
+       if (cpu_is_omap34xx())
+               return omap3_pm_set_suspend_state(
+                       (struct powerdomain *)data, (int)val);
+       return -EINVAL;
 }
 
 DEFINE_SIMPLE_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
@@ -553,8 +580,10 @@ static int option_set(void *data, u64 val)
 
        *option = val;
 
-       if (option == &enable_off_mode)
-               omap3_pm_off_mode_enable(val);
+       if (option == &enable_off_mode) {
+               if (cpu_is_omap34xx())
+                       omap3_pm_off_mode_enable(val);
+       }
 
        return 0;
 }
@@ -609,6 +638,9 @@ static int __init pm_dbg_init(void)
                                   &sleep_while_idle, &pm_dbg_option_fops);
        (void) debugfs_create_file("wakeup_timer_seconds", S_IRUGO | S_IWUGO, d,
                                   &wakeup_timer_seconds, &pm_dbg_option_fops);
+       (void) debugfs_create_file("wakeup_timer_milliseconds",
+                       S_IRUGO | S_IWUGO, d, &wakeup_timer_milliseconds,
+                       &pm_dbg_option_fops);
        pm_dbg_init_done = 1;
 
        return 0;
index 68f9f2e..59ca03b 100644 (file)
 #include <plat/omap_device.h>
 #include <plat/common.h>
 
+#include <plat/powerdomain.h>
+#include <plat/clockdomain.h>
+
 static struct omap_device_pm_latency *pm_lats;
 
 static struct device *mpu_dev;
-static struct device *dsp_dev;
+static struct device *iva_dev;
 static struct device *l3_dev;
+static struct device *dsp_dev;
 
 struct device *omap2_get_mpuss_device(void)
 {
@@ -30,10 +34,10 @@ struct device *omap2_get_mpuss_device(void)
        return mpu_dev;
 }
 
-struct device *omap2_get_dsp_device(void)
+struct device *omap2_get_iva_device(void)
 {
-       WARN_ON_ONCE(!dsp_dev);
-       return dsp_dev;
+       WARN_ON_ONCE(!iva_dev);
+       return iva_dev;
 }
 
 struct device *omap2_get_l3_device(void)
@@ -42,6 +46,13 @@ struct device *omap2_get_l3_device(void)
        return l3_dev;
 }
 
+struct device *omap4_get_dsp_device(void)
+{
+       WARN_ON_ONCE(!dsp_dev);
+       return dsp_dev;
+}
+EXPORT_SYMBOL(omap4_get_dsp_device);
+
 /* static int _init_omap_device(struct omap_hwmod *oh, void *user) */
 static int _init_omap_device(char *name, struct device **new_dev)
 {
@@ -69,8 +80,60 @@ static int _init_omap_device(char *name, struct device **new_dev)
 static void omap2_init_processor_devices(void)
 {
        _init_omap_device("mpu", &mpu_dev);
-       _init_omap_device("iva", &dsp_dev);
-       _init_omap_device("l3_main", &l3_dev);
+       _init_omap_device("iva", &iva_dev);
+       if (cpu_is_omap44xx()) {
+               _init_omap_device("l3_main_1", &l3_dev);
+               _init_omap_device("dsp", &dsp_dev);
+       } else {
+               _init_omap_device("l3_main", &l3_dev);
+       }
+}
+
+/*
+ * This sets pwrdm state (other than mpu & core. Currently only ON &
+ * RET are supported. Function is assuming that clkdm doesn't have
+ * hw_sup mode enabled.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
+{
+       u32 cur_state;
+       int sleep_switch = 0;
+       int ret = 0;
+
+       if (pwrdm == NULL || IS_ERR(pwrdm))
+               return -EINVAL;
+
+       while (!(pwrdm->pwrsts & (1 << state))) {
+               if (state == PWRDM_POWER_OFF)
+                       return ret;
+               state--;
+       }
+
+       cur_state = pwrdm_read_next_pwrst(pwrdm);
+       if (cur_state == state)
+               return ret;
+
+       if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
+               omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+               sleep_switch = 1;
+               pwrdm_wait_transition(pwrdm);
+       }
+
+       ret = pwrdm_set_next_pwrst(pwrdm, state);
+       if (ret) {
+               printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
+                      pwrdm->name);
+               goto err;
+       }
+
+       if (sleep_switch) {
+               omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+               pwrdm_wait_transition(pwrdm);
+               pwrdm_state_switch(pwrdm);
+       }
+
+err:
+       return ret;
 }
 
 static int __init omap2_common_pm_init(void)
index 3de6ece..0d75bfd 100644 (file)
 
 #include <plat/powerdomain.h>
 
-extern u32 enable_off_mode;
-extern u32 sleep_while_idle;
-
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap3_can_sleep(void);
-extern int set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap3_idle_init(void);
 
 struct cpuidle_params {
@@ -48,10 +45,16 @@ extern struct omap_dm_timer *gptimer_wakeup;
 
 #ifdef CONFIG_PM_DEBUG
 extern void omap2_pm_dump(int mode, int resume, unsigned int us);
+extern void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds);
 extern int omap2_pm_debug;
+extern u32 enable_off_mode;
+extern u32 sleep_while_idle;
 #else
 #define omap2_pm_dump(mode, resume, us)                do {} while (0);
+#define omap2_pm_wakeup_on_timer(seconds, milliseconds)        do {} while (0);
 #define omap2_pm_debug                         0
+#define enable_off_mode 0
+#define sleep_while_idle 0
 #endif
 
 #if defined(CONFIG_CPU_IDLE)
index 6aeedea..a40457d 100644 (file)
@@ -38,7 +38,6 @@
 #include <mach/irqs.h>
 #include <plat/clock.h>
 #include <plat/sram.h>
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/board.h>
 
@@ -48,6 +47,7 @@
 #include "cm-regbits-24xx.h"
 #include "sdrc.h"
 #include "pm.h"
+#include "control.h"
 
 #include <plat/powerdomain.h>
 #include <plat/clockdomain.h>
@@ -245,6 +245,8 @@ static int omap2_can_sleep(void)
 {
        if (omap2_fclks_active())
                return 0;
+       if (!omap_uart_can_sleep())
+               return 0;
        if (osc_ck->usecount > 1)
                return 0;
        if (omap_dma_running())
index 7b03426..75c0cd1 100644 (file)
 #include <plat/sram.h>
 #include <plat/clockdomain.h>
 #include <plat/powerdomain.h>
-#include <plat/control.h>
 #include <plat/serial.h>
 #include <plat/sdrc.h>
 #include <plat/prcm.h>
 #include <plat/gpmc.h>
 #include <plat/dma.h>
-#include <plat/dmtimer.h>
 
 #include <asm/tlbflush.h>
 
 #include "prm.h"
 #include "pm.h"
 #include "sdrc.h"
+#include "control.h"
 
 /* Scratchpad offsets */
-#define OMAP343X_TABLE_ADDRESS_OFFSET     0x31
-#define OMAP343X_TABLE_VALUE_OFFSET       0x30
-#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0x32
-
-u32 enable_off_mode;
-u32 sleep_while_idle;
-u32 wakeup_timer_seconds;
-u32 wakeup_timer_milliseconds;
+#define OMAP343X_TABLE_ADDRESS_OFFSET     0xc4
+#define OMAP343X_TABLE_VALUE_OFFSET       0xc0
+#define OMAP343X_CONTROL_REG_VALUE_OFFSET  0xc8
 
 struct power_state {
        struct powerdomain *pwrdm;
@@ -316,7 +310,7 @@ static void restore_control_register(u32 val)
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
-       u32 *scratchpad_address;
+       void __iomem *scratchpad_address;
        u32 previous_value, control_reg_value;
        u32 *address;
 
@@ -351,7 +345,6 @@ void omap_sram_idle(void)
        int core_next_state = PWRDM_POWER_ON;
        int core_prev_state, per_prev_state;
        u32 sdrc_pwr = 0;
-       int per_state_modified = 0;
 
        if (!_omap_sram_idle)
                return;
@@ -385,9 +378,9 @@ void omap_sram_idle(void)
        /* Enable IO-PAD and IO-CHAIN wakeups */
        per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
        core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
-       if (omap3_has_io_wakeup() && \
-                       (per_next_state < PWRDM_POWER_ON ||
-                       core_next_state < PWRDM_POWER_ON)) {
+       if (omap3_has_io_wakeup() &&
+           (per_next_state < PWRDM_POWER_ON ||
+            core_next_state < PWRDM_POWER_ON)) {
                prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
                omap3_enable_io_chain();
        }
@@ -395,20 +388,12 @@ void omap_sram_idle(void)
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(2);
+               omap_uart_prepare_idle(3);
                omap2_gpio_prepare_for_idle(per_next_state);
-               if (per_next_state == PWRDM_POWER_OFF) {
-                       if (core_next_state == PWRDM_POWER_ON) {
-                               per_next_state = PWRDM_POWER_RET;
-                               pwrdm_set_next_pwrst(per_pwrdm, per_next_state);
-                               per_state_modified = 1;
-                       } else
+               if (per_next_state == PWRDM_POWER_OFF)
                                omap3_per_save_context();
-               }
        }
 
-       if (pwrdm_read_pwrst(cam_pwrdm) == PWRDM_POWER_ON)
-               omap2_clkdm_deny_idle(mpu_pwrdm->pwrdm_clkdms[0]);
-
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
                omap_uart_prepare_idle(0);
@@ -475,8 +460,7 @@ void omap_sram_idle(void)
                if (per_prev_state == PWRDM_POWER_OFF)
                        omap3_per_restore_context();
                omap_uart_resume_idle(2);
-               if (per_state_modified)
-                       pwrdm_set_next_pwrst(per_pwrdm, PWRDM_POWER_OFF);
+               omap_uart_resume_idle(3);
        }
 
        /* Disable IO-PAD and IO-CHAIN wakeup */
@@ -501,51 +485,6 @@ int omap3_can_sleep(void)
        return 1;
 }
 
-/* This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported. Function is assuming that clkdm doesn't have
- * hw_sup mode enabled. */
-int set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
-{
-       u32 cur_state;
-       int sleep_switch = 0;
-       int ret = 0;
-
-       if (pwrdm == NULL || IS_ERR(pwrdm))
-               return -EINVAL;
-
-       while (!(pwrdm->pwrsts & (1 << state))) {
-               if (state == PWRDM_POWER_OFF)
-                       return ret;
-               state--;
-       }
-
-       cur_state = pwrdm_read_next_pwrst(pwrdm);
-       if (cur_state == state)
-               return ret;
-
-       if (pwrdm_read_pwrst(pwrdm) < PWRDM_POWER_ON) {
-               omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-               sleep_switch = 1;
-               pwrdm_wait_transition(pwrdm);
-       }
-
-       ret = pwrdm_set_next_pwrst(pwrdm, state);
-       if (ret) {
-               printk(KERN_ERR "Unable to set state of powerdomain: %s\n",
-                      pwrdm->name);
-               goto err;
-       }
-
-       if (sleep_switch) {
-               omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-               pwrdm_wait_transition(pwrdm);
-               pwrdm_state_switch(pwrdm);
-       }
-
-err:
-       return ret;
-}
-
 static void omap3_pm_idle(void)
 {
        local_irq_disable();
@@ -567,23 +506,6 @@ out:
 #ifdef CONFIG_SUSPEND
 static suspend_state_t suspend_state;
 
-static void omap2_pm_wakeup_on_timer(u32 seconds, u32 milliseconds)
-{
-       u32 tick_rate, cycles;
-
-       if (!seconds && !milliseconds)
-               return;
-
-       tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer_wakeup));
-       cycles = tick_rate * seconds + tick_rate * milliseconds / 1000;
-       omap_dm_timer_stop(gptimer_wakeup);
-       omap_dm_timer_set_load_start(gptimer_wakeup, 0, 0xffffffff - cycles);
-
-       pr_info("PM: Resume timer in %u.%03u secs"
-               " (%d ticks at %d ticks/sec.)\n",
-               seconds, milliseconds, cycles, tick_rate);
-}
-
 static int omap3_pm_prepare(void)
 {
        disable_hlt();
@@ -604,7 +526,7 @@ static int omap3_pm_suspend(void)
                pwrst->saved_state = pwrdm_read_next_pwrst(pwrst->pwrdm);
        /* Set ones wanted by suspend */
        list_for_each_entry(pwrst, &pwrst_list, node) {
-               if (set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
+               if (omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state))
                        goto restore;
                if (pwrdm_clear_all_prev_pwrst(pwrst->pwrdm))
                        goto restore;
@@ -625,7 +547,7 @@ restore:
                               pwrst->pwrdm->name, pwrst->next_state);
                        ret = -1;
                }
-               set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
+               omap_set_pwrdm_state(pwrst->pwrdm, pwrst->saved_state);
        }
        if (ret)
                printk(KERN_ERR "Could not enter target state in pm_suspend\n");
@@ -756,6 +678,14 @@ static void __init omap3_d2d_idle(void)
 
 static void __init prcm_setup_regs(void)
 {
+       u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ?
+                                       OMAP3630_AUTO_UART4_MASK : 0;
+       u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
+                                       OMAP3630_EN_UART4_MASK : 0;
+       u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
+                                       OMAP3630_GRPSEL_UART4_MASK : 0;
+
+
        /* XXX Reset all wkdeps. This should be done when initializing
         * powerdomains */
        prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
@@ -842,6 +772,7 @@ static void __init prcm_setup_regs(void)
                CM_AUTOIDLE);
 
        cm_write_mod_reg(
+               omap3630_auto_uart4_mask |
                OMAP3430_AUTO_GPIO6_MASK |
                OMAP3430_AUTO_GPIO5_MASK |
                OMAP3430_AUTO_GPIO4_MASK |
@@ -918,14 +849,16 @@ static void __init prcm_setup_regs(void)
                                OMAP3430_DSS_MOD, PM_WKEN);
 
        /* Enable wakeups in PER */
-       prm_write_mod_reg(OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
+       prm_write_mod_reg(omap3630_en_uart4_mask |
+                         OMAP3430_EN_GPIO2_MASK | OMAP3430_EN_GPIO3_MASK |
                          OMAP3430_EN_GPIO4_MASK | OMAP3430_EN_GPIO5_MASK |
                          OMAP3430_EN_GPIO6_MASK | OMAP3430_EN_UART3_MASK |
                          OMAP3430_EN_MCBSP2_MASK | OMAP3430_EN_MCBSP3_MASK |
                          OMAP3430_EN_MCBSP4_MASK,
                          OMAP3430_PER_MOD, PM_WKEN);
        /* and allow them to wake up MPU */
-       prm_write_mod_reg(OMAP3430_GRPSEL_GPIO2_MASK |
+       prm_write_mod_reg(omap3630_grpsel_uart4_mask |
+                         OMAP3430_GRPSEL_GPIO2_MASK |
                          OMAP3430_GRPSEL_GPIO3_MASK |
                          OMAP3430_GRPSEL_GPIO4_MASK |
                          OMAP3430_GRPSEL_GPIO5_MASK |
@@ -974,7 +907,7 @@ void omap3_pm_off_mode_enable(int enable)
 
        list_for_each_entry(pwrst, &pwrst_list, node) {
                pwrst->next_state = state;
-               set_pwrdm_state(pwrst->pwrdm, state);
+               omap_set_pwrdm_state(pwrst->pwrdm, state);
        }
 }
 
@@ -1019,7 +952,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
        if (pwrdm_has_hdwr_sar(pwrdm))
                pwrdm_enable_hdwr_sar(pwrdm);
 
-       return set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
+       return omap_set_pwrdm_state(pwrst->pwrdm, pwrst->next_state);
 }
 
 /*
@@ -1029,9 +962,6 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
  */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-       clkdm_clear_all_wkdeps(clkdm);
-       clkdm_clear_all_sleepdeps(clkdm);
-
        if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
                omap2_clkdm_allow_idle(clkdm);
        else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
diff --git a/arch/arm/mach-omap2/pm_bus.c b/arch/arm/mach-omap2/pm_bus.c
new file mode 100644 (file)
index 0000000..784989f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Runtime PM support code for OMAP
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap-pm.h>
+
+#ifdef CONFIG_PM_RUNTIME
+int omap_pm_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       int r, ret = 0;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       ret = pm_generic_runtime_suspend(dev);
+
+       if (!ret && dev->parent == &omap_device_parent) {
+               r = omap_device_idle(pdev);
+               WARN_ON(r);
+       }
+
+       return ret;
+};
+
+int omap_pm_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       int r;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       if (dev->parent == &omap_device_parent) {
+               r = omap_device_enable(pdev);
+               WARN_ON(r);
+       }
+
+       return pm_generic_runtime_resume(dev);
+};
+#else
+#define omap_pm_runtime_suspend NULL
+#define omap_pm_runtime_resume NULL
+#endif /* CONFIG_PM_RUNTIME */
+
+static int __init omap_pm_runtime_init(void)
+{
+       const struct dev_pm_ops *pm;
+       struct dev_pm_ops *omap_pm;
+
+       pm = platform_bus_get_pm_ops();
+       if (!pm) {
+               pr_err("%s: unable to get dev_pm_ops from platform_bus\n",
+                       __func__);
+               return -ENODEV;
+       }
+
+       omap_pm = kmemdup(pm, sizeof(struct dev_pm_ops), GFP_KERNEL);
+       if (!omap_pm) {
+               pr_err("%s: unable to alloc memory for new dev_pm_ops\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       omap_pm->runtime_suspend = omap_pm_runtime_suspend;
+       omap_pm->runtime_resume = omap_pm_runtime_resume;
+
+       platform_bus_set_pm_ops(omap_pm);
+
+       return 0;
+}
+core_initcall(omap_pm_runtime_init);
index c721951..9c01b55 100644 (file)
@@ -98,7 +98,7 @@ static struct powerdomain dss_44xx_pwrdm = {
        .prcm_offs        = OMAP4430_PRM_DSS_MOD,
        .omap_chip        = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
        .pwrsts           = PWRSTS_OFF_RET_ON,
-       .pwrsts_logic_ret = PWRSTS_OFF_RET,
+       .pwrsts_logic_ret = PWRSTS_OFF,
        .banks            = 1,
        .pwrsts_mem_ret = {
                [0] = PWRDM_POWER_OFF,  /* dss_mem */
index 995b7ed..298a22a 100644 (file)
 #define OMAP3430_EN_MPU_SHIFT                          1
 
 /* CM_FCLKEN_PER, CM_ICLKEN_PER, PM_WKEN_PER shared bits */
+
+#define OMAP3630_EN_UART4_MASK                         (1 << 18)
+#define OMAP3630_EN_UART4_SHIFT                                18
 #define OMAP3430_EN_GPIO6_MASK                         (1 << 17)
 #define OMAP3430_EN_GPIO6_SHIFT                                17
 #define OMAP3430_EN_GPIO5_MASK                         (1 << 16)
 #define OMAP3430_EN_MCBSP2_SHIFT                       0
 
 /* CM_IDLEST_PER, PM_WKST_PER shared bits */
+#define OMAP3630_ST_UART4_SHIFT                                18
+#define OMAP3630_ST_UART4_MASK                         (1 << 18)
 #define OMAP3430_ST_GPIO6_SHIFT                                17
 #define OMAP3430_ST_GPIO6_MASK                         (1 << 17)
 #define OMAP3430_ST_GPIO5_SHIFT                                16
index c201374..a51846e 100644 (file)
 #include <plat/common.h>
 #include <plat/prcm.h>
 #include <plat/irqs.h>
-#include <plat/control.h>
 
 #include "clock.h"
 #include "clock2xxx.h"
 #include "cm.h"
 #include "prm.h"
 #include "prm-regbits-24xx.h"
+#include "prm-regbits-44xx.h"
+#include "control.h"
 
 static void __iomem *prm_base;
 static void __iomem *cm_base;
@@ -118,7 +119,7 @@ struct omap3_prcm_regs {
        u32 wkup_pm_wken;
 };
 
-struct omap3_prcm_regs prcm_context;
+static struct omap3_prcm_regs prcm_context;
 
 u32 omap_prcm_get_reset_sources(void)
 {
@@ -161,8 +162,8 @@ void omap_prcm_arch_reset(char mode, const char *cmd)
                prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
                                                 OMAP2_RM_RSTCTRL);
        if (cpu_is_omap44xx())
-               prm_set_mod_reg_bits(OMAP_RST_DPLL3_MASK, prcm_offs,
-                                                OMAP4_RM_RSTCTRL);
+               prm_set_mod_reg_bits(OMAP4430_RST_GLOBAL_WARM_SW_MASK,
+                                    prcm_offs, OMAP4_RM_RSTCTRL);
 }
 
 static inline u32 __omap_prcm_read(void __iomem *base, s16 module, u16 reg)
@@ -215,6 +216,30 @@ u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
        return v;
 }
 
+/* Read a PRM register, AND it, and shift the result down to bit 0 */
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask)
+{
+       u32 v;
+
+       v = __raw_readl(reg);
+       v &= mask;
+       v >>= __ffs(mask);
+
+       return v;
+}
+
+/* Read-modify-write a register in a PRM module. Caller must lock */
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg)
+{
+       u32 v;
+
+       v = __raw_readl(reg);
+       v &= ~mask;
+       v |= bits;
+       __raw_writel(v, reg);
+
+       return v;
+}
 /* Read a register in a CM module */
 u32 cm_read_mod_reg(s16 module, u16 idx)
 {
index 7fd6023..9e63cb7 100644 (file)
 #define OMAP3430_MEMRETSTATE_MASK                      (1 << 8)
 
 /* PM_MPUGRPSEL_PER, PM_IVA2GRPSEL_PER shared bits */
+#define OMAP3630_GRPSEL_UART4_MASK                     (1 << 18)
 #define OMAP3430_GRPSEL_GPIO6_MASK                     (1 << 17)
 #define OMAP3430_GRPSEL_GPIO5_MASK                     (1 << 16)
 #define OMAP3430_GRPSEL_GPIO4_MASK                     (1 << 15)
index 597be4a..25b19b6 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * OMAP44xx Power Management register bits
  *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley (paul@pwsan.com)
  * Rajendra Nayak (rnayak@ti.com)
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ABBOFF_ACT_EXPORT_SHIFT                               1
-#define OMAP4430_ABBOFF_ACT_EXPORT_MASK                                        BITFIELD(1, 1)
+#define OMAP4430_ABBOFF_ACT_EXPORT_MASK                                        (1 << 1)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ABBOFF_SLEEP_EXPORT_SHIFT                             2
-#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK                              BITFIELD(2, 2)
+#define OMAP4430_ABBOFF_SLEEP_EXPORT_MASK                              (1 << 2)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_ABB_IVA_DONE_EN_SHIFT                                 31
-#define OMAP4430_ABB_IVA_DONE_EN_MASK                                  BITFIELD(31, 31)
+#define OMAP4430_ABB_IVA_DONE_EN_MASK                                  (1 << 31)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_ABB_IVA_DONE_ST_SHIFT                                 31
-#define OMAP4430_ABB_IVA_DONE_ST_MASK                                  BITFIELD(31, 31)
+#define OMAP4430_ABB_IVA_DONE_ST_MASK                                  (1 << 31)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_ABB_MPU_DONE_EN_SHIFT                                 7
-#define OMAP4430_ABB_MPU_DONE_EN_MASK                                  BITFIELD(7, 7)
+#define OMAP4430_ABB_MPU_DONE_EN_MASK                                  (1 << 7)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_ABB_MPU_DONE_ST_SHIFT                                 7
-#define OMAP4430_ABB_MPU_DONE_ST_MASK                                  BITFIELD(7, 7)
+#define OMAP4430_ABB_MPU_DONE_ST_MASK                                  (1 << 7)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_ACTIVE_FBB_SEL_SHIFT                                  2
-#define OMAP4430_ACTIVE_FBB_SEL_MASK                                   BITFIELD(2, 2)
+#define OMAP4430_ACTIVE_FBB_SEL_MASK                                   (1 << 2)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_ACTIVE_RBB_SEL_SHIFT                                  1
-#define OMAP4430_ACTIVE_RBB_SEL_MASK                                   BITFIELD(1, 1)
+#define OMAP4430_ACTIVE_RBB_SEL_MASK                                   (1 << 1)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_AESSMEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_AESSMEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_AESSMEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_AESSMEM_RETSTATE_SHIFT                                        8
-#define OMAP4430_AESSMEM_RETSTATE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_AESSMEM_RETSTATE_MASK                                 (1 << 8)
 
 /* Used by PM_ABE_PWRSTST */
 #define OMAP4430_AESSMEM_STATEST_SHIFT                                 4
-#define OMAP4430_AESSMEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_AESSMEM_STATEST_MASK                                  (0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_AIPOFF_SHIFT                                          8
-#define OMAP4430_AIPOFF_MASK                                           BITFIELD(8, 8)
+#define OMAP4430_AIPOFF_MASK                                           (1 << 8)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_CORE_L_SHIFT                            0
-#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK                             BITFIELD(0, 1)
+#define OMAP4430_AUTO_CTRL_VDD_CORE_L_MASK                             (0x3 << 0)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_IVA_L_SHIFT                             4
-#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK                              BITFIELD(4, 5)
+#define OMAP4430_AUTO_CTRL_VDD_IVA_L_MASK                              (0x3 << 4)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_AUTO_CTRL_VDD_MPU_L_SHIFT                             2
-#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK                              BITFIELD(2, 3)
+#define OMAP4430_AUTO_CTRL_VDD_MPU_L_MASK                              (0x3 << 2)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_RA_ERR_SHIFT                                     25
+#define OMAP4430_BYPS_RA_ERR_MASK                                      (1 << 25)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_SA_ERR_SHIFT                                     24
+#define OMAP4430_BYPS_SA_ERR_MASK                                      (1 << 24)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_BYPS_TIMEOUT_ERR_SHIFT                                        26
+#define OMAP4430_BYPS_TIMEOUT_ERR_MASK                                 (1 << 26)
+
+/* Used by PRM_RSTST */
+#define OMAP4430_C2C_RST_SHIFT                                         10
+#define OMAP4430_C2C_RST_MASK                                          (1 << 10)
 
 /* Used by PM_CAM_PWRSTCTRL */
 #define OMAP4430_CAM_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_CAM_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_CAM_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_CAM_PWRSTST */
 #define OMAP4430_CAM_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_CAM_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_CAM_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by PRM_CLKREQCTRL */
 #define OMAP4430_CLKREQ_COND_SHIFT                                     0
-#define OMAP4430_CLKREQ_COND_MASK                                      BITFIELD(0, 2)
+#define OMAP4430_CLKREQ_COND_MASK                                      (0x7 << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_CORE_L_SHIFT                                        0
-#define OMAP4430_CMDRA_VDD_CORE_L_MASK                                 BITFIELD(0, 7)
+#define OMAP4430_CMDRA_VDD_CORE_L_MASK                                 (0xff << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_IVA_L_SHIFT                                 8
-#define OMAP4430_CMDRA_VDD_IVA_L_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_CMDRA_VDD_IVA_L_MASK                                  (0xff << 8)
 
 /* Used by PRM_VC_VAL_SMPS_RA_CMD */
 #define OMAP4430_CMDRA_VDD_MPU_L_SHIFT                                 16
-#define OMAP4430_CMDRA_VDD_MPU_L_MASK                                  BITFIELD(16, 23)
+#define OMAP4430_CMDRA_VDD_MPU_L_MASK                                  (0xff << 16)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_CORE_L_SHIFT                                  4
-#define OMAP4430_CMD_VDD_CORE_L_MASK                                   BITFIELD(4, 4)
+#define OMAP4430_CMD_VDD_CORE_L_MASK                                   (1 << 4)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_IVA_L_SHIFT                                   12
-#define OMAP4430_CMD_VDD_IVA_L_MASK                                    BITFIELD(12, 12)
+#define OMAP4430_CMD_VDD_IVA_L_MASK                                    (1 << 12)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_CMD_VDD_MPU_L_SHIFT                                   17
-#define OMAP4430_CMD_VDD_MPU_L_MASK                                    BITFIELD(17, 17)
+#define OMAP4430_CMD_VDD_MPU_L_MASK                                    (1 << 17)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OCMRAM_ONSTATE_SHIFT                             18
-#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK                              BITFIELD(18, 19)
+#define OMAP4430_CORE_OCMRAM_ONSTATE_MASK                              (0x3 << 18)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OCMRAM_RETSTATE_SHIFT                            9
-#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK                             BITFIELD(9, 9)
+#define OMAP4430_CORE_OCMRAM_RETSTATE_MASK                             (1 << 9)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_CORE_OCMRAM_STATEST_SHIFT                             6
-#define OMAP4430_CORE_OCMRAM_STATEST_MASK                              BITFIELD(6, 7)
+#define OMAP4430_CORE_OCMRAM_STATEST_MASK                              (0x3 << 6)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OTHER_BANK_ONSTATE_SHIFT                         16
-#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK                          BITFIELD(16, 17)
+#define OMAP4430_CORE_OTHER_BANK_ONSTATE_MASK                          (0x3 << 16)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_CORE_OTHER_BANK_RETSTATE_SHIFT                                8
-#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK                         BITFIELD(8, 8)
+#define OMAP4430_CORE_OTHER_BANK_RETSTATE_MASK                         (1 << 8)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_CORE_OTHER_BANK_STATEST_SHIFT                         4
-#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK                          BITFIELD(4, 5)
+#define OMAP4430_CORE_OTHER_BANK_STATEST_MASK                          (0x3 << 4)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_CUSTOM_SHIFT                                          6
+#define OMAP4430_CUSTOM_MASK                                           (0x3 << 6)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_DATA_SHIFT                                            16
-#define OMAP4430_DATA_MASK                                             BITFIELD(16, 23)
+#define OMAP4430_DATA_MASK                                             (0xff << 16)
 
 /* Used by PRM_DEVICE_OFF_CTRL */
 #define OMAP4430_DEVICE_OFF_ENABLE_SHIFT                               0
-#define OMAP4430_DEVICE_OFF_ENABLE_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_DEVICE_OFF_ENABLE_MASK                                        (1 << 0)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_DFILTEREN_SHIFT                                       6
-#define OMAP4430_DFILTEREN_MASK                                                BITFIELD(6, 6)
+#define OMAP4430_DFILTEREN_MASK                                                (1 << 6)
 
-/* Used by PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
+/*
+ * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
+ * PRM_LDO_SRAM_MPU_SETUP, PRM_SRAM_WKUP_SETUP
+ */
+#define OMAP4430_DISABLE_RTA_EXPORT_SHIFT                              0
+#define OMAP4430_DISABLE_RTA_EXPORT_MASK                               (1 << 0)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
 #define OMAP4430_DPLL_ABE_RECAL_EN_SHIFT                               4
-#define OMAP4430_DPLL_ABE_RECAL_EN_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_DPLL_ABE_RECAL_EN_MASK                                        (1 << 4)
 
-/* Used by PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
 #define OMAP4430_DPLL_ABE_RECAL_ST_SHIFT                               4
-#define OMAP4430_DPLL_ABE_RECAL_ST_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_DPLL_ABE_RECAL_ST_MASK                                        (1 << 4)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_CORE_RECAL_EN_SHIFT                              0
-#define OMAP4430_DPLL_CORE_RECAL_EN_MASK                               BITFIELD(0, 0)
+#define OMAP4430_DPLL_CORE_RECAL_EN_MASK                               (1 << 0)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_CORE_RECAL_ST_SHIFT                              0
-#define OMAP4430_DPLL_CORE_RECAL_ST_MASK                               BITFIELD(0, 0)
+#define OMAP4430_DPLL_CORE_RECAL_ST_MASK                               (1 << 0)
 
 /* Used by PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_DDRPHY_RECAL_EN_SHIFT                            6
-#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK                             BITFIELD(6, 6)
+#define OMAP4430_DPLL_DDRPHY_RECAL_EN_MASK                             (1 << 6)
 
 /* Used by PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_DDRPHY_RECAL_ST_SHIFT                            6
-#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK                             BITFIELD(6, 6)
+#define OMAP4430_DPLL_DDRPHY_RECAL_ST_MASK                             (1 << 6)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU, PRM_IRQENABLE_TESLA */
 #define OMAP4430_DPLL_IVA_RECAL_EN_SHIFT                               2
-#define OMAP4430_DPLL_IVA_RECAL_EN_MASK                                        BITFIELD(2, 2)
+#define OMAP4430_DPLL_IVA_RECAL_EN_MASK                                        (1 << 2)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU, PRM_IRQSTATUS_TESLA */
 #define OMAP4430_DPLL_IVA_RECAL_ST_SHIFT                               2
-#define OMAP4430_DPLL_IVA_RECAL_ST_MASK                                        BITFIELD(2, 2)
+#define OMAP4430_DPLL_IVA_RECAL_ST_MASK                                        (1 << 2)
 
 /* Used by PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_MPU_RECAL_EN_SHIFT                               1
-#define OMAP4430_DPLL_MPU_RECAL_EN_MASK                                        BITFIELD(1, 1)
+#define OMAP4430_DPLL_MPU_RECAL_EN_MASK                                        (1 << 1)
 
 /* Used by PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_MPU_RECAL_ST_SHIFT                               1
-#define OMAP4430_DPLL_MPU_RECAL_ST_MASK                                        BITFIELD(1, 1)
+#define OMAP4430_DPLL_MPU_RECAL_ST_MASK                                        (1 << 1)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_PER_RECAL_EN_SHIFT                               3
-#define OMAP4430_DPLL_PER_RECAL_EN_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_DPLL_PER_RECAL_EN_MASK                                        (1 << 3)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_PER_RECAL_ST_SHIFT                               3
-#define OMAP4430_DPLL_PER_RECAL_ST_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_DPLL_PER_RECAL_ST_MASK                                        (1 << 3)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_DPLL_UNIPRO_RECAL_EN_SHIFT                            7
-#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK                             BITFIELD(7, 7)
+#define OMAP4430_DPLL_UNIPRO_RECAL_EN_MASK                             (1 << 7)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_DPLL_UNIPRO_RECAL_ST_SHIFT                            7
-#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK                             BITFIELD(7, 7)
-
-/* Used by PRM_IRQENABLE_MPU */
-#define OMAP4430_DPLL_USB_RECAL_EN_SHIFT                               5
-#define OMAP4430_DPLL_USB_RECAL_EN_MASK                                        BITFIELD(5, 5)
-
-/* Used by PRM_IRQSTATUS_MPU */
-#define OMAP4430_DPLL_USB_RECAL_ST_SHIFT                               5
-#define OMAP4430_DPLL_USB_RECAL_ST_MASK                                        BITFIELD(5, 5)
+#define OMAP4430_DPLL_UNIPRO_RECAL_ST_MASK                             (1 << 7)
 
 /* Used by PM_DSS_PWRSTCTRL */
 #define OMAP4430_DSS_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_DSS_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_DSS_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_DSS_PWRSTCTRL */
 #define OMAP4430_DSS_MEM_RETSTATE_SHIFT                                        8
-#define OMAP4430_DSS_MEM_RETSTATE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_DSS_MEM_RETSTATE_MASK                                 (1 << 8)
 
 /* Used by PM_DSS_PWRSTST */
 #define OMAP4430_DSS_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_DSS_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_DSS_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_L2RAM_ONSTATE_SHIFT                            20
-#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK                             BITFIELD(20, 21)
+#define OMAP4430_DUCATI_L2RAM_ONSTATE_MASK                             (0x3 << 20)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_L2RAM_RETSTATE_SHIFT                           10
-#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK                            BITFIELD(10, 10)
+#define OMAP4430_DUCATI_L2RAM_RETSTATE_MASK                            (1 << 10)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_DUCATI_L2RAM_STATEST_SHIFT                            8
-#define OMAP4430_DUCATI_L2RAM_STATEST_MASK                             BITFIELD(8, 9)
+#define OMAP4430_DUCATI_L2RAM_STATEST_MASK                             (0x3 << 8)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_UNICACHE_ONSTATE_SHIFT                         22
-#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK                          BITFIELD(22, 23)
+#define OMAP4430_DUCATI_UNICACHE_ONSTATE_MASK                          (0x3 << 22)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_DUCATI_UNICACHE_RETSTATE_SHIFT                                11
-#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK                         BITFIELD(11, 11)
+#define OMAP4430_DUCATI_UNICACHE_RETSTATE_MASK                         (1 << 11)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_DUCATI_UNICACHE_STATEST_SHIFT                         10
-#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK                          BITFIELD(10, 11)
+#define OMAP4430_DUCATI_UNICACHE_STATEST_MASK                          (0x3 << 10)
 
 /* Used by RM_MPU_RSTST */
 #define OMAP4430_EMULATION_RST_SHIFT                                   0
-#define OMAP4430_EMULATION_RST_MASK                                    BITFIELD(0, 0)
+#define OMAP4430_EMULATION_RST_MASK                                    (1 << 0)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_EMULATION_RST1ST_SHIFT                                        3
-#define OMAP4430_EMULATION_RST1ST_MASK                                 BITFIELD(3, 3)
+#define OMAP4430_EMULATION_RST1ST_MASK                                 (1 << 3)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_EMULATION_RST2ST_SHIFT                                        4
-#define OMAP4430_EMULATION_RST2ST_MASK                                 BITFIELD(4, 4)
+#define OMAP4430_EMULATION_RST2ST_MASK                                 (1 << 4)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_EMULATION_SEQ1_RST1ST_SHIFT                           3
-#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK                            BITFIELD(3, 3)
+#define OMAP4430_EMULATION_SEQ1_RST1ST_MASK                            (1 << 3)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_EMULATION_SEQ2_RST2ST_SHIFT                           4
-#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK                            BITFIELD(4, 4)
+#define OMAP4430_EMULATION_SEQ2_RST2ST_MASK                            (1 << 4)
 
 /* Used by PM_EMU_PWRSTCTRL */
 #define OMAP4430_EMU_BANK_ONSTATE_SHIFT                                        16
-#define OMAP4430_EMU_BANK_ONSTATE_MASK                                 BITFIELD(16, 17)
+#define OMAP4430_EMU_BANK_ONSTATE_MASK                                 (0x3 << 16)
 
 /* Used by PM_EMU_PWRSTST */
 #define OMAP4430_EMU_BANK_STATEST_SHIFT                                        4
-#define OMAP4430_EMU_BANK_STATEST_MASK                                 BITFIELD(4, 5)
-
-/*
- * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
- * PRM_LDO_SRAM_MPU_SETUP, PRM_SRAM_WKUP_SETUP
- */
-#define OMAP4430_ENABLE_RTA_EXPORT_SHIFT                               0
-#define OMAP4430_ENABLE_RTA_EXPORT_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_EMU_BANK_STATEST_MASK                                 (0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
-#define OMAP4430_ENFUNC1_SHIFT                                         3
-#define OMAP4430_ENFUNC1_MASK                                          BITFIELD(3, 3)
+#define OMAP4430_ENFUNC1_EXPORT_SHIFT                                  3
+#define OMAP4430_ENFUNC1_EXPORT_MASK                                   (1 << 3)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
-#define OMAP4430_ENFUNC3_SHIFT                                         5
-#define OMAP4430_ENFUNC3_MASK                                          BITFIELD(5, 5)
+#define OMAP4430_ENFUNC3_EXPORT_SHIFT                                  5
+#define OMAP4430_ENFUNC3_EXPORT_MASK                                   (1 << 5)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ENFUNC4_SHIFT                                         6
-#define OMAP4430_ENFUNC4_MASK                                          BITFIELD(6, 6)
+#define OMAP4430_ENFUNC4_MASK                                          (1 << 6)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_IVA_SETUP,
  * PRM_LDO_SRAM_MPU_SETUP
  */
 #define OMAP4430_ENFUNC5_SHIFT                                         7
-#define OMAP4430_ENFUNC5_MASK                                          BITFIELD(7, 7)
+#define OMAP4430_ENFUNC5_MASK                                          (1 << 7)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_ERRORGAIN_SHIFT                                       16
-#define OMAP4430_ERRORGAIN_MASK                                                BITFIELD(16, 23)
+#define OMAP4430_ERRORGAIN_MASK                                                (0xff << 16)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_ERROROFFSET_SHIFT                                     24
-#define OMAP4430_ERROROFFSET_MASK                                      BITFIELD(24, 31)
+#define OMAP4430_ERROROFFSET_MASK                                      (0xff << 24)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_EXTERNAL_WARM_RST_SHIFT                               5
-#define OMAP4430_EXTERNAL_WARM_RST_MASK                                        BITFIELD(5, 5)
+#define OMAP4430_EXTERNAL_WARM_RST_MASK                                        (1 << 5)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_FORCEUPDATE_SHIFT                                     1
-#define OMAP4430_FORCEUPDATE_MASK                                      BITFIELD(1, 1)
+#define OMAP4430_FORCEUPDATE_MASK                                      (1 << 1)
 
 /* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */
 #define OMAP4430_FORCEUPDATEWAIT_SHIFT                                 8
-#define OMAP4430_FORCEUPDATEWAIT_MASK                                  BITFIELD(8, 31)
+#define OMAP4430_FORCEUPDATEWAIT_MASK                                  (0xffffff << 8)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_TESLA */
 #define OMAP4430_FORCEWKUP_EN_SHIFT                                    10
-#define OMAP4430_FORCEWKUP_EN_MASK                                     BITFIELD(10, 10)
+#define OMAP4430_FORCEWKUP_EN_MASK                                     (1 << 10)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_TESLA */
 #define OMAP4430_FORCEWKUP_ST_SHIFT                                    10
-#define OMAP4430_FORCEWKUP_ST_MASK                                     BITFIELD(10, 10)
+#define OMAP4430_FORCEWKUP_ST_MASK                                     (1 << 10)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_FUNC_SHIFT                                            16
+#define OMAP4430_FUNC_MASK                                             (0xfff << 16)
 
 /* Used by PM_GFX_PWRSTCTRL */
 #define OMAP4430_GFX_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_GFX_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_GFX_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_GFX_PWRSTST */
 #define OMAP4430_GFX_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_GFX_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_GFX_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_GLOBAL_COLD_RST_SHIFT                                 0
-#define OMAP4430_GLOBAL_COLD_RST_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_GLOBAL_COLD_RST_MASK                                  (1 << 0)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_GLOBAL_WARM_SW_RST_SHIFT                              1
-#define OMAP4430_GLOBAL_WARM_SW_RST_MASK                               BITFIELD(1, 1)
+#define OMAP4430_GLOBAL_WARM_SW_RST_MASK                               (1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_GLOBAL_WUEN_SHIFT                                     16
-#define OMAP4430_GLOBAL_WUEN_MASK                                      BITFIELD(16, 16)
+#define OMAP4430_GLOBAL_WUEN_MASK                                      (1 << 16)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_HSMCODE_SHIFT                                         0
-#define OMAP4430_HSMCODE_MASK                                          BITFIELD(0, 2)
+#define OMAP4430_HSMCODE_MASK                                          (0x7 << 0)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_HSMODEEN_SHIFT                                                3
-#define OMAP4430_HSMODEEN_MASK                                         BITFIELD(3, 3)
+#define OMAP4430_HSMODEEN_MASK                                         (1 << 3)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_HSSCLH_SHIFT                                          16
-#define OMAP4430_HSSCLH_MASK                                           BITFIELD(16, 23)
+#define OMAP4430_HSSCLH_MASK                                           (0xff << 16)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_HSSCLL_SHIFT                                          24
-#define OMAP4430_HSSCLL_MASK                                           BITFIELD(24, 31)
+#define OMAP4430_HSSCLL_MASK                                           (0xff << 24)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_HWA_MEM_ONSTATE_SHIFT                                 16
-#define OMAP4430_HWA_MEM_ONSTATE_MASK                                  BITFIELD(16, 17)
+#define OMAP4430_HWA_MEM_ONSTATE_MASK                                  (0x3 << 16)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_HWA_MEM_RETSTATE_SHIFT                                        8
-#define OMAP4430_HWA_MEM_RETSTATE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_HWA_MEM_RETSTATE_MASK                                 (1 << 8)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_HWA_MEM_STATEST_SHIFT                                 4
-#define OMAP4430_HWA_MEM_STATEST_MASK                                  BITFIELD(4, 5)
+#define OMAP4430_HWA_MEM_STATEST_MASK                                  (0x3 << 4)
 
 /* Used by RM_MPU_RSTST */
 #define OMAP4430_ICECRUSHER_MPU_RST_SHIFT                              1
-#define OMAP4430_ICECRUSHER_MPU_RST_MASK                               BITFIELD(1, 1)
+#define OMAP4430_ICECRUSHER_MPU_RST_MASK                               (1 << 1)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_ICECRUSHER_RST1ST_SHIFT                               5
-#define OMAP4430_ICECRUSHER_RST1ST_MASK                                        BITFIELD(5, 5)
+#define OMAP4430_ICECRUSHER_RST1ST_MASK                                        (1 << 5)
 
 /* Used by RM_DUCATI_RSTST */
 #define OMAP4430_ICECRUSHER_RST2ST_SHIFT                               6
-#define OMAP4430_ICECRUSHER_RST2ST_MASK                                        BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_RST2ST_MASK                                        (1 << 6)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_ICECRUSHER_SEQ1_RST1ST_SHIFT                          5
-#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK                           BITFIELD(5, 5)
+#define OMAP4430_ICECRUSHER_SEQ1_RST1ST_MASK                           (1 << 5)
 
 /* Used by RM_IVAHD_RSTST */
 #define OMAP4430_ICECRUSHER_SEQ2_RST2ST_SHIFT                          6
-#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK                           BITFIELD(6, 6)
+#define OMAP4430_ICECRUSHER_SEQ2_RST2ST_MASK                           (1 << 6)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_ICEPICK_RST_SHIFT                                     9
-#define OMAP4430_ICEPICK_RST_MASK                                      BITFIELD(9, 9)
+#define OMAP4430_ICEPICK_RST_MASK                                      (1 << 9)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_INITVDD_SHIFT                                         2
-#define OMAP4430_INITVDD_MASK                                          BITFIELD(2, 2)
+#define OMAP4430_INITVDD_MASK                                          (1 << 2)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_INITVOLTAGE_SHIFT                                     8
-#define OMAP4430_INITVOLTAGE_MASK                                      BITFIELD(8, 15)
+#define OMAP4430_INITVOLTAGE_MASK                                      (0xff << 8)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_INTRANSITION_SHIFT                                    20
-#define OMAP4430_INTRANSITION_MASK                                     BITFIELD(20, 20)
+#define OMAP4430_INTRANSITION_MASK                                     (1 << 20)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_IO_EN_SHIFT                                           9
-#define OMAP4430_IO_EN_MASK                                            BITFIELD(9, 9)
+#define OMAP4430_IO_EN_MASK                                            (1 << 9)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_IO_ON_STATUS_SHIFT                                    5
-#define OMAP4430_IO_ON_STATUS_MASK                                     BITFIELD(5, 5)
+#define OMAP4430_IO_ON_STATUS_MASK                                     (1 << 5)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_IO_ST_SHIFT                                           9
-#define OMAP4430_IO_ST_MASK                                            BITFIELD(9, 9)
+#define OMAP4430_IO_ST_MASK                                            (1 << 9)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOCLK_OVERRIDE_SHIFT                                 0
-#define OMAP4430_ISOCLK_OVERRIDE_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_ISOCLK_OVERRIDE_MASK                                  (1 << 0)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOCLK_STATUS_SHIFT                                   1
-#define OMAP4430_ISOCLK_STATUS_MASK                                    BITFIELD(1, 1)
+#define OMAP4430_ISOCLK_STATUS_MASK                                    (1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_ISOOVR_EXTEND_SHIFT                                   4
-#define OMAP4430_ISOOVR_EXTEND_MASK                                    BITFIELD(4, 4)
+#define OMAP4430_ISOOVR_EXTEND_MASK                                    (1 << 4)
 
 /* Used by PRM_IO_COUNT */
 #define OMAP4430_ISO_2_ON_TIME_SHIFT                                   0
-#define OMAP4430_ISO_2_ON_TIME_MASK                                    BITFIELD(0, 7)
+#define OMAP4430_ISO_2_ON_TIME_MASK                                    (0xff << 0)
 
 /* Used by PM_L3INIT_PWRSTCTRL */
 #define OMAP4430_L3INIT_BANK1_ONSTATE_SHIFT                            16
-#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK                             BITFIELD(16, 17)
+#define OMAP4430_L3INIT_BANK1_ONSTATE_MASK                             (0x3 << 16)
 
 /* Used by PM_L3INIT_PWRSTCTRL */
 #define OMAP4430_L3INIT_BANK1_RETSTATE_SHIFT                           8
-#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK                            BITFIELD(8, 8)
+#define OMAP4430_L3INIT_BANK1_RETSTATE_MASK                            (1 << 8)
 
 /* Used by PM_L3INIT_PWRSTST */
 #define OMAP4430_L3INIT_BANK1_STATEST_SHIFT                            4
-#define OMAP4430_L3INIT_BANK1_STATEST_MASK                             BITFIELD(4, 5)
+#define OMAP4430_L3INIT_BANK1_STATEST_MASK                             (0x3 << 4)
+
+/*
+ * Used by PM_ABE_PWRSTST, PM_CORE_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
+ */
+#define OMAP4430_LASTPOWERSTATEENTERED_SHIFT                           24
+#define OMAP4430_LASTPOWERSTATEENTERED_MASK                            (0x3 << 24)
 
 /*
- * Used by PM_CORE_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL,
- * PM_MPU_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL,
- * PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL,
+ * PM_IVAHD_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_LOGICRETSTATE_SHIFT                                   2
-#define OMAP4430_LOGICRETSTATE_MASK                                    BITFIELD(2, 2)
+#define OMAP4430_LOGICRETSTATE_MASK                                    (1 << 2)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_LOGICSTATEST_SHIFT                                    2
-#define OMAP4430_LOGICSTATEST_MASK                                     BITFIELD(2, 2)
+#define OMAP4430_LOGICSTATEST_MASK                                     (1 << 2)
 
 /*
- * Used by RM_WKUP_GPIO1_CONTEXT, RM_WKUP_KEYBOARD_CONTEXT,
- * RM_WKUP_L4WKUP_CONTEXT, RM_WKUP_RTC_CONTEXT, RM_WKUP_SARRAM_CONTEXT,
- * RM_WKUP_SYNCTIMER_CONTEXT, RM_WKUP_TIMER12_CONTEXT, RM_WKUP_TIMER1_CONTEXT,
- * RM_WKUP_USIM_CONTEXT, RM_WKUP_WDT1_CONTEXT, RM_WKUP_WDT2_CONTEXT,
- * RM_EMU_DEBUGSS_CONTEXT, RM_D2D_SAD2D_CONTEXT, RM_D2D_SAD2D_FW_CONTEXT,
- * RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
- * RM_L3INSTR_L3_INSTR_CONTEXT, RM_L3INSTR_OCP_WP1_CONTEXT,
- * RM_L3_1_L3_1_CONTEXT, RM_L3_2_L3_2_CONTEXT, RM_L3_2_OCMC_RAM_CONTEXT,
- * RM_L4CFG_L4_CFG_CONTEXT, RM_L4CFG_SAR_ROM_CONTEXT, RM_MEMIF_DLL_CONTEXT,
- * RM_MEMIF_DLL_H_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT,
- * RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT, RM_L3INIT_CCPTX_CONTEXT,
- * RM_L3INIT_EMAC_CONTEXT, RM_L3INIT_P1500_CONTEXT, RM_L3INIT_PCIESS_CONTEXT,
- * RM_L3INIT_SATA_CONTEXT, RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT,
- * RM_L3INIT_USBPHYOCP2SCP_CONTEXT, RM_L3INIT_XHPI_CONTEXT,
- * RM_ABE_AESS_CONTEXT, RM_ABE_DMIC_CONTEXT, RM_ABE_MCASP_CONTEXT,
+ * Used by RM_ABE_AESS_CONTEXT, RM_ABE_DMIC_CONTEXT, RM_ABE_MCASP_CONTEXT,
  * RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT, RM_ABE_MCBSP3_CONTEXT,
  * RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT, RM_ABE_TIMER5_CONTEXT,
  * RM_ABE_TIMER6_CONTEXT, RM_ABE_TIMER7_CONTEXT, RM_ABE_TIMER8_CONTEXT,
- * RM_ABE_WDT3_CONTEXT, RM_GFX_GFX_CONTEXT, RM_MPU_MPU_CONTEXT,
- * RM_CEFUSE_CEFUSE_CONTEXT, RM_ALWON_MDMINTC_CONTEXT,
- * RM_ALWON_SR_CORE_CONTEXT, RM_ALWON_SR_IVA_CONTEXT, RM_ALWON_SR_MPU_CONTEXT,
- * RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT, RM_L4PER_ADC_CONTEXT,
- * RM_L4PER_DMTIMER10_CONTEXT, RM_L4PER_DMTIMER11_CONTEXT,
- * RM_L4PER_DMTIMER2_CONTEXT, RM_L4PER_DMTIMER3_CONTEXT,
- * RM_L4PER_DMTIMER4_CONTEXT, RM_L4PER_DMTIMER9_CONTEXT, RM_L4PER_ELM_CONTEXT,
- * RM_L4PER_HDQ1W_CONTEXT, RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT,
- * RM_L4PER_I2C2_CONTEXT, RM_L4PER_I2C3_CONTEXT, RM_L4PER_I2C4_CONTEXT,
- * RM_L4PER_I2C5_CONTEXT, RM_L4PER_L4_PER_CONTEXT, RM_L4PER_MCASP2_CONTEXT,
- * RM_L4PER_MCASP3_CONTEXT, RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MCSPI1_CONTEXT,
- * RM_L4PER_MCSPI2_CONTEXT, RM_L4PER_MCSPI3_CONTEXT, RM_L4PER_MCSPI4_CONTEXT,
- * RM_L4PER_MGATE_CONTEXT, RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT,
- * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_MSPROHG_CONTEXT,
- * RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT,
- * RM_TESLA_TESLA_CONTEXT, RM_IVAHD_IVAHD_CONTEXT, RM_IVAHD_SL2_CONTEXT
+ * RM_ABE_WDT3_CONTEXT, RM_ALWON_MDMINTC_CONTEXT, RM_ALWON_SR_CORE_CONTEXT,
+ * RM_ALWON_SR_IVA_CONTEXT, RM_ALWON_SR_MPU_CONTEXT, RM_CAM_FDIF_CONTEXT,
+ * RM_CAM_ISS_CONTEXT, RM_CEFUSE_CEFUSE_CONTEXT, RM_D2D_SAD2D_CONTEXT,
+ * RM_D2D_SAD2D_FW_CONTEXT, RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT,
+ * RM_DUCATI_DUCATI_CONTEXT, RM_EMU_DEBUGSS_CONTEXT, RM_GFX_GFX_CONTEXT,
+ * RM_IVAHD_IVAHD_CONTEXT, RM_IVAHD_SL2_CONTEXT, RM_L3INIT_CCPTX_CONTEXT,
+ * RM_L3INIT_EMAC_CONTEXT, RM_L3INIT_P1500_CONTEXT, RM_L3INIT_PCIESS_CONTEXT,
+ * RM_L3INIT_SATA_CONTEXT, RM_L3INIT_TPPSS_CONTEXT, RM_L3INIT_UNIPRO1_CONTEXT,
+ * RM_L3INIT_USBPHYOCP2SCP_CONTEXT, RM_L3INIT_XHPI_CONTEXT,
+ * RM_L3INSTR_L3_3_CONTEXT, RM_L3INSTR_L3_INSTR_CONTEXT,
+ * RM_L3INSTR_OCP_WP1_CONTEXT, RM_L3_1_L3_1_CONTEXT, RM_L3_2_L3_2_CONTEXT,
+ * RM_L3_2_OCMC_RAM_CONTEXT, RM_L4CFG_L4_CFG_CONTEXT, RM_L4CFG_SAR_ROM_CONTEXT,
+ * RM_L4PER_ADC_CONTEXT, RM_L4PER_DMTIMER10_CONTEXT,
+ * RM_L4PER_DMTIMER11_CONTEXT, RM_L4PER_DMTIMER2_CONTEXT,
+ * RM_L4PER_DMTIMER3_CONTEXT, RM_L4PER_DMTIMER4_CONTEXT,
+ * RM_L4PER_DMTIMER9_CONTEXT, RM_L4PER_ELM_CONTEXT, RM_L4PER_HDQ1W_CONTEXT,
+ * RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT, RM_L4PER_I2C2_CONTEXT,
+ * RM_L4PER_I2C3_CONTEXT, RM_L4PER_I2C4_CONTEXT, RM_L4PER_I2C5_CONTEXT,
+ * RM_L4PER_L4_PER_CONTEXT, RM_L4PER_MCASP2_CONTEXT, RM_L4PER_MCASP3_CONTEXT,
+ * RM_L4PER_MCBSP4_CONTEXT, RM_L4PER_MCSPI1_CONTEXT, RM_L4PER_MCSPI2_CONTEXT,
+ * RM_L4PER_MCSPI3_CONTEXT, RM_L4PER_MCSPI4_CONTEXT, RM_L4PER_MGATE_CONTEXT,
+ * RM_L4PER_MMCSD3_CONTEXT, RM_L4PER_MMCSD4_CONTEXT, RM_L4PER_MMCSD5_CONTEXT,
+ * RM_L4PER_MSPROHG_CONTEXT, RM_L4PER_SLIMBUS2_CONTEXT,
+ * RM_L4SEC_PKAEIP29_CONTEXT, RM_MEMIF_DLL_CONTEXT, RM_MEMIF_DLL_H_CONTEXT,
+ * RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT, RM_MEMIF_EMIF_2_CONTEXT,
+ * RM_MEMIF_EMIF_FW_CONTEXT, RM_MPU_MPU_CONTEXT, RM_TESLA_TESLA_CONTEXT,
+ * RM_WKUP_GPIO1_CONTEXT, RM_WKUP_KEYBOARD_CONTEXT, RM_WKUP_L4WKUP_CONTEXT,
+ * RM_WKUP_RTC_CONTEXT, RM_WKUP_SARRAM_CONTEXT, RM_WKUP_SYNCTIMER_CONTEXT,
+ * RM_WKUP_TIMER12_CONTEXT, RM_WKUP_TIMER1_CONTEXT, RM_WKUP_USIM_CONTEXT,
+ * RM_WKUP_WDT1_CONTEXT, RM_WKUP_WDT2_CONTEXT
  */
 #define OMAP4430_LOSTCONTEXT_DFF_SHIFT                                 0
-#define OMAP4430_LOSTCONTEXT_DFF_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_LOSTCONTEXT_DFF_MASK                                  (1 << 0)
 
 /*
  * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_D2D_SAD2D_CONTEXT,
- * RM_D2D_SAD2D_FW_CONTEXT, RM_DUCATI_DUCATI_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
+ * RM_D2D_SAD2D_FW_CONTEXT, RM_DSS_DSS_CONTEXT, RM_DUCATI_DUCATI_CONTEXT,
+ * RM_L3INIT_HSI_CONTEXT, RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT,
+ * RM_L3INIT_MMC6_CONTEXT, RM_L3INIT_USB_HOST_CONTEXT,
+ * RM_L3INIT_USB_HOST_FS_CONTEXT, RM_L3INIT_USB_OTG_CONTEXT,
+ * RM_L3INIT_USB_TLL_CONTEXT, RM_L3INSTR_L3_3_CONTEXT,
  * RM_L3INSTR_OCP_WP1_CONTEXT, RM_L3_1_L3_1_CONTEXT, RM_L3_2_GPMC_CONTEXT,
  * RM_L3_2_L3_2_CONTEXT, RM_L4CFG_HW_SEM_CONTEXT, RM_L4CFG_L4_CFG_CONTEXT,
- * RM_L4CFG_MAILBOX_CONTEXT, RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT,
- * RM_MEMIF_EMIF_2_CONTEXT, RM_MEMIF_EMIF_FW_CONTEXT, RM_MEMIF_EMIF_H1_CONTEXT,
- * RM_MEMIF_EMIF_H2_CONTEXT, RM_SDMA_SDMA_CONTEXT, RM_L3INIT_HSI_CONTEXT,
- * RM_L3INIT_MMC1_CONTEXT, RM_L3INIT_MMC2_CONTEXT, RM_L3INIT_MMC6_CONTEXT,
- * RM_L3INIT_USB_HOST_CONTEXT, RM_L3INIT_USB_HOST_FS_CONTEXT,
- * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_USB_TLL_CONTEXT, RM_DSS_DSS_CONTEXT,
- * RM_L4PER_GPIO2_CONTEXT, RM_L4PER_GPIO3_CONTEXT, RM_L4PER_GPIO4_CONTEXT,
- * RM_L4PER_GPIO5_CONTEXT, RM_L4PER_GPIO6_CONTEXT, RM_L4PER_I2C1_CONTEXT,
- * RM_L4PER_L4_PER_CONTEXT, RM_L4PER_UART1_CONTEXT, RM_L4PER_UART2_CONTEXT,
- * RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT, RM_L4SEC_AES1_CONTEXT,
- * RM_L4SEC_AES2_CONTEXT, RM_L4SEC_CRYPTODMA_CONTEXT, RM_L4SEC_DES3DES_CONTEXT,
- * RM_L4SEC_RNG_CONTEXT, RM_L4SEC_SHA2MD51_CONTEXT, RM_TESLA_TESLA_CONTEXT
+ * RM_L4CFG_MAILBOX_CONTEXT, RM_L4PER_GPIO2_CONTEXT, RM_L4PER_GPIO3_CONTEXT,
+ * RM_L4PER_GPIO4_CONTEXT, RM_L4PER_GPIO5_CONTEXT, RM_L4PER_GPIO6_CONTEXT,
+ * RM_L4PER_I2C1_CONTEXT, RM_L4PER_L4_PER_CONTEXT, RM_L4PER_UART1_CONTEXT,
+ * RM_L4PER_UART2_CONTEXT, RM_L4PER_UART3_CONTEXT, RM_L4PER_UART4_CONTEXT,
+ * RM_L4SEC_AES1_CONTEXT, RM_L4SEC_AES2_CONTEXT, RM_L4SEC_CRYPTODMA_CONTEXT,
+ * RM_L4SEC_DES3DES_CONTEXT, RM_L4SEC_RNG_CONTEXT, RM_L4SEC_SHA2MD51_CONTEXT,
+ * RM_MEMIF_DMM_CONTEXT, RM_MEMIF_EMIF_1_CONTEXT, RM_MEMIF_EMIF_2_CONTEXT,
+ * RM_MEMIF_EMIF_FW_CONTEXT, RM_MEMIF_EMIF_H1_CONTEXT,
+ * RM_MEMIF_EMIF_H2_CONTEXT, RM_SDMA_SDMA_CONTEXT, RM_TESLA_TESLA_CONTEXT
  */
 #define OMAP4430_LOSTCONTEXT_RFF_SHIFT                                 1
-#define OMAP4430_LOSTCONTEXT_RFF_MASK                                  BITFIELD(1, 1)
+#define OMAP4430_LOSTCONTEXT_RFF_MASK                                  (1 << 1)
 
 /* Used by RM_ABE_AESS_CONTEXT */
 #define OMAP4430_LOSTMEM_AESSMEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_AESSMEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_AESSMEM_MASK                                  (1 << 8)
 
 /* Used by RM_CAM_FDIF_CONTEXT, RM_CAM_ISS_CONTEXT */
 #define OMAP4430_LOSTMEM_CAM_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_CAM_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CAM_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_L3INSTR_OCP_WP1_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_NRET_BANK_SHIFT                          8
-#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK                           BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK_MASK                           (1 << 8)
 
 /* Renamed from LOSTMEM_CORE_NRET_BANK Used by RM_MEMIF_DMM_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_SHIFT                      9
-#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_MASK                       BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_CORE_NRET_BANK_9_9_MASK                       (1 << 9)
 
 /* Used by RM_L3_2_OCMC_RAM_CONTEXT */
 #define OMAP4430_LOSTMEM_CORE_OCMRAM_SHIFT                             8
-#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK                              BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_OCMRAM_MASK                              (1 << 8)
 
 /*
  * Used by RM_D2D_MODEM_ICR_CONTEXT, RM_MEMIF_DMM_CONTEXT,
  * RM_SDMA_SDMA_CONTEXT
  */
 #define OMAP4430_LOSTMEM_CORE_OTHER_BANK_SHIFT                         8
-#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK                          BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_CORE_OTHER_BANK_MASK                          (1 << 8)
 
 /* Used by RM_DSS_DEISS_CONTEXT, RM_DSS_DSS_CONTEXT */
 #define OMAP4430_LOSTMEM_DSS_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_DSS_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_DSS_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_DUCATI_DUCATI_CONTEXT */
 #define OMAP4430_LOSTMEM_DUCATI_L2RAM_SHIFT                            9
-#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK                             BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_DUCATI_L2RAM_MASK                             (1 << 9)
 
 /* Used by RM_DUCATI_DUCATI_CONTEXT */
 #define OMAP4430_LOSTMEM_DUCATI_UNICACHE_SHIFT                         8
-#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK                          BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_DUCATI_UNICACHE_MASK                          (1 << 8)
 
 /* Used by RM_EMU_DEBUGSS_CONTEXT */
 #define OMAP4430_LOSTMEM_EMU_BANK_SHIFT                                        8
-#define OMAP4430_LOSTMEM_EMU_BANK_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_EMU_BANK_MASK                                 (1 << 8)
 
 /* Used by RM_GFX_GFX_CONTEXT */
 #define OMAP4430_LOSTMEM_GFX_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_GFX_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_GFX_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_HWA_MEM_SHIFT                                 10
-#define OMAP4430_LOSTMEM_HWA_MEM_MASK                                  BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_HWA_MEM_MASK                                  (1 << 10)
 
 /*
  * Used by RM_L3INIT_CCPTX_CONTEXT, RM_L3INIT_EMAC_CONTEXT,
  * RM_L3INIT_USB_OTG_CONTEXT, RM_L3INIT_XHPI_CONTEXT
  */
 #define OMAP4430_LOSTMEM_L3INIT_BANK1_SHIFT                            8
-#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK                             BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_L3INIT_BANK1_MASK                             (1 << 8)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_L1_SHIFT                                  8
-#define OMAP4430_LOSTMEM_MPU_L1_MASK                                   BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_MPU_L1_MASK                                   (1 << 8)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_L2_SHIFT                                  9
-#define OMAP4430_LOSTMEM_MPU_L2_MASK                                   BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_MPU_L2_MASK                                   (1 << 9)
 
 /* Used by RM_MPU_MPU_CONTEXT */
 #define OMAP4430_LOSTMEM_MPU_RAM_SHIFT                                 10
-#define OMAP4430_LOSTMEM_MPU_RAM_MASK                                  BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_MPU_RAM_MASK                                  (1 << 10)
 
 /*
  * Used by RM_L4PER_HECC1_CONTEXT, RM_L4PER_HECC2_CONTEXT,
  * RM_L4PER_MMCSD5_CONTEXT, RM_L4PER_SLIMBUS2_CONTEXT, RM_L4SEC_PKAEIP29_CONTEXT
  */
 #define OMAP4430_LOSTMEM_NONRETAINED_BANK_SHIFT                                8
-#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK                         BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_NONRETAINED_BANK_MASK                         (1 << 8)
 
 /*
  * Used by RM_ABE_DMIC_CONTEXT, RM_ABE_MCBSP1_CONTEXT, RM_ABE_MCBSP2_CONTEXT,
  * RM_ABE_MCBSP3_CONTEXT, RM_ABE_PDM_CONTEXT, RM_ABE_SLIMBUS_CONTEXT
  */
 #define OMAP4430_LOSTMEM_PERIHPMEM_SHIFT                               8
-#define OMAP4430_LOSTMEM_PERIHPMEM_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_PERIHPMEM_MASK                                        (1 << 8)
 
 /*
  * Used by RM_L4PER_MSPROHG_CONTEXT, RM_L4PER_UART1_CONTEXT,
  * RM_L4SEC_CRYPTODMA_CONTEXT
  */
 #define OMAP4430_LOSTMEM_RETAINED_BANK_SHIFT                           8
-#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK                            BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_RETAINED_BANK_MASK                            (1 << 8)
 
 /* Used by RM_IVAHD_SL2_CONTEXT */
 #define OMAP4430_LOSTMEM_SL2_MEM_SHIFT                                 8
-#define OMAP4430_LOSTMEM_SL2_MEM_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_SL2_MEM_MASK                                  (1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_TCM1_MEM_SHIFT                                        8
-#define OMAP4430_LOSTMEM_TCM1_MEM_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_TCM1_MEM_MASK                                 (1 << 8)
 
 /* Used by RM_IVAHD_IVAHD_CONTEXT */
 #define OMAP4430_LOSTMEM_TCM2_MEM_SHIFT                                        9
-#define OMAP4430_LOSTMEM_TCM2_MEM_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TCM2_MEM_MASK                                 (1 << 9)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_EDMA_SHIFT                              10
-#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK                               BITFIELD(10, 10)
+#define OMAP4430_LOSTMEM_TESLA_EDMA_MASK                               (1 << 10)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_L1_SHIFT                                        8
-#define OMAP4430_LOSTMEM_TESLA_L1_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_TESLA_L1_MASK                                 (1 << 8)
 
 /* Used by RM_TESLA_TESLA_CONTEXT */
 #define OMAP4430_LOSTMEM_TESLA_L2_SHIFT                                        9
-#define OMAP4430_LOSTMEM_TESLA_L2_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_LOSTMEM_TESLA_L2_MASK                                 (1 << 9)
 
 /* Used by RM_WKUP_SARRAM_CONTEXT */
 #define OMAP4430_LOSTMEM_WKUP_BANK_SHIFT                               8
-#define OMAP4430_LOSTMEM_WKUP_BANK_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_LOSTMEM_WKUP_BANK_MASK                                        (1 << 8)
 
 /*
- * Used by PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_L3INIT_PWRSTCTRL,
- * PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
- * PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
+ * PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_IVAHD_PWRSTCTRL,
+ * PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_LOWPOWERSTATECHANGE_SHIFT                             4
-#define OMAP4430_LOWPOWERSTATECHANGE_MASK                              BITFIELD(4, 4)
-
-/* Used by PM_CORE_PWRSTCTRL */
-#define OMAP4430_MEMORYCHANGE_SHIFT                                    3
-#define OMAP4430_MEMORYCHANGE_MASK                                     BITFIELD(3, 3)
+#define OMAP4430_LOWPOWERSTATECHANGE_MASK                              (1 << 4)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_READY_SHIFT                                     1
-#define OMAP4430_MODEM_READY_MASK                                      BITFIELD(1, 1)
+#define OMAP4430_MODEM_READY_MASK                                      (1 << 1)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_SHUTDOWN_IRQ_SHIFT                              9
-#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK                               BITFIELD(9, 9)
+#define OMAP4430_MODEM_SHUTDOWN_IRQ_MASK                               (1 << 9)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_SLEEP_ST_SHIFT                                  16
-#define OMAP4430_MODEM_SLEEP_ST_MASK                                   BITFIELD(16, 16)
+#define OMAP4430_MODEM_SLEEP_ST_MASK                                   (1 << 16)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_MODEM_WAKE_IRQ_SHIFT                                  8
-#define OMAP4430_MODEM_WAKE_IRQ_MASK                                   BITFIELD(8, 8)
+#define OMAP4430_MODEM_WAKE_IRQ_MASK                                   (1 << 8)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L1_ONSTATE_SHIFT                                  16
-#define OMAP4430_MPU_L1_ONSTATE_MASK                                   BITFIELD(16, 17)
+#define OMAP4430_MPU_L1_ONSTATE_MASK                                   (0x3 << 16)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L1_RETSTATE_SHIFT                                 8
-#define OMAP4430_MPU_L1_RETSTATE_MASK                                  BITFIELD(8, 8)
+#define OMAP4430_MPU_L1_RETSTATE_MASK                                  (1 << 8)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_L1_STATEST_SHIFT                                  4
-#define OMAP4430_MPU_L1_STATEST_MASK                                   BITFIELD(4, 5)
+#define OMAP4430_MPU_L1_STATEST_MASK                                   (0x3 << 4)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L2_ONSTATE_SHIFT                                  18
-#define OMAP4430_MPU_L2_ONSTATE_MASK                                   BITFIELD(18, 19)
+#define OMAP4430_MPU_L2_ONSTATE_MASK                                   (0x3 << 18)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_L2_RETSTATE_SHIFT                                 9
-#define OMAP4430_MPU_L2_RETSTATE_MASK                                  BITFIELD(9, 9)
+#define OMAP4430_MPU_L2_RETSTATE_MASK                                  (1 << 9)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_L2_STATEST_SHIFT                                  6
-#define OMAP4430_MPU_L2_STATEST_MASK                                   BITFIELD(6, 7)
+#define OMAP4430_MPU_L2_STATEST_MASK                                   (0x3 << 6)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_RAM_ONSTATE_SHIFT                                 20
-#define OMAP4430_MPU_RAM_ONSTATE_MASK                                  BITFIELD(20, 21)
+#define OMAP4430_MPU_RAM_ONSTATE_MASK                                  (0x3 << 20)
 
 /* Used by PM_MPU_PWRSTCTRL */
 #define OMAP4430_MPU_RAM_RETSTATE_SHIFT                                        10
-#define OMAP4430_MPU_RAM_RETSTATE_MASK                                 BITFIELD(10, 10)
+#define OMAP4430_MPU_RAM_RETSTATE_MASK                                 (1 << 10)
 
 /* Used by PM_MPU_PWRSTST */
 #define OMAP4430_MPU_RAM_STATEST_SHIFT                                 8
-#define OMAP4430_MPU_RAM_STATEST_MASK                                  BITFIELD(8, 9)
+#define OMAP4430_MPU_RAM_STATEST_MASK                                  (0x3 << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_MPU_SECURITY_VIOL_RST_SHIFT                           2
-#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK                            BITFIELD(2, 2)
+#define OMAP4430_MPU_SECURITY_VIOL_RST_MASK                            (1 << 2)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_MPU_WDT_RST_SHIFT                                     3
-#define OMAP4430_MPU_WDT_RST_MASK                                      BITFIELD(3, 3)
+#define OMAP4430_MPU_WDT_RST_MASK                                      (1 << 3)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_NONRETAINED_BANK_ONSTATE_SHIFT                                18
-#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK                         BITFIELD(18, 19)
+#define OMAP4430_NONRETAINED_BANK_ONSTATE_MASK                         (0x3 << 18)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_NONRETAINED_BANK_RETSTATE_SHIFT                       9
-#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK                                BITFIELD(9, 9)
+#define OMAP4430_NONRETAINED_BANK_RETSTATE_MASK                                (1 << 9)
 
 /* Used by PM_L4PER_PWRSTST */
 #define OMAP4430_NONRETAINED_BANK_STATEST_SHIFT                                6
-#define OMAP4430_NONRETAINED_BANK_STATEST_MASK                         BITFIELD(6, 7)
+#define OMAP4430_NONRETAINED_BANK_STATEST_MASK                         (0x3 << 6)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_OCP_NRET_BANK_ONSTATE_SHIFT                           24
-#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK                            BITFIELD(24, 25)
+#define OMAP4430_OCP_NRET_BANK_ONSTATE_MASK                            (0x3 << 24)
 
 /* Used by PM_CORE_PWRSTCTRL */
 #define OMAP4430_OCP_NRET_BANK_RETSTATE_SHIFT                          12
-#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK                           BITFIELD(12, 12)
+#define OMAP4430_OCP_NRET_BANK_RETSTATE_MASK                           (1 << 12)
 
 /* Used by PM_CORE_PWRSTST */
 #define OMAP4430_OCP_NRET_BANK_STATEST_SHIFT                           12
-#define OMAP4430_OCP_NRET_BANK_STATEST_MASK                            BITFIELD(12, 13)
+#define OMAP4430_OCP_NRET_BANK_STATEST_MASK                            (0x3 << 12)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_OFF_SHIFT                                             0
-#define OMAP4430_OFF_MASK                                              BITFIELD(0, 7)
-
-/* Used by PRM_LDO_BANDGAP_CTRL */
-#define OMAP4430_OFF_ENABLE_SHIFT                                      0
-#define OMAP4430_OFF_ENABLE_MASK                                       BITFIELD(0, 0)
+#define OMAP4430_OFF_MASK                                              (0xff << 0)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_ON_SHIFT                                              24
-#define OMAP4430_ON_MASK                                               BITFIELD(24, 31)
+#define OMAP4430_ON_MASK                                               (0xff << 24)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_ONLP_SHIFT                                            16
-#define OMAP4430_ONLP_MASK                                             BITFIELD(16, 23)
+#define OMAP4430_ONLP_MASK                                             (0xff << 16)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_OPP_CHANGE_SHIFT                                      2
-#define OMAP4430_OPP_CHANGE_MASK                                       BITFIELD(2, 2)
+#define OMAP4430_OPP_CHANGE_MASK                                       (1 << 2)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_OPP_SEL_SHIFT                                         0
-#define OMAP4430_OPP_SEL_MASK                                          BITFIELD(0, 1)
+#define OMAP4430_OPP_SEL_MASK                                          (0x3 << 0)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_PCHARGECNT_VALUE_SHIFT                                        0
-#define OMAP4430_PCHARGECNT_VALUE_MASK                                 BITFIELD(0, 5)
+#define OMAP4430_PCHARGECNT_VALUE_MASK                                 (0x3f << 0)
 
 /* Used by PRM_PSCON_COUNT */
 #define OMAP4430_PCHARGE_TIME_SHIFT                                    0
-#define OMAP4430_PCHARGE_TIME_MASK                                     BITFIELD(0, 7)
+#define OMAP4430_PCHARGE_TIME_MASK                                     (0xff << 0)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_PERIPHMEM_ONSTATE_SHIFT                               20
-#define OMAP4430_PERIPHMEM_ONSTATE_MASK                                        BITFIELD(20, 21)
+#define OMAP4430_PERIPHMEM_ONSTATE_MASK                                        (0x3 << 20)
 
 /* Used by PM_ABE_PWRSTCTRL */
 #define OMAP4430_PERIPHMEM_RETSTATE_SHIFT                              10
-#define OMAP4430_PERIPHMEM_RETSTATE_MASK                               BITFIELD(10, 10)
+#define OMAP4430_PERIPHMEM_RETSTATE_MASK                               (1 << 10)
 
 /* Used by PM_ABE_PWRSTST */
 #define OMAP4430_PERIPHMEM_STATEST_SHIFT                               8
-#define OMAP4430_PERIPHMEM_STATEST_MASK                                        BITFIELD(8, 9)
+#define OMAP4430_PERIPHMEM_STATEST_MASK                                        (0x3 << 8)
 
 /* Used by PRM_PHASE1_CNDP */
 #define OMAP4430_PHASE1_CNDP_SHIFT                                     0
-#define OMAP4430_PHASE1_CNDP_MASK                                      BITFIELD(0, 31)
+#define OMAP4430_PHASE1_CNDP_MASK                                      (0xffffffff << 0)
 
 /* Used by PRM_PHASE2A_CNDP */
 #define OMAP4430_PHASE2A_CNDP_SHIFT                                    0
-#define OMAP4430_PHASE2A_CNDP_MASK                                     BITFIELD(0, 31)
+#define OMAP4430_PHASE2A_CNDP_MASK                                     (0xffffffff << 0)
 
 /* Used by PRM_PHASE2B_CNDP */
 #define OMAP4430_PHASE2B_CNDP_SHIFT                                    0
-#define OMAP4430_PHASE2B_CNDP_MASK                                     BITFIELD(0, 31)
+#define OMAP4430_PHASE2B_CNDP_MASK                                     (0xffffffff << 0)
 
 /* Used by PRM_PSCON_COUNT */
 #define OMAP4430_PONOUT_2_PGOODIN_TIME_SHIFT                           8
-#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK                            BITFIELD(8, 15)
+#define OMAP4430_PONOUT_2_PGOODIN_TIME_MASK                            (0xff << 8)
 
 /*
- * Used by PM_EMU_PWRSTCTRL, PM_CORE_PWRSTCTRL, PM_CAM_PWRSTCTRL,
- * PM_L3INIT_PWRSTCTRL, PM_ABE_PWRSTCTRL, PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL,
- * PM_CEFUSE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
- * PM_TESLA_PWRSTCTRL, PM_IVAHD_PWRSTCTRL
+ * Used by PM_ABE_PWRSTCTRL, PM_CAM_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL,
+ * PM_CORE_PWRSTCTRL, PM_DSS_PWRSTCTRL, PM_EMU_PWRSTCTRL, PM_GFX_PWRSTCTRL,
+ * PM_IVAHD_PWRSTCTRL, PM_L3INIT_PWRSTCTRL, PM_L4PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL, PM_TESLA_PWRSTCTRL
  */
 #define OMAP4430_POWERSTATE_SHIFT                                      0
-#define OMAP4430_POWERSTATE_MASK                                       BITFIELD(0, 1)
+#define OMAP4430_POWERSTATE_MASK                                       (0x3 << 0)
 
 /*
- * Used by PM_EMU_PWRSTST, PM_CORE_PWRSTST, PM_CAM_PWRSTST, PM_L3INIT_PWRSTST,
- * PM_ABE_PWRSTST, PM_GFX_PWRSTST, PM_MPU_PWRSTST, PM_CEFUSE_PWRSTST,
- * PM_DSS_PWRSTST, PM_L4PER_PWRSTST, PM_TESLA_PWRSTST, PM_IVAHD_PWRSTST
+ * Used by PM_ABE_PWRSTST, PM_CAM_PWRSTST, PM_CEFUSE_PWRSTST, PM_CORE_PWRSTST,
+ * PM_DSS_PWRSTST, PM_EMU_PWRSTST, PM_GFX_PWRSTST, PM_IVAHD_PWRSTST,
+ * PM_L3INIT_PWRSTST, PM_L4PER_PWRSTST, PM_MPU_PWRSTST, PM_TESLA_PWRSTST
  */
 #define OMAP4430_POWERSTATEST_SHIFT                                    0
-#define OMAP4430_POWERSTATEST_MASK                                     BITFIELD(0, 1)
+#define OMAP4430_POWERSTATEST_MASK                                     (0x3 << 0)
 
 /* Used by PRM_PWRREQCTRL */
 #define OMAP4430_PWRREQ_COND_SHIFT                                     0
-#define OMAP4430_PWRREQ_COND_MASK                                      BITFIELD(0, 1)
+#define OMAP4430_PWRREQ_COND_MASK                                      (0x3 << 0)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_CORE_L_SHIFT                                        3
-#define OMAP4430_RACEN_VDD_CORE_L_MASK                                 BITFIELD(3, 3)
+#define OMAP4430_RACEN_VDD_CORE_L_MASK                                 (1 << 3)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_IVA_L_SHIFT                                 11
-#define OMAP4430_RACEN_VDD_IVA_L_MASK                                  BITFIELD(11, 11)
+#define OMAP4430_RACEN_VDD_IVA_L_MASK                                  (1 << 11)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RACEN_VDD_MPU_L_SHIFT                                 20
-#define OMAP4430_RACEN_VDD_MPU_L_MASK                                  BITFIELD(20, 20)
+#define OMAP4430_RACEN_VDD_MPU_L_MASK                                  (1 << 20)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_CORE_L_SHIFT                                  2
-#define OMAP4430_RAC_VDD_CORE_L_MASK                                   BITFIELD(2, 2)
+#define OMAP4430_RAC_VDD_CORE_L_MASK                                   (1 << 2)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_IVA_L_SHIFT                                   10
-#define OMAP4430_RAC_VDD_IVA_L_MASK                                    BITFIELD(10, 10)
+#define OMAP4430_RAC_VDD_IVA_L_MASK                                    (1 << 10)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAC_VDD_MPU_L_SHIFT                                   19
-#define OMAP4430_RAC_VDD_MPU_L_MASK                                    BITFIELD(19, 19)
+#define OMAP4430_RAC_VDD_MPU_L_MASK                                    (1 << 19)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_DOWN_COUNT_SHIFT                                 16
-#define OMAP4430_RAMP_DOWN_COUNT_MASK                                  BITFIELD(16, 21)
+#define OMAP4430_RAMP_DOWN_COUNT_MASK                                  (0x3f << 16)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_DOWN_PRESCAL_SHIFT                               24
-#define OMAP4430_RAMP_DOWN_PRESCAL_MASK                                        BITFIELD(24, 25)
+#define OMAP4430_RAMP_DOWN_PRESCAL_MASK                                        (0x3 << 24)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_UP_COUNT_SHIFT                                   0
-#define OMAP4430_RAMP_UP_COUNT_MASK                                    BITFIELD(0, 5)
+#define OMAP4430_RAMP_UP_COUNT_MASK                                    (0x3f << 0)
 
 /*
  * Used by PRM_VOLTSETUP_CORE_OFF, PRM_VOLTSETUP_CORE_RET_SLEEP,
  * PRM_VOLTSETUP_MPU_RET_SLEEP
  */
 #define OMAP4430_RAMP_UP_PRESCAL_SHIFT                                 8
-#define OMAP4430_RAMP_UP_PRESCAL_MASK                                  BITFIELD(8, 9)
+#define OMAP4430_RAMP_UP_PRESCAL_MASK                                  (0x3 << 8)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_CORE_L_SHIFT                                  1
-#define OMAP4430_RAV_VDD_CORE_L_MASK                                   BITFIELD(1, 1)
+#define OMAP4430_RAV_VDD_CORE_L_MASK                                   (1 << 1)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_IVA_L_SHIFT                                   9
-#define OMAP4430_RAV_VDD_IVA_L_MASK                                    BITFIELD(9, 9)
+#define OMAP4430_RAV_VDD_IVA_L_MASK                                    (1 << 9)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_RAV_VDD_MPU_L_SHIFT                                   18
-#define OMAP4430_RAV_VDD_MPU_L_MASK                                    BITFIELD(18, 18)
+#define OMAP4430_RAV_VDD_MPU_L_MASK                                    (1 << 18)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_REGADDR_SHIFT                                         8
-#define OMAP4430_REGADDR_MASK                                          BITFIELD(8, 15)
+#define OMAP4430_REGADDR_MASK                                          (0xff << 8)
 
 /*
  * Used by PRM_VC_VAL_CMD_VDD_CORE_L, PRM_VC_VAL_CMD_VDD_IVA_L,
  * PRM_VC_VAL_CMD_VDD_MPU_L
  */
 #define OMAP4430_RET_SHIFT                                             8
-#define OMAP4430_RET_MASK                                              BITFIELD(8, 15)
+#define OMAP4430_RET_MASK                                              (0xff << 8)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_RETAINED_BANK_ONSTATE_SHIFT                           16
-#define OMAP4430_RETAINED_BANK_ONSTATE_MASK                            BITFIELD(16, 17)
+#define OMAP4430_RETAINED_BANK_ONSTATE_MASK                            (0x3 << 16)
 
 /* Used by PM_L4PER_PWRSTCTRL */
 #define OMAP4430_RETAINED_BANK_RETSTATE_SHIFT                          8
-#define OMAP4430_RETAINED_BANK_RETSTATE_MASK                           BITFIELD(8, 8)
+#define OMAP4430_RETAINED_BANK_RETSTATE_MASK                           (1 << 8)
 
 /* Used by PM_L4PER_PWRSTST */
 #define OMAP4430_RETAINED_BANK_STATEST_SHIFT                           4
-#define OMAP4430_RETAINED_BANK_STATEST_MASK                            BITFIELD(4, 5)
+#define OMAP4430_RETAINED_BANK_STATEST_MASK                            (0x3 << 4)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_RETMODE_ENABLE_SHIFT                                  0
-#define OMAP4430_RETMODE_ENABLE_MASK                                   BITFIELD(0, 0)
+#define OMAP4430_RETMODE_ENABLE_MASK                                   (1 << 0)
 
-/* Used by REVISION_PRM */
-#define OMAP4430_REV_SHIFT                                             0
-#define OMAP4430_REV_MASK                                              BITFIELD(0, 7)
-
-/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */
+/* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL, RM_TESLA_RSTCTRL */
 #define OMAP4430_RST1_SHIFT                                            0
-#define OMAP4430_RST1_MASK                                             BITFIELD(0, 0)
+#define OMAP4430_RST1_MASK                                             (1 << 0)
 
-/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */
+/* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST, RM_TESLA_RSTST */
 #define OMAP4430_RST1ST_SHIFT                                          0
-#define OMAP4430_RST1ST_MASK                                           BITFIELD(0, 0)
+#define OMAP4430_RST1ST_MASK                                           (1 << 0)
 
-/* Used by RM_DUCATI_RSTCTRL, RM_TESLA_RSTCTRL, RM_IVAHD_RSTCTRL */
+/* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL, RM_TESLA_RSTCTRL */
 #define OMAP4430_RST2_SHIFT                                            1
-#define OMAP4430_RST2_MASK                                             BITFIELD(1, 1)
+#define OMAP4430_RST2_MASK                                             (1 << 1)
 
-/* Used by RM_DUCATI_RSTST, RM_TESLA_RSTST, RM_IVAHD_RSTST */
+/* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST, RM_TESLA_RSTST */
 #define OMAP4430_RST2ST_SHIFT                                          1
-#define OMAP4430_RST2ST_MASK                                           BITFIELD(1, 1)
+#define OMAP4430_RST2ST_MASK                                           (1 << 1)
 
 /* Used by RM_DUCATI_RSTCTRL, RM_IVAHD_RSTCTRL */
 #define OMAP4430_RST3_SHIFT                                            2
-#define OMAP4430_RST3_MASK                                             BITFIELD(2, 2)
+#define OMAP4430_RST3_MASK                                             (1 << 2)
 
 /* Used by RM_DUCATI_RSTST, RM_IVAHD_RSTST */
 #define OMAP4430_RST3ST_SHIFT                                          2
-#define OMAP4430_RST3ST_MASK                                           BITFIELD(2, 2)
+#define OMAP4430_RST3ST_MASK                                           (1 << 2)
 
 /* Used by PRM_RSTTIME */
 #define OMAP4430_RSTTIME1_SHIFT                                                0
-#define OMAP4430_RSTTIME1_MASK                                         BITFIELD(0, 9)
+#define OMAP4430_RSTTIME1_MASK                                         (0x3ff << 0)
 
 /* Used by PRM_RSTTIME */
 #define OMAP4430_RSTTIME2_SHIFT                                                10
-#define OMAP4430_RSTTIME2_MASK                                         BITFIELD(10, 14)
+#define OMAP4430_RSTTIME2_MASK                                         (0x1f << 10)
 
 /* Used by PRM_RSTCTRL */
 #define OMAP4430_RST_GLOBAL_COLD_SW_SHIFT                              1
-#define OMAP4430_RST_GLOBAL_COLD_SW_MASK                               BITFIELD(1, 1)
+#define OMAP4430_RST_GLOBAL_COLD_SW_MASK                               (1 << 1)
 
 /* Used by PRM_RSTCTRL */
 #define OMAP4430_RST_GLOBAL_WARM_SW_SHIFT                              0
-#define OMAP4430_RST_GLOBAL_WARM_SW_MASK                               BITFIELD(0, 0)
+#define OMAP4430_RST_GLOBAL_WARM_SW_MASK                               (1 << 0)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_R_RTL_SHIFT                                           11
+#define OMAP4430_R_RTL_MASK                                            (0x1f << 11)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_CORE_L_SHIFT                                   0
-#define OMAP4430_SA_VDD_CORE_L_MASK                                    BITFIELD(0, 0)
+#define OMAP4430_SA_VDD_CORE_L_MASK                                    (1 << 0)
 
 /* Renamed from SA_VDD_CORE_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_CORE_L_0_6_SHIFT                               0
-#define OMAP4430_SA_VDD_CORE_L_0_6_MASK                                        BITFIELD(0, 6)
+#define OMAP4430_SA_VDD_CORE_L_0_6_MASK                                        (0x7f << 0)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_IVA_L_SHIFT                                    8
-#define OMAP4430_SA_VDD_IVA_L_MASK                                     BITFIELD(8, 8)
+#define OMAP4430_SA_VDD_IVA_L_MASK                                     (1 << 8)
 
 /* Renamed from SA_VDD_IVA_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT                     8
-#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK                      BITFIELD(8, 14)
+#define OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK                      (0x7f << 8)
 
 /* Used by PRM_VC_CFG_CHANNEL */
 #define OMAP4430_SA_VDD_MPU_L_SHIFT                                    16
-#define OMAP4430_SA_VDD_MPU_L_MASK                                     BITFIELD(16, 16)
+#define OMAP4430_SA_VDD_MPU_L_MASK                                     (1 << 16)
 
 /* Renamed from SA_VDD_MPU_L Used by PRM_VC_SMPS_SA */
 #define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT                     16
-#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK                      BITFIELD(16, 22)
+#define OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK                      (0x7f << 16)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_SCHEME_SHIFT                                          30
+#define OMAP4430_SCHEME_MASK                                           (0x3 << 30)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_SCLH_SHIFT                                            0
-#define OMAP4430_SCLH_MASK                                             BITFIELD(0, 7)
+#define OMAP4430_SCLH_MASK                                             (0xff << 0)
 
 /* Used by PRM_VC_CFG_I2C_CLK */
 #define OMAP4430_SCLL_SHIFT                                            8
-#define OMAP4430_SCLL_MASK                                             BITFIELD(8, 15)
+#define OMAP4430_SCLL_MASK                                             (0xff << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_SECURE_WDT_RST_SHIFT                                  4
-#define OMAP4430_SECURE_WDT_RST_MASK                                   BITFIELD(4, 4)
+#define OMAP4430_SECURE_WDT_RST_MASK                                   (1 << 4)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_SL2_MEM_ONSTATE_SHIFT                                 18
-#define OMAP4430_SL2_MEM_ONSTATE_MASK                                  BITFIELD(18, 19)
+#define OMAP4430_SL2_MEM_ONSTATE_MASK                                  (0x3 << 18)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_SL2_MEM_RETSTATE_SHIFT                                        9
-#define OMAP4430_SL2_MEM_RETSTATE_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_SL2_MEM_RETSTATE_MASK                                 (1 << 9)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_SL2_MEM_STATEST_SHIFT                                 6
-#define OMAP4430_SL2_MEM_STATEST_MASK                                  BITFIELD(6, 7)
+#define OMAP4430_SL2_MEM_STATEST_MASK                                  (0x3 << 6)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_SLAVEADDR_SHIFT                                       0
-#define OMAP4430_SLAVEADDR_MASK                                                BITFIELD(0, 6)
+#define OMAP4430_SLAVEADDR_MASK                                                (0x7f << 0)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SLEEP_RBB_SEL_SHIFT                                   3
-#define OMAP4430_SLEEP_RBB_SEL_MASK                                    BITFIELD(3, 3)
+#define OMAP4430_SLEEP_RBB_SEL_MASK                                    (1 << 3)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_SLPCNT_VALUE_SHIFT                                    16
-#define OMAP4430_SLPCNT_VALUE_MASK                                     BITFIELD(16, 23)
+#define OMAP4430_SLPCNT_VALUE_MASK                                     (0xff << 16)
 
 /* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */
 #define OMAP4430_SMPSWAITTIMEMAX_SHIFT                                 8
-#define OMAP4430_SMPSWAITTIMEMAX_MASK                                  BITFIELD(8, 23)
+#define OMAP4430_SMPSWAITTIMEMAX_MASK                                  (0xffff << 8)
 
 /* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */
 #define OMAP4430_SMPSWAITTIMEMIN_SHIFT                                 8
-#define OMAP4430_SMPSWAITTIMEMIN_MASK                                  BITFIELD(8, 23)
+#define OMAP4430_SMPSWAITTIMEMIN_MASK                                  (0xffff << 8)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_CORE_SHIFT                                        1
+#define OMAP4430_SMPS_RA_ERR_CORE_MASK                                 (1 << 1)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_IVA_SHIFT                                 9
+#define OMAP4430_SMPS_RA_ERR_IVA_MASK                                  (1 << 9)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_RA_ERR_MPU_SHIFT                                 17
+#define OMAP4430_SMPS_RA_ERR_MPU_MASK                                  (1 << 17)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_CORE_SHIFT                                        0
+#define OMAP4430_SMPS_SA_ERR_CORE_MASK                                 (1 << 0)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_IVA_SHIFT                                 8
+#define OMAP4430_SMPS_SA_ERR_IVA_MASK                                  (1 << 8)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_SA_ERR_MPU_SHIFT                                 16
+#define OMAP4430_SMPS_SA_ERR_MPU_MASK                                  (1 << 16)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_CORE_SHIFT                           2
+#define OMAP4430_SMPS_TIMEOUT_ERR_CORE_MASK                            (1 << 2)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_IVA_SHIFT                            10
+#define OMAP4430_SMPS_TIMEOUT_ERR_IVA_MASK                             (1 << 10)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_SMPS_TIMEOUT_ERR_MPU_SHIFT                            18
+#define OMAP4430_SMPS_TIMEOUT_ERR_MPU_MASK                             (1 << 18)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SR2EN_SHIFT                                           0
-#define OMAP4430_SR2EN_MASK                                            BITFIELD(0, 0)
+#define OMAP4430_SR2EN_MASK                                            (1 << 0)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_SR2_IN_TRANSITION_SHIFT                               6
-#define OMAP4430_SR2_IN_TRANSITION_MASK                                        BITFIELD(6, 6)
+#define OMAP4430_SR2_IN_TRANSITION_MASK                                        (1 << 6)
 
 /* Used by PRM_LDO_ABB_IVA_CTRL, PRM_LDO_ABB_MPU_CTRL */
 #define OMAP4430_SR2_STATUS_SHIFT                                      3
-#define OMAP4430_SR2_STATUS_MASK                                       BITFIELD(3, 4)
+#define OMAP4430_SR2_STATUS_MASK                                       (0x3 << 3)
 
 /* Used by PRM_LDO_ABB_IVA_SETUP, PRM_LDO_ABB_MPU_SETUP */
 #define OMAP4430_SR2_WTCNT_VALUE_SHIFT                                 8
-#define OMAP4430_SR2_WTCNT_VALUE_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_SR2_WTCNT_VALUE_MASK                                  (0xff << 8)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_SRAMLDO_STATUS_SHIFT                                  8
-#define OMAP4430_SRAMLDO_STATUS_MASK                                   BITFIELD(8, 8)
+#define OMAP4430_SRAMLDO_STATUS_MASK                                   (1 << 8)
 
 /*
  * Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_IVA_CTRL,
  * PRM_LDO_SRAM_MPU_CTRL
  */
 #define OMAP4430_SRAM_IN_TRANSITION_SHIFT                              9
-#define OMAP4430_SRAM_IN_TRANSITION_MASK                               BITFIELD(9, 9)
+#define OMAP4430_SRAM_IN_TRANSITION_MASK                               (1 << 9)
 
 /* Used by PRM_VC_CFG_I2C_MODE */
 #define OMAP4430_SRMODEEN_SHIFT                                                4
-#define OMAP4430_SRMODEEN_MASK                                         BITFIELD(4, 4)
+#define OMAP4430_SRMODEEN_MASK                                         (1 << 4)
 
 /* Used by PRM_VOLTSETUP_WARMRESET */
 #define OMAP4430_STABLE_COUNT_SHIFT                                    0
-#define OMAP4430_STABLE_COUNT_MASK                                     BITFIELD(0, 5)
+#define OMAP4430_STABLE_COUNT_MASK                                     (0x3f << 0)
 
 /* Used by PRM_VOLTSETUP_WARMRESET */
 #define OMAP4430_STABLE_PRESCAL_SHIFT                                  8
-#define OMAP4430_STABLE_PRESCAL_MASK                                   BITFIELD(8, 9)
+#define OMAP4430_STABLE_PRESCAL_MASK                                   (0x3 << 8)
+
+/* Used by PRM_LDO_BANDGAP_SETUP */
+#define OMAP4430_STARTUP_COUNT_SHIFT                                   0
+#define OMAP4430_STARTUP_COUNT_MASK                                    (0xff << 0)
+
+/* Renamed from STARTUP_COUNT Used by PRM_SRAM_COUNT */
+#define OMAP4430_STARTUP_COUNT_24_31_SHIFT                             24
+#define OMAP4430_STARTUP_COUNT_24_31_MASK                              (0xff << 24)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM1_MEM_ONSTATE_SHIFT                                        20
-#define OMAP4430_TCM1_MEM_ONSTATE_MASK                                 BITFIELD(20, 21)
+#define OMAP4430_TCM1_MEM_ONSTATE_MASK                                 (0x3 << 20)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM1_MEM_RETSTATE_SHIFT                               10
-#define OMAP4430_TCM1_MEM_RETSTATE_MASK                                        BITFIELD(10, 10)
+#define OMAP4430_TCM1_MEM_RETSTATE_MASK                                        (1 << 10)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_TCM1_MEM_STATEST_SHIFT                                        8
-#define OMAP4430_TCM1_MEM_STATEST_MASK                                 BITFIELD(8, 9)
+#define OMAP4430_TCM1_MEM_STATEST_MASK                                 (0x3 << 8)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM2_MEM_ONSTATE_SHIFT                                        22
-#define OMAP4430_TCM2_MEM_ONSTATE_MASK                                 BITFIELD(22, 23)
+#define OMAP4430_TCM2_MEM_ONSTATE_MASK                                 (0x3 << 22)
 
 /* Used by PM_IVAHD_PWRSTCTRL */
 #define OMAP4430_TCM2_MEM_RETSTATE_SHIFT                               11
-#define OMAP4430_TCM2_MEM_RETSTATE_MASK                                        BITFIELD(11, 11)
+#define OMAP4430_TCM2_MEM_RETSTATE_MASK                                        (1 << 11)
 
 /* Used by PM_IVAHD_PWRSTST */
 #define OMAP4430_TCM2_MEM_STATEST_SHIFT                                        10
-#define OMAP4430_TCM2_MEM_STATEST_MASK                                 BITFIELD(10, 11)
+#define OMAP4430_TCM2_MEM_STATEST_MASK                                 (0x3 << 10)
 
 /* Used by RM_TESLA_RSTST */
 #define OMAP4430_TESLASS_EMU_RSTST_SHIFT                               2
-#define OMAP4430_TESLASS_EMU_RSTST_MASK                                        BITFIELD(2, 2)
+#define OMAP4430_TESLASS_EMU_RSTST_MASK                                        (1 << 2)
 
 /* Used by RM_TESLA_RSTST */
 #define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_SHIFT                         3
-#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK                          BITFIELD(3, 3)
+#define OMAP4430_TESLA_DSP_EMU_REQ_RSTST_MASK                          (1 << 3)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_EDMA_ONSTATE_SHIFT                              20
-#define OMAP4430_TESLA_EDMA_ONSTATE_MASK                               BITFIELD(20, 21)
+#define OMAP4430_TESLA_EDMA_ONSTATE_MASK                               (0x3 << 20)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_EDMA_RETSTATE_SHIFT                             10
-#define OMAP4430_TESLA_EDMA_RETSTATE_MASK                              BITFIELD(10, 10)
+#define OMAP4430_TESLA_EDMA_RETSTATE_MASK                              (1 << 10)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_EDMA_STATEST_SHIFT                              8
-#define OMAP4430_TESLA_EDMA_STATEST_MASK                               BITFIELD(8, 9)
+#define OMAP4430_TESLA_EDMA_STATEST_MASK                               (0x3 << 8)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L1_ONSTATE_SHIFT                                        16
-#define OMAP4430_TESLA_L1_ONSTATE_MASK                                 BITFIELD(16, 17)
+#define OMAP4430_TESLA_L1_ONSTATE_MASK                                 (0x3 << 16)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L1_RETSTATE_SHIFT                               8
-#define OMAP4430_TESLA_L1_RETSTATE_MASK                                        BITFIELD(8, 8)
+#define OMAP4430_TESLA_L1_RETSTATE_MASK                                        (1 << 8)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_L1_STATEST_SHIFT                                        4
-#define OMAP4430_TESLA_L1_STATEST_MASK                                 BITFIELD(4, 5)
+#define OMAP4430_TESLA_L1_STATEST_MASK                                 (0x3 << 4)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L2_ONSTATE_SHIFT                                        18
-#define OMAP4430_TESLA_L2_ONSTATE_MASK                                 BITFIELD(18, 19)
+#define OMAP4430_TESLA_L2_ONSTATE_MASK                                 (0x3 << 18)
 
 /* Used by PM_TESLA_PWRSTCTRL */
 #define OMAP4430_TESLA_L2_RETSTATE_SHIFT                               9
-#define OMAP4430_TESLA_L2_RETSTATE_MASK                                        BITFIELD(9, 9)
+#define OMAP4430_TESLA_L2_RETSTATE_MASK                                        (1 << 9)
 
 /* Used by PM_TESLA_PWRSTST */
 #define OMAP4430_TESLA_L2_STATEST_SHIFT                                        6
-#define OMAP4430_TESLA_L2_STATEST_MASK                                 BITFIELD(6, 7)
+#define OMAP4430_TESLA_L2_STATEST_MASK                                 (0x3 << 6)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_TIMEOUT_SHIFT                                         0
-#define OMAP4430_TIMEOUT_MASK                                          BITFIELD(0, 15)
+#define OMAP4430_TIMEOUT_MASK                                          (0xffff << 0)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_TIMEOUTEN_SHIFT                                       3
-#define OMAP4430_TIMEOUTEN_MASK                                                BITFIELD(3, 3)
+#define OMAP4430_TIMEOUTEN_MASK                                                (1 << 3)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_TRANSITION_EN_SHIFT                                   8
-#define OMAP4430_TRANSITION_EN_MASK                                    BITFIELD(8, 8)
+#define OMAP4430_TRANSITION_EN_MASK                                    (1 << 8)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_TRANSITION_ST_SHIFT                                   8
-#define OMAP4430_TRANSITION_ST_MASK                                    BITFIELD(8, 8)
+#define OMAP4430_TRANSITION_ST_MASK                                    (1 << 8)
 
 /* Used by PRM_VC_VAL_BYPASS */
 #define OMAP4430_VALID_SHIFT                                           24
-#define OMAP4430_VALID_MASK                                            BITFIELD(24, 24)
+#define OMAP4430_VALID_MASK                                            (1 << 24)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_BYPASSACK_EN_SHIFT                                 14
-#define OMAP4430_VC_BYPASSACK_EN_MASK                                  BITFIELD(14, 14)
+#define OMAP4430_VC_BYPASSACK_EN_MASK                                  (1 << 14)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_BYPASSACK_ST_SHIFT                                 14
-#define OMAP4430_VC_BYPASSACK_ST_MASK                                  BITFIELD(14, 14)
+#define OMAP4430_VC_BYPASSACK_ST_MASK                                  (1 << 14)
+
+/* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
+#define OMAP4430_VC_CORE_VPACK_EN_SHIFT                                        22
+#define OMAP4430_VC_CORE_VPACK_EN_MASK                                 (1 << 22)
+
+/* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
+#define OMAP4430_VC_CORE_VPACK_ST_SHIFT                                        22
+#define OMAP4430_VC_CORE_VPACK_ST_MASK                                 (1 << 22)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_IVA_VPACK_EN_SHIFT                                 30
-#define OMAP4430_VC_IVA_VPACK_EN_MASK                                  BITFIELD(30, 30)
+#define OMAP4430_VC_IVA_VPACK_EN_MASK                                  (1 << 30)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_IVA_VPACK_ST_SHIFT                                 30
-#define OMAP4430_VC_IVA_VPACK_ST_MASK                                  BITFIELD(30, 30)
+#define OMAP4430_VC_IVA_VPACK_ST_MASK                                  (1 << 30)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VC_MPU_VPACK_EN_SHIFT                                 6
-#define OMAP4430_VC_MPU_VPACK_EN_MASK                                  BITFIELD(6, 6)
+#define OMAP4430_VC_MPU_VPACK_EN_MASK                                  (1 << 6)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VC_MPU_VPACK_ST_SHIFT                                 6
-#define OMAP4430_VC_MPU_VPACK_ST_MASK                                  BITFIELD(6, 6)
+#define OMAP4430_VC_MPU_VPACK_ST_MASK                                  (1 << 6)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_RAERR_EN_SHIFT                                     12
-#define OMAP4430_VC_RAERR_EN_MASK                                      BITFIELD(12, 12)
+#define OMAP4430_VC_RAERR_EN_MASK                                      (1 << 12)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_RAERR_ST_SHIFT                                     12
-#define OMAP4430_VC_RAERR_ST_MASK                                      BITFIELD(12, 12)
+#define OMAP4430_VC_RAERR_ST_MASK                                      (1 << 12)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_SAERR_EN_SHIFT                                     11
-#define OMAP4430_VC_SAERR_EN_MASK                                      BITFIELD(11, 11)
+#define OMAP4430_VC_SAERR_EN_MASK                                      (1 << 11)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_SAERR_ST_SHIFT                                     11
-#define OMAP4430_VC_SAERR_ST_MASK                                      BITFIELD(11, 11)
+#define OMAP4430_VC_SAERR_ST_MASK                                      (1 << 11)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VC_TOERR_EN_SHIFT                                     13
-#define OMAP4430_VC_TOERR_EN_MASK                                      BITFIELD(13, 13)
+#define OMAP4430_VC_TOERR_EN_MASK                                      (1 << 13)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VC_TOERR_ST_SHIFT                                     13
-#define OMAP4430_VC_TOERR_ST_MASK                                      BITFIELD(13, 13)
+#define OMAP4430_VC_TOERR_ST_MASK                                      (1 << 13)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_VDDMAX_SHIFT                                          24
-#define OMAP4430_VDDMAX_MASK                                           BITFIELD(24, 31)
+#define OMAP4430_VDDMAX_MASK                                           (0xff << 24)
 
 /* Used by PRM_VP_CORE_VLIMITTO, PRM_VP_IVA_VLIMITTO, PRM_VP_MPU_VLIMITTO */
 #define OMAP4430_VDDMIN_SHIFT                                          16
-#define OMAP4430_VDDMIN_MASK                                           BITFIELD(16, 23)
+#define OMAP4430_VDDMIN_MASK                                           (0xff << 16)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_CORE_I2C_DISABLE_SHIFT                            12
-#define OMAP4430_VDD_CORE_I2C_DISABLE_MASK                             BITFIELD(12, 12)
+#define OMAP4430_VDD_CORE_I2C_DISABLE_MASK                             (1 << 12)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_CORE_VOLT_MGR_RST_SHIFT                           8
-#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK                            BITFIELD(8, 8)
+#define OMAP4430_VDD_CORE_VOLT_MGR_RST_MASK                            (1 << 8)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_IVA_I2C_DISABLE_SHIFT                             14
-#define OMAP4430_VDD_IVA_I2C_DISABLE_MASK                              BITFIELD(14, 14)
+#define OMAP4430_VDD_IVA_I2C_DISABLE_MASK                              (1 << 14)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_IVA_PRESENCE_SHIFT                                        9
-#define OMAP4430_VDD_IVA_PRESENCE_MASK                                 BITFIELD(9, 9)
+#define OMAP4430_VDD_IVA_PRESENCE_MASK                                 (1 << 9)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_IVA_VOLT_MGR_RST_SHIFT                            7
-#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK                             BITFIELD(7, 7)
+#define OMAP4430_VDD_IVA_VOLT_MGR_RST_MASK                             (1 << 7)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_MPU_I2C_DISABLE_SHIFT                             13
-#define OMAP4430_VDD_MPU_I2C_DISABLE_MASK                              BITFIELD(13, 13)
+#define OMAP4430_VDD_MPU_I2C_DISABLE_MASK                              (1 << 13)
 
 /* Used by PRM_VOLTCTRL */
 #define OMAP4430_VDD_MPU_PRESENCE_SHIFT                                        8
-#define OMAP4430_VDD_MPU_PRESENCE_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_VDD_MPU_PRESENCE_MASK                                 (1 << 8)
 
 /* Used by PRM_RSTST */
 #define OMAP4430_VDD_MPU_VOLT_MGR_RST_SHIFT                            6
-#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK                             BITFIELD(6, 6)
+#define OMAP4430_VDD_MPU_VOLT_MGR_RST_MASK                             (1 << 6)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_CORE_SHIFT                                        4
+#define OMAP4430_VFSM_RA_ERR_CORE_MASK                                 (1 << 4)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_IVA_SHIFT                                 12
+#define OMAP4430_VFSM_RA_ERR_IVA_MASK                                  (1 << 12)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_RA_ERR_MPU_SHIFT                                 20
+#define OMAP4430_VFSM_RA_ERR_MPU_MASK                                  (1 << 20)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_CORE_SHIFT                                        3
+#define OMAP4430_VFSM_SA_ERR_CORE_MASK                                 (1 << 3)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_IVA_SHIFT                                 11
+#define OMAP4430_VFSM_SA_ERR_IVA_MASK                                  (1 << 11)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_SA_ERR_MPU_SHIFT                                 19
+#define OMAP4430_VFSM_SA_ERR_MPU_MASK                                  (1 << 19)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_CORE_SHIFT                           5
+#define OMAP4430_VFSM_TIMEOUT_ERR_CORE_MASK                            (1 << 5)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_IVA_SHIFT                            13
+#define OMAP4430_VFSM_TIMEOUT_ERR_IVA_MASK                             (1 << 13)
+
+/* Used by PRM_VC_ERRST */
+#define OMAP4430_VFSM_TIMEOUT_ERR_MPU_SHIFT                            21
+#define OMAP4430_VFSM_TIMEOUT_ERR_MPU_MASK                             (1 << 21)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_CORE_L_SHIFT                                        0
-#define OMAP4430_VOLRA_VDD_CORE_L_MASK                                 BITFIELD(0, 7)
+#define OMAP4430_VOLRA_VDD_CORE_L_MASK                                 (0xff << 0)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_IVA_L_SHIFT                                 8
-#define OMAP4430_VOLRA_VDD_IVA_L_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_VOLRA_VDD_IVA_L_MASK                                  (0xff << 8)
 
 /* Used by PRM_VC_VAL_SMPS_RA_VOL */
 #define OMAP4430_VOLRA_VDD_MPU_L_SHIFT                                 16
-#define OMAP4430_VOLRA_VDD_MPU_L_MASK                                  BITFIELD(16, 23)
+#define OMAP4430_VOLRA_VDD_MPU_L_MASK                                  (0xff << 16)
 
 /* Used by PRM_VP_CORE_CONFIG, PRM_VP_IVA_CONFIG, PRM_VP_MPU_CONFIG */
 #define OMAP4430_VPENABLE_SHIFT                                                0
-#define OMAP4430_VPENABLE_MASK                                         BITFIELD(0, 0)
+#define OMAP4430_VPENABLE_MASK                                         (1 << 0)
 
 /* Used by PRM_VP_CORE_STATUS, PRM_VP_IVA_STATUS, PRM_VP_MPU_STATUS */
 #define OMAP4430_VPINIDLE_SHIFT                                                0
-#define OMAP4430_VPINIDLE_MASK                                         BITFIELD(0, 0)
+#define OMAP4430_VPINIDLE_MASK                                         (1 << 0)
 
 /* Used by PRM_VP_CORE_VOLTAGE, PRM_VP_IVA_VOLTAGE, PRM_VP_MPU_VOLTAGE */
 #define OMAP4430_VPVOLTAGE_SHIFT                                       0
-#define OMAP4430_VPVOLTAGE_MASK                                                BITFIELD(0, 7)
+#define OMAP4430_VPVOLTAGE_MASK                                                (0xff << 0)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_EQVALUE_EN_SHIFT                              20
-#define OMAP4430_VP_CORE_EQVALUE_EN_MASK                               BITFIELD(20, 20)
+#define OMAP4430_VP_CORE_EQVALUE_EN_MASK                               (1 << 20)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_EQVALUE_ST_SHIFT                              20
-#define OMAP4430_VP_CORE_EQVALUE_ST_MASK                               BITFIELD(20, 20)
+#define OMAP4430_VP_CORE_EQVALUE_ST_MASK                               (1 << 20)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_MAXVDD_EN_SHIFT                               18
-#define OMAP4430_VP_CORE_MAXVDD_EN_MASK                                        BITFIELD(18, 18)
+#define OMAP4430_VP_CORE_MAXVDD_EN_MASK                                        (1 << 18)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_MAXVDD_ST_SHIFT                               18
-#define OMAP4430_VP_CORE_MAXVDD_ST_MASK                                        BITFIELD(18, 18)
+#define OMAP4430_VP_CORE_MAXVDD_ST_MASK                                        (1 << 18)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_MINVDD_EN_SHIFT                               17
-#define OMAP4430_VP_CORE_MINVDD_EN_MASK                                        BITFIELD(17, 17)
+#define OMAP4430_VP_CORE_MINVDD_EN_MASK                                        (1 << 17)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_MINVDD_ST_SHIFT                               17
-#define OMAP4430_VP_CORE_MINVDD_ST_MASK                                        BITFIELD(17, 17)
+#define OMAP4430_VP_CORE_MINVDD_ST_MASK                                        (1 << 17)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_NOSMPSACK_EN_SHIFT                            19
-#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK                             BITFIELD(19, 19)
+#define OMAP4430_VP_CORE_NOSMPSACK_EN_MASK                             (1 << 19)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_NOSMPSACK_ST_SHIFT                            19
-#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK                             BITFIELD(19, 19)
+#define OMAP4430_VP_CORE_NOSMPSACK_ST_MASK                             (1 << 19)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_SHIFT                                16
-#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK                         BITFIELD(16, 16)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_EN_MASK                         (1 << 16)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_SHIFT                                16
-#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK                         BITFIELD(16, 16)
+#define OMAP4430_VP_CORE_OPPCHANGEDONE_ST_MASK                         (1 << 16)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_CORE_TRANXDONE_EN_SHIFT                            21
-#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK                             BITFIELD(21, 21)
+#define OMAP4430_VP_CORE_TRANXDONE_EN_MASK                             (1 << 21)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_CORE_TRANXDONE_ST_SHIFT                            21
-#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK                             BITFIELD(21, 21)
+#define OMAP4430_VP_CORE_TRANXDONE_ST_MASK                             (1 << 21)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_EQVALUE_EN_SHIFT                               28
-#define OMAP4430_VP_IVA_EQVALUE_EN_MASK                                        BITFIELD(28, 28)
+#define OMAP4430_VP_IVA_EQVALUE_EN_MASK                                        (1 << 28)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_EQVALUE_ST_SHIFT                               28
-#define OMAP4430_VP_IVA_EQVALUE_ST_MASK                                        BITFIELD(28, 28)
+#define OMAP4430_VP_IVA_EQVALUE_ST_MASK                                        (1 << 28)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_MAXVDD_EN_SHIFT                                        26
-#define OMAP4430_VP_IVA_MAXVDD_EN_MASK                                 BITFIELD(26, 26)
+#define OMAP4430_VP_IVA_MAXVDD_EN_MASK                                 (1 << 26)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_MAXVDD_ST_SHIFT                                        26
-#define OMAP4430_VP_IVA_MAXVDD_ST_MASK                                 BITFIELD(26, 26)
+#define OMAP4430_VP_IVA_MAXVDD_ST_MASK                                 (1 << 26)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_MINVDD_EN_SHIFT                                        25
-#define OMAP4430_VP_IVA_MINVDD_EN_MASK                                 BITFIELD(25, 25)
+#define OMAP4430_VP_IVA_MINVDD_EN_MASK                                 (1 << 25)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_MINVDD_ST_SHIFT                                        25
-#define OMAP4430_VP_IVA_MINVDD_ST_MASK                                 BITFIELD(25, 25)
+#define OMAP4430_VP_IVA_MINVDD_ST_MASK                                 (1 << 25)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_NOSMPSACK_EN_SHIFT                             27
-#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK                              BITFIELD(27, 27)
+#define OMAP4430_VP_IVA_NOSMPSACK_EN_MASK                              (1 << 27)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_NOSMPSACK_ST_SHIFT                             27
-#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK                              BITFIELD(27, 27)
+#define OMAP4430_VP_IVA_NOSMPSACK_ST_MASK                              (1 << 27)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_SHIFT                         24
-#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK                          BITFIELD(24, 24)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_EN_MASK                          (1 << 24)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_SHIFT                         24
-#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK                          BITFIELD(24, 24)
+#define OMAP4430_VP_IVA_OPPCHANGEDONE_ST_MASK                          (1 << 24)
 
 /* Used by PRM_IRQENABLE_DUCATI, PRM_IRQENABLE_MPU */
 #define OMAP4430_VP_IVA_TRANXDONE_EN_SHIFT                             29
-#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK                              BITFIELD(29, 29)
+#define OMAP4430_VP_IVA_TRANXDONE_EN_MASK                              (1 << 29)
 
 /* Used by PRM_IRQSTATUS_DUCATI, PRM_IRQSTATUS_MPU */
 #define OMAP4430_VP_IVA_TRANXDONE_ST_SHIFT                             29
-#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK                              BITFIELD(29, 29)
+#define OMAP4430_VP_IVA_TRANXDONE_ST_MASK                              (1 << 29)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_EQVALUE_EN_SHIFT                               4
-#define OMAP4430_VP_MPU_EQVALUE_EN_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_VP_MPU_EQVALUE_EN_MASK                                        (1 << 4)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_EQVALUE_ST_SHIFT                               4
-#define OMAP4430_VP_MPU_EQVALUE_ST_MASK                                        BITFIELD(4, 4)
+#define OMAP4430_VP_MPU_EQVALUE_ST_MASK                                        (1 << 4)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_MAXVDD_EN_SHIFT                                        2
-#define OMAP4430_VP_MPU_MAXVDD_EN_MASK                                 BITFIELD(2, 2)
+#define OMAP4430_VP_MPU_MAXVDD_EN_MASK                                 (1 << 2)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_MAXVDD_ST_SHIFT                                        2
-#define OMAP4430_VP_MPU_MAXVDD_ST_MASK                                 BITFIELD(2, 2)
+#define OMAP4430_VP_MPU_MAXVDD_ST_MASK                                 (1 << 2)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_MINVDD_EN_SHIFT                                        1
-#define OMAP4430_VP_MPU_MINVDD_EN_MASK                                 BITFIELD(1, 1)
+#define OMAP4430_VP_MPU_MINVDD_EN_MASK                                 (1 << 1)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_MINVDD_ST_SHIFT                                        1
-#define OMAP4430_VP_MPU_MINVDD_ST_MASK                                 BITFIELD(1, 1)
+#define OMAP4430_VP_MPU_MINVDD_ST_MASK                                 (1 << 1)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_NOSMPSACK_EN_SHIFT                             3
-#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK                              BITFIELD(3, 3)
+#define OMAP4430_VP_MPU_NOSMPSACK_EN_MASK                              (1 << 3)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_NOSMPSACK_ST_SHIFT                             3
-#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK                              BITFIELD(3, 3)
+#define OMAP4430_VP_MPU_NOSMPSACK_ST_MASK                              (1 << 3)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_SHIFT                         0
-#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK                          BITFIELD(0, 0)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_EN_MASK                          (1 << 0)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_SHIFT                         0
-#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK                          BITFIELD(0, 0)
+#define OMAP4430_VP_MPU_OPPCHANGEDONE_ST_MASK                          (1 << 0)
 
 /* Used by PRM_IRQENABLE_MPU_2 */
 #define OMAP4430_VP_MPU_TRANXDONE_EN_SHIFT                             5
-#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK                              BITFIELD(5, 5)
+#define OMAP4430_VP_MPU_TRANXDONE_EN_MASK                              (1 << 5)
 
 /* Used by PRM_IRQSTATUS_MPU_2 */
 #define OMAP4430_VP_MPU_TRANXDONE_ST_SHIFT                             5
-#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK                              BITFIELD(5, 5)
+#define OMAP4430_VP_MPU_TRANXDONE_ST_MASK                              (1 << 5)
 
 /* Used by PRM_SRAM_COUNT */
 #define OMAP4430_VSETUPCNT_VALUE_SHIFT                                 8
-#define OMAP4430_VSETUPCNT_VALUE_MASK                                  BITFIELD(8, 15)
+#define OMAP4430_VSETUPCNT_VALUE_MASK                                  (0xff << 8)
 
 /* Used by PRM_VP_CORE_VSTEPMAX, PRM_VP_IVA_VSTEPMAX, PRM_VP_MPU_VSTEPMAX */
 #define OMAP4430_VSTEPMAX_SHIFT                                                0
-#define OMAP4430_VSTEPMAX_MASK                                         BITFIELD(0, 7)
+#define OMAP4430_VSTEPMAX_MASK                                         (0xff << 0)
 
 /* Used by PRM_VP_CORE_VSTEPMIN, PRM_VP_IVA_VSTEPMIN, PRM_VP_MPU_VSTEPMIN */
 #define OMAP4430_VSTEPMIN_SHIFT                                                0
-#define OMAP4430_VSTEPMIN_MASK                                         BITFIELD(0, 7)
+#define OMAP4430_VSTEPMIN_MASK                                         (0xff << 0)
 
 /* Used by PRM_MODEM_IF_CTRL */
 #define OMAP4430_WAKE_MODEM_SHIFT                                      0
-#define OMAP4430_WAKE_MODEM_MASK                                       BITFIELD(0, 0)
+#define OMAP4430_WAKE_MODEM_MASK                                       (1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_DUCATI_SHIFT                            1
-#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK                             BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DISPC_DUCATI_MASK                             (1 << 1)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_DISPC_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DISPC_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_DISPC_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DISPC_TESLA_SHIFT                             2
-#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK                              BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DISPC_TESLA_MASK                              (1 << 2)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DMIC_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_SHIFT                          6
-#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK                           BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DMIC_DMA_TESLA_MASK                           (1 << 6)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_ABE_DMIC_WKDEP */
 #define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_SHIFT                          2
-#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK                           BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_DMIC_IRQ_TESLA_MASK                           (1 << 2)
 
 /* Used by PM_L4PER_DMTIMER10_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER10_MPU_SHIFT                           0
-#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK                            BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER10_MPU_MASK                            (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER11_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_SHIFT                                1
-#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK                         BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER11_DUCATI_MASK                         (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER11_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER11_MPU_SHIFT                           0
-#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK                            BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER11_MPU_MASK                            (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER2_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER2_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER2_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER3_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER3_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER3_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER3_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER3_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER4_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER4_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER4_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER4_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER4_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_DMTIMER9_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_DMTIMER9_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_DMTIMER9_WKDEP */
 #define OMAP4430_WKUPDEP_DMTIMER9_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_DMTIMER9_MPU_MASK                             (1 << 0)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_DUCATI_SHIFT                             5
-#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK                              BITFIELD(5, 5)
+#define OMAP4430_WKUPDEP_DSI1_DUCATI_MASK                              (1 << 5)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_MPU_SHIFT                                        4
-#define OMAP4430_WKUPDEP_DSI1_MPU_MASK                                 BITFIELD(4, 4)
+#define OMAP4430_WKUPDEP_DSI1_MPU_MASK                                 (1 << 4)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_SDMA_SHIFT                               7
-#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK                                        BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_DSI1_SDMA_MASK                                        (1 << 7)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI1_TESLA_SHIFT                              6
-#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK                               BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_DSI1_TESLA_MASK                               (1 << 6)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_DUCATI_SHIFT                             9
-#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK                              BITFIELD(9, 9)
+#define OMAP4430_WKUPDEP_DSI2_DUCATI_MASK                              (1 << 9)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_MPU_SHIFT                                        8
-#define OMAP4430_WKUPDEP_DSI2_MPU_MASK                                 BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_DSI2_MPU_MASK                                 (1 << 8)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_SDMA_SHIFT                               11
-#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK                                        BITFIELD(11, 11)
+#define OMAP4430_WKUPDEP_DSI2_SDMA_MASK                                        (1 << 11)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_DSI2_TESLA_SHIFT                              10
-#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK                               BITFIELD(10, 10)
+#define OMAP4430_WKUPDEP_DSI2_TESLA_MASK                               (1 << 10)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_SHIFT                       1
-#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK                                BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_DUCATI_MASK                                (1 << 1)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_WKUP_GPIO1_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO1_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_SHIFT                       1
-#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK                                BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_DUCATI_MASK                                (1 << 1)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO2_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO2_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO3_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO3_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO3_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO4_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO4_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO4_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO5_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO5_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO5_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_GPIO6_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ1_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_GPIO6_WKDEP */
 #define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_GPIO6_IRQ2_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIDMA_SDMA_SHIFT                            19
-#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK                             BITFIELD(19, 19)
+#define OMAP4430_WKUPDEP_HDMIDMA_SDMA_MASK                             (1 << 19)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_SHIFT                          13
-#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK                           BITFIELD(13, 13)
+#define OMAP4430_WKUPDEP_HDMIIRQ_DUCATI_MASK                           (1 << 13)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_MPU_SHIFT                             12
-#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK                              BITFIELD(12, 12)
+#define OMAP4430_WKUPDEP_HDMIIRQ_MPU_MASK                              (1 << 12)
 
 /* Used by PM_DSS_DSS_WKDEP */
 #define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_SHIFT                           14
-#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK                            BITFIELD(14, 14)
+#define OMAP4430_WKUPDEP_HDMIIRQ_TESLA_MASK                            (1 << 14)
 
 /* Used by PM_L4PER_HECC1_WKDEP */
 #define OMAP4430_WKUPDEP_HECC1_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_HECC1_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HECC1_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_HECC2_WKDEP */
 #define OMAP4430_WKUPDEP_HECC2_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_HECC2_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HECC2_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_DSP_TESLA_SHIFT                           6
-#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK                            BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_HSI_DSP_TESLA_MASK                            (1 << 6)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_HSI_MCU_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_HSI_MCU_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_HSI_MCU_MPU_MASK                              (1 << 0)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C1_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C1_WKDEP */
 #define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C1_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C2_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C2_WKDEP */
 #define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C2_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C3_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C3_WKDEP */
 #define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C3_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C4_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L4PER_I2C4_WKDEP */
 #define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C4_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L4PER_I2C5_WKDEP */
 #define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_SHIFT                           7
-#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_MASK                            BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_I2C5_DMA_SDMA_MASK                            (1 << 7)
 
 /* Used by PM_L4PER_I2C5_WKDEP */
 #define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_I2C5_IRQ_MPU_MASK                             (1 << 0)
 
 /* Used by PM_WKUP_KEYBOARD_WKDEP */
 #define OMAP4430_WKUPDEP_KEYBOARD_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_KEYBOARD_MPU_MASK                             (1 << 0)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_SHIFT                         7
-#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK                          BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_SDMA_MASK                          (1 << 7)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP1_DMA_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_MPU_MASK                           (1 << 0)
 
 /* Used by PM_ABE_MCASP_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_SHIFT                                2
-#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK                         BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP1_IRQ_TESLA_MASK                         (1 << 2)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_SHIFT                         7
-#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK                          BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_SDMA_MASK                          (1 << 7)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP2_DMA_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_MCASP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_SHIFT                                2
-#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK                         BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP2_IRQ_TESLA_MASK                         (1 << 2)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_SHIFT                         7
-#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK                          BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_SDMA_MASK                          (1 << 7)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_SHIFT                                6
-#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK                         BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_MCASP3_DMA_TESLA_MASK                         (1 << 6)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_SHIFT                          0
-#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK                           BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_MPU_MASK                           (1 << 0)
 
 /* Used by PM_L4PER_MCASP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_SHIFT                                2
-#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK                         BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCASP3_IRQ_TESLA_MASK                         (1 << 2)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP1_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP1_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_ABE_MCBSP1_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP1_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP1_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP2_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP2_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_ABE_MCBSP2_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP2_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP2_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP3_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP3_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_ABE_MCBSP3_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP3_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP3_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCBSP4_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCBSP4_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCBSP4_WKDEP */
 #define OMAP4430_WKUPDEP_MCBSP4_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCBSP4_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI1_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI1_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI1_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCSPI1_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI1_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MCSPI1_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MCSPI2_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI2_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI2_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI2_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI2_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCSPI3_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI3_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI3_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI3_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI3_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI3_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MCSPI4_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI4_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MCSPI4_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MCSPI4_WKDEP */
 #define OMAP4430_WKUPDEP_MCSPI4_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MCSPI4_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC1_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_MMC1_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC1_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_SDMA_SHIFT                               3
-#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC1_SDMA_MASK                                        (1 << 3)
 
 /* Used by PM_L3INIT_MMC1_WKDEP */
 #define OMAP4430_WKUPDEP_MMC1_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC1_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC2_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_MMC2_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC2_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_SDMA_SHIFT                               3
-#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMC2_SDMA_MASK                                        (1 << 3)
 
 /* Used by PM_L3INIT_MMC2_WKDEP */
 #define OMAP4430_WKUPDEP_MMC2_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC2_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMC6_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_MMC6_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMC6_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_MMC6_WKDEP */
 #define OMAP4430_WKUPDEP_MMC6_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_MMC6_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD3_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD3_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MMCSD3_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD3_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD3_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD4_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD4_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MMCSD4_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD4_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD4_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_MMCSD5_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_MMCSD5_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L4PER_MMCSD5_WKDEP */
 #define OMAP4430_WKUPDEP_MMCSD5_SDMA_SHIFT                             3
-#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK                              BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_MMCSD5_SDMA_MASK                              (1 << 3)
 
 /* Used by PM_L3INIT_PCIESS_WKDEP */
 #define OMAP4430_WKUPDEP_PCIESS_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_PCIESS_MPU_MASK                               (1 << 0)
 
 /* Used by PM_L3INIT_PCIESS_WKDEP */
 #define OMAP4430_WKUPDEP_PCIESS_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PCIESS_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_DMA_SDMA_SHIFT                            7
-#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK                             BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_PDM_DMA_SDMA_MASK                             (1 << 7)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_DMA_TESLA_SHIFT                           6
-#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK                            BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_PDM_DMA_TESLA_MASK                            (1 << 6)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_IRQ_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_PDM_IRQ_MPU_MASK                              (1 << 0)
 
 /* Used by PM_ABE_PDM_WKDEP */
 #define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_SHIFT                           2
-#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK                            BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_PDM_IRQ_TESLA_MASK                            (1 << 2)
 
 /* Used by PM_WKUP_RTC_WKDEP */
 #define OMAP4430_WKUPDEP_RTC_MPU_SHIFT                                 0
-#define OMAP4430_WKUPDEP_RTC_MPU_MASK                                  BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_RTC_MPU_MASK                                  (1 << 0)
 
 /* Used by PM_L3INIT_SATA_WKDEP */
 #define OMAP4430_WKUPDEP_SATA_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_SATA_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SATA_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_SATA_WKDEP */
 #define OMAP4430_WKUPDEP_SATA_TESLA_SHIFT                              2
-#define OMAP4430_WKUPDEP_SATA_TESLA_MASK                               BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SATA_TESLA_MASK                               (1 << 2)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_SHIFT                       7
-#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK                                BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_SDMA_MASK                                (1 << 7)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_SHIFT                      6
-#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK                       BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS1_DMA_TESLA_MASK                       (1 << 6)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_SHIFT                                0
-#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK                         BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_MPU_MASK                         (1 << 0)
 
 /* Used by PM_ABE_SLIMBUS_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_SHIFT                      2
-#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK                       BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS1_IRQ_TESLA_MASK                       (1 << 2)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_SHIFT                       7
-#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK                                BITFIELD(7, 7)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_SDMA_MASK                                (1 << 7)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_SHIFT                      6
-#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK                       BITFIELD(6, 6)
+#define OMAP4430_WKUPDEP_SLIMBUS2_DMA_TESLA_MASK                       (1 << 6)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_SHIFT                                0
-#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK                         BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_MPU_MASK                         (1 << 0)
 
 /* Used by PM_L4PER_SLIMBUS2_WKDEP */
 #define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_SHIFT                      2
-#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK                       BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_SLIMBUS2_IRQ_TESLA_MASK                       (1 << 2)
 
 /* Used by PM_ALWON_SR_CORE_WKDEP */
 #define OMAP4430_WKUPDEP_SR_CORE_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_CORE_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_ALWON_SR_CORE_WKDEP */
 #define OMAP4430_WKUPDEP_SR_CORE_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_CORE_MPU_MASK                              (1 << 0)
 
 /* Used by PM_ALWON_SR_IVA_WKDEP */
 #define OMAP4430_WKUPDEP_SR_IVA_DUCATI_SHIFT                           1
-#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK                            BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_SR_IVA_DUCATI_MASK                            (1 << 1)
 
 /* Used by PM_ALWON_SR_IVA_WKDEP */
 #define OMAP4430_WKUPDEP_SR_IVA_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_IVA_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ALWON_SR_MPU_WKDEP */
 #define OMAP4430_WKUPDEP_SR_MPU_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_SR_MPU_MPU_MASK                               (1 << 0)
 
 /* Used by PM_WKUP_TIMER12_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER12_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER12_MPU_MASK                              (1 << 0)
 
 /* Used by PM_WKUP_TIMER1_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER1_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER1_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER5_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER5_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER5_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER5_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER5_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER5_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_TIMER6_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER6_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER6_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER6_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER6_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER6_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_TIMER7_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER7_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER7_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER7_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER7_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER7_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_ABE_TIMER8_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER8_MPU_SHIFT                              0
-#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK                               BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_TIMER8_MPU_MASK                               (1 << 0)
 
 /* Used by PM_ABE_TIMER8_WKDEP */
 #define OMAP4430_WKUPDEP_TIMER8_TESLA_SHIFT                            2
-#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK                             BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_TIMER8_TESLA_MASK                             (1 << 2)
 
 /* Used by PM_L4PER_UART1_WKDEP */
 #define OMAP4430_WKUPDEP_UART1_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART1_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART1_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART1_WKDEP */
 #define OMAP4430_WKUPDEP_UART1_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART1_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART1_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L4PER_UART2_WKDEP */
 #define OMAP4430_WKUPDEP_UART2_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART2_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART2_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART2_WKDEP */
 #define OMAP4430_WKUPDEP_UART2_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART2_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART2_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_DUCATI_SHIFT                            1
-#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK                             BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UART3_DUCATI_MASK                             (1 << 1)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART3_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART3_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART3_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART3_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L4PER_UART3_WKDEP */
 #define OMAP4430_WKUPDEP_UART3_TESLA_SHIFT                             2
-#define OMAP4430_WKUPDEP_UART3_TESLA_MASK                              BITFIELD(2, 2)
+#define OMAP4430_WKUPDEP_UART3_TESLA_MASK                              (1 << 2)
 
 /* Used by PM_L4PER_UART4_WKDEP */
 #define OMAP4430_WKUPDEP_UART4_MPU_SHIFT                               0
-#define OMAP4430_WKUPDEP_UART4_MPU_MASK                                        BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UART4_MPU_MASK                                        (1 << 0)
 
 /* Used by PM_L4PER_UART4_WKDEP */
 #define OMAP4430_WKUPDEP_UART4_SDMA_SHIFT                              3
-#define OMAP4430_WKUPDEP_UART4_SDMA_MASK                               BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_UART4_SDMA_MASK                               (1 << 3)
 
 /* Used by PM_L3INIT_UNIPRO1_WKDEP */
 #define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_UNIPRO1_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_UNIPRO1_WKDEP */
 #define OMAP4430_WKUPDEP_UNIPRO1_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_UNIPRO1_MPU_MASK                              (1 << 0)
 
 /* Used by PM_L3INIT_USB_HOST_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_DUCATI_SHIFT                         1
-#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK                          BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_DUCATI_MASK                          (1 << 1)
 
 /* Used by PM_L3INIT_USB_HOST_FS_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_SHIFT                      1
-#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK                       BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_DUCATI_MASK                       (1 << 1)
 
 /* Used by PM_L3INIT_USB_HOST_FS_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_SHIFT                         0
-#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK                          BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_HOST_FS_MPU_MASK                          (1 << 0)
 
 /* Used by PM_L3INIT_USB_HOST_WKDEP */
 #define OMAP4430_WKUPDEP_USB_HOST_MPU_SHIFT                            0
-#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK                             BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_HOST_MPU_MASK                             (1 << 0)
 
 /* Used by PM_L3INIT_USB_OTG_WKDEP */
 #define OMAP4430_WKUPDEP_USB_OTG_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_OTG_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_USB_OTG_WKDEP */
 #define OMAP4430_WKUPDEP_USB_OTG_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_OTG_MPU_MASK                              (1 << 0)
 
 /* Used by PM_L3INIT_USB_TLL_WKDEP */
 #define OMAP4430_WKUPDEP_USB_TLL_DUCATI_SHIFT                          1
-#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK                           BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_USB_TLL_DUCATI_MASK                           (1 << 1)
 
 /* Used by PM_L3INIT_USB_TLL_WKDEP */
 #define OMAP4430_WKUPDEP_USB_TLL_MPU_SHIFT                             0
-#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK                              BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USB_TLL_MPU_MASK                              (1 << 0)
 
 /* Used by PM_WKUP_USIM_WKDEP */
 #define OMAP4430_WKUPDEP_USIM_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_USIM_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_USIM_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_WKUP_USIM_WKDEP */
 #define OMAP4430_WKUPDEP_USIM_SDMA_SHIFT                               3
-#define OMAP4430_WKUPDEP_USIM_SDMA_MASK                                        BITFIELD(3, 3)
+#define OMAP4430_WKUPDEP_USIM_SDMA_MASK                                        (1 << 3)
 
 /* Used by PM_WKUP_WDT2_WKDEP */
 #define OMAP4430_WKUPDEP_WDT2_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_WDT2_DUCATI_MASK                              (1 << 1)
 
 /* Used by PM_WKUP_WDT2_WKDEP */
 #define OMAP4430_WKUPDEP_WDT2_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_WDT2_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_WDT2_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_ABE_WDT3_WKDEP */
 #define OMAP4430_WKUPDEP_WDT3_MPU_SHIFT                                        0
-#define OMAP4430_WKUPDEP_WDT3_MPU_MASK                                 BITFIELD(0, 0)
+#define OMAP4430_WKUPDEP_WDT3_MPU_MASK                                 (1 << 0)
 
 /* Used by PM_L3INIT_HSI_WKDEP */
 #define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_SHIFT                                8
-#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK                         BITFIELD(8, 8)
+#define OMAP4430_WKUPDEP_WGM_HSI_WAKE_MPU_MASK                         (1 << 8)
 
 /* Used by PM_L3INIT_XHPI_WKDEP */
 #define OMAP4430_WKUPDEP_XHPI_DUCATI_SHIFT                             1
-#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK                              BITFIELD(1, 1)
+#define OMAP4430_WKUPDEP_XHPI_DUCATI_MASK                              (1 << 1)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_WUCLK_CTRL_SHIFT                                      8
-#define OMAP4430_WUCLK_CTRL_MASK                                       BITFIELD(8, 8)
+#define OMAP4430_WUCLK_CTRL_MASK                                       (1 << 8)
 
 /* Used by PRM_IO_PMCTRL */
 #define OMAP4430_WUCLK_STATUS_SHIFT                                    9
-#define OMAP4430_WUCLK_STATUS_MASK                                     BITFIELD(9, 9)
+#define OMAP4430_WUCLK_STATUS_MASK                                     (1 << 9)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_X_MAJOR_SHIFT                                         8
+#define OMAP4430_X_MAJOR_MASK                                          (0x7 << 8)
+
+/* Used by REVISION_PRM */
+#define OMAP4430_Y_MINOR_SHIFT                                         0
+#define OMAP4430_Y_MINOR_MASK                                          (0x3f << 0)
 #endif
index 588873b..7be040b 100644 (file)
@@ -5,7 +5,7 @@
  * OMAP2/3 Power/Reset Management (PRM) register definitions
  *
  * Copyright (C) 2007-2009 Texas Instruments, Inc.
- * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2010 Nokia Corporation
  *
  * Written by Paul Walmsley
  *
@@ -246,6 +246,15 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
        return prm_rmw_mod_reg_bits(bits, 0x0, module, idx);
 }
 
+/* These omap2_ PRM functions apply to both OMAP2 and 3 */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
+
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift);
+
 #endif
 
 /*
@@ -398,4 +407,11 @@ static inline u32 prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
 #define OMAP_POWERSTATE_MASK                           (0x3 << 0)
 
 
+/*
+ * MAX_MODULE_HARDRESET_WAIT: Maximum microseconds to wait for an OMAP
+ * submodule to exit hardreset
+ */
+#define MAX_MODULE_HARDRESET_WAIT              10000
+
+
 #endif
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
new file mode 100644 (file)
index 0000000..421771e
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * OMAP2/3 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-24xx.h"
+#include "prm-regbits-34xx.h"
+
+/**
+ * omap2_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL if called while running on a non-OMAP2/3 chip.
+ */
+int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
+{
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       return prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL,
+                                      (1 << shift));
+}
+
+/**
+ * omap2_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
+{
+       u32 mask;
+
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       mask = 1 << shift;
+       prm_rmw_mod_reg_bits(mask, mask, prm_mod, OMAP2_RM_RSTCTRL);
+
+       return 0;
+}
+
+/**
+ * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @prm_mod: PRM submodule base (e.g. CORE_MOD)
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+{
+       u32 mask;
+       int c;
+
+       if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
+               return -EINVAL;
+
+       mask = 1 << shift;
+
+       /* Check the current status to avoid de-asserting the line twice */
+       if (prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
+       /* de-assert the reset control line */
+       prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
+       /* wait the status to be set */
+       omap_test_timeout(prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
+                                                 mask),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
new file mode 100644 (file)
index 0000000..a1ff918
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * OMAP4 PRM module functions
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Copyright (C) 2010 Nokia Corporation
+ * Benoît Cousson
+ * Paul Walmsley
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+#include <plat/prcm.h>
+
+#include "prm.h"
+#include "prm-regbits-44xx.h"
+
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET               4
+
+/**
+ * omap4_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to check
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int omap4_prm_is_hardreset_asserted(void __iomem *rstctrl_reg, u8 shift)
+{
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       return omap4_prm_read_bits_shift(rstctrl_reg, (1 << shift));
+}
+
+/**
+ * omap4_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to assert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int omap4_prm_assert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+       u32 mask;
+
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       mask = 1 << shift;
+       omap4_prm_rmw_reg_bits(mask, mask, rstctrl_reg);
+
+       return 0;
+}
+
+/**
+ * omap4_prm_deassert_hardreset - deassert a submodule hardreset line and wait
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @shift: register bit shift corresponding to the reset line to deassert
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int omap4_prm_deassert_hardreset(void __iomem *rstctrl_reg, u8 shift)
+{
+       u32 mask;
+       void __iomem *rstst_reg;
+       int c;
+
+       if (!cpu_is_omap44xx() || !rstctrl_reg)
+               return -EINVAL;
+
+       rstst_reg = rstctrl_reg + OMAP4_RST_CTRL_ST_OFFSET;
+
+       mask = 1 << shift;
+
+       /* Check the current status to avoid de-asserting the line twice */
+       if (omap4_prm_read_bits_shift(rstctrl_reg, mask) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       omap4_prm_rmw_reg_bits(0xffffffff, mask, rstst_reg);
+       /* de-assert the reset control line */
+       omap4_prm_rmw_reg_bits(mask, 0, rstctrl_reg);
+       /* wait the status to be set */
+       omap_test_timeout(omap4_prm_read_bits_shift(rstst_reg, mask),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
+
index fe8ef26..59839db 100644 (file)
 #define OMAP4430_PRM_IRQSTATUS_TESLA                   OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0030)
 #define OMAP4_PRM_IRQENABLE_TESLA_OFFSET               0x0038
 #define OMAP4430_PRM_IRQENABLE_TESLA                   OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0038)
-#define OMAP4_PRM_PRM_PROFILING_CLKCTRL_OFFSET         0x0040
-#define OMAP4430_PRM_PRM_PROFILING_CLKCTRL             OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040)
+#define OMAP4_CM_PRM_PROFILING_CLKCTRL_OFFSET          0x0040
+#define OMAP4430_CM_PRM_PROFILING_CLKCTRL              OMAP44XX_PRM_REGADDR(OMAP4430_PRM_OCP_SOCKET_MOD, 0x0040)
 
 /* PRM.CKGEN_PRM register offsets */
 #define OMAP4_CM_ABE_DSS_SYS_CLKSEL_OFFSET             0x0000
 #define OMAP4430_CM_ABE_DSS_SYS_CLKSEL                 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0000)
-#define OMAP4_CM_DPLL_SYS_REF_CLKSEL_OFFSET            0x0004
-#define OMAP4430_CM_DPLL_SYS_REF_CLKSEL                        OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0004)
 #define OMAP4_CM_L4_WKUP_CLKSEL_OFFSET                 0x0008
 #define OMAP4430_CM_L4_WKUP_CLKSEL                     OMAP44XX_PRM_REGADDR(OMAP4430_PRM_CKGEN_MOD, 0x0008)
 #define OMAP4_CM_ABE_PLL_REF_CLKSEL_OFFSET             0x000c
 #define OMAP4430_PRM_LDO_ABB_IVA_SETUP                 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00d8)
 #define OMAP4_PRM_LDO_ABB_IVA_CTRL_OFFSET              0x00dc
 #define OMAP4430_PRM_LDO_ABB_IVA_CTRL                  OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00dc)
-#define OMAP4_PRM_LDO_BANDGAP_CTRL_OFFSET              0x00e0
-#define OMAP4430_PRM_LDO_BANDGAP_CTRL                  OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0)
+#define OMAP4_PRM_LDO_BANDGAP_SETUP_OFFSET             0x00e0
+#define OMAP4430_PRM_LDO_BANDGAP_SETUP                 OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e0)
 #define OMAP4_PRM_DEVICE_OFF_CTRL_OFFSET               0x00e4
 #define OMAP4430_PRM_DEVICE_OFF_CTRL                   OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00e4)
 #define OMAP4_PRM_PHASE1_CNDP_OFFSET                   0x00e8
 #define OMAP4430_PRM_PHASE2B_CNDP                      OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f0)
 #define OMAP4_PRM_MODEM_IF_CTRL_OFFSET                 0x00f4
 #define OMAP4430_PRM_MODEM_IF_CTRL                     OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f4)
+#define OMAP4_PRM_VC_ERRST_OFFSET                      0x00f8
+#define OMAP4430_PRM_VC_ERRST                          OMAP44XX_PRM_REGADDR(OMAP4430_PRM_DEVICE_MOD, 0x00f8)
 
 /*
  * PRCM_MPU
 /* PRCM_MPU.DEVICE_PRM register offsets */
 #define OMAP4_PRCM_MPU_PRM_RSTST_OFFSET                        0x0000
 #define OMAP4430_PRCM_MPU_PRM_RSTST                    OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0000)
+#define OMAP4_PRCM_MPU_PRM_PSCON_COUNT_OFFSET          0x0004
+#define OMAP4430_PRCM_MPU_PRM_PSCON_COUNT              OMAP44XX_PRCM_MPU_REGADDR(OMAP4430_PRCM_MPU_DEVICE_PRM_MOD, 0x0004)
 
 /* PRCM_MPU.CPU0 register offsets */
 #define OMAP4_PM_CPU0_PWRSTCTRL_OFFSET                 0x0000
index 566e991..becf0e3 100644 (file)
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/serial_8250.h>
+#include <linux/pm_runtime.h>
+
+#ifdef CONFIG_SERIAL_OMAP
+#include <plat/omap-serial.h>
+#endif
 
 #include <plat/common.h>
 #include <plat/board.h>
 #include <plat/clock.h>
-#include <plat/control.h>
+#include <plat/dma.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 
 #include "prm.h"
 #include "pm.h"
+#include "cm.h"
 #include "prm-regbits-34xx.h"
+#include "control.h"
 
 #define UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV    0x52
 #define UART_OMAP_WER          0x17    /* Wake-up enable register */
@@ -48,6 +59,8 @@
  */
 #define DEFAULT_TIMEOUT 0
 
+#define MAX_UART_HWMOD_NAME_LEN                16
+
 struct omap_uart_state {
        int num;
        int can_sleep;
@@ -58,14 +71,21 @@ struct omap_uart_state {
        void __iomem *wk_en;
        u32 wk_mask;
        u32 padconf;
+       u32 dma_enabled;
 
        struct clk *ick;
        struct clk *fck;
        int clocked;
 
-       struct plat_serial8250_port *p;
+       int irq;
+       int regshift;
+       int irqflags;
+       void __iomem *membase;
+       resource_size_t mapbase;
+
        struct list_head node;
-       struct platform_device pdev;
+       struct omap_hwmod *oh;
+       struct platform_device *pdev;
 
        u32 errata;
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
@@ -83,75 +103,47 @@ struct omap_uart_state {
 };
 
 static LIST_HEAD(uart_list);
+static u8 num_uarts;
 
-static struct plat_serial8250_port serial_platform_data0[] = {
-       {
-               .irq            = 72,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
-};
+/*
+ * Since these idle/enable hooks are used in the idle path itself
+ * which has interrupts disabled, use the non-locking versions of
+ * the hwmod enable/disable functions.
+ */
+static int uart_idle_hwmod(struct omap_device *od)
+{
+       _omap_hwmod_idle(od->hwmods[0]);
 
-static struct plat_serial8250_port serial_platform_data1[] = {
-       {
-               .irq            = 73,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
-};
+       return 0;
+}
 
-static struct plat_serial8250_port serial_platform_data2[] = {
-       {
-               .irq            = 74,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
-};
+static int uart_enable_hwmod(struct omap_device *od)
+{
+       _omap_hwmod_enable(od->hwmods[0]);
 
-static struct plat_serial8250_port serial_platform_data3[] = {
+       return 0;
+}
+
+static struct omap_device_pm_latency omap_uart_latency[] = {
        {
-               .irq            = 70,
-               .flags          = UPF_BOOT_AUTOCONF,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = OMAP24XX_BASE_BAUD * 16,
-       }, {
-               .flags          = 0
-       }
+               .deactivate_func = uart_idle_hwmod,
+               .activate_func   = uart_enable_hwmod,
+               .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+       },
 };
 
-void __init omap2_set_globals_uart(struct omap_globals *omap2_globals)
-{
-       serial_platform_data0[0].mapbase = omap2_globals->uart1_phys;
-       serial_platform_data1[0].mapbase = omap2_globals->uart2_phys;
-       serial_platform_data2[0].mapbase = omap2_globals->uart3_phys;
-       serial_platform_data3[0].mapbase = omap2_globals->uart4_phys;
-}
-
 static inline unsigned int __serial_read_reg(struct uart_port *up,
-                                          int offset)
+                                            int offset)
 {
        offset <<= up->regshift;
        return (unsigned int)__raw_readb(up->membase + offset);
 }
 
-static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
+static inline unsigned int serial_read_reg(struct omap_uart_state *uart,
                                           int offset)
 {
-       offset <<= up->regshift;
-       return (unsigned int)__raw_readb(up->membase + offset);
+       offset <<= uart->regshift;
+       return (unsigned int)__raw_readb(uart->membase + offset);
 }
 
 static inline void __serial_write_reg(struct uart_port *up, int offset,
@@ -161,11 +153,11 @@ static inline void __serial_write_reg(struct uart_port *up, int offset,
        __raw_writeb(value, up->membase + offset);
 }
 
-static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
+static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
                                    int value)
 {
-       offset <<= p->regshift;
-       __raw_writeb(value, p->membase + offset);
+       offset <<= uart->regshift;
+       __raw_writeb(value, uart->membase + offset);
 }
 
 /*
@@ -173,14 +165,12 @@ static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
  * properly. Note that the TX watermark initialization may not be needed
  * once the 8250.c watermark handling code is merged.
  */
+
 static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 {
-       struct plat_serial8250_port *p = uart->p;
-
-       serial_write_reg(p, UART_OMAP_MDR1, 0x07);
-       serial_write_reg(p, UART_OMAP_SCR, 0x08);
-       serial_write_reg(p, UART_OMAP_MDR1, 0x00);
-       serial_write_reg(p, UART_OMAP_SYSC, (0x02 << 3) | (1 << 2) | (1 << 0));
+       serial_write_reg(uart, UART_OMAP_MDR1, 0x07);
+       serial_write_reg(uart, UART_OMAP_SCR, 0x08);
+       serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
 }
 
 #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
@@ -197,24 +187,23 @@ static inline void __init omap_uart_reset(struct omap_uart_state *uart)
 static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
                u8 fcr_val)
 {
-       struct plat_serial8250_port *p = uart->p;
        u8 timeout = 255;
 
-       serial_write_reg(p, UART_OMAP_MDR1, mdr1_val);
+       serial_write_reg(uart, UART_OMAP_MDR1, mdr1_val);
        udelay(2);
-       serial_write_reg(p, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
+       serial_write_reg(uart, UART_FCR, fcr_val | UART_FCR_CLEAR_XMIT |
                        UART_FCR_CLEAR_RCVR);
        /*
         * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and
         * TX_FIFO_E bit is 1.
         */
-       while (UART_LSR_THRE != (serial_read_reg(p, UART_LSR) &
+       while (UART_LSR_THRE != (serial_read_reg(uart, UART_LSR) &
                                (UART_LSR_THRE | UART_LSR_DR))) {
                timeout--;
                if (!timeout) {
                        /* Should *never* happen. we warn and carry on */
-                       dev_crit(&uart->pdev.dev, "Errata i202: timedout %x\n",
-                               serial_read_reg(p, UART_LSR));
+                       dev_crit(&uart->pdev->dev, "Errata i202: timedout %x\n",
+                       serial_read_reg(uart, UART_LSR));
                        break;
                }
                udelay(1);
@@ -224,23 +213,22 @@ static void omap_uart_mdr1_errataset(struct omap_uart_state *uart, u8 mdr1_val,
 static void omap_uart_save_context(struct omap_uart_state *uart)
 {
        u16 lcr = 0;
-       struct plat_serial8250_port *p = uart->p;
 
        if (!enable_off_mode)
                return;
 
-       lcr = serial_read_reg(p, UART_LCR);
-       serial_write_reg(p, UART_LCR, 0xBF);
-       uart->dll = serial_read_reg(p, UART_DLL);
-       uart->dlh = serial_read_reg(p, UART_DLM);
-       serial_write_reg(p, UART_LCR, lcr);
-       uart->ier = serial_read_reg(p, UART_IER);
-       uart->sysc = serial_read_reg(p, UART_OMAP_SYSC);
-       uart->scr = serial_read_reg(p, UART_OMAP_SCR);
-       uart->wer = serial_read_reg(p, UART_OMAP_WER);
-       serial_write_reg(p, UART_LCR, 0x80);
-       uart->mcr = serial_read_reg(p, UART_MCR);
-       serial_write_reg(p, UART_LCR, lcr);
+       lcr = serial_read_reg(uart, UART_LCR);
+       serial_write_reg(uart, UART_LCR, 0xBF);
+       uart->dll = serial_read_reg(uart, UART_DLL);
+       uart->dlh = serial_read_reg(uart, UART_DLM);
+       serial_write_reg(uart, UART_LCR, lcr);
+       uart->ier = serial_read_reg(uart, UART_IER);
+       uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
+       uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
+       uart->wer = serial_read_reg(uart, UART_OMAP_WER);
+       serial_write_reg(uart, UART_LCR, 0x80);
+       uart->mcr = serial_read_reg(uart, UART_MCR);
+       serial_write_reg(uart, UART_LCR, lcr);
 
        uart->context_valid = 1;
 }
@@ -248,7 +236,6 @@ static void omap_uart_save_context(struct omap_uart_state *uart)
 static void omap_uart_restore_context(struct omap_uart_state *uart)
 {
        u16 efr = 0;
-       struct plat_serial8250_port *p = uart->p;
 
        if (!enable_off_mode)
                return;
@@ -261,29 +248,30 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
        if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
                omap_uart_mdr1_errataset(uart, 0x07, 0xA0);
        else
-               serial_write_reg(p, UART_OMAP_MDR1, 0x7);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       efr = serial_read_reg(p, UART_EFR);
-       serial_write_reg(p, UART_EFR, UART_EFR_ECB);
-       serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-       serial_write_reg(p, UART_IER, 0x0);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       serial_write_reg(p, UART_DLL, uart->dll);
-       serial_write_reg(p, UART_DLM, uart->dlh);
-       serial_write_reg(p, UART_LCR, 0x0); /* Operational mode */
-       serial_write_reg(p, UART_IER, uart->ier);
-       serial_write_reg(p, UART_LCR, 0x80);
-       serial_write_reg(p, UART_MCR, uart->mcr);
-       serial_write_reg(p, UART_LCR, 0xBF); /* Config B mode */
-       serial_write_reg(p, UART_EFR, efr);
-       serial_write_reg(p, UART_LCR, UART_LCR_WLEN8);
-       serial_write_reg(p, UART_OMAP_SCR, uart->scr);
-       serial_write_reg(p, UART_OMAP_WER, uart->wer);
-       serial_write_reg(p, UART_OMAP_SYSC, uart->sysc);
+               serial_write_reg(uart, UART_OMAP_MDR1, 0x7);
+       serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+       efr = serial_read_reg(uart, UART_EFR);
+       serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
+       serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
+       serial_write_reg(uart, UART_IER, 0x0);
+       serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+       serial_write_reg(uart, UART_DLL, uart->dll);
+       serial_write_reg(uart, UART_DLM, uart->dlh);
+       serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
+       serial_write_reg(uart, UART_IER, uart->ier);
+       serial_write_reg(uart, UART_LCR, 0x80);
+       serial_write_reg(uart, UART_MCR, uart->mcr);
+       serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
+       serial_write_reg(uart, UART_EFR, efr);
+       serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
+       serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
+       serial_write_reg(uart, UART_OMAP_WER, uart->wer);
+       serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
        if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
                omap_uart_mdr1_errataset(uart, 0x00, 0xA1);
        else
-               serial_write_reg(p, UART_OMAP_MDR1, 0x00); /* UART 16x mode */
+               /* UART 16x mode */
+               serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
 }
 #else
 static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
@@ -295,8 +283,7 @@ static inline void omap_uart_enable_clocks(struct omap_uart_state *uart)
        if (uart->clocked)
                return;
 
-       clk_enable(uart->ick);
-       clk_enable(uart->fck);
+       omap_device_enable(uart->pdev);
        uart->clocked = 1;
        omap_uart_restore_context(uart);
 }
@@ -310,8 +297,7 @@ static inline void omap_uart_disable_clocks(struct omap_uart_state *uart)
 
        omap_uart_save_context(uart);
        uart->clocked = 0;
-       clk_disable(uart->ick);
-       clk_disable(uart->fck);
+       omap_device_idle(uart->pdev);
 }
 
 static void omap_uart_enable_wakeup(struct omap_uart_state *uart)
@@ -349,18 +335,24 @@ static void omap_uart_disable_wakeup(struct omap_uart_state *uart)
 }
 
 static void omap_uart_smart_idle_enable(struct omap_uart_state *uart,
-                                         int enable)
+                                              int enable)
 {
-       struct plat_serial8250_port *p = uart->p;
-       u16 sysc;
+       u8 idlemode;
 
-       sysc = serial_read_reg(p, UART_OMAP_SYSC) & 0x7;
-       if (enable)
-               sysc |= 0x2 << 3;
-       else
-               sysc |= 0x1 << 3;
+       if (enable) {
+               /**
+                * Errata 2.15: [UART]:Cannot Acknowledge Idle Requests
+                * in Smartidle Mode When Configured for DMA Operations.
+                */
+               if (uart->dma_enabled)
+                       idlemode = HWMOD_IDLEMODE_FORCE;
+               else
+                       idlemode = HWMOD_IDLEMODE_SMART;
+       } else {
+               idlemode = HWMOD_IDLEMODE_NO;
+       }
 
-       serial_write_reg(p, UART_OMAP_SYSC, sysc);
+       omap_hwmod_set_slave_idlemode(uart->oh, idlemode);
 }
 
 static void omap_uart_block_sleep(struct omap_uart_state *uart)
@@ -377,7 +369,7 @@ static void omap_uart_block_sleep(struct omap_uart_state *uart)
 
 static void omap_uart_allow_sleep(struct omap_uart_state *uart)
 {
-       if (device_may_wakeup(&uart->pdev.dev))
+       if (device_may_wakeup(&uart->pdev->dev))
                omap_uart_enable_wakeup(uart);
        else
                omap_uart_disable_wakeup(uart);
@@ -472,6 +464,7 @@ int omap_uart_can_sleep(void)
  * UART will not idle or sleep for its timeout period.
  *
  **/
+/* static int first_interrupt; */
 static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 {
        struct omap_uart_state *uart = dev_id;
@@ -483,7 +476,6 @@ static irqreturn_t omap_uart_interrupt(int irq, void *dev_id)
 
 static void omap_uart_idle_init(struct omap_uart_state *uart)
 {
-       struct plat_serial8250_port *p = uart->p;
        int ret;
 
        uart->can_sleep = 0;
@@ -495,7 +487,7 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
        omap_uart_smart_idle_enable(uart, 0);
 
        if (cpu_is_omap34xx()) {
-               u32 mod = (uart->num == 2) ? OMAP3430_PER_MOD : CORE_MOD;
+               u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
                u32 wk_mask = 0;
                u32 padconf = 0;
 
@@ -514,19 +506,17 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                        wk_mask = OMAP3430_ST_UART3_MASK;
                        padconf = 0x19e;
                        break;
+               case 3:
+                       wk_mask = OMAP3630_ST_UART4_MASK;
+                       padconf = 0x0d2;
+                       break;
                }
                uart->wk_mask = wk_mask;
                uart->padconf = padconf;
        } else if (cpu_is_omap24xx()) {
                u32 wk_mask = 0;
+               u32 wk_en = PM_WKEN1, wk_st = PM_WKST1;
 
-               if (cpu_is_omap2430()) {
-                       uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKEN1);
-                       uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, PM_WKST1);
-               } else if (cpu_is_omap2420()) {
-                       uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKEN1);
-                       uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, PM_WKST1);
-               }
                switch (uart->num) {
                case 0:
                        wk_mask = OMAP24XX_ST_UART1_MASK;
@@ -535,10 +525,19 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                        wk_mask = OMAP24XX_ST_UART2_MASK;
                        break;
                case 2:
+                       wk_en = OMAP24XX_PM_WKEN2;
+                       wk_st = OMAP24XX_PM_WKST2;
                        wk_mask = OMAP24XX_ST_UART3_MASK;
                        break;
                }
                uart->wk_mask = wk_mask;
+               if (cpu_is_omap2430()) {
+                       uart->wk_en = OMAP2430_PRM_REGADDR(CORE_MOD, wk_en);
+                       uart->wk_st = OMAP2430_PRM_REGADDR(CORE_MOD, wk_st);
+               } else if (cpu_is_omap2420()) {
+                       uart->wk_en = OMAP2420_PRM_REGADDR(CORE_MOD, wk_en);
+                       uart->wk_st = OMAP2420_PRM_REGADDR(CORE_MOD, wk_st);
+               }
        } else {
                uart->wk_en = NULL;
                uart->wk_st = NULL;
@@ -546,9 +545,9 @@ static void omap_uart_idle_init(struct omap_uart_state *uart)
                uart->padconf = 0;
        }
 
-       p->irqflags |= IRQF_SHARED;
-       ret = request_irq(p->irq, omap_uart_interrupt, IRQF_SHARED,
-                         "serial idle", (void *)uart);
+       uart->irqflags |= IRQF_SHARED;
+       ret = request_threaded_irq(uart->irq, NULL, omap_uart_interrupt,
+                                  IRQF_SHARED, "serial idle", (void *)uart);
        WARN_ON(ret);
 }
 
@@ -558,11 +557,17 @@ void omap_uart_enable_irqs(int enable)
        struct omap_uart_state *uart;
 
        list_for_each_entry(uart, &uart_list, node) {
-               if (enable)
-                       ret = request_irq(uart->p->irq, omap_uart_interrupt,
-                               IRQF_SHARED, "serial idle", (void *)uart);
-               else
-                       free_irq(uart->p->irq, (void *)uart);
+               if (enable) {
+                       pm_runtime_put_sync(&uart->pdev->dev);
+                       ret = request_threaded_irq(uart->irq, NULL,
+                                                  omap_uart_interrupt,
+                                                  IRQF_SHARED,
+                                                  "serial idle",
+                                                  (void *)uart);
+               } else {
+                       pm_runtime_get_noresume(&uart->pdev->dev);
+                       free_irq(uart->irq, (void *)uart);
+               }
        }
 }
 
@@ -570,10 +575,9 @@ static ssize_t sleep_timeout_show(struct device *dev,
                                  struct device_attribute *attr,
                                  char *buf)
 {
-       struct platform_device *pdev = container_of(dev,
-                                       struct platform_device, dev);
-       struct omap_uart_state *uart = container_of(pdev,
-                                       struct omap_uart_state, pdev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_device *odev = to_omap_device(pdev);
+       struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
 
        return sprintf(buf, "%u\n", uart->timeout / HZ);
 }
@@ -582,10 +586,9 @@ static ssize_t sleep_timeout_store(struct device *dev,
                                   struct device_attribute *attr,
                                   const char *buf, size_t n)
 {
-       struct platform_device *pdev = container_of(dev,
-                                       struct platform_device, dev);
-       struct omap_uart_state *uart = container_of(pdev,
-                                       struct omap_uart_state, pdev);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct omap_device *odev = to_omap_device(pdev);
+       struct omap_uart_state *uart = odev->hwmods[0]->dev_attr;
        unsigned int value;
 
        if (sscanf(buf, "%u", &value) != 1) {
@@ -608,48 +611,15 @@ static DEVICE_ATTR(sleep_timeout, 0644, sleep_timeout_show,
 #define DEV_CREATE_FILE(dev, attr) WARN_ON(device_create_file(dev, attr))
 #else
 static inline void omap_uart_idle_init(struct omap_uart_state *uart) {}
+static void omap_uart_block_sleep(struct omap_uart_state *uart)
+{
+       /* Needed to enable UART clocks when built without CONFIG_PM */
+       omap_uart_enable_clocks(uart);
+}
 #define DEV_CREATE_FILE(dev, attr)
 #endif /* CONFIG_PM */
 
-static struct omap_uart_state omap_uart[] = {
-       {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = PLAT8250_DEV_PLATFORM,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data0,
-                       },
-               },
-       }, {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = PLAT8250_DEV_PLATFORM1,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data1,
-                       },
-               },
-       }, {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = PLAT8250_DEV_PLATFORM2,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data2,
-                       },
-               },
-       },
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-       {
-               .pdev = {
-                       .name                   = "serial8250",
-                       .id                     = 3,
-                       .dev                    = {
-                               .platform_data  = serial_platform_data3,
-                       },
-               },
-       },
-#endif
-};
-
+#ifndef CONFIG_SERIAL_OMAP
 /*
  * Override the default 8250 read handler: mem_serial_in()
  * Empty RX fifo read causes an abort on omap3630 and omap4
@@ -682,71 +652,44 @@ static void serial_out_override(struct uart_port *up, int offset, int value)
        }
        __serial_write_reg(up, offset, value);
 }
+#endif
+
 void __init omap_serial_early_init(void)
 {
-       int i, nr_ports;
-       char name[16];
+       int i = 0;
 
-       if (!(cpu_is_omap3630() || cpu_is_omap4430()))
-               nr_ports = 3;
-       else
-               nr_ports = ARRAY_SIZE(omap_uart);
+       do {
+               char oh_name[MAX_UART_HWMOD_NAME_LEN];
+               struct omap_hwmod *oh;
+               struct omap_uart_state *uart;
 
-       /*
-        * Make sure the serial ports are muxed on at this point.
-        * You have to mux them off in device drivers later on
-        * if not needed.
-        */
+               snprintf(oh_name, MAX_UART_HWMOD_NAME_LEN,
+                        "uart%d", i + 1);
+               oh = omap_hwmod_lookup(oh_name);
+               if (!oh)
+                       break;
 
-       for (i = 0; i < nr_ports; i++) {
-               struct omap_uart_state *uart = &omap_uart[i];
-               struct platform_device *pdev = &uart->pdev;
-               struct device *dev = &pdev->dev;
-               struct plat_serial8250_port *p = dev->platform_data;
+               uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
+               if (WARN_ON(!uart))
+                       return;
+
+               uart->oh = oh;
+               uart->num = i++;
+               list_add_tail(&uart->node, &uart_list);
+               num_uarts++;
 
-               /* Don't map zero-based physical address */
-               if (p->mapbase == 0) {
-                       dev_warn(dev, "no physical address for uart#%d,"
-                                " so skipping early_init...\n", i);
-                       continue;
-               }
                /*
-                * Module 4KB + L4 interconnect 4KB
-                * Static mapping, never released
+                * NOTE: omap_hwmod_init() has not yet been called,
+                *       so no hwmod functions will work yet.
                 */
-               p->membase = ioremap(p->mapbase, SZ_8K);
-               if (!p->membase) {
-                       dev_err(dev, "ioremap failed for uart%i\n", i + 1);
-                       continue;
-               }
-
-               sprintf(name, "uart%d_ick", i + 1);
-               uart->ick = clk_get(NULL, name);
-               if (IS_ERR(uart->ick)) {
-                       dev_err(dev, "Could not get uart%d_ick\n", i + 1);
-                       uart->ick = NULL;
-               }
 
-               sprintf(name, "uart%d_fck", i+1);
-               uart->fck = clk_get(NULL, name);
-               if (IS_ERR(uart->fck)) {
-                       dev_err(dev, "Could not get uart%d_fck\n", i + 1);
-                       uart->fck = NULL;
-               }
-
-               /* FIXME: Remove this once the clkdev is ready */
-               if (!cpu_is_omap44xx()) {
-                       if (!uart->ick || !uart->fck)
-                               continue;
-               }
-
-               uart->num = i;
-               p->private_data = uart;
-               uart->p = p;
-
-               if (cpu_is_omap44xx())
-                       p->irq += 32;
-       }
+               /*
+                * During UART early init, device need to be probed
+                * to determine SoC specific init before omap_device
+                * is ready.  Therefore, don't allow idle here
+                */
+               uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
+       } while (1);
 }
 
 /**
@@ -763,53 +706,135 @@ void __init omap_serial_early_init(void)
 void __init omap_serial_init_port(int port)
 {
        struct omap_uart_state *uart;
-       struct platform_device *pdev;
-       struct device *dev;
-
-       BUG_ON(port < 0);
-       BUG_ON(port >= ARRAY_SIZE(omap_uart));
-
-       uart = &omap_uart[port];
-       pdev = &uart->pdev;
-       dev = &pdev->dev;
+       struct omap_hwmod *oh;
+       struct omap_device *od;
+       void *pdata = NULL;
+       u32 pdata_size = 0;
+       char *name;
+#ifndef CONFIG_SERIAL_OMAP
+       struct plat_serial8250_port ports[2] = {
+               {},
+               {.flags = 0},
+       };
+       struct plat_serial8250_port *p = &ports[0];
+#else
+       struct omap_uart_port_info omap_up;
+#endif
 
-       /* Don't proceed if there's no clocks available */
-       if (unlikely(!uart->ick || !uart->fck)) {
-               WARN(1, "%s: can't init uart%d, no clocks available\n",
-                    kobject_name(&dev->kobj), port);
+       if (WARN_ON(port < 0))
+               return;
+       if (WARN_ON(port >= num_uarts))
                return;
-       }
-
-       omap_uart_enable_clocks(uart);
-
-       omap_uart_reset(uart);
-       omap_uart_idle_init(uart);
 
-       list_add_tail(&uart->node, &uart_list);
+       list_for_each_entry(uart, &uart_list, node)
+               if (port == uart->num)
+                       break;
 
-       if (WARN_ON(platform_device_register(pdev)))
-               return;
+       oh = uart->oh;
+       uart->dma_enabled = 0;
+#ifndef CONFIG_SERIAL_OMAP
+       name = "serial8250";
 
-       if ((cpu_is_omap34xx() && uart->padconf) ||
-           (uart->wk_en && uart->wk_mask)) {
-               device_init_wakeup(dev, true);
-               DEV_CREATE_FILE(dev, &dev_attr_sleep_timeout);
-       }
+       /*
+        * !! 8250 driver does not use standard IORESOURCE* It
+        * has it's own custom pdata that can be taken from
+        * the hwmod resource data.  But, this needs to be
+        * done after the build.
+        *
+        * ?? does it have to be done before the register ??
+        * YES, because platform_device_data_add() copies
+        * pdata, it does not use a pointer.
+        */
+       p->flags = UPF_BOOT_AUTOCONF;
+       p->iotype = UPIO_MEM;
+       p->regshift = 2;
+       p->uartclk = OMAP24XX_BASE_BAUD * 16;
+       p->irq = oh->mpu_irqs[0].irq;
+       p->mapbase = oh->slaves[0]->addr->pa_start;
+       p->membase = omap_hwmod_get_mpu_rt_va(oh);
+       p->irqflags = IRQF_SHARED;
+       p->private_data = uart;
 
        /*
         * omap44xx: Never read empty UART fifo
         * omap3xxx: Never read empty UART fifo on UARTs
         * with IP rev >=0x52
         */
+       uart->regshift = p->regshift;
+       uart->membase = p->membase;
        if (cpu_is_omap44xx())
                uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
-       else if ((serial_read_reg(uart->p, UART_OMAP_MVER) & 0xFF)
+       else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
                        >= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
                uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
 
        if (uart->errata & UART_ERRATA_FIFO_FULL_ABORT) {
-               uart->p->serial_in = serial_in_override;
-               uart->p->serial_out = serial_out_override;
+               p->serial_in = serial_in_override;
+               p->serial_out = serial_out_override;
+       }
+
+       pdata = &ports[0];
+       pdata_size = 2 * sizeof(struct plat_serial8250_port);
+#else
+
+       name = DRIVER_NAME;
+
+       omap_up.dma_enabled = uart->dma_enabled;
+       omap_up.uartclk = OMAP24XX_BASE_BAUD * 16;
+       omap_up.mapbase = oh->slaves[0]->addr->pa_start;
+       omap_up.membase = omap_hwmod_get_mpu_rt_va(oh);
+       omap_up.irqflags = IRQF_SHARED;
+       omap_up.flags = UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
+
+       pdata = &omap_up;
+       pdata_size = sizeof(struct omap_uart_port_info);
+#endif
+
+       if (WARN_ON(!oh))
+               return;
+
+       od = omap_device_build(name, uart->num, oh, pdata, pdata_size,
+                              omap_uart_latency,
+                              ARRAY_SIZE(omap_uart_latency), false);
+       WARN(IS_ERR(od), "Could not build omap_device for %s: %s.\n",
+            name, oh->name);
+
+       uart->irq = oh->mpu_irqs[0].irq;
+       uart->regshift = 2;
+       uart->mapbase = oh->slaves[0]->addr->pa_start;
+       uart->membase = omap_hwmod_get_mpu_rt_va(oh);
+       uart->pdev = &od->pdev;
+
+       oh->dev_attr = uart;
+
+       /*
+        * Because of early UART probing, UART did not get idled
+        * on init.  Now that omap_device is ready, ensure full idle
+        * before doing omap_device_enable().
+        */
+       omap_hwmod_idle(uart->oh);
+
+       omap_device_enable(uart->pdev);
+       omap_uart_idle_init(uart);
+       omap_uart_reset(uart);
+       omap_hwmod_enable_wakeup(uart->oh);
+       omap_device_idle(uart->pdev);
+
+       /*
+        * Need to block sleep long enough for interrupt driven
+        * driver to start.  Console driver is in polling mode
+        * so device needs to be kept enabled while polling driver
+        * is in use.
+        */
+       if (uart->timeout)
+               uart->timeout = (30 * HZ);
+       omap_uart_block_sleep(uart);
+       uart->timeout = DEFAULT_TIMEOUT;
+
+       if ((cpu_is_omap34xx() && uart->padconf) ||
+           (uart->wk_en && uart->wk_mask)) {
+               device_init_wakeup(&od->pdev.dev, true);
+               DEV_CREATE_FILE(&od->pdev.dev, &dev_attr_sleep_timeout);
        }
 
        /* Enable the MDR1 errata for OMAP3 */
@@ -826,13 +851,8 @@ void __init omap_serial_init_port(int port)
  */
 void __init omap_serial_init(void)
 {
-       int i, nr_ports;
-
-       if (!(cpu_is_omap3630() || cpu_is_omap4430()))
-               nr_ports = 3;
-       else
-               nr_ports = ARRAY_SIZE(omap_uart);
+       struct omap_uart_state *uart;
 
-       for (i = 0; i < nr_ports; i++)
-               omap_serial_init_port(i);
+       list_for_each_entry(uart, &uart_list, node)
+               omap_serial_init_port(uart->num);
 }
index ba53191..2fb205a 100644 (file)
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <mach/io.h>
-#include <plat/control.h>
 
 #include "cm.h"
 #include "prm.h"
 #include "sdrc.h"
+#include "control.h"
 
 #define SDRC_SCRATCHPAD_SEM_V  0xfa00291c
 
index de99ba2..3637274 100644 (file)
@@ -129,8 +129,11 @@ ENTRY(omap3_sram_configure_core_dpll)
        ldr     r4, [sp, #80]
        str     r4, omap_sdrc_mr_1_val
 skip_cs1_params:
+       mrc     p15, 0, r8, c1, c0, 0   @ read ctrl register
+       bic     r10, r8, #0x800         @ clear Z-bit, disable branch prediction
+       mcr     p15, 0, r10, c1, c0, 0  @ write ctrl register
        dsb                             @ flush buffered writes to interconnect
-
+       isb                             @ prevent speculative exec past here
        cmp     r3, #1                  @ if increasing SDRC clk rate,
        bleq    configure_sdrc          @ program the SDRC regs early (for RFR)
        cmp     r1, #SDRC_UNLOCK_DLL    @ set the intended DLL state
@@ -148,6 +151,7 @@ skip_cs1_params:
        beq     return_to_sdram         @ return to SDRAM code, otherwise,
        bl      configure_sdrc          @ reprogram SDRC regs now
 return_to_sdram:
+       mcr     p15, 0, r8, c1, c0, 0   @ restore ctrl register
        isb                             @ prevent speculative exec past here
        mov     r0, #0                  @ return value
        ldmfd   sp!, {r1-r12, pc}       @ restore regs and return
index 74fbed8..e13c29e 100644 (file)
@@ -40,6 +40,8 @@
 #include <plat/dmtimer.h>
 #include <asm/localtimer.h>
 
+#include "timer-gp.h"
+
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID         12
 
@@ -228,8 +230,10 @@ static void __init omap2_gp_clocksource_init(void)
 static void __init omap2_gp_timer_init(void)
 {
 #ifdef CONFIG_LOCAL_TIMERS
-       twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
-       BUG_ON(!twd_base);
+       if (cpu_is_omap44xx()) {
+               twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_256);
+               BUG_ON(!twd_base);
+       }
 #endif
        omap_dm_timer_init();
 
diff --git a/arch/arm/mach-omap2/timer-gp.h b/arch/arm/mach-omap2/timer-gp.h
new file mode 100644 (file)
index 0000000..5c1072c
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * OMAP2/3 GPTIMER support.headers
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+
+extern int __init omap2_gp_clockevent_set_gptimer(u8 id);
+
+#endif
index a216d88..1481078 100644 (file)
 
 #include <asm/irq.h>
 
-#include <plat/control.h>
 #include <plat/usb.h>
 #include <plat/board.h>
 
+#include "control.h"
+#include "mux.h"
+
 #define INT_USB_IRQ_GEN                INT_24XX_USB_IRQ_GEN
 #define INT_USB_IRQ_NISO       INT_24XX_USB_IRQ_NISO
 #define INT_USB_IRQ_ISO                INT_24XX_USB_IRQ_ISO
 #define INT_USB_IRQ_HGEN       INT_24XX_USB_IRQ_HGEN
 #define INT_USB_IRQ_OTG                INT_24XX_USB_IRQ_OTG
 
-#include "mux.h"
-
 #if defined(CONFIG_ARCH_OMAP2)
 
 #ifdef CONFIG_USB_GADGET_OMAP
index a57713c..acd9552 100644 (file)
@@ -16,6 +16,10 @@ config ARCH_TEGRA_2x_SOC
 
 endchoice
 
+config TEGRA_PCI
+       bool "PCI Express support"
+       select PCI
+
 comment "Tegra board type"
 
 config MACH_HARMONY
@@ -47,4 +51,11 @@ config TEGRA_DEBUG_UARTE
 
 endchoice
 
+config TEGRA_SYSTEM_DMA
+       bool "Enable system DMA driver for NVIDIA Tegra SoCs"
+       default y
+       help
+         Adds system DMA functionality for NVIDIA Tegra SoCs, used by
+         several Tegra device drivers
+
 endif
index 51e9370..cdbc68e 100644 (file)
@@ -1,14 +1,21 @@
 obj-y                                   += common.o
 obj-y                                   += io.o
-obj-y                                   += irq.o
+obj-y                                   += irq.o legacy_irq.o
 obj-y                                   += clock.o
 obj-y                                   += timer.o
 obj-y                                   += gpio.o
 obj-y                                   += pinmux.o
+obj-y                                  += fuse.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clock.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_dvfs.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += pinmux-t2-tables.o
 obj-$(CONFIG_SMP)                       += platsmp.o localtimer.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
+obj-$(CONFIG_TEGRA_SYSTEM_DMA)         += dma.o
+obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
+obj-$(CONFIG_TEGRA_PCI)                        += pcie.o
 
 obj-${CONFIG_MACH_HARMONY}              += board-harmony.o
 obj-${CONFIG_MACH_HARMONY}              += board-harmony-pinmux.o
+obj-${CONFIG_MACH_HARMONY}              += board-harmony-pcie.o
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c
new file mode 100644 (file)
index 0000000..f7e7d45
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * arch/arm/mach-tegra/board-harmony-pcie.c
+ *
+ * Copyright (C) 2010 CompuLab, Ltd.
+ * Mike Rapoport <mike@compulab.co.il>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+
+#include <asm/mach-types.h>
+
+#include <mach/pinmux.h>
+#include "board.h"
+
+#ifdef CONFIG_TEGRA_PCI
+
+static int __init harmony_pcie_init(void)
+{
+       int err;
+
+       if (!machine_is_harmony())
+               return 0;
+
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL);
+
+       err = tegra_pcie_init(true, true);
+       if (err)
+               goto err_pcie;
+
+       return 0;
+
+err_pcie:
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_TRISTATE);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE);
+       tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE);
+
+       return err;
+}
+
+subsys_initcall(harmony_pcie_init);
+
+#endif
index 3d06354..0de565c 100644 (file)
@@ -27,6 +27,7 @@ void __init tegra_common_init(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_init_clock(void);
+int __init tegra_pcie_init(bool init_port0, bool init_port1);
 
 extern struct sys_timer tegra_timer;
 #endif
index 03ad578..ae19f95 100644 (file)
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/seq_file.h>
+#include <linux/regulator/consumer.h>
 #include <asm/clkdev.h>
 
 #include "clock.h"
+#include "board.h"
+#include "fuse.h"
 
 static LIST_HEAD(clocks);
 
 static DEFINE_SPINLOCK(clock_lock);
+static DEFINE_MUTEX(dvfs_lock);
+
+static int clk_is_dvfs(struct clk *c)
+{
+       return (c->dvfs != NULL);
+};
+
+static int dvfs_set_rate(struct dvfs *d, unsigned long rate)
+{
+       struct dvfs_table *t;
+
+       if (d->table == NULL)
+               return -ENODEV;
+
+       for (t = d->table; t->rate != 0; t++) {
+               if (rate <= t->rate) {
+                       if (!d->reg)
+                               return 0;
+
+                       return regulator_set_voltage(d->reg,
+                               t->millivolts * 1000,
+                               d->max_millivolts * 1000);
+               }
+       }
+
+       return -EINVAL;
+}
+
+static void dvfs_init(struct clk *c)
+{
+       int process_id;
+       int i;
+       struct dvfs_table *table;
+
+       process_id = c->dvfs->cpu ? tegra_core_process_id() :
+               tegra_cpu_process_id();
+
+       for (i = 0; i < c->dvfs->process_id_table_length; i++)
+               if (process_id == c->dvfs->process_id_table[i].process_id)
+                       c->dvfs->table = c->dvfs->process_id_table[i].table;
+
+       if (c->dvfs->table == NULL) {
+               pr_err("Failed to find dvfs table for clock %s process %d\n",
+                       c->name, process_id);
+               return;
+       }
+
+       c->dvfs->max_millivolts = 0;
+       for (table = c->dvfs->table; table->rate != 0; table++)
+               if (c->dvfs->max_millivolts < table->millivolts)
+                       c->dvfs->max_millivolts = table->millivolts;
+
+       c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id);
+
+       if (IS_ERR(c->dvfs->reg)) {
+               pr_err("Failed to get regulator %s for clock %s\n",
+                       c->dvfs->reg_id, c->name);
+               c->dvfs->reg = NULL;
+               return;
+       }
+
+       if (c->refcnt > 0)
+               dvfs_set_rate(c->dvfs, c->rate);
+}
 
 struct clk *tegra_get_clock_by_name(const char *name)
 {
@@ -48,14 +115,31 @@ struct clk *tegra_get_clock_by_name(const char *name)
        return ret;
 }
 
+static void clk_recalculate_rate(struct clk *c)
+{
+       u64 rate;
+
+       if (!c->parent)
+               return;
+
+       rate = c->parent->rate;
+
+       if (c->mul != 0 && c->div != 0) {
+               rate = rate * c->mul;
+               do_div(rate, c->div);
+       }
+
+       if (rate > c->max_rate)
+               pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n",
+                       c->name, rate, c->max_rate);
+
+       c->rate = rate;
+}
+
 int clk_reparent(struct clk *c, struct clk *parent)
 {
        pr_debug("%s: %s\n", __func__, c->name);
-       if (c->refcnt && c->parent)
-               clk_disable_locked(c->parent);
        c->parent = parent;
-       if (c->refcnt && c->parent)
-               clk_enable_locked(c->parent);
        list_del(&c->sibling);
        list_add_tail(&c->sibling, &parent->children);
        return 0;
@@ -67,8 +151,7 @@ static void propagate_rate(struct clk *c)
        pr_debug("%s: %s\n", __func__, c->name);
        list_for_each_entry(clkp, &c->children, sibling) {
                pr_debug("   %s\n", clkp->name);
-               if (clkp->ops->recalculate_rate)
-                       clkp->ops->recalculate_rate(clkp);
+               clk_recalculate_rate(clkp);
                propagate_rate(clkp);
        }
 }
@@ -77,6 +160,8 @@ void clk_init(struct clk *c)
 {
        unsigned long flags;
 
+       pr_debug("%s: %s\n", __func__, c->name);
+
        spin_lock_irqsave(&clock_lock, flags);
 
        INIT_LIST_HEAD(&c->children);
@@ -85,6 +170,8 @@ void clk_init(struct clk *c)
        if (c->ops && c->ops->init)
                c->ops->init(c);
 
+       clk_recalculate_rate(c);
+
        list_add(&c->node, &clocks);
 
        if (c->parent)
@@ -122,13 +209,38 @@ int clk_enable_locked(struct clk *c)
        return 0;
 }
 
+int clk_enable_cansleep(struct clk *c)
+{
+       int ret;
+       unsigned long flags;
+
+       mutex_lock(&dvfs_lock);
+
+       if (clk_is_dvfs(c) && c->refcnt > 0)
+               dvfs_set_rate(c->dvfs, c->rate);
+
+       spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_enable_locked(c);
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       mutex_unlock(&dvfs_lock);
+
+       return ret;
+}
+EXPORT_SYMBOL(clk_enable_cansleep);
+
 int clk_enable(struct clk *c)
 {
        int ret;
        unsigned long flags;
+
+       if (clk_is_dvfs(c))
+               BUG();
+
        spin_lock_irqsave(&clock_lock, flags);
        ret = clk_enable_locked(c);
        spin_unlock_irqrestore(&clock_lock, flags);
+
        return ret;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -152,9 +264,30 @@ void clk_disable_locked(struct clk *c)
        c->refcnt--;
 }
 
+void clk_disable_cansleep(struct clk *c)
+{
+       unsigned long flags;
+
+       mutex_lock(&dvfs_lock);
+
+       spin_lock_irqsave(&clock_lock, flags);
+       clk_disable_locked(c);
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       if (clk_is_dvfs(c) && c->refcnt == 0)
+               dvfs_set_rate(c->dvfs, c->rate);
+
+       mutex_unlock(&dvfs_lock);
+}
+EXPORT_SYMBOL(clk_disable_cansleep);
+
 void clk_disable(struct clk *c)
 {
        unsigned long flags;
+
+       if (clk_is_dvfs(c))
+               BUG();
+
        spin_lock_irqsave(&clock_lock, flags);
        clk_disable_locked(c);
        spin_unlock_irqrestore(&clock_lock, flags);
@@ -175,6 +308,8 @@ int clk_set_parent_locked(struct clk *c, struct clk *parent)
        if (ret)
                return ret;
 
+       clk_recalculate_rate(c);
+
        propagate_rate(c);
 
        return 0;
@@ -197,22 +332,69 @@ struct clk *clk_get_parent(struct clk *c)
 }
 EXPORT_SYMBOL(clk_get_parent);
 
-int clk_set_rate(struct clk *c, unsigned long rate)
+int clk_set_rate_locked(struct clk *c, unsigned long rate)
+{
+       int ret;
+
+       if (rate > c->max_rate)
+               rate = c->max_rate;
+
+       if (!c->ops || !c->ops->set_rate)
+               return -ENOSYS;
+
+       ret = c->ops->set_rate(c, rate);
+
+       if (ret)
+               return ret;
+
+       clk_recalculate_rate(c);
+
+       propagate_rate(c);
+
+       return 0;
+}
+
+int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
 {
        int ret = 0;
        unsigned long flags;
 
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       mutex_lock(&dvfs_lock);
+
+       if (rate > c->rate)
+               ret = dvfs_set_rate(c->dvfs, rate);
+       if (ret)
+               goto out;
+
        spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_set_rate_locked(c, rate);
+       spin_unlock_irqrestore(&clock_lock, flags);
 
-       pr_debug("%s: %s\n", __func__, c->name);
+       if (ret)
+               goto out;
 
-       if (c->ops && c->ops->set_rate)
-               ret = c->ops->set_rate(c, rate);
-       else
-               ret = -ENOSYS;
+       ret = dvfs_set_rate(c->dvfs, rate);
 
-       propagate_rate(c);
+out:
+       mutex_unlock(&dvfs_lock);
+       return ret;
+}
+EXPORT_SYMBOL(clk_set_rate_cansleep);
+
+int clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret = 0;
+       unsigned long flags;
+
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       if (clk_is_dvfs(c))
+               BUG();
 
+       spin_lock_irqsave(&clock_lock, flags);
+       ret = clk_set_rate_locked(c, rate);
        spin_unlock_irqrestore(&clock_lock, flags);
 
        return ret;
@@ -235,6 +417,20 @@ unsigned long clk_get_rate(struct clk *c)
 }
 EXPORT_SYMBOL(clk_get_rate);
 
+long clk_round_rate(struct clk *c, unsigned long rate)
+{
+       pr_debug("%s: %s\n", __func__, c->name);
+
+       if (!c->ops || !c->ops->round_rate)
+               return -ENOSYS;
+
+       if (rate > c->max_rate)
+               rate = c->max_rate;
+
+       return c->ops->round_rate(c, rate);
+}
+EXPORT_SYMBOL(clk_round_rate);
+
 static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
 {
        struct clk *c;
@@ -308,13 +504,28 @@ void tegra_periph_reset_assert(struct clk *c)
 }
 EXPORT_SYMBOL(tegra_periph_reset_assert);
 
-int __init tegra_init_clock(void)
+void __init tegra_init_clock(void)
 {
        tegra2_init_clocks();
+}
+
+int __init tegra_init_dvfs(void)
+{
+       struct clk *c, *safe;
+
+       mutex_lock(&dvfs_lock);
+
+       list_for_each_entry_safe(c, safe, &clocks, node)
+               if (c->dvfs)
+                       dvfs_init(c);
+
+       mutex_unlock(&dvfs_lock);
 
        return 0;
 }
 
+late_initcall(tegra_init_dvfs);
+
 #ifdef CONFIG_DEBUG_FS
 static struct dentry *clk_debugfs_root;
 
@@ -324,7 +535,7 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
        struct clk *child;
        struct clk *safe;
        const char *state = "uninit";
-       char div[5] = {0};
+       char div[8] = {0};
 
        if (c->state == ON)
                state = "on";
@@ -332,16 +543,26 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
                state = "off";
 
        if (c->mul != 0 && c->div != 0) {
-               BUG_ON(c->mul > 2);
-               if (c->mul > c->div)
-                       snprintf(div, sizeof(div), "x%d", c->mul / c->div);
-               else
+               if (c->mul > c->div) {
+                       int mul = c->mul / c->div;
+                       int mul2 = (c->mul * 10 / c->div) % 10;
+                       int mul3 = (c->mul * 10) % c->div;
+                       if (mul2 == 0 && mul3 == 0)
+                               snprintf(div, sizeof(div), "x%d", mul);
+                       else if (mul3 == 0)
+                               snprintf(div, sizeof(div), "x%d.%d", mul, mul2);
+                       else
+                               snprintf(div, sizeof(div), "x%d.%d..", mul, mul2);
+               } else {
                        snprintf(div, sizeof(div), "%d%s", c->div / c->mul,
                                (c->div % c->mul) ? ".5" : "");
+               }
        }
 
-       seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n",
-               level * 3 + 1, c->set ? "" : "*",
+       seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n",
+               level * 3 + 1, "",
+               c->rate > c->max_rate ? '!' : ' ',
+               !c->set ? '*' : ' ',
                30 - level * 3, c->name,
                state, c->refcnt, div, c->rate);
        list_for_each_entry_safe(child, safe, &c->children, sibling) {
@@ -353,8 +574,8 @@ static int clock_tree_show(struct seq_file *s, void *data)
 {
        struct clk *c;
        unsigned long flags;
-       seq_printf(s, " clock                          state  ref div   rate      \n");
-       seq_printf(s, "-----------------------------------------------------------\n");
+       seq_printf(s, "   clock                          state  ref div      rate\n");
+       seq_printf(s, "--------------------------------------------------------------\n");
        spin_lock_irqsave(&clock_lock, flags);
        list_for_each_entry(c, &clocks, node)
                if (c->parent == NULL)
index af7c70e..94fd859 100644 (file)
 #define DIV_U71                        (1 << 1)
 #define DIV_U71_FIXED          (1 << 2)
 #define DIV_2                  (1 << 3)
-#define PLL_FIXED              (1 << 4)
-#define PLL_HAS_CPCON          (1 << 5)
-#define MUX                    (1 << 6)
-#define PLLD                   (1 << 7)
-#define PERIPH_NO_RESET                (1 << 8)
-#define PERIPH_NO_ENB          (1 << 9)
-#define PERIPH_EMC_ENB         (1 << 10)
-#define PERIPH_MANUAL_RESET    (1 << 11)
-#define PLL_ALT_MISC_REG       (1 << 12)
+#define DIV_U16                        (1 << 4)
+#define PLL_FIXED              (1 << 5)
+#define PLL_HAS_CPCON          (1 << 6)
+#define MUX                    (1 << 7)
+#define PLLD                   (1 << 8)
+#define PERIPH_NO_RESET                (1 << 9)
+#define PERIPH_NO_ENB          (1 << 10)
+#define PERIPH_EMC_ENB         (1 << 11)
+#define PERIPH_MANUAL_RESET    (1 << 12)
+#define PLL_ALT_MISC_REG       (1 << 13)
+#define PLLU                   (1 << 14)
 #define ENABLE_ON_INIT         (1 << 28)
 
 struct clk;
+struct regulator;
+
+struct dvfs_table {
+       unsigned long rate;
+       int millivolts;
+};
+
+struct dvfs_process_id_table {
+       int process_id;
+       struct dvfs_table *table;
+};
+
+
+struct dvfs {
+       struct regulator *reg;
+       struct dvfs_table *table;
+       int max_millivolts;
+
+       int process_id_table_length;
+       const char *reg_id;
+       bool cpu;
+       struct dvfs_process_id_table process_id_table[];
+};
 
 struct clk_mux_sel {
        struct clk      *input;
@@ -58,12 +83,9 @@ struct clk_ops {
        void            (*init)(struct clk *);
        int             (*enable)(struct clk *);
        void            (*disable)(struct clk *);
-       void            (*recalc)(struct clk *);
        int             (*set_parent)(struct clk *, struct clk *);
        int             (*set_rate)(struct clk *, unsigned long);
-       unsigned long   (*get_rate)(struct clk *);
        long            (*round_rate)(struct clk *, unsigned long);
-       unsigned long   (*recalculate_rate)(struct clk *);
 };
 
 enum clk_state {
@@ -85,6 +107,7 @@ struct clk {
        struct clk                      *parent;
        struct clk_lookup               lookup;
        unsigned long                   rate;
+       unsigned long                   max_rate;
        u32                             flags;
        u32                             refcnt;
        const char                      *name;
@@ -103,10 +126,6 @@ struct clk {
        unsigned long                   cf_max;
        unsigned long                   vco_min;
        unsigned long                   vco_max;
-       u32                             m;
-       u32                             n;
-       u32                             p;
-       u32                             cpcon;
        const struct clk_pll_table      *pll_table;
 
        /* DIV */
@@ -117,6 +136,12 @@ struct clk {
        const struct clk_mux_sel        *inputs;
        u32                             sel;
        u32                             reg_mask;
+
+       /* Virtual cpu clock */
+       struct clk                      *main;
+       struct clk                      *backup;
+
+       struct dvfs                     *dvfs;
 };
 
 
@@ -141,6 +166,7 @@ unsigned long clk_measure_input_freq(void);
 void clk_disable_locked(struct clk *c);
 int clk_enable_locked(struct clk *c);
 int clk_set_parent_locked(struct clk *c, struct clk *parent);
+int clk_set_rate_locked(struct clk *c, unsigned long rate);
 int clk_reparent(struct clk *c, struct clk *parent);
 void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
 
index 039a514..7c91e2b 100644 (file)
 
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
 
 #include <asm/hardware/cache-l2x0.h>
 
 #include <mach/iomap.h>
+#include <mach/dma.h>
 
 #include "board.h"
 #include "clock.h"
+#include "fuse.h"
 
 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
        /* name         parent          rate            enabled */
@@ -35,8 +39,8 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
        { "pll_p_out2", "pll_p",        48000000,       true },
        { "pll_p_out3", "pll_p",        72000000,       true },
        { "pll_p_out4", "pll_p",        108000000,      true },
-       { "sys",        "pll_p_out4",   108000000,      true },
-       { "hclk",       "sys",          108000000,      true },
+       { "sclk",       "pll_p_out4",   108000000,      true },
+       { "hclk",       "sclk",         108000000,      true },
        { "pclk",       "hclk",         54000000,       true },
        { NULL,         NULL,           0,              0},
 };
@@ -51,11 +55,16 @@ void __init tegra_init_cache(void)
 
        l2x0_init(p, 0x6C080001, 0x8200c3fe);
 #endif
+
 }
 
 void __init tegra_common_init(void)
 {
+       tegra_init_fuse();
        tegra_init_clock();
        tegra_clk_init_from_table(common_clk_init_table);
        tegra_init_cache();
+#ifdef CONFIG_TEGRA_SYSTEM_DMA
+       tegra_dma_init();
+#endif
 }
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
new file mode 100644 (file)
index 0000000..fea5719
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * arch/arm/mach-tegra/cpu-tegra.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *     Based on arch/arm/plat-omap/cpu-omap.c, (C) 2005 Nokia 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/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+
+#include <mach/hardware.h>
+#include <mach/clk.h>
+
+/* Frequency table index must be sequential starting at 0 */
+static struct cpufreq_frequency_table freq_table[] = {
+       { 0, 312000 },
+       { 1, 456000 },
+       { 2, 608000 },
+       { 3, 760000 },
+       { 4, 816000 },
+       { 5, 912000 },
+       { 6, 1000000 },
+       { 7, CPUFREQ_TABLE_END },
+};
+
+#define NUM_CPUS       2
+
+static struct clk *cpu_clk;
+
+static unsigned long target_cpu_speed[NUM_CPUS];
+
+int tegra_verify_speed(struct cpufreq_policy *policy)
+{
+       return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+unsigned int tegra_getspeed(unsigned int cpu)
+{
+       unsigned long rate;
+
+       if (cpu >= NUM_CPUS)
+               return 0;
+
+       rate = clk_get_rate(cpu_clk) / 1000;
+       return rate;
+}
+
+static int tegra_update_cpu_speed(void)
+{
+       int i;
+       unsigned long rate = 0;
+       int ret = 0;
+       struct cpufreq_freqs freqs;
+
+       for_each_online_cpu(i)
+               rate = max(rate, target_cpu_speed[i]);
+
+       freqs.old = tegra_getspeed(0);
+       freqs.new = rate;
+
+       if (freqs.old == freqs.new)
+               return ret;
+
+       for_each_online_cpu(freqs.cpu)
+               cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+       printk(KERN_DEBUG "cpufreq-tegra: transition: %u --> %u\n",
+              freqs.old, freqs.new);
+#endif
+
+       ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000);
+       if (ret) {
+               pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
+                       freqs.new);
+               return ret;
+       }
+
+       for_each_online_cpu(freqs.cpu)
+               cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+       return 0;
+}
+
+static int tegra_target(struct cpufreq_policy *policy,
+                      unsigned int target_freq,
+                      unsigned int relation)
+{
+       int idx;
+       unsigned int freq;
+
+       cpufreq_frequency_table_target(policy, freq_table, target_freq,
+               relation, &idx);
+
+       freq = freq_table[idx].frequency;
+
+       target_cpu_speed[policy->cpu] = freq;
+
+       return tegra_update_cpu_speed();
+}
+
+static int tegra_cpu_init(struct cpufreq_policy *policy)
+{
+       if (policy->cpu >= NUM_CPUS)
+               return -EINVAL;
+
+       cpu_clk = clk_get_sys(NULL, "cpu");
+       if (IS_ERR(cpu_clk))
+               return PTR_ERR(cpu_clk);
+
+       cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+       policy->cur = tegra_getspeed(policy->cpu);
+       target_cpu_speed[policy->cpu] = policy->cur;
+
+       /* FIXME: what's the actual transition time? */
+       policy->cpuinfo.transition_latency = 300 * 1000;
+
+       policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
+       cpumask_copy(policy->related_cpus, cpu_possible_mask);
+
+       return 0;
+}
+
+static int tegra_cpu_exit(struct cpufreq_policy *policy)
+{
+       cpufreq_frequency_table_cpuinfo(policy, freq_table);
+       clk_put(cpu_clk);
+       return 0;
+}
+
+static struct freq_attr *tegra_cpufreq_attr[] = {
+       &cpufreq_freq_attr_scaling_available_freqs,
+       NULL,
+};
+
+static struct cpufreq_driver tegra_cpufreq_driver = {
+       .verify         = tegra_verify_speed,
+       .target         = tegra_target,
+       .get            = tegra_getspeed,
+       .init           = tegra_cpu_init,
+       .exit           = tegra_cpu_exit,
+       .name           = "tegra",
+       .attr           = tegra_cpufreq_attr,
+};
+
+static int __init tegra_cpufreq_init(void)
+{
+       return cpufreq_register_driver(&tegra_cpufreq_driver);
+}
+
+static void __exit tegra_cpufreq_exit(void)
+{
+        cpufreq_unregister_driver(&tegra_cpufreq_driver);
+}
+
+
+MODULE_AUTHOR("Colin Cross <ccross@android.com>");
+MODULE_DESCRIPTION("cpufreq driver for Nvidia Tegra2");
+MODULE_LICENSE("GPL");
+module_init(tegra_cpufreq_init);
+module_exit(tegra_cpufreq_exit);
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c
new file mode 100644 (file)
index 0000000..edda6ec
--- /dev/null
@@ -0,0 +1,752 @@
+/*
+ * arch/arm/mach-tegra/dma.c
+ *
+ * System DMA driver for NVIDIA Tegra SoCs
+ *
+ * Copyright (c) 2008-2009, 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.
+ */
+
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+#include <mach/iomap.h>
+
+#define APB_DMA_GEN                            0x000
+#define GEN_ENABLE                             (1<<31)
+
+#define APB_DMA_CNTRL                          0x010
+
+#define APB_DMA_IRQ_MASK                       0x01c
+
+#define APB_DMA_IRQ_MASK_SET                   0x020
+
+#define APB_DMA_CHAN_CSR                       0x000
+#define CSR_ENB                                        (1<<31)
+#define CSR_IE_EOC                             (1<<30)
+#define CSR_HOLD                               (1<<29)
+#define CSR_DIR                                        (1<<28)
+#define CSR_ONCE                               (1<<27)
+#define CSR_FLOW                               (1<<21)
+#define CSR_REQ_SEL_SHIFT                      16
+#define CSR_REQ_SEL_MASK                       (0x1F<<CSR_REQ_SEL_SHIFT)
+#define CSR_REQ_SEL_INVALID                    (31<<CSR_REQ_SEL_SHIFT)
+#define CSR_WCOUNT_SHIFT                       2
+#define CSR_WCOUNT_MASK                                0xFFFC
+
+#define APB_DMA_CHAN_STA                               0x004
+#define STA_BUSY                               (1<<31)
+#define STA_ISE_EOC                            (1<<30)
+#define STA_HALT                               (1<<29)
+#define STA_PING_PONG                          (1<<28)
+#define STA_COUNT_SHIFT                                2
+#define STA_COUNT_MASK                         0xFFFC
+
+#define APB_DMA_CHAN_AHB_PTR                           0x010
+
+#define APB_DMA_CHAN_AHB_SEQ                           0x014
+#define AHB_SEQ_INTR_ENB                       (1<<31)
+#define AHB_SEQ_BUS_WIDTH_SHIFT                        28
+#define AHB_SEQ_BUS_WIDTH_MASK                 (0x7<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_8                    (0<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_16                   (1<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_32                   (2<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_64                   (3<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_BUS_WIDTH_128                  (4<<AHB_SEQ_BUS_WIDTH_SHIFT)
+#define AHB_SEQ_DATA_SWAP                      (1<<27)
+#define AHB_SEQ_BURST_MASK                     (0x7<<24)
+#define AHB_SEQ_BURST_1                                (4<<24)
+#define AHB_SEQ_BURST_4                                (5<<24)
+#define AHB_SEQ_BURST_8                                (6<<24)
+#define AHB_SEQ_DBL_BUF                                (1<<19)
+#define AHB_SEQ_WRAP_SHIFT                     16
+#define AHB_SEQ_WRAP_MASK                      (0x7<<AHB_SEQ_WRAP_SHIFT)
+
+#define APB_DMA_CHAN_APB_PTR                           0x018
+
+#define APB_DMA_CHAN_APB_SEQ                           0x01c
+#define APB_SEQ_BUS_WIDTH_SHIFT                        28
+#define APB_SEQ_BUS_WIDTH_MASK                 (0x7<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_8                    (0<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_16                   (1<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_32                   (2<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_64                   (3<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_BUS_WIDTH_128                  (4<<APB_SEQ_BUS_WIDTH_SHIFT)
+#define APB_SEQ_DATA_SWAP                      (1<<27)
+#define APB_SEQ_WRAP_SHIFT                     16
+#define APB_SEQ_WRAP_MASK                      (0x7<<APB_SEQ_WRAP_SHIFT)
+
+#define TEGRA_SYSTEM_DMA_CH_NR                 16
+#define TEGRA_SYSTEM_DMA_AVP_CH_NUM            4
+#define TEGRA_SYSTEM_DMA_CH_MIN                        0
+#define TEGRA_SYSTEM_DMA_CH_MAX        \
+       (TEGRA_SYSTEM_DMA_CH_NR - TEGRA_SYSTEM_DMA_AVP_CH_NUM - 1)
+
+#define NV_DMA_MAX_TRASFER_SIZE 0x10000
+
+const unsigned int ahb_addr_wrap_table[8] = {
+       0, 32, 64, 128, 256, 512, 1024, 2048
+};
+
+const unsigned int apb_addr_wrap_table[8] = {0, 1, 2, 4, 8, 16, 32, 64};
+
+const unsigned int bus_width_table[5] = {8, 16, 32, 64, 128};
+
+#define TEGRA_DMA_NAME_SIZE 16
+struct tegra_dma_channel {
+       struct list_head        list;
+       int                     id;
+       spinlock_t              lock;
+       char                    name[TEGRA_DMA_NAME_SIZE];
+       void  __iomem           *addr;
+       int                     mode;
+       int                     irq;
+
+       /* Register shadow */
+       u32                     csr;
+       u32                     ahb_seq;
+       u32                     ahb_ptr;
+       u32                     apb_seq;
+       u32                     apb_ptr;
+};
+
+#define  NV_DMA_MAX_CHANNELS  32
+
+static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
+static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
+
+static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+static void tegra_dma_init_hw(struct tegra_dma_channel *ch);
+static void tegra_dma_stop(struct tegra_dma_channel *ch);
+
+void tegra_dma_flush(struct tegra_dma_channel *ch)
+{
+}
+EXPORT_SYMBOL(tegra_dma_flush);
+
+void tegra_dma_dequeue(struct tegra_dma_channel *ch)
+{
+       struct tegra_dma_req *req;
+
+       req = list_entry(ch->list.next, typeof(*req), node);
+
+       tegra_dma_dequeue_req(ch, req);
+       return;
+}
+
+void tegra_dma_stop(struct tegra_dma_channel *ch)
+{
+       unsigned int csr;
+       unsigned int status;
+
+       csr = ch->csr;
+       csr &= ~CSR_IE_EOC;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       csr &= ~CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       status = readl(ch->addr + APB_DMA_CHAN_STA);
+       if (status & STA_ISE_EOC)
+               writel(status, ch->addr + APB_DMA_CHAN_STA);
+}
+
+int tegra_dma_cancel(struct tegra_dma_channel *ch)
+{
+       unsigned int csr;
+       unsigned long irq_flags;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       while (!list_empty(&ch->list))
+               list_del(ch->list.next);
+
+       csr = ch->csr;
+       csr &= ~CSR_REQ_SEL_MASK;
+       csr |= CSR_REQ_SEL_INVALID;
+
+       /* Set the enable as that is not shadowed */
+       csr |= CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       tegra_dma_stop(ch);
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+       return 0;
+}
+
+int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *_req)
+{
+       unsigned int csr;
+       unsigned int status;
+       struct tegra_dma_req *req = NULL;
+       int found = 0;
+       unsigned long irq_flags;
+       int to_transfer;
+       int req_transfer_count;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       list_for_each_entry(req, &ch->list, node) {
+               if (req == _req) {
+                       list_del(&req->node);
+                       found = 1;
+                       break;
+               }
+       }
+       if (!found) {
+               spin_unlock_irqrestore(&ch->lock, irq_flags);
+               return 0;
+       }
+
+       /* STOP the DMA and get the transfer count.
+        * Getting the transfer count is tricky.
+        *  - Change the source selector to invalid to stop the DMA from
+        *    FIFO to memory.
+        *  - Read the status register to know the number of pending
+        *    bytes to be transfered.
+        *  - Finally stop or program the DMA to the next buffer in the
+        *    list.
+        */
+       csr = ch->csr;
+       csr &= ~CSR_REQ_SEL_MASK;
+       csr |= CSR_REQ_SEL_INVALID;
+
+       /* Set the enable as that is not shadowed */
+       csr |= CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       /* Get the transfer count */
+       status = readl(ch->addr + APB_DMA_CHAN_STA);
+       to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
+       req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+       req_transfer_count += 1;
+       to_transfer += 1;
+
+       req->bytes_transferred = req_transfer_count;
+
+       if (status & STA_BUSY)
+               req->bytes_transferred -= to_transfer;
+
+       /* In continous transfer mode, DMA only tracks the count of the
+        * half DMA buffer. So, if the DMA already finished half the DMA
+        * then add the half buffer to the completed count.
+        *
+        *      FIXME: There can be a race here. What if the req to
+        *      dequue happens at the same time as the DMA just moved to
+        *      the new buffer and SW didn't yet received the interrupt?
+        */
+       if (ch->mode & TEGRA_DMA_MODE_CONTINOUS)
+               if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL)
+                       req->bytes_transferred += req_transfer_count;
+
+       req->bytes_transferred *= 4;
+
+       tegra_dma_stop(ch);
+       if (!list_empty(&ch->list)) {
+               /* if the list is not empty, queue the next request */
+               struct tegra_dma_req *next_req;
+               next_req = list_entry(ch->list.next,
+                       typeof(*next_req), node);
+               tegra_dma_update_hw(ch, next_req);
+       }
+       req->status = -TEGRA_DMA_REQ_ERROR_ABORTED;
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+       /* Callback should be called without any lock */
+       req->complete(req);
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dma_dequeue_req);
+
+bool tegra_dma_is_empty(struct tegra_dma_channel *ch)
+{
+       unsigned long irq_flags;
+       bool is_empty;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       if (list_empty(&ch->list))
+               is_empty = true;
+       else
+               is_empty = false;
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+       return is_empty;
+}
+EXPORT_SYMBOL(tegra_dma_is_empty);
+
+bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *_req)
+{
+       unsigned long irq_flags;
+       struct tegra_dma_req *req;
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+       list_for_each_entry(req, &ch->list, node) {
+               if (req == _req) {
+                       spin_unlock_irqrestore(&ch->lock, irq_flags);
+                       return true;
+               }
+       }
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+       return false;
+}
+EXPORT_SYMBOL(tegra_dma_is_req_inflight);
+
+int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req)
+{
+       unsigned long irq_flags;
+       int start_dma = 0;
+
+       if (req->size > NV_DMA_MAX_TRASFER_SIZE ||
+               req->source_addr & 0x3 || req->dest_addr & 0x3) {
+               pr_err("Invalid DMA request for channel %d\n", ch->id);
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&ch->lock, irq_flags);
+
+       req->bytes_transferred = 0;
+       req->status = 0;
+       req->buffer_status = 0;
+       if (list_empty(&ch->list))
+               start_dma = 1;
+
+       list_add_tail(&req->node, &ch->list);
+
+       if (start_dma)
+               tegra_dma_update_hw(ch, req);
+
+       spin_unlock_irqrestore(&ch->lock, irq_flags);
+
+       return 0;
+}
+EXPORT_SYMBOL(tegra_dma_enqueue_req);
+
+struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
+{
+       int channel;
+       struct tegra_dma_channel *ch;
+
+       /* first channel is the shared channel */
+       if (mode & TEGRA_DMA_SHARED) {
+               channel = TEGRA_SYSTEM_DMA_CH_MIN;
+       } else {
+               channel = find_first_zero_bit(channel_usage,
+                       ARRAY_SIZE(dma_channels));
+               if (channel >= ARRAY_SIZE(dma_channels))
+                       return NULL;
+       }
+       __set_bit(channel, channel_usage);
+       ch = &dma_channels[channel];
+       ch->mode = mode;
+       return ch;
+}
+EXPORT_SYMBOL(tegra_dma_allocate_channel);
+
+void tegra_dma_free_channel(struct tegra_dma_channel *ch)
+{
+       if (ch->mode & TEGRA_DMA_SHARED)
+               return;
+       tegra_dma_cancel(ch);
+       __clear_bit(ch->id, channel_usage);
+}
+EXPORT_SYMBOL(tegra_dma_free_channel);
+
+static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req)
+{
+       if (req->to_memory) {
+               ch->apb_ptr = req->source_addr;
+               ch->ahb_ptr = req->dest_addr;
+       } else {
+               ch->apb_ptr = req->dest_addr;
+               ch->ahb_ptr = req->source_addr;
+       }
+       writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+       writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+
+       req->status = TEGRA_DMA_REQ_INFLIGHT;
+       return;
+}
+
+static void tegra_dma_update_hw(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req)
+{
+       int ahb_addr_wrap;
+       int apb_addr_wrap;
+       int ahb_bus_width;
+       int apb_bus_width;
+       int index;
+       unsigned long csr;
+
+
+       ch->csr |= CSR_FLOW;
+       ch->csr &= ~CSR_REQ_SEL_MASK;
+       ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
+       ch->ahb_seq &= ~AHB_SEQ_BURST_MASK;
+       ch->ahb_seq |= AHB_SEQ_BURST_1;
+
+       /* One shot mode is always single buffered,
+        * continuous mode is always double buffered
+        * */
+       if (ch->mode & TEGRA_DMA_MODE_ONESHOT) {
+               ch->csr |= CSR_ONCE;
+               ch->ahb_seq &= ~AHB_SEQ_DBL_BUF;
+               ch->csr &= ~CSR_WCOUNT_MASK;
+               ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT;
+       } else {
+               ch->csr &= ~CSR_ONCE;
+               ch->ahb_seq |= AHB_SEQ_DBL_BUF;
+
+               /* In double buffered mode, we set the size to half the
+                * requested size and interrupt when half the buffer
+                * is full */
+               ch->csr &= ~CSR_WCOUNT_MASK;
+               ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT;
+       }
+
+       if (req->to_memory) {
+               ch->csr &= ~CSR_DIR;
+               ch->apb_ptr = req->source_addr;
+               ch->ahb_ptr = req->dest_addr;
+
+               apb_addr_wrap = req->source_wrap;
+               ahb_addr_wrap = req->dest_wrap;
+               apb_bus_width = req->source_bus_width;
+               ahb_bus_width = req->dest_bus_width;
+
+       } else {
+               ch->csr |= CSR_DIR;
+               ch->apb_ptr = req->dest_addr;
+               ch->ahb_ptr = req->source_addr;
+
+               apb_addr_wrap = req->dest_wrap;
+               ahb_addr_wrap = req->source_wrap;
+               apb_bus_width = req->dest_bus_width;
+               ahb_bus_width = req->source_bus_width;
+       }
+
+       apb_addr_wrap >>= 2;
+       ahb_addr_wrap >>= 2;
+
+       /* set address wrap for APB size */
+       index = 0;
+       do  {
+               if (apb_addr_wrap_table[index] == apb_addr_wrap)
+                       break;
+               index++;
+       } while (index < ARRAY_SIZE(apb_addr_wrap_table));
+       BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table));
+       ch->apb_seq &= ~APB_SEQ_WRAP_MASK;
+       ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT;
+
+       /* set address wrap for AHB size */
+       index = 0;
+       do  {
+               if (ahb_addr_wrap_table[index] == ahb_addr_wrap)
+                       break;
+               index++;
+       } while (index < ARRAY_SIZE(ahb_addr_wrap_table));
+       BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table));
+       ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK;
+       ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
+
+       for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
+               if (bus_width_table[index] == ahb_bus_width)
+                       break;
+       }
+       BUG_ON(index == ARRAY_SIZE(bus_width_table));
+       ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK;
+       ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
+
+       for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
+               if (bus_width_table[index] == apb_bus_width)
+                       break;
+       }
+       BUG_ON(index == ARRAY_SIZE(bus_width_table));
+       ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK;
+       ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
+
+       ch->csr |= CSR_IE_EOC;
+
+       /* update hw registers with the shadow */
+       writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR);
+       writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
+       writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+       writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
+       writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+
+       csr = ch->csr | CSR_ENB;
+       writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+
+       req->status = TEGRA_DMA_REQ_INFLIGHT;
+}
+
+static void tegra_dma_init_hw(struct tegra_dma_channel *ch)
+{
+       /* One shot with an interrupt to CPU after transfer */
+       ch->csr = CSR_ONCE | CSR_IE_EOC;
+       ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB;
+       ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT;
+}
+
+static void handle_oneshot_dma(struct tegra_dma_channel *ch)
+{
+       struct tegra_dma_req *req;
+
+       spin_lock(&ch->lock);
+       if (list_empty(&ch->list)) {
+               spin_unlock(&ch->lock);
+               return;
+       }
+
+       req = list_entry(ch->list.next, typeof(*req), node);
+       if (req) {
+               int bytes_transferred;
+
+               bytes_transferred =
+                       (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+               bytes_transferred += 1;
+               bytes_transferred <<= 2;
+
+               list_del(&req->node);
+               req->bytes_transferred = bytes_transferred;
+               req->status = TEGRA_DMA_REQ_SUCCESS;
+
+               spin_unlock(&ch->lock);
+               /* Callback should be called without any lock */
+               pr_debug("%s: transferred %d bytes\n", __func__,
+                       req->bytes_transferred);
+               req->complete(req);
+               spin_lock(&ch->lock);
+       }
+
+       if (!list_empty(&ch->list)) {
+               req = list_entry(ch->list.next, typeof(*req), node);
+               /* the complete function we just called may have enqueued
+                  another req, in which case dma has already started */
+               if (req->status != TEGRA_DMA_REQ_INFLIGHT)
+                       tegra_dma_update_hw(ch, req);
+       }
+       spin_unlock(&ch->lock);
+}
+
+static void handle_continuous_dma(struct tegra_dma_channel *ch)
+{
+       struct tegra_dma_req *req;
+
+       spin_lock(&ch->lock);
+       if (list_empty(&ch->list)) {
+               spin_unlock(&ch->lock);
+               return;
+       }
+
+       req = list_entry(ch->list.next, typeof(*req), node);
+       if (req) {
+               if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) {
+                       /* Load the next request into the hardware, if available
+                        * */
+                       if (!list_is_last(&req->node, &ch->list)) {
+                               struct tegra_dma_req *next_req;
+
+                               next_req = list_entry(req->node.next,
+                                       typeof(*next_req), node);
+                               tegra_dma_update_hw_partial(ch, next_req);
+                       }
+                       req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL;
+                       req->status = TEGRA_DMA_REQ_SUCCESS;
+                       /* DMA lock is NOT held when callback is called */
+                       spin_unlock(&ch->lock);
+                       if (likely(req->threshold))
+                               req->threshold(req);
+                       return;
+
+               } else if (req->buffer_status ==
+                       TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL) {
+                       /* Callback when the buffer is completely full (i.e on
+                        * the second  interrupt */
+                       int bytes_transferred;
+
+                       bytes_transferred =
+                               (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+                       bytes_transferred += 1;
+                       bytes_transferred <<= 3;
+
+                       req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
+                       req->bytes_transferred = bytes_transferred;
+                       req->status = TEGRA_DMA_REQ_SUCCESS;
+                       list_del(&req->node);
+
+                       /* DMA lock is NOT held when callbak is called */
+                       spin_unlock(&ch->lock);
+                       req->complete(req);
+                       return;
+
+               } else {
+                       BUG();
+               }
+       }
+       spin_unlock(&ch->lock);
+}
+
+static irqreturn_t dma_isr(int irq, void *data)
+{
+       struct tegra_dma_channel *ch = data;
+       unsigned long status;
+
+       status = readl(ch->addr + APB_DMA_CHAN_STA);
+       if (status & STA_ISE_EOC)
+               writel(status, ch->addr + APB_DMA_CHAN_STA);
+       else {
+               pr_warning("Got a spurious ISR for DMA channel %d\n", ch->id);
+               return IRQ_HANDLED;
+       }
+       return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t dma_thread_fn(int irq, void *data)
+{
+       struct tegra_dma_channel *ch = data;
+
+       if (ch->mode & TEGRA_DMA_MODE_ONESHOT)
+               handle_oneshot_dma(ch);
+       else
+               handle_continuous_dma(ch);
+
+
+       return IRQ_HANDLED;
+}
+
+int __init tegra_dma_init(void)
+{
+       int ret = 0;
+       int i;
+       unsigned int irq;
+       void __iomem *addr;
+
+       addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+       writel(GEN_ENABLE, addr + APB_DMA_GEN);
+       writel(0, addr + APB_DMA_CNTRL);
+       writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX),
+              addr + APB_DMA_IRQ_MASK_SET);
+
+       memset(channel_usage, 0, sizeof(channel_usage));
+       memset(dma_channels, 0, sizeof(dma_channels));
+
+       /* Reserve all the channels we are not supposed to touch */
+       for (i = 0; i < TEGRA_SYSTEM_DMA_CH_MIN; i++)
+               __set_bit(i, channel_usage);
+
+       for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
+               struct tegra_dma_channel *ch = &dma_channels[i];
+
+               __clear_bit(i, channel_usage);
+
+               ch->id = i;
+               snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i);
+
+               ch->addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+                       TEGRA_APB_DMA_CH0_SIZE * i);
+
+               spin_lock_init(&ch->lock);
+               INIT_LIST_HEAD(&ch->list);
+               tegra_dma_init_hw(ch);
+
+               irq = INT_APB_DMA_CH0 + i;
+               ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
+                       dma_channels[i].name, ch);
+               if (ret) {
+                       pr_err("Failed to register IRQ %d for DMA %d\n",
+                               irq, i);
+                       goto fail;
+               }
+               ch->irq = irq;
+       }
+       /* mark the shared channel allocated */
+       __set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage);
+
+       for (i = TEGRA_SYSTEM_DMA_CH_MAX+1; i < NV_DMA_MAX_CHANNELS; i++)
+               __set_bit(i, channel_usage);
+
+       return ret;
+fail:
+       writel(0, addr + APB_DMA_GEN);
+       for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
+               struct tegra_dma_channel *ch = &dma_channels[i];
+               if (ch->irq)
+                       free_irq(ch->irq, ch);
+       }
+       return ret;
+}
+
+#ifdef CONFIG_PM
+static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3];
+
+void tegra_dma_suspend(void)
+{
+       void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+       u32 *ctx = apb_dma;
+       int i;
+
+       *ctx++ = readl(addr + APB_DMA_GEN);
+       *ctx++ = readl(addr + APB_DMA_CNTRL);
+       *ctx++ = readl(addr + APB_DMA_IRQ_MASK);
+
+       for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
+               addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+                                 TEGRA_APB_DMA_CH0_SIZE * i);
+
+               *ctx++ = readl(addr + APB_DMA_CHAN_CSR);
+               *ctx++ = readl(addr + APB_DMA_CHAN_AHB_PTR);
+               *ctx++ = readl(addr + APB_DMA_CHAN_AHB_SEQ);
+               *ctx++ = readl(addr + APB_DMA_CHAN_APB_PTR);
+               *ctx++ = readl(addr + APB_DMA_CHAN_APB_SEQ);
+       }
+}
+
+void tegra_dma_resume(void)
+{
+       void __iomem *addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
+       u32 *ctx = apb_dma;
+       int i;
+
+       writel(*ctx++, addr + APB_DMA_GEN);
+       writel(*ctx++, addr + APB_DMA_CNTRL);
+       writel(*ctx++, addr + APB_DMA_IRQ_MASK);
+
+       for (i = 0; i < TEGRA_SYSTEM_DMA_CH_NR; i++) {
+               addr = IO_ADDRESS(TEGRA_APB_DMA_CH0_BASE +
+                                 TEGRA_APB_DMA_CH0_SIZE * i);
+
+               writel(*ctx++, addr + APB_DMA_CHAN_CSR);
+               writel(*ctx++, addr + APB_DMA_CHAN_AHB_PTR);
+               writel(*ctx++, addr + APB_DMA_CHAN_AHB_SEQ);
+               writel(*ctx++, addr + APB_DMA_CHAN_APB_PTR);
+               writel(*ctx++, addr + APB_DMA_CHAN_APB_SEQ);
+       }
+}
+
+#endif
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
new file mode 100644 (file)
index 0000000..1fa26d9
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * arch/arm/mach-tegra/fuse.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/iomap.h>
+
+#include "fuse.h"
+
+#define FUSE_UID_LOW           0x108
+#define FUSE_UID_HIGH          0x10c
+#define FUSE_SKU_INFO          0x110
+#define FUSE_SPARE_BIT         0x200
+
+static inline u32 fuse_readl(unsigned long offset)
+{
+       return readl(IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+}
+
+static inline void fuse_writel(u32 value, unsigned long offset)
+{
+       writel(value, IO_TO_VIRT(TEGRA_FUSE_BASE + offset));
+}
+
+void tegra_init_fuse(void)
+{
+       u32 reg = readl(IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+       reg |= 1 << 28;
+       writel(reg, IO_TO_VIRT(TEGRA_CLK_RESET_BASE + 0x48));
+
+       pr_info("Tegra SKU: %d CPU Process: %d Core Process: %d\n",
+               tegra_sku_id(), tegra_cpu_process_id(),
+               tegra_core_process_id());
+}
+
+unsigned long long tegra_chip_uid(void)
+{
+       unsigned long long lo, hi;
+
+       lo = fuse_readl(FUSE_UID_LOW);
+       hi = fuse_readl(FUSE_UID_HIGH);
+       return (hi << 32ull) | lo;
+}
+
+int tegra_sku_id(void)
+{
+       int sku_id;
+       u32 reg = fuse_readl(FUSE_SKU_INFO);
+       sku_id = reg & 0xFF;
+       return sku_id;
+}
+
+int tegra_cpu_process_id(void)
+{
+       int cpu_process_id;
+       u32 reg = fuse_readl(FUSE_SPARE_BIT);
+       cpu_process_id = (reg >> 6) & 3;
+       return cpu_process_id;
+}
+
+int tegra_core_process_id(void)
+{
+       int core_process_id;
+       u32 reg = fuse_readl(FUSE_SPARE_BIT);
+       core_process_id = (reg >> 12) & 3;
+       return core_process_id;
+}
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
new file mode 100644 (file)
index 0000000..584b2e2
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/mach-tegra/fuse.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+unsigned long long tegra_chip_uid(void);
+int tegra_sku_id(void);
+int tegra_cpu_process_id(void);
+int tegra_core_process_id(void);
+void tegra_init_fuse(void);
index fe78fba..0775265 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/interrupt.h>
 
 #include <linux/io.h>
 #include <linux/gpio.h>
@@ -60,6 +61,13 @@ struct tegra_gpio_bank {
        int bank;
        int irq;
        spinlock_t lvl_lock[4];
+#ifdef CONFIG_PM
+       u32 cnf[4];
+       u32 out[4];
+       u32 oe[4];
+       u32 int_enb[4];
+       u32 int_lvl[4];
+#endif
 };
 
 
@@ -131,7 +139,7 @@ static struct gpio_chip tegra_gpio_chip = {
        .direction_output       = tegra_gpio_direction_output,
        .set                    = tegra_gpio_set,
        .base                   = 0,
-       .ngpio                  = ARCH_NR_GPIOS,
+       .ngpio                  = TEGRA_NR_GPIOS,
 };
 
 static void tegra_gpio_irq_ack(unsigned int irq)
@@ -244,6 +252,76 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 
 }
 
+#ifdef CONFIG_PM
+void tegra_gpio_resume(void)
+{
+       unsigned long flags;
+       int b, p, i;
+
+       local_irq_save(flags);
+
+       for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+               struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+               for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
+                       unsigned int gpio = (b<<5) | (p<<3);
+                       __raw_writel(bank->cnf[p], GPIO_CNF(gpio));
+                       __raw_writel(bank->out[p], GPIO_OUT(gpio));
+                       __raw_writel(bank->oe[p], GPIO_OE(gpio));
+                       __raw_writel(bank->int_lvl[p], GPIO_INT_LVL(gpio));
+                       __raw_writel(bank->int_enb[p], GPIO_INT_ENB(gpio));
+               }
+       }
+
+       local_irq_restore(flags);
+
+       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc || (desc->status & IRQ_WAKEUP))
+                       continue;
+               enable_irq(i);
+       }
+}
+
+void tegra_gpio_suspend(void)
+{
+       unsigned long flags;
+       int b, p, i;
+
+       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc)
+                       continue;
+               if (desc->status & IRQ_WAKEUP) {
+                       int gpio = i - INT_GPIO_BASE;
+                       pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7);
+                       continue;
+               }
+               disable_irq(i);
+       }
+
+       local_irq_save(flags);
+       for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
+               struct tegra_gpio_bank *bank = &tegra_gpio_banks[b];
+
+               for (p = 0; p < ARRAY_SIZE(bank->oe); p++) {
+                       unsigned int gpio = (b<<5) | (p<<3);
+                       bank->cnf[p] = __raw_readl(GPIO_CNF(gpio));
+                       bank->out[p] = __raw_readl(GPIO_OUT(gpio));
+                       bank->oe[p] = __raw_readl(GPIO_OE(gpio));
+                       bank->int_enb[p] = __raw_readl(GPIO_INT_ENB(gpio));
+                       bank->int_lvl[p] = __raw_readl(GPIO_INT_LVL(gpio));
+               }
+       }
+       local_irq_restore(flags);
+}
+
+static int tegra_gpio_wake_enable(unsigned int irq, unsigned int enable)
+{
+       struct tegra_gpio_bank *bank = get_irq_chip_data(irq);
+       return set_irq_wake(bank->irq, enable);
+}
+#endif
 
 static struct irq_chip tegra_gpio_irq_chip = {
        .name           = "GPIO",
@@ -251,6 +329,9 @@ static struct irq_chip tegra_gpio_irq_chip = {
        .mask           = tegra_gpio_irq_mask,
        .unmask         = tegra_gpio_irq_unmask,
        .set_type       = tegra_gpio_irq_set_type,
+#ifdef CONFIG_PM
+       .set_wake       = tegra_gpio_wake_enable,
+#endif
 };
 
 
@@ -274,7 +355,7 @@ static int __init tegra_gpio_init(void)
 
        gpiochip_add(&tegra_gpio_chip);
 
-       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + ARCH_NR_GPIOS); i++) {
+       for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
                bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
 
                lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
@@ -312,15 +393,16 @@ static int dbg_gpio_show(struct seq_file *s, void *unused)
        for (i = 0; i < 7; i++) {
                for (j = 0; j < 4; j++) {
                        int gpio = tegra_gpio_compose(i, j, 0);
-                       seq_printf(s, "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
-                              i, j,
-                              __raw_readl(GPIO_CNF(gpio)),
-                              __raw_readl(GPIO_OE(gpio)),
-                              __raw_readl(GPIO_OUT(gpio)),
-                              __raw_readl(GPIO_IN(gpio)),
-                              __raw_readl(GPIO_INT_STA(gpio)),
-                              __raw_readl(GPIO_INT_ENB(gpio)),
-                              __raw_readl(GPIO_INT_LVL(gpio)));
+                       seq_printf(s,
+                               "%d:%d %02x %02x %02x %02x %02x %02x %06x\n",
+                               i, j,
+                               __raw_readl(GPIO_CNF(gpio)),
+                               __raw_readl(GPIO_OE(gpio)),
+                               __raw_readl(GPIO_OUT(gpio)),
+                               __raw_readl(GPIO_IN(gpio)),
+                               __raw_readl(GPIO_INT_STA(gpio)),
+                               __raw_readl(GPIO_INT_ENB(gpio)),
+                               __raw_readl(GPIO_INT_LVL(gpio)));
                }
        }
        return 0;
index 2896f25..d772395 100644 (file)
@@ -23,4 +23,9 @@
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 
+int clk_enable_cansleep(struct clk *clk);
+void clk_disable_cansleep(struct clk *clk);
+int clk_set_rate_cansleep(struct clk *clk, unsigned long rate);
+int clk_set_parent_cansleep(struct clk *clk, struct clk *parent);
+
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/dma.h b/arch/arm/mach-tegra/include/mach/dma.h
new file mode 100644 (file)
index 0000000..39011bd
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * arch/arm/mach-tegra/include/mach/dma.h
+ *
+ * Copyright (c) 2008-2009, 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 __MACH_TEGRA_DMA_H
+#define __MACH_TEGRA_DMA_H
+
+#include <linux/list.h>
+
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
+
+struct tegra_dma_req;
+struct tegra_dma_channel;
+
+#define TEGRA_DMA_REQ_SEL_CNTR                 0
+#define TEGRA_DMA_REQ_SEL_I2S_2                        1
+#define TEGRA_DMA_REQ_SEL_I2S_1                        2
+#define TEGRA_DMA_REQ_SEL_SPD_I                        3
+#define TEGRA_DMA_REQ_SEL_UI_I                 4
+#define TEGRA_DMA_REQ_SEL_MIPI                 5
+#define TEGRA_DMA_REQ_SEL_I2S2_2               6
+#define TEGRA_DMA_REQ_SEL_I2S2_1               7
+#define TEGRA_DMA_REQ_SEL_UARTA                        8
+#define TEGRA_DMA_REQ_SEL_UARTB                        9
+#define TEGRA_DMA_REQ_SEL_UARTC                        10
+#define TEGRA_DMA_REQ_SEL_SPI                  11
+#define TEGRA_DMA_REQ_SEL_AC97                 12
+#define TEGRA_DMA_REQ_SEL_ACMODEM              13
+#define TEGRA_DMA_REQ_SEL_SL4B                 14
+#define TEGRA_DMA_REQ_SEL_SL2B1                        15
+#define TEGRA_DMA_REQ_SEL_SL2B2                        16
+#define TEGRA_DMA_REQ_SEL_SL2B3                        17
+#define TEGRA_DMA_REQ_SEL_SL2B4                        18
+#define TEGRA_DMA_REQ_SEL_UARTD                        19
+#define TEGRA_DMA_REQ_SEL_UARTE                        20
+#define TEGRA_DMA_REQ_SEL_I2C                  21
+#define TEGRA_DMA_REQ_SEL_I2C2                 22
+#define TEGRA_DMA_REQ_SEL_I2C3                 23
+#define TEGRA_DMA_REQ_SEL_DVC_I2C              24
+#define TEGRA_DMA_REQ_SEL_OWR                  25
+#define TEGRA_DMA_REQ_SEL_INVALID              31
+
+enum tegra_dma_mode {
+       TEGRA_DMA_SHARED = 1,
+       TEGRA_DMA_MODE_CONTINOUS = 2,
+       TEGRA_DMA_MODE_ONESHOT = 4,
+};
+
+enum tegra_dma_req_error {
+       TEGRA_DMA_REQ_SUCCESS = 0,
+       TEGRA_DMA_REQ_ERROR_ABORTED,
+       TEGRA_DMA_REQ_INFLIGHT,
+};
+
+enum tegra_dma_req_buff_status {
+       TEGRA_DMA_REQ_BUF_STATUS_EMPTY = 0,
+       TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL,
+       TEGRA_DMA_REQ_BUF_STATUS_FULL,
+};
+
+struct tegra_dma_req {
+       struct list_head node;
+       unsigned int modid;
+       int instance;
+
+       /* Called when the req is complete and from the DMA ISR context.
+        * When this is called the req structure is no longer queued by
+        * the DMA channel.
+        *
+        * State of the DMA depends on the number of req it has. If there are
+        * no DMA requests queued up, then it will STOP the DMA. It there are
+        * more requests in the DMA, then it will queue the next request.
+        */
+       void (*complete)(struct tegra_dma_req *req);
+
+       /*  This is a called from the DMA ISR context when the DMA is still in
+        *  progress and is actively filling same buffer.
+        *
+        *  In case of continous mode receive, this threshold is 1/2 the buffer
+        *  size. In other cases, this will not even be called as there is no
+        *  hardware support for it.
+        *
+        * In the case of continous mode receive, if there is next req already
+        * queued, DMA programs the HW to use that req when this req is
+        * completed. If there is no "next req" queued, then DMA ISR doesn't do
+        * anything before calling this callback.
+        *
+        *      This is mainly used by the cases, where the clients has queued
+        *      only one req and want to get some sort of DMA threshold
+        *      callback to program the next buffer.
+        *
+        */
+       void (*threshold)(struct tegra_dma_req *req);
+
+       /* 1 to copy to memory.
+        * 0 to copy from the memory to device FIFO */
+       int to_memory;
+
+       void *virt_addr;
+
+       unsigned long source_addr;
+       unsigned long dest_addr;
+       unsigned long dest_wrap;
+       unsigned long source_wrap;
+       unsigned long source_bus_width;
+       unsigned long dest_bus_width;
+       unsigned long req_sel;
+       unsigned int size;
+
+       /* Updated by the DMA driver on the conpletion of the request. */
+       int bytes_transferred;
+       int status;
+
+       /* DMA completion tracking information */
+       int buffer_status;
+
+       /* Client specific data */
+       void *dev;
+};
+
+int tegra_dma_enqueue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+int tegra_dma_dequeue_req(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+void tegra_dma_dequeue(struct tegra_dma_channel *ch);
+void tegra_dma_flush(struct tegra_dma_channel *ch);
+
+bool tegra_dma_is_req_inflight(struct tegra_dma_channel *ch,
+       struct tegra_dma_req *req);
+bool tegra_dma_is_empty(struct tegra_dma_channel *ch);
+
+struct tegra_dma_channel *tegra_dma_allocate_channel(int mode);
+void tegra_dma_free_channel(struct tegra_dma_channel *ch);
+
+int __init tegra_dma_init(void);
+
+#endif
+
+#endif
index 540e822..e31f486 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <mach/irqs.h>
 
-#define ARCH_NR_GPIOS          INT_GPIO_NR
+#define TEGRA_NR_GPIOS         INT_GPIO_NR
 
 #include <asm-generic/gpio.h>
 
@@ -35,7 +35,7 @@
 
 static inline int gpio_to_irq(unsigned int gpio)
 {
-       if (gpio < ARCH_NR_GPIOS)
+       if (gpio < TEGRA_NR_GPIOS)
                return INT_GPIO_BASE + gpio;
        return -EINVAL;
 }
index 6014edf..56e43b3 100644 (file)
@@ -21,4 +21,8 @@
 #ifndef __MACH_TEGRA_HARDWARE_H
 #define __MACH_TEGRA_HARDWARE_H
 
+#define PCIBIOS_MIN_IO                 0x1000
+#define PCIBIOS_MIN_MEM                        0
+#define pcibios_assign_all_busses()    1
+
 #endif
index 35edfc3..f0981b1 100644 (file)
@@ -21,7 +21,7 @@
 #ifndef __MACH_TEGRA_IO_H
 #define __MACH_TEGRA_IO_H
 
-#define IO_SPACE_LIMIT 0xffffffff
+#define IO_SPACE_LIMIT 0xffff
 
 /* On TEGRA, many peripherals are very closely packed in
  * two 256MB io windows (that actually only use about 64KB
  *
  */
 
+#define IO_IRAM_PHYS   0x40000000
+#define IO_IRAM_VIRT   0xFE400000
+#define IO_IRAM_SIZE   SZ_256K
+
 #define IO_CPU_PHYS     0x50040000
 #define IO_CPU_VIRT     0xFE000000
 #define IO_CPU_SIZE    SZ_16K
@@ -55,6 +59,8 @@
                IO_TO_VIRT_XLATE((n), IO_APB_PHYS, IO_APB_VIRT) :       \
        IO_TO_VIRT_BETWEEN((n), IO_CPU_PHYS, IO_CPU_SIZE) ?             \
                IO_TO_VIRT_XLATE((n), IO_CPU_PHYS, IO_CPU_VIRT) :       \
+       IO_TO_VIRT_BETWEEN((n), IO_IRAM_PHYS, IO_IRAM_SIZE) ?           \
+               IO_TO_VIRT_XLATE((n), IO_IRAM_PHYS, IO_IRAM_VIRT) :     \
        0)
 
 #ifndef __ASSEMBLER__
@@ -67,10 +73,20 @@ void tegra_iounmap(volatile void __iomem *addr);
 
 #define IO_ADDRESS(n) ((void __iomem *) IO_TO_VIRT(n))
 
+#ifdef CONFIG_TEGRA_PCI
+extern void __iomem *tegra_pcie_io_base;
+
+static inline void __iomem *__io(unsigned long addr)
+{
+       return tegra_pcie_io_base + (addr & IO_SPACE_LIMIT);
+}
+#else
 static inline void __iomem *__io(unsigned long addr)
 {
        return (void __iomem *)addr;
 }
+#endif
+
 #define __io(a)         __io(a)
 #define __mem_pci(a)    (a)
 
index 1741f7d..44a4f4b 100644 (file)
 
 #include <asm/sizes.h>
 
+#define TEGRA_IRAM_BASE                        0x40000000
+#define TEGRA_IRAM_SIZE                        SZ_256K
+
 #define TEGRA_ARM_PERIF_BASE           0x50040000
 #define TEGRA_ARM_PERIF_SIZE           SZ_8K
 
+#define TEGRA_ARM_PL310_BASE           0x50043000
+#define TEGRA_ARM_PL310_SIZE           SZ_4K
+
 #define TEGRA_ARM_INT_DIST_BASE                0x50041000
 #define TEGRA_ARM_INT_DIST_SIZE                SZ_4K
 
 #define TEGRA_FLOW_CTRL_BASE           0x60007000
 #define TEGRA_FLOW_CTRL_SIZE           20
 
-#define TEGRA_STATMON_BASE             0x6000C4000
+#define TEGRA_AHB_DMA_BASE             0x60008000
+#define TEGRA_AHB_DMA_SIZE             SZ_4K
+
+#define TEGRA_AHB_DMA_CH0_BASE         0x60009000
+#define TEGRA_AHB_DMA_CH0_SIZE         32
+
+#define TEGRA_APB_DMA_BASE             0x6000A000
+#define TEGRA_APB_DMA_SIZE             SZ_4K
+
+#define TEGRA_APB_DMA_CH0_BASE         0x6000B000
+#define TEGRA_APB_DMA_CH0_SIZE         32
+
+#define TEGRA_AHB_GIZMO_BASE           0x6000C004
+#define TEGRA_AHB_GIZMO_SIZE           0x10C
+
+#define TEGRA_STATMON_BASE             0x6000C400
 #define TEGRA_STATMON_SIZE             SZ_1K
 
 #define TEGRA_GPIO_BASE                        0x6000D000
 #define TEGRA_I2C3_BASE                        0x7000C500
 #define TEGRA_I2C3_SIZE                        SZ_256
 
-#define TEGRA_OWR_BASE                 0x7000D000
+#define TEGRA_OWR_BASE                 0x7000C600
 #define TEGRA_OWR_SIZE                 80
 
 #define TEGRA_DVC_BASE                 0x7000D000
 #define TEGRA_USB_BASE                 0xC5000000
 #define TEGRA_USB_SIZE                 SZ_16K
 
-#define TEGRA_USB1_BASE                        0xC5004000
-#define TEGRA_USB1_SIZE                        SZ_16K
-
-#define TEGRA_USB2_BASE                        0xC5008000
+#define TEGRA_USB2_BASE                        0xC5004000
 #define TEGRA_USB2_SIZE                        SZ_16K
 
+#define TEGRA_USB3_BASE                        0xC5008000
+#define TEGRA_USB3_SIZE                        SZ_16K
+
 #define TEGRA_SDMMC1_BASE              0xC8000000
 #define TEGRA_SDMMC1_SIZE              SZ_512
 
index 20f640e..71bbf34 100644 (file)
@@ -25,6 +25,7 @@
 
 #define IRQ_LOCALTIMER                  29
 
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
 /* Primary Interrupt Controller */
 #define INT_PRI_BASE                   (INT_GIC_BASE + 32)
 #define INT_TMR1                       (INT_PRI_BASE + 0)
 #define INT_GPIO_NR                    (28 * 8)
 
 #define NR_IRQS                                (INT_GPIO_BASE + INT_GPIO_NR)
+#endif
 
 #endif
diff --git a/arch/arm/mach-tegra/include/mach/legacy_irq.h b/arch/arm/mach-tegra/include/mach/legacy_irq.h
new file mode 100644 (file)
index 0000000..db1eb3d
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-tegra/include/mach/legacy_irq.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H
+#define _ARCH_ARM_MACH_TEGRA_LEGARY_IRQ_H
+
+void tegra_legacy_mask_irq(unsigned int irq);
+void tegra_legacy_unmask_irq(unsigned int irq);
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
+void tegra_legacy_force_irq_set(unsigned int irq);
+void tegra_legacy_force_irq_clr(unsigned int irq);
+int tegra_legacy_force_irq_status(unsigned int irq);
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
+unsigned long tegra_legacy_vfiq(int nr);
+unsigned long tegra_legacy_class(int nr);
+
+#endif
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-t2.h b/arch/arm/mach-tegra/include/mach/pinmux-t2.h
new file mode 100644 (file)
index 0000000..e5b9d74
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * linux/arch/arm/mach-tegra/include/mach/pinmux-t2.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_PINMUX_T2_H
+#define __MACH_TEGRA_PINMUX_T2_H
+
+enum tegra_pingroup {
+       TEGRA_PINGROUP_ATA = 0,
+       TEGRA_PINGROUP_ATB,
+       TEGRA_PINGROUP_ATC,
+       TEGRA_PINGROUP_ATD,
+       TEGRA_PINGROUP_ATE,
+       TEGRA_PINGROUP_CDEV1,
+       TEGRA_PINGROUP_CDEV2,
+       TEGRA_PINGROUP_CRTP,
+       TEGRA_PINGROUP_CSUS,
+       TEGRA_PINGROUP_DAP1,
+       TEGRA_PINGROUP_DAP2,
+       TEGRA_PINGROUP_DAP3,
+       TEGRA_PINGROUP_DAP4,
+       TEGRA_PINGROUP_DDC,
+       TEGRA_PINGROUP_DTA,
+       TEGRA_PINGROUP_DTB,
+       TEGRA_PINGROUP_DTC,
+       TEGRA_PINGROUP_DTD,
+       TEGRA_PINGROUP_DTE,
+       TEGRA_PINGROUP_DTF,
+       TEGRA_PINGROUP_GMA,
+       TEGRA_PINGROUP_GMB,
+       TEGRA_PINGROUP_GMC,
+       TEGRA_PINGROUP_GMD,
+       TEGRA_PINGROUP_GME,
+       TEGRA_PINGROUP_GPU,
+       TEGRA_PINGROUP_GPU7,
+       TEGRA_PINGROUP_GPV,
+       TEGRA_PINGROUP_HDINT,
+       TEGRA_PINGROUP_I2CP,
+       TEGRA_PINGROUP_IRRX,
+       TEGRA_PINGROUP_IRTX,
+       TEGRA_PINGROUP_KBCA,
+       TEGRA_PINGROUP_KBCB,
+       TEGRA_PINGROUP_KBCC,
+       TEGRA_PINGROUP_KBCD,
+       TEGRA_PINGROUP_KBCE,
+       TEGRA_PINGROUP_KBCF,
+       TEGRA_PINGROUP_LCSN,
+       TEGRA_PINGROUP_LD0,
+       TEGRA_PINGROUP_LD1,
+       TEGRA_PINGROUP_LD10,
+       TEGRA_PINGROUP_LD11,
+       TEGRA_PINGROUP_LD12,
+       TEGRA_PINGROUP_LD13,
+       TEGRA_PINGROUP_LD14,
+       TEGRA_PINGROUP_LD15,
+       TEGRA_PINGROUP_LD16,
+       TEGRA_PINGROUP_LD17,
+       TEGRA_PINGROUP_LD2,
+       TEGRA_PINGROUP_LD3,
+       TEGRA_PINGROUP_LD4,
+       TEGRA_PINGROUP_LD5,
+       TEGRA_PINGROUP_LD6,
+       TEGRA_PINGROUP_LD7,
+       TEGRA_PINGROUP_LD8,
+       TEGRA_PINGROUP_LD9,
+       TEGRA_PINGROUP_LDC,
+       TEGRA_PINGROUP_LDI,
+       TEGRA_PINGROUP_LHP0,
+       TEGRA_PINGROUP_LHP1,
+       TEGRA_PINGROUP_LHP2,
+       TEGRA_PINGROUP_LHS,
+       TEGRA_PINGROUP_LM0,
+       TEGRA_PINGROUP_LM1,
+       TEGRA_PINGROUP_LPP,
+       TEGRA_PINGROUP_LPW0,
+       TEGRA_PINGROUP_LPW1,
+       TEGRA_PINGROUP_LPW2,
+       TEGRA_PINGROUP_LSC0,
+       TEGRA_PINGROUP_LSC1,
+       TEGRA_PINGROUP_LSCK,
+       TEGRA_PINGROUP_LSDA,
+       TEGRA_PINGROUP_LSDI,
+       TEGRA_PINGROUP_LSPI,
+       TEGRA_PINGROUP_LVP0,
+       TEGRA_PINGROUP_LVP1,
+       TEGRA_PINGROUP_LVS,
+       TEGRA_PINGROUP_OWC,
+       TEGRA_PINGROUP_PMC,
+       TEGRA_PINGROUP_PTA,
+       TEGRA_PINGROUP_RM,
+       TEGRA_PINGROUP_SDB,
+       TEGRA_PINGROUP_SDC,
+       TEGRA_PINGROUP_SDD,
+       TEGRA_PINGROUP_SDIO1,
+       TEGRA_PINGROUP_SLXA,
+       TEGRA_PINGROUP_SLXC,
+       TEGRA_PINGROUP_SLXD,
+       TEGRA_PINGROUP_SLXK,
+       TEGRA_PINGROUP_SPDI,
+       TEGRA_PINGROUP_SPDO,
+       TEGRA_PINGROUP_SPIA,
+       TEGRA_PINGROUP_SPIB,
+       TEGRA_PINGROUP_SPIC,
+       TEGRA_PINGROUP_SPID,
+       TEGRA_PINGROUP_SPIE,
+       TEGRA_PINGROUP_SPIF,
+       TEGRA_PINGROUP_SPIG,
+       TEGRA_PINGROUP_SPIH,
+       TEGRA_PINGROUP_UAA,
+       TEGRA_PINGROUP_UAB,
+       TEGRA_PINGROUP_UAC,
+       TEGRA_PINGROUP_UAD,
+       TEGRA_PINGROUP_UCA,
+       TEGRA_PINGROUP_UCB,
+       TEGRA_PINGROUP_UDA,
+       /* these pin groups only have pullup and pull down control */
+       TEGRA_PINGROUP_CK32,
+       TEGRA_PINGROUP_DDRC,
+       TEGRA_PINGROUP_PMCA,
+       TEGRA_PINGROUP_PMCB,
+       TEGRA_PINGROUP_PMCC,
+       TEGRA_PINGROUP_PMCD,
+       TEGRA_PINGROUP_PMCE,
+       TEGRA_PINGROUP_XM2C,
+       TEGRA_PINGROUP_XM2D,
+       TEGRA_MAX_PINGROUP,
+};
+
+enum tegra_drive_pingroup {
+       TEGRA_DRIVE_PINGROUP_AO1 = 0,
+       TEGRA_DRIVE_PINGROUP_AO2,
+       TEGRA_DRIVE_PINGROUP_AT1,
+       TEGRA_DRIVE_PINGROUP_AT2,
+       TEGRA_DRIVE_PINGROUP_CDEV1,
+       TEGRA_DRIVE_PINGROUP_CDEV2,
+       TEGRA_DRIVE_PINGROUP_CSUS,
+       TEGRA_DRIVE_PINGROUP_DAP1,
+       TEGRA_DRIVE_PINGROUP_DAP2,
+       TEGRA_DRIVE_PINGROUP_DAP3,
+       TEGRA_DRIVE_PINGROUP_DAP4,
+       TEGRA_DRIVE_PINGROUP_DBG,
+       TEGRA_DRIVE_PINGROUP_LCD1,
+       TEGRA_DRIVE_PINGROUP_LCD2,
+       TEGRA_DRIVE_PINGROUP_SDMMC2,
+       TEGRA_DRIVE_PINGROUP_SDMMC3,
+       TEGRA_DRIVE_PINGROUP_SPI,
+       TEGRA_DRIVE_PINGROUP_UAA,
+       TEGRA_DRIVE_PINGROUP_UAB,
+       TEGRA_DRIVE_PINGROUP_UART2,
+       TEGRA_DRIVE_PINGROUP_UART3,
+       TEGRA_DRIVE_PINGROUP_VI1,
+       TEGRA_DRIVE_PINGROUP_VI2,
+       TEGRA_DRIVE_PINGROUP_XM2A,
+       TEGRA_DRIVE_PINGROUP_XM2C,
+       TEGRA_DRIVE_PINGROUP_XM2D,
+       TEGRA_DRIVE_PINGROUP_XM2CLK,
+       TEGRA_DRIVE_PINGROUP_MEMCOMP,
+       TEGRA_MAX_DRIVE_PINGROUP,
+};
+
+#endif
+
index 41c8ce5..defd877 100644 (file)
 #ifndef __MACH_TEGRA_PINMUX_H
 #define __MACH_TEGRA_PINMUX_H
 
-enum tegra_pingroup {
-       TEGRA_PINGROUP_ATA = 0,
-       TEGRA_PINGROUP_ATB,
-       TEGRA_PINGROUP_ATC,
-       TEGRA_PINGROUP_ATD,
-       TEGRA_PINGROUP_ATE,
-       TEGRA_PINGROUP_CDEV1,
-       TEGRA_PINGROUP_CDEV2,
-       TEGRA_PINGROUP_CRTP,
-       TEGRA_PINGROUP_CSUS,
-       TEGRA_PINGROUP_DAP1,
-       TEGRA_PINGROUP_DAP2,
-       TEGRA_PINGROUP_DAP3,
-       TEGRA_PINGROUP_DAP4,
-       TEGRA_PINGROUP_DDC,
-       TEGRA_PINGROUP_DTA,
-       TEGRA_PINGROUP_DTB,
-       TEGRA_PINGROUP_DTC,
-       TEGRA_PINGROUP_DTD,
-       TEGRA_PINGROUP_DTE,
-       TEGRA_PINGROUP_DTF,
-       TEGRA_PINGROUP_GMA,
-       TEGRA_PINGROUP_GMB,
-       TEGRA_PINGROUP_GMC,
-       TEGRA_PINGROUP_GMD,
-       TEGRA_PINGROUP_GME,
-       TEGRA_PINGROUP_GPU,
-       TEGRA_PINGROUP_GPU7,
-       TEGRA_PINGROUP_GPV,
-       TEGRA_PINGROUP_HDINT,
-       TEGRA_PINGROUP_I2CP,
-       TEGRA_PINGROUP_IRRX,
-       TEGRA_PINGROUP_IRTX,
-       TEGRA_PINGROUP_KBCA,
-       TEGRA_PINGROUP_KBCB,
-       TEGRA_PINGROUP_KBCC,
-       TEGRA_PINGROUP_KBCD,
-       TEGRA_PINGROUP_KBCE,
-       TEGRA_PINGROUP_KBCF,
-       TEGRA_PINGROUP_LCSN,
-       TEGRA_PINGROUP_LD0,
-       TEGRA_PINGROUP_LD1,
-       TEGRA_PINGROUP_LD10,
-       TEGRA_PINGROUP_LD11,
-       TEGRA_PINGROUP_LD12,
-       TEGRA_PINGROUP_LD13,
-       TEGRA_PINGROUP_LD14,
-       TEGRA_PINGROUP_LD15,
-       TEGRA_PINGROUP_LD16,
-       TEGRA_PINGROUP_LD17,
-       TEGRA_PINGROUP_LD2,
-       TEGRA_PINGROUP_LD3,
-       TEGRA_PINGROUP_LD4,
-       TEGRA_PINGROUP_LD5,
-       TEGRA_PINGROUP_LD6,
-       TEGRA_PINGROUP_LD7,
-       TEGRA_PINGROUP_LD8,
-       TEGRA_PINGROUP_LD9,
-       TEGRA_PINGROUP_LDC,
-       TEGRA_PINGROUP_LDI,
-       TEGRA_PINGROUP_LHP0,
-       TEGRA_PINGROUP_LHP1,
-       TEGRA_PINGROUP_LHP2,
-       TEGRA_PINGROUP_LHS,
-       TEGRA_PINGROUP_LM0,
-       TEGRA_PINGROUP_LM1,
-       TEGRA_PINGROUP_LPP,
-       TEGRA_PINGROUP_LPW0,
-       TEGRA_PINGROUP_LPW1,
-       TEGRA_PINGROUP_LPW2,
-       TEGRA_PINGROUP_LSC0,
-       TEGRA_PINGROUP_LSC1,
-       TEGRA_PINGROUP_LSCK,
-       TEGRA_PINGROUP_LSDA,
-       TEGRA_PINGROUP_LSDI,
-       TEGRA_PINGROUP_LSPI,
-       TEGRA_PINGROUP_LVP0,
-       TEGRA_PINGROUP_LVP1,
-       TEGRA_PINGROUP_LVS,
-       TEGRA_PINGROUP_OWC,
-       TEGRA_PINGROUP_PMC,
-       TEGRA_PINGROUP_PTA,
-       TEGRA_PINGROUP_RM,
-       TEGRA_PINGROUP_SDB,
-       TEGRA_PINGROUP_SDC,
-       TEGRA_PINGROUP_SDD,
-       TEGRA_PINGROUP_SDIO1,
-       TEGRA_PINGROUP_SLXA,
-       TEGRA_PINGROUP_SLXC,
-       TEGRA_PINGROUP_SLXD,
-       TEGRA_PINGROUP_SLXK,
-       TEGRA_PINGROUP_SPDI,
-       TEGRA_PINGROUP_SPDO,
-       TEGRA_PINGROUP_SPIA,
-       TEGRA_PINGROUP_SPIB,
-       TEGRA_PINGROUP_SPIC,
-       TEGRA_PINGROUP_SPID,
-       TEGRA_PINGROUP_SPIE,
-       TEGRA_PINGROUP_SPIF,
-       TEGRA_PINGROUP_SPIG,
-       TEGRA_PINGROUP_SPIH,
-       TEGRA_PINGROUP_UAA,
-       TEGRA_PINGROUP_UAB,
-       TEGRA_PINGROUP_UAC,
-       TEGRA_PINGROUP_UAD,
-       TEGRA_PINGROUP_UCA,
-       TEGRA_PINGROUP_UCB,
-       TEGRA_PINGROUP_UDA,
-       /* these pin groups only have pullup and pull down control */
-       TEGRA_PINGROUP_CK32,
-       TEGRA_PINGROUP_DDRC,
-       TEGRA_PINGROUP_PMCA,
-       TEGRA_PINGROUP_PMCB,
-       TEGRA_PINGROUP_PMCC,
-       TEGRA_PINGROUP_PMCD,
-       TEGRA_PINGROUP_PMCE,
-       TEGRA_PINGROUP_XM2C,
-       TEGRA_PINGROUP_XM2D,
-       TEGRA_MAX_PINGROUP,
-};
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#include "pinmux-t2.h"
+#else
+#error "Undefined Tegra architecture"
+#endif
 
 enum tegra_mux_func {
        TEGRA_MUX_RSVD = 0x8000,
@@ -205,6 +90,7 @@ enum tegra_mux_func {
        TEGRA_MUX_VI,
        TEGRA_MUX_VI_SENSOR_CLK,
        TEGRA_MUX_XIO,
+       TEGRA_MUX_SAFE,
        TEGRA_MAX_MUX,
 };
 
@@ -219,6 +105,18 @@ enum tegra_tristate {
        TEGRA_TRI_TRISTATE = 1,
 };
 
+enum tegra_vddio {
+       TEGRA_VDDIO_BB = 0,
+       TEGRA_VDDIO_LCD,
+       TEGRA_VDDIO_VI,
+       TEGRA_VDDIO_UART,
+       TEGRA_VDDIO_DDR,
+       TEGRA_VDDIO_NAND,
+       TEGRA_VDDIO_SYS,
+       TEGRA_VDDIO_AUDIO,
+       TEGRA_VDDIO_SD,
+};
+
 struct tegra_pingroup_config {
        enum tegra_pingroup     pingroup;
        enum tegra_mux_func     func;
@@ -270,38 +168,6 @@ enum tegra_pull_strength {
        TEGRA_MAX_PULL,
 };
 
-enum tegra_drive_pingroup {
-       TEGRA_DRIVE_PINGROUP_AO1 = 0,
-       TEGRA_DRIVE_PINGROUP_AO2,
-       TEGRA_DRIVE_PINGROUP_AT1,
-       TEGRA_DRIVE_PINGROUP_AT2,
-       TEGRA_DRIVE_PINGROUP_CDEV1,
-       TEGRA_DRIVE_PINGROUP_CDEV2,
-       TEGRA_DRIVE_PINGROUP_CSUS,
-       TEGRA_DRIVE_PINGROUP_DAP1,
-       TEGRA_DRIVE_PINGROUP_DAP2,
-       TEGRA_DRIVE_PINGROUP_DAP3,
-       TEGRA_DRIVE_PINGROUP_DAP4,
-       TEGRA_DRIVE_PINGROUP_DBG,
-       TEGRA_DRIVE_PINGROUP_LCD1,
-       TEGRA_DRIVE_PINGROUP_LCD2,
-       TEGRA_DRIVE_PINGROUP_SDMMC2,
-       TEGRA_DRIVE_PINGROUP_SDMMC3,
-       TEGRA_DRIVE_PINGROUP_SPI,
-       TEGRA_DRIVE_PINGROUP_UAA,
-       TEGRA_DRIVE_PINGROUP_UAB,
-       TEGRA_DRIVE_PINGROUP_UART2,
-       TEGRA_DRIVE_PINGROUP_UART3,
-       TEGRA_DRIVE_PINGROUP_VI1,
-       TEGRA_DRIVE_PINGROUP_VI2,
-       TEGRA_DRIVE_PINGROUP_XM2A,
-       TEGRA_DRIVE_PINGROUP_XM2C,
-       TEGRA_DRIVE_PINGROUP_XM2D,
-       TEGRA_DRIVE_PINGROUP_XM2CLK,
-       TEGRA_DRIVE_PINGROUP_MEMCOMP,
-       TEGRA_MAX_DRIVE_PINGROUP,
-};
-
 enum tegra_drive {
        TEGRA_DRIVE_DIV_8 = 0,
        TEGRA_DRIVE_DIV_4,
@@ -331,18 +197,44 @@ struct tegra_drive_pingroup_config {
        enum tegra_slew slew_falling;
 };
 
-int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func);
-int tegra_pinmux_set_tristate(enum tegra_pingroup pg, enum tegra_tristate tristate);
-int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg, enum tegra_pullupdown pupd);
+struct tegra_drive_pingroup_desc {
+       const char *name;
+       s16 reg;
+};
+
+struct tegra_pingroup_desc {
+       const char *name;
+       int funcs[4];
+       int func_safe;
+       int vddio;
+       s16 tri_reg;    /* offset into the TRISTATE_REG_* register bank */
+       s16 mux_reg;    /* offset into the PIN_MUX_CTL_* register bank */
+       s16 pupd_reg;   /* offset into the PULL_UPDOWN_REG_* register bank */
+       s8 tri_bit;     /* offset into the TRISTATE_REG_* register bit */
+       s8 mux_bit;     /* offset into the PIN_MUX_CTL_* register bit */
+       s8 pupd_bit;    /* offset into the PULL_UPDOWN_REG_* register bit */
+};
+
+extern const struct tegra_pingroup_desc tegra_soc_pingroups[];
+extern const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[];
 
-void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
-       enum tegra_mux_func func, enum tegra_pullupdown pupd,
+int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
        enum tegra_tristate tristate);
+int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
+       enum tegra_pullupdown pupd);
 
-void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len);
+void tegra_pinmux_config_table(const struct tegra_pingroup_config *config,
+       int len);
 
 void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
        int len);
-
+void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
+       int len);
+void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
+       int len);
+void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_tristate tristate);
+void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_pullupdown pupd);
 #endif
 
index 9fe2c5c..31848a9 100644 (file)
@@ -49,6 +49,12 @@ static struct map_desc tegra_io_desc[] __initdata = {
                .length = IO_CPU_SIZE,
                .type = MT_DEVICE,
        },
+       {
+               .virtual = IO_IRAM_VIRT,
+               .pfn = __phys_to_pfn(IO_IRAM_PHYS),
+               .length = IO_IRAM_SIZE,
+               .type = MT_DEVICE,
+       },
 };
 
 void __init tegra_map_common_io(void)
index 1fdbe70..50a8dfb 100644 (file)
@@ -4,6 +4,8 @@
  * Author:
  *     Colin Cross <ccross@google.com>
  *
+ * Copyright (C) 2010, 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.
 
 #include "board.h"
 
+#define INT_SYS_NR     (INT_GPIO_BASE - INT_PRI_BASE)
+#define INT_SYS_SZ     (INT_SEC_BASE - INT_PRI_BASE)
+#define PPI_NR         ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
+
+#define APBDMA_IRQ_STA_CPU  0x14
+#define APBDMA_IRQ_MASK_SET 0x20
+#define APBDMA_IRQ_MASK_CLR 0x24
+
+#define ICTLR_CPU_IER          0x20
+#define ICTLR_CPU_IER_SET      0x24
+#define ICTLR_CPU_IER_CLR      0x28
+#define ICTLR_CPU_IEP_CLASS    0x2c
+#define ICTLR_COP_IER          0x30
+#define ICTLR_COP_IER_SET      0x34
+#define ICTLR_COP_IER_CLR      0x38
+#define ICTLR_COP_IEP_CLASS    0x3c
+
+static void (*gic_mask_irq)(unsigned int irq);
+static void (*gic_unmask_irq)(unsigned int irq);
+
+#define irq_to_ictlr(irq) (((irq)-32) >> 5)
+static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);
+#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100)
+
+static void tegra_mask(unsigned int irq)
+{
+       void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
+       gic_mask_irq(irq);
+       writel(1<<(irq&31), addr+ICTLR_CPU_IER_CLR);
+}
+
+static void tegra_unmask(unsigned int irq)
+{
+       void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq));
+       gic_unmask_irq(irq);
+       writel(1<<(irq&31), addr+ICTLR_CPU_IER_SET);
+}
+
+#ifdef CONFIG_PM
+
+static int tegra_set_wake(unsigned int irq, unsigned int on)
+{
+       return 0;
+}
+#endif
+
+static struct irq_chip tegra_irq = {
+       .name           = "PPI",
+       .mask           = tegra_mask,
+       .unmask         = tegra_unmask,
+#ifdef CONFIG_PM
+       .set_wake       = tegra_set_wake,
+#endif
+};
+
 void __init tegra_init_irq(void)
 {
+       struct irq_chip *gic;
+       unsigned int i;
+
+       for (i = 0; i < PPI_NR; i++) {
+               writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR);
+               writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
+       }
+
        gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
        gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+
+       gic = get_irq_chip(29);
+       gic_unmask_irq = gic->unmask;
+       gic_mask_irq = gic->mask;
+       tegra_irq.ack = gic->ack;
+#ifdef CONFIG_SMP
+       tegra_irq.set_affinity = gic->set_affinity;
+#endif
+
+       for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+               set_irq_chip(i, &tegra_irq);
+               set_irq_handler(i, handle_level_irq);
+               set_irq_flags(i, IRQF_VALID);
+       }
+}
+
+#ifdef CONFIG_PM
+static u32 cop_ier[PPI_NR];
+static u32 cpu_ier[PPI_NR];
+static u32 cpu_iep[PPI_NR];
+
+void tegra_irq_suspend(void)
+{
+       unsigned long flags;
+       int i;
+
+       for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc)
+                       continue;
+               if (desc->status & IRQ_WAKEUP) {
+                       pr_debug("irq %d is wakeup\n", i);
+                       continue;
+               }
+               disable_irq(i);
+       }
+
+       local_irq_save(flags);
+       for (i = 0; i < PPI_NR; i++) {
+               void __iomem *ictlr = ictlr_to_virt(i);
+               cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
+               cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
+               cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
+               writel(~0, ictlr + ICTLR_COP_IER_CLR);
+       }
+       local_irq_restore(flags);
+}
+
+void tegra_irq_resume(void)
+{
+       unsigned long flags;
+       int i;
+
+       local_irq_save(flags);
+       for (i = 0; i < PPI_NR; i++) {
+               void __iomem *ictlr = ictlr_to_virt(i);
+               writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
+               writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+               writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
+               writel(0, ictlr + ICTLR_COP_IEP_CLASS);
+               writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
+               writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
+       }
+       local_irq_restore(flags);
+
+       for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
+               struct irq_desc *desc = irq_to_desc(i);
+               if (!desc || (desc->status & IRQ_WAKEUP))
+                       continue;
+               enable_irq(i);
+       }
 }
+#endif
diff --git a/arch/arm/mach-tegra/legacy_irq.c b/arch/arm/mach-tegra/legacy_irq.c
new file mode 100644 (file)
index 0000000..7cc8601
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * arch/arm/mach-tegra/legacy_irq.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <mach/iomap.h>
+#include <mach/legacy_irq.h>
+
+#define ICTLR_CPU_IER          0x20
+#define ICTLR_CPU_IER_SET      0x24
+#define ICTLR_CPU_IER_CLR      0x28
+#define ICTLR_CPU_IEP_CLASS    0x2C
+#define ICTLR_CPU_IEP_VFIQ     0x08
+#define ICTLR_CPU_IEP_FIR      0x14
+#define ICTLR_CPU_IEP_FIR_SET  0x18
+#define ICTLR_CPU_IEP_FIR_CLR  0x1c
+
+static void __iomem *ictlr_reg_base[] = {
+       IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
+       IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
+       IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
+       IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
+};
+
+/* When going into deep sleep, the CPU is powered down, taking the GIC with it
+   In order to wake, the wake interrupts need to be enabled in the legacy
+   interrupt controller. */
+void tegra_legacy_unmask_irq(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IER_SET);
+}
+
+void tegra_legacy_mask_irq(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IER_CLR);
+}
+
+void tegra_legacy_force_irq_set(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_SET);
+}
+
+void tegra_legacy_force_irq_clr(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(1 << (irq & 31), base + ICTLR_CPU_IEP_FIR_CLR);
+}
+
+int tegra_legacy_force_irq_status(unsigned int irq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       return !!(readl(base + ICTLR_CPU_IEP_FIR) & (1 << (irq & 31)));
+}
+
+void tegra_legacy_select_fiq(unsigned int irq, bool fiq)
+{
+       void __iomem *base;
+       pr_debug("%s: %d\n", __func__, irq);
+
+       irq -= 32;
+       base = ictlr_reg_base[irq>>5];
+       writel(fiq << (irq & 31), base + ICTLR_CPU_IEP_CLASS);
+}
+
+unsigned long tegra_legacy_vfiq(int nr)
+{
+       void __iomem *base;
+       base = ictlr_reg_base[nr];
+       return readl(base + ICTLR_CPU_IEP_VFIQ);
+}
+
+unsigned long tegra_legacy_class(int nr)
+{
+       void __iomem *base;
+       base = ictlr_reg_base[nr];
+       return readl(base + ICTLR_CPU_IEP_CLASS);
+}
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
new file mode 100644 (file)
index 0000000..53f5fa3
--- /dev/null
@@ -0,0 +1,915 @@
+/*
+ * arch/arm/mach-tegra/pci.c
+ *
+ * PCIe host controller driver for TEGRA(2) SOCs
+ *
+ * Copyright (c) 2010, CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on NVIDIA PCIe driver
+ * Copyright (c) 2008-2009, NVIDIA Corporation.
+ *
+ * Bits taken from arch/arm/mach-dove/pcie.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+
+#include <asm/sizes.h>
+#include <asm/mach/pci.h>
+
+#include <mach/pinmux.h>
+#include <mach/iomap.h>
+#include <mach/clk.h>
+
+/* register definitions */
+#define AFI_OFFSET     0x3800
+#define PADS_OFFSET    0x3000
+#define RP0_OFFSET     0x0000
+#define RP1_OFFSET     0x1000
+
+#define AFI_AXI_BAR0_SZ        0x00
+#define AFI_AXI_BAR1_SZ        0x04
+#define AFI_AXI_BAR2_SZ        0x08
+#define AFI_AXI_BAR3_SZ        0x0c
+#define AFI_AXI_BAR4_SZ        0x10
+#define AFI_AXI_BAR5_SZ        0x14
+
+#define AFI_AXI_BAR0_START     0x18
+#define AFI_AXI_BAR1_START     0x1c
+#define AFI_AXI_BAR2_START     0x20
+#define AFI_AXI_BAR3_START     0x24
+#define AFI_AXI_BAR4_START     0x28
+#define AFI_AXI_BAR5_START     0x2c
+
+#define AFI_FPCI_BAR0  0x30
+#define AFI_FPCI_BAR1  0x34
+#define AFI_FPCI_BAR2  0x38
+#define AFI_FPCI_BAR3  0x3c
+#define AFI_FPCI_BAR4  0x40
+#define AFI_FPCI_BAR5  0x44
+
+#define AFI_CACHE_BAR0_SZ      0x48
+#define AFI_CACHE_BAR0_ST      0x4c
+#define AFI_CACHE_BAR1_SZ      0x50
+#define AFI_CACHE_BAR1_ST      0x54
+
+#define AFI_MSI_BAR_SZ         0x60
+#define AFI_MSI_FPCI_BAR_ST    0x64
+#define AFI_MSI_AXI_BAR_ST     0x68
+
+#define AFI_CONFIGURATION              0xac
+#define  AFI_CONFIGURATION_EN_FPCI     (1 << 0)
+
+#define AFI_FPCI_ERROR_MASKS   0xb0
+
+#define AFI_INTR_MASK          0xb4
+#define  AFI_INTR_MASK_INT_MASK        (1 << 0)
+#define  AFI_INTR_MASK_MSI_MASK        (1 << 8)
+
+#define AFI_INTR_CODE          0xb8
+#define  AFI_INTR_CODE_MASK    0xf
+#define  AFI_INTR_MASTER_ABORT 4
+#define  AFI_INTR_LEGACY       6
+
+#define AFI_INTR_SIGNATURE     0xbc
+#define AFI_SM_INTR_ENABLE     0xc4
+
+#define AFI_AFI_INTR_ENABLE            0xc8
+#define  AFI_INTR_EN_INI_SLVERR                (1 << 0)
+#define  AFI_INTR_EN_INI_DECERR                (1 << 1)
+#define  AFI_INTR_EN_TGT_SLVERR                (1 << 2)
+#define  AFI_INTR_EN_TGT_DECERR                (1 << 3)
+#define  AFI_INTR_EN_TGT_WRERR         (1 << 4)
+#define  AFI_INTR_EN_DFPCI_DECERR      (1 << 5)
+#define  AFI_INTR_EN_AXI_DECERR                (1 << 6)
+#define  AFI_INTR_EN_FPCI_TIMEOUT      (1 << 7)
+
+#define AFI_PCIE_CONFIG                                        0x0f8
+#define  AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE         (1 << 1)
+#define  AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE         (1 << 2)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK      (0xf << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_SINGLE    (0x0 << 20)
+#define  AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL      (0x1 << 20)
+
+#define AFI_FUSE                       0x104
+#define  AFI_FUSE_PCIE_T0_GEN2_DIS     (1 << 2)
+
+#define AFI_PEX0_CTRL                  0x110
+#define AFI_PEX1_CTRL                  0x118
+#define  AFI_PEX_CTRL_RST              (1 << 0)
+#define  AFI_PEX_CTRL_REFCLK_EN                (1 << 3)
+
+#define RP_VEND_XP     0x00000F00
+#define  RP_VEND_XP_DL_UP      (1 << 30)
+
+#define RP_LINK_CONTROL_STATUS                 0x00000090
+#define  RP_LINK_CONTROL_STATUS_LINKSTAT_MASK  0x3fff0000
+
+#define PADS_CTL_SEL           0x0000009C
+
+#define PADS_CTL               0x000000A0
+#define  PADS_CTL_IDDQ_1L      (1 << 0)
+#define  PADS_CTL_TX_DATA_EN_1L        (1 << 6)
+#define  PADS_CTL_RX_DATA_EN_1L        (1 << 10)
+
+#define PADS_PLL_CTL                           0x000000B8
+#define  PADS_PLL_CTL_RST_B4SM                 (1 << 1)
+#define  PADS_PLL_CTL_LOCKDET                  (1 << 8)
+#define  PADS_PLL_CTL_REFCLK_MASK              (0x3 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CML      (0 << 16)
+#define  PADS_PLL_CTL_REFCLK_INTERNAL_CMOS     (1 << 16)
+#define  PADS_PLL_CTL_REFCLK_EXTERNAL          (2 << 16)
+#define  PADS_PLL_CTL_TXCLKREF_MASK            (0x1 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV10           (0 << 20)
+#define  PADS_PLL_CTL_TXCLKREF_DIV5            (1 << 20)
+
+/* PMC access is required for PCIE xclk (un)clamping */
+#define PMC_SCRATCH42          0x144
+#define PMC_SCRATCH42_PCX_CLAMP        (1 << 0)
+
+static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+#define pmc_writel(value, reg) \
+       __raw_writel(value, (u32)reg_pmc_base + (reg))
+#define pmc_readl(reg) \
+       __raw_readl((u32)reg_pmc_base + (reg))
+
+/*
+ * Tegra2 defines 1GB in the AXI address map for PCIe.
+ *
+ * That address space is split into different regions, with sizes and
+ * offsets as follows:
+ *
+ * 0x80000000 - 0x80003fff - PCI controller registers
+ * 0x80004000 - 0x80103fff - PCI configuration space
+ * 0x80104000 - 0x80203fff - PCI extended configuration space
+ * 0x80203fff - 0x803fffff - unused
+ * 0x80400000 - 0x8040ffff - downstream IO
+ * 0x80410000 - 0x8fffffff - unused
+ * 0x90000000 - 0x9fffffff - non-prefetchable memory
+ * 0xa0000000 - 0xbfffffff - prefetchable memory
+ */
+#define TEGRA_PCIE_BASE                0x80000000
+
+#define PCIE_REGS_SZ           SZ_16K
+#define PCIE_CFG_OFF           PCIE_REGS_SZ
+#define PCIE_CFG_SZ            SZ_1M
+#define PCIE_EXT_CFG_OFF       (PCIE_CFG_SZ + PCIE_CFG_OFF)
+#define PCIE_EXT_CFG_SZ                SZ_1M
+#define PCIE_IOMAP_SZ          (PCIE_REGS_SZ + PCIE_CFG_SZ + PCIE_EXT_CFG_SZ)
+
+#define MMIO_BASE              (TEGRA_PCIE_BASE + SZ_4M)
+#define MMIO_SIZE              SZ_64K
+#define MEM_BASE_0             (TEGRA_PCIE_BASE + SZ_256M)
+#define MEM_SIZE_0             SZ_128M
+#define MEM_BASE_1             (MEM_BASE_0 + MEM_SIZE_0)
+#define MEM_SIZE_1             SZ_128M
+#define PREFETCH_MEM_BASE_0    (MEM_BASE_1 + MEM_SIZE_1)
+#define PREFETCH_MEM_SIZE_0    SZ_128M
+#define PREFETCH_MEM_BASE_1    (PREFETCH_MEM_BASE_0 + PREFETCH_MEM_SIZE_0)
+#define PREFETCH_MEM_SIZE_1    SZ_128M
+
+#define  PCIE_CONF_BUS(b)      ((b) << 16)
+#define  PCIE_CONF_DEV(d)      ((d) << 11)
+#define  PCIE_CONF_FUNC(f)     ((f) << 8)
+#define  PCIE_CONF_REG(r)      \
+       (((r) & ~0x3) | (((r) < 256) ? PCIE_CFG_OFF : PCIE_EXT_CFG_OFF))
+
+struct tegra_pcie_port {
+       int                     index;
+       u8                      root_bus_nr;
+       void __iomem            *base;
+
+       bool                    link_up;
+
+       char                    io_space_name[16];
+       char                    mem_space_name[16];
+       char                    prefetch_space_name[20];
+       struct resource         res[3];
+};
+
+struct tegra_pcie_info {
+       struct tegra_pcie_port  port[2];
+       int                     num_ports;
+
+       void __iomem            *regs;
+       struct resource         res_mmio;
+
+       struct clk              *pex_clk;
+       struct clk              *afi_clk;
+       struct clk              *pcie_xclk;
+       struct clk              *pll_e;
+};
+
+static struct tegra_pcie_info tegra_pcie = {
+       .res_mmio = {
+               .name = "PCI IO",
+               .start = MMIO_BASE,
+               .end = MMIO_BASE + MMIO_SIZE - 1,
+               .flags = IORESOURCE_MEM,
+       },
+};
+
+void __iomem *tegra_pcie_io_base;
+EXPORT_SYMBOL(tegra_pcie_io_base);
+
+static inline void afi_writel(u32 value, unsigned long offset)
+{
+       writel(value, offset + AFI_OFFSET + tegra_pcie.regs);
+}
+
+static inline u32 afi_readl(unsigned long offset)
+{
+       return readl(offset + AFI_OFFSET + tegra_pcie.regs);
+}
+
+static inline void pads_writel(u32 value, unsigned long offset)
+{
+       writel(value, offset + PADS_OFFSET + tegra_pcie.regs);
+}
+
+static inline u32 pads_readl(unsigned long offset)
+{
+       return readl(offset + PADS_OFFSET + tegra_pcie.regs);
+}
+
+static struct tegra_pcie_port *bus_to_port(int bus)
+{
+       int i;
+
+       for (i = tegra_pcie.num_ports - 1; i >= 0; i--) {
+               int rbus = tegra_pcie.port[i].root_bus_nr;
+               if (rbus != -1 && rbus == bus)
+                       break;
+       }
+
+       return i >= 0 ? tegra_pcie.port + i : NULL;
+}
+
+static int tegra_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
+                               int where, int size, u32 *val)
+{
+       struct tegra_pcie_port *pp = bus_to_port(bus->number);
+       void __iomem *addr;
+
+       if (pp) {
+               if (devfn != 0) {
+                       *val = 0xffffffff;
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+               }
+
+               addr = pp->base + (where & ~0x3);
+       } else {
+               addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) +
+                                         PCIE_CONF_DEV(PCI_SLOT(devfn)) +
+                                         PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
+                                         PCIE_CONF_REG(where));
+       }
+
+       *val = readl(addr);
+
+       if (size == 1)
+               *val = (*val >> (8 * (where & 3))) & 0xff;
+       else if (size == 2)
+               *val = (*val >> (8 * (where & 3))) & 0xffff;
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int tegra_pcie_write_conf(struct pci_bus *bus, unsigned int devfn,
+                                int where, int size, u32 val)
+{
+       struct tegra_pcie_port *pp = bus_to_port(bus->number);
+       void __iomem *addr;
+
+       u32 mask;
+       u32 tmp;
+
+       if (pp) {
+               if (devfn != 0)
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+
+               addr = pp->base + (where & ~0x3);
+       } else {
+               addr = tegra_pcie.regs + (PCIE_CONF_BUS(bus->number) +
+                                         PCIE_CONF_DEV(PCI_SLOT(devfn)) +
+                                         PCIE_CONF_FUNC(PCI_FUNC(devfn)) +
+                                         PCIE_CONF_REG(where));
+       }
+
+       if (size == 4) {
+               writel(val, addr);
+               return PCIBIOS_SUCCESSFUL;
+       }
+
+       if (size == 2)
+               mask = ~(0xffff << ((where & 0x3) * 8));
+       else if (size == 1)
+               mask = ~(0xff << ((where & 0x3) * 8));
+       else
+               return PCIBIOS_BAD_REGISTER_NUMBER;
+
+       tmp = readl(addr) & mask;
+       tmp |= val << ((where & 0x3) * 8);
+       writel(tmp, addr);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops tegra_pcie_ops = {
+       .read   = tegra_pcie_read_conf,
+       .write  = tegra_pcie_write_conf,
+};
+
+static void __devinit tegra_pcie_fixup_bridge(struct pci_dev *dev)
+{
+       u16 reg;
+
+       if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) {
+               pci_read_config_word(dev, PCI_COMMAND, &reg);
+               reg |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+                       PCI_COMMAND_MASTER | PCI_COMMAND_SERR);
+               pci_write_config_word(dev, PCI_COMMAND, reg);
+       }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_fixup_bridge);
+
+/* Tegra PCIE root complex wrongly reports device class */
+static void __devinit tegra_pcie_fixup_class(struct pci_dev *dev)
+{
+       dev->class = PCI_CLASS_BRIDGE_PCI << 8;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf0, tegra_pcie_fixup_class);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_NVIDIA, 0x0bf1, tegra_pcie_fixup_class);
+
+/* Tegra PCIE requires relaxed ordering */
+static void __devinit tegra_pcie_relax_enable(struct pci_dev *dev)
+{
+       u16 val16;
+       int pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
+
+       if (pos <= 0) {
+               dev_err(&dev->dev, "skipping relaxed ordering fixup\n");
+               return;
+       }
+
+       pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &val16);
+       val16 |= PCI_EXP_DEVCTL_RELAX_EN;
+       pci_write_config_word(dev, pos + PCI_EXP_DEVCTL, val16);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, tegra_pcie_relax_enable);
+
+static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
+{
+       struct tegra_pcie_port *pp;
+
+       if (nr >= tegra_pcie.num_ports)
+               return 0;
+
+       pp = tegra_pcie.port + nr;
+       pp->root_bus_nr = sys->busnr;
+
+       /*
+        * IORESOURCE_IO
+        */
+       snprintf(pp->io_space_name, sizeof(pp->io_space_name),
+                "PCIe %d I/O", pp->index);
+       pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
+       pp->res[0].name = pp->io_space_name;
+       if (pp->index == 0) {
+               pp->res[0].start = PCIBIOS_MIN_IO;
+               pp->res[0].end = pp->res[0].start + SZ_32K - 1;
+       } else {
+               pp->res[0].start = PCIBIOS_MIN_IO + SZ_32K;
+               pp->res[0].end = IO_SPACE_LIMIT;
+       }
+       pp->res[0].flags = IORESOURCE_IO;
+       if (request_resource(&ioport_resource, &pp->res[0]))
+               panic("Request PCIe IO resource failed\n");
+       sys->resource[0] = &pp->res[0];
+
+       /*
+        * IORESOURCE_MEM
+        */
+       snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
+                "PCIe %d MEM", pp->index);
+       pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
+       pp->res[1].name = pp->mem_space_name;
+       if (pp->index == 0) {
+               pp->res[1].start = MEM_BASE_0;
+               pp->res[1].end = pp->res[1].start + MEM_SIZE_0 - 1;
+       } else {
+               pp->res[1].start = MEM_BASE_1;
+               pp->res[1].end = pp->res[1].start + MEM_SIZE_1 - 1;
+       }
+       pp->res[1].flags = IORESOURCE_MEM;
+       if (request_resource(&iomem_resource, &pp->res[1]))
+               panic("Request PCIe Memory resource failed\n");
+       sys->resource[1] = &pp->res[1];
+
+       /*
+        * IORESOURCE_MEM | IORESOURCE_PREFETCH
+        */
+       snprintf(pp->prefetch_space_name, sizeof(pp->prefetch_space_name),
+                "PCIe %d PREFETCH MEM", pp->index);
+       pp->prefetch_space_name[sizeof(pp->prefetch_space_name) - 1] = 0;
+       pp->res[2].name = pp->prefetch_space_name;
+       if (pp->index == 0) {
+               pp->res[2].start = PREFETCH_MEM_BASE_0;
+               pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_0 - 1;
+       } else {
+               pp->res[2].start = PREFETCH_MEM_BASE_1;
+               pp->res[2].end = pp->res[2].start + PREFETCH_MEM_SIZE_1 - 1;
+       }
+       pp->res[2].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+       if (request_resource(&iomem_resource, &pp->res[2]))
+               panic("Request PCIe Prefetch Memory resource failed\n");
+       sys->resource[2] = &pp->res[2];
+
+       return 1;
+}
+
+static int tegra_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return INT_PCIE_INTR;
+}
+
+static struct pci_bus __init *tegra_pcie_scan_bus(int nr,
+                                                 struct pci_sys_data *sys)
+{
+       struct tegra_pcie_port *pp;
+
+       if (nr >= tegra_pcie.num_ports)
+               return 0;
+
+       pp = tegra_pcie.port + nr;
+       pp->root_bus_nr = sys->busnr;
+
+       return pci_scan_bus(sys->busnr, &tegra_pcie_ops, sys);
+}
+
+static struct hw_pci tegra_pcie_hw __initdata = {
+       .nr_controllers = 2,
+       .setup          = tegra_pcie_setup,
+       .scan           = tegra_pcie_scan_bus,
+       .swizzle        = pci_std_swizzle,
+       .map_irq        = tegra_pcie_map_irq,
+};
+
+
+static irqreturn_t tegra_pcie_isr(int irq, void *arg)
+{
+       const char *err_msg[] = {
+               "Unknown",
+               "AXI slave error",
+               "AXI decode error",
+               "Target abort",
+               "Master abort",
+               "Invalid write",
+               "Response decoding error",
+               "AXI response decoding error",
+               "Transcation timeout",
+       };
+
+       u32 code, signature;
+
+       code = afi_readl(AFI_INTR_CODE) & AFI_INTR_CODE_MASK;
+       signature = afi_readl(AFI_INTR_SIGNATURE);
+       afi_writel(0, AFI_INTR_CODE);
+
+       if (code == AFI_INTR_LEGACY)
+               return IRQ_NONE;
+
+       if (code >= ARRAY_SIZE(err_msg))
+               code = 0;
+
+       /*
+        * do not pollute kernel log with master abort reports since they
+        * happen a lot during enumeration
+        */
+       if (code == AFI_INTR_MASTER_ABORT)
+               pr_debug("PCIE: %s, signature: %08x\n", err_msg[code], signature);
+       else
+               pr_err("PCIE: %s, signature: %08x\n", err_msg[code], signature);
+
+       return IRQ_HANDLED;
+}
+
+static void tegra_pcie_setup_translations(void)
+{
+       u32 fpci_bar;
+       u32 size;
+       u32 axi_address;
+
+       /* Bar 0: config Bar */
+       fpci_bar = ((u32)0xfdff << 16);
+       size = PCIE_CFG_SZ;
+       axi_address = TEGRA_PCIE_BASE + PCIE_CFG_OFF;
+       afi_writel(axi_address, AFI_AXI_BAR0_START);
+       afi_writel(size >> 12, AFI_AXI_BAR0_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR0);
+
+       /* Bar 1: extended config Bar */
+       fpci_bar = ((u32)0xfe1 << 20);
+       size = PCIE_EXT_CFG_SZ;
+       axi_address = TEGRA_PCIE_BASE + PCIE_EXT_CFG_OFF;
+       afi_writel(axi_address, AFI_AXI_BAR1_START);
+       afi_writel(size >> 12, AFI_AXI_BAR1_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR1);
+
+       /* Bar 2: downstream IO bar */
+       fpci_bar = ((__u32)0xfdfc << 16);
+       size = MMIO_SIZE;
+       axi_address = MMIO_BASE;
+       afi_writel(axi_address, AFI_AXI_BAR2_START);
+       afi_writel(size >> 12, AFI_AXI_BAR2_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR2);
+
+       /* Bar 3: prefetchable memory BAR */
+       fpci_bar = (((PREFETCH_MEM_BASE_0 >> 12) & 0x0fffffff) << 4) | 0x1;
+       size =  PREFETCH_MEM_SIZE_0 +  PREFETCH_MEM_SIZE_1;
+       axi_address = PREFETCH_MEM_BASE_0;
+       afi_writel(axi_address, AFI_AXI_BAR3_START);
+       afi_writel(size >> 12, AFI_AXI_BAR3_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR3);
+
+       /* Bar 4: non prefetchable memory BAR */
+       fpci_bar = (((MEM_BASE_0 >> 12) & 0x0FFFFFFF) << 4) | 0x1;
+       size = MEM_SIZE_0 + MEM_SIZE_1;
+       axi_address = MEM_BASE_0;
+       afi_writel(axi_address, AFI_AXI_BAR4_START);
+       afi_writel(size >> 12, AFI_AXI_BAR4_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR4);
+
+       /* Bar 5: NULL out the remaining BAR as it is not used */
+       fpci_bar = 0;
+       size = 0;
+       axi_address = 0;
+       afi_writel(axi_address, AFI_AXI_BAR5_START);
+       afi_writel(size >> 12, AFI_AXI_BAR5_SZ);
+       afi_writel(fpci_bar, AFI_FPCI_BAR5);
+
+       /* map all upstream transactions as uncached */
+       afi_writel(PHYS_OFFSET, AFI_CACHE_BAR0_ST);
+       afi_writel(0, AFI_CACHE_BAR0_SZ);
+       afi_writel(0, AFI_CACHE_BAR1_ST);
+       afi_writel(0, AFI_CACHE_BAR1_SZ);
+
+       /* No MSI */
+       afi_writel(0, AFI_MSI_FPCI_BAR_ST);
+       afi_writel(0, AFI_MSI_BAR_SZ);
+       afi_writel(0, AFI_MSI_AXI_BAR_ST);
+       afi_writel(0, AFI_MSI_BAR_SZ);
+}
+
+static void tegra_pcie_enable_controller(void)
+{
+       u32 val, reg;
+       int i;
+
+       /* Enable slot clock and pulse the reset signals */
+       for (i = 0, reg = AFI_PEX0_CTRL; i < 2; i++, reg += 0x8) {
+               val = afi_readl(reg) |  AFI_PEX_CTRL_REFCLK_EN;
+               afi_writel(val, reg);
+               val &= ~AFI_PEX_CTRL_RST;
+               afi_writel(val, reg);
+
+               val = afi_readl(reg) | AFI_PEX_CTRL_RST;
+               afi_writel(val, reg);
+       }
+
+       /* Enable dual controller and both ports */
+       val = afi_readl(AFI_PCIE_CONFIG);
+       val &= ~(AFI_PCIE_CONFIG_PCIEC0_DISABLE_DEVICE |
+                AFI_PCIE_CONFIG_PCIEC1_DISABLE_DEVICE |
+                AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_MASK);
+       val |= AFI_PCIE_CONFIG_SM2TMS0_XBAR_CONFIG_DUAL;
+       afi_writel(val, AFI_PCIE_CONFIG);
+
+       val = afi_readl(AFI_FUSE) & ~AFI_FUSE_PCIE_T0_GEN2_DIS;
+       afi_writel(val, AFI_FUSE);
+
+       /* Initialze internal PHY, enable up to 16 PCIE lanes */
+       pads_writel(0x0, PADS_CTL_SEL);
+
+       /* override IDDQ to 1 on all 4 lanes */
+       val = pads_readl(PADS_CTL) | PADS_CTL_IDDQ_1L;
+       pads_writel(val, PADS_CTL);
+
+       /*
+        * set up PHY PLL inputs select PLLE output as refclock,
+        * set TX ref sel to div10 (not div5)
+        */
+       val = pads_readl(PADS_PLL_CTL);
+       val &= ~(PADS_PLL_CTL_REFCLK_MASK | PADS_PLL_CTL_TXCLKREF_MASK);
+       val |= (PADS_PLL_CTL_REFCLK_INTERNAL_CML | PADS_PLL_CTL_TXCLKREF_DIV10);
+       pads_writel(val, PADS_PLL_CTL);
+
+       /* take PLL out of reset  */
+       val = pads_readl(PADS_PLL_CTL) | PADS_PLL_CTL_RST_B4SM;
+       pads_writel(val, PADS_PLL_CTL);
+
+       /*
+        * Hack, set the clock voltage to the DEFAULT provided by hw folks.
+        * This doesn't exist in the documentation
+        */
+       pads_writel(0xfa5cfa5c, 0xc8);
+
+       /* Wait for the PLL to lock */
+       do {
+               val = pads_readl(PADS_PLL_CTL);
+       } while (!(val & PADS_PLL_CTL_LOCKDET));
+
+       /* turn off IDDQ override */
+       val = pads_readl(PADS_CTL) & ~PADS_CTL_IDDQ_1L;
+       pads_writel(val, PADS_CTL);
+
+       /* enable TX/RX data */
+       val = pads_readl(PADS_CTL);
+       val |= (PADS_CTL_TX_DATA_EN_1L | PADS_CTL_RX_DATA_EN_1L);
+       pads_writel(val, PADS_CTL);
+
+       /* Take the PCIe interface module out of reset */
+       tegra_periph_reset_deassert(tegra_pcie.pcie_xclk);
+
+       /* Finally enable PCIe */
+       val = afi_readl(AFI_CONFIGURATION) | AFI_CONFIGURATION_EN_FPCI;
+       afi_writel(val, AFI_CONFIGURATION);
+
+       val = (AFI_INTR_EN_INI_SLVERR | AFI_INTR_EN_INI_DECERR |
+              AFI_INTR_EN_TGT_SLVERR | AFI_INTR_EN_TGT_DECERR |
+              AFI_INTR_EN_TGT_WRERR | AFI_INTR_EN_DFPCI_DECERR);
+       afi_writel(val, AFI_AFI_INTR_ENABLE);
+       afi_writel(0xffffffff, AFI_SM_INTR_ENABLE);
+
+       /* FIXME: No MSI for now, only INT */
+       afi_writel(AFI_INTR_MASK_INT_MASK, AFI_INTR_MASK);
+
+       /* Disable all execptions */
+       afi_writel(0, AFI_FPCI_ERROR_MASKS);
+
+       return;
+}
+
+static void tegra_pcie_xclk_clamp(bool clamp)
+{
+       u32 reg;
+
+       reg = pmc_readl(PMC_SCRATCH42) & ~PMC_SCRATCH42_PCX_CLAMP;
+
+       if (clamp)
+               reg |= PMC_SCRATCH42_PCX_CLAMP;
+
+       pmc_writel(reg, PMC_SCRATCH42);
+}
+
+static int tegra_pcie_power_on(void)
+{
+       tegra_pcie_xclk_clamp(true);
+       tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+       tegra_pcie_xclk_clamp(false);
+
+       clk_enable(tegra_pcie.afi_clk);
+       clk_enable(tegra_pcie.pex_clk);
+       return clk_enable(tegra_pcie.pll_e);
+}
+
+static void tegra_pcie_power_off(void)
+{
+       tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
+       tegra_periph_reset_assert(tegra_pcie.afi_clk);
+       tegra_periph_reset_assert(tegra_pcie.pex_clk);
+
+       tegra_pcie_xclk_clamp(true);
+}
+
+static int tegra_pcie_clocks_get(void)
+{
+       int err;
+
+       tegra_pcie.pex_clk = clk_get(NULL, "pex");
+       if (IS_ERR(tegra_pcie.pex_clk))
+               return PTR_ERR(tegra_pcie.pex_clk);
+
+       tegra_pcie.afi_clk = clk_get(NULL, "afi");
+       if (IS_ERR(tegra_pcie.afi_clk)) {
+               err = PTR_ERR(tegra_pcie.afi_clk);
+               goto err_afi_clk;
+       }
+
+       tegra_pcie.pcie_xclk = clk_get(NULL, "pcie_xclk");
+       if (IS_ERR(tegra_pcie.pcie_xclk)) {
+               err =  PTR_ERR(tegra_pcie.pcie_xclk);
+               goto err_pcie_xclk;
+       }
+
+       tegra_pcie.pll_e = clk_get_sys(NULL, "pll_e");
+       if (IS_ERR(tegra_pcie.pll_e)) {
+               err = PTR_ERR(tegra_pcie.pll_e);
+               goto err_pll_e;
+       }
+
+       return 0;
+
+err_pll_e:
+       clk_put(tegra_pcie.pcie_xclk);
+err_pcie_xclk:
+       clk_put(tegra_pcie.afi_clk);
+err_afi_clk:
+       clk_put(tegra_pcie.pex_clk);
+
+       return err;
+}
+
+static void tegra_pcie_clocks_put(void)
+{
+       clk_put(tegra_pcie.pll_e);
+       clk_put(tegra_pcie.pcie_xclk);
+       clk_put(tegra_pcie.afi_clk);
+       clk_put(tegra_pcie.pex_clk);
+}
+
+static int __init tegra_pcie_get_resources(void)
+{
+       struct resource *res_mmio = &tegra_pcie.res_mmio;
+       int err;
+
+       err = tegra_pcie_clocks_get();
+       if (err) {
+               pr_err("PCIE: failed to get clocks: %d\n", err);
+               return err;
+       }
+
+       err = tegra_pcie_power_on();
+       if (err) {
+               pr_err("PCIE: failed to power up: %d\n", err);
+               goto err_pwr_on;
+       }
+
+       tegra_pcie.regs = ioremap_nocache(TEGRA_PCIE_BASE, PCIE_IOMAP_SZ);
+       if (tegra_pcie.regs == NULL) {
+               pr_err("PCIE: Failed to map PCI/AFI registers\n");
+               err = -ENOMEM;
+               goto err_map_reg;
+       }
+
+       err = request_resource(&iomem_resource, res_mmio);
+       if (err) {
+               pr_err("PCIE: Failed to request resources: %d\n", err);
+               goto err_req_io;
+       }
+
+       tegra_pcie_io_base = ioremap_nocache(res_mmio->start,
+                                            resource_size(res_mmio));
+       if (tegra_pcie_io_base == NULL) {
+               pr_err("PCIE: Failed to map IO\n");
+               err = -ENOMEM;
+               goto err_map_io;
+       }
+
+       err = request_irq(INT_PCIE_INTR, tegra_pcie_isr,
+                         IRQF_SHARED, "PCIE", &tegra_pcie);
+       if (err) {
+               pr_err("PCIE: Failed to register IRQ: %d\n", err);
+               goto err_irq;
+       }
+       set_irq_flags(INT_PCIE_INTR, IRQF_VALID);
+
+       return 0;
+
+err_irq:
+       iounmap(tegra_pcie_io_base);
+err_map_io:
+       release_resource(&tegra_pcie.res_mmio);
+err_req_io:
+       iounmap(tegra_pcie.regs);
+err_map_reg:
+       tegra_pcie_power_off();
+err_pwr_on:
+       tegra_pcie_clocks_put();
+
+       return err;
+}
+
+/*
+ * FIXME: If there are no PCIe cards attached, then calling this function
+ * can result in the increase of the bootup time as there are big timeout
+ * loops.
+ */
+#define TEGRA_PCIE_LINKUP_TIMEOUT      200     /* up to 1.2 seconds */
+static bool tegra_pcie_check_link(struct tegra_pcie_port *pp, int idx,
+                                 u32 reset_reg)
+{
+       u32 reg;
+       int retries = 3;
+       int timeout;
+
+       do {
+               timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
+               while (timeout) {
+                       reg = readl(pp->base + RP_VEND_XP);
+
+                       if (reg & RP_VEND_XP_DL_UP)
+                               break;
+
+                       mdelay(1);
+                       timeout--;
+               }
+
+               if (!timeout)  {
+                       pr_err("PCIE: port %d: link down, retrying\n", idx);
+                       goto retry;
+               }
+
+               timeout = TEGRA_PCIE_LINKUP_TIMEOUT;
+               while (timeout) {
+                       reg = readl(pp->base + RP_LINK_CONTROL_STATUS);
+
+                       if (reg & 0x20000000)
+                               return true;
+
+                       mdelay(1);
+                       timeout--;
+               }
+
+retry:
+               /* Pulse the PEX reset */
+               reg = afi_readl(reset_reg) | AFI_PEX_CTRL_RST;
+               afi_writel(reg, reset_reg);
+               mdelay(1);
+               reg = afi_readl(reset_reg) & ~AFI_PEX_CTRL_RST;
+               afi_writel(reg, reset_reg);
+
+               retries--;
+       } while (retries);
+
+       return false;
+}
+
+static void __init tegra_pcie_add_port(int index, u32 offset, u32 reset_reg)
+{
+       struct tegra_pcie_port *pp;
+
+       pp = tegra_pcie.port + tegra_pcie.num_ports;
+
+       pp->index = -1;
+       pp->base = tegra_pcie.regs + offset;
+       pp->link_up = tegra_pcie_check_link(pp, index, reset_reg);
+
+       if (!pp->link_up) {
+               pp->base = NULL;
+               printk(KERN_INFO "PCIE: port %d: link down, ignoring\n", index);
+               return;
+       }
+
+       tegra_pcie.num_ports++;
+       pp->index = index;
+       pp->root_bus_nr = -1;
+       memset(pp->res, 0, sizeof(pp->res));
+}
+
+int __init tegra_pcie_init(bool init_port0, bool init_port1)
+{
+       int err;
+
+       if (!(init_port0 || init_port1))
+               return -ENODEV;
+
+       err = tegra_pcie_get_resources();
+       if (err)
+               return err;
+
+       tegra_pcie_enable_controller();
+
+       /* setup the AFI address translations */
+       tegra_pcie_setup_translations();
+
+       if (init_port0)
+               tegra_pcie_add_port(0, RP0_OFFSET, AFI_PEX0_CTRL);
+
+       if (init_port1)
+               tegra_pcie_add_port(1, RP1_OFFSET, AFI_PEX1_CTRL);
+
+       pci_common_init(&tegra_pcie_hw);
+
+       return 0;
+}
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c
new file mode 100644 (file)
index 0000000..a6ea34e
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * linux/arch/arm/mach-tegra/pinmux-t2-tables.c
+ *
+ * Common pinmux configurations for Tegra 2 SoCs
+ *
+ * Copyright (C) 2010 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#include <mach/iomap.h>
+#include <mach/pinmux.h>
+
+#define DRIVE_PINGROUP(pg_name, r)                             \
+       [TEGRA_DRIVE_PINGROUP_ ## pg_name] = {                  \
+               .name = #pg_name,                               \
+               .reg = r                                        \
+       }
+
+const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE_PINGROUP] = {
+       DRIVE_PINGROUP(AO1,             0x868),
+       DRIVE_PINGROUP(AO2,             0x86c),
+       DRIVE_PINGROUP(AT1,             0x870),
+       DRIVE_PINGROUP(AT2,             0x874),
+       DRIVE_PINGROUP(CDEV1,           0x878),
+       DRIVE_PINGROUP(CDEV2,           0x87c),
+       DRIVE_PINGROUP(CSUS,            0x880),
+       DRIVE_PINGROUP(DAP1,            0x884),
+       DRIVE_PINGROUP(DAP2,            0x888),
+       DRIVE_PINGROUP(DAP3,            0x88c),
+       DRIVE_PINGROUP(DAP4,            0x890),
+       DRIVE_PINGROUP(DBG,             0x894),
+       DRIVE_PINGROUP(LCD1,            0x898),
+       DRIVE_PINGROUP(LCD2,            0x89c),
+       DRIVE_PINGROUP(SDMMC2,          0x8a0),
+       DRIVE_PINGROUP(SDMMC3,          0x8a4),
+       DRIVE_PINGROUP(SPI,             0x8a8),
+       DRIVE_PINGROUP(UAA,             0x8ac),
+       DRIVE_PINGROUP(UAB,             0x8b0),
+       DRIVE_PINGROUP(UART2,           0x8b4),
+       DRIVE_PINGROUP(UART3,           0x8b8),
+       DRIVE_PINGROUP(VI1,             0x8bc),
+       DRIVE_PINGROUP(VI2,             0x8c0),
+       DRIVE_PINGROUP(XM2A,            0x8c4),
+       DRIVE_PINGROUP(XM2C,            0x8c8),
+       DRIVE_PINGROUP(XM2D,            0x8cc),
+       DRIVE_PINGROUP(XM2CLK,          0x8d0),
+       DRIVE_PINGROUP(MEMCOMP,         0x8d4),
+};
+
+#define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe,         \
+                tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)    \
+       [TEGRA_PINGROUP_ ## pg_name] = {                        \
+               .name = #pg_name,                               \
+               .vddio = TEGRA_VDDIO_ ## vdd,                   \
+               .funcs = {                                      \
+                       TEGRA_MUX_ ## f0,                       \
+                       TEGRA_MUX_ ## f1,                       \
+                       TEGRA_MUX_ ## f2,                       \
+                       TEGRA_MUX_ ## f3,                       \
+               },                                              \
+               .func_safe = TEGRA_MUX_ ## f_safe,              \
+               .tri_reg = tri_r,                               \
+               .tri_bit = tri_b,                               \
+               .mux_reg = mux_r,                               \
+               .mux_bit = mux_b,                               \
+               .pupd_reg = pupd_r,                             \
+               .pupd_bit = pupd_b,                             \
+       }
+
+const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = {
+       PINGROUP(ATA,   NAND,  IDE,       NAND,      GMI,       RSVD,          IDE,       0x14, 0,  0x80, 24, 0xA0, 0),
+       PINGROUP(ATB,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 1,  0x80, 16, 0xA0, 2),
+       PINGROUP(ATC,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 2,  0x80, 22, 0xA0, 4),
+       PINGROUP(ATD,   NAND,  IDE,       NAND,      GMI,       SDIO4,         IDE,       0x14, 3,  0x80, 20, 0xA0, 6),
+       PINGROUP(ATE,   NAND,  IDE,       NAND,      GMI,       RSVD,          IDE,       0x18, 25, 0x80, 12, 0xA0, 8),
+       PINGROUP(CDEV1, AUDIO, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    OSC,       0x14, 4,  0x88, 2,  0xA8, 0),
+       PINGROUP(CDEV2, AUDIO, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     OSC,       0x14, 5,  0x88, 4,  0xA8, 2),
+       PINGROUP(CRTP,  LCD,   CRT,       RSVD,      RSVD,      RSVD,          RSVD,      0x20, 14, 0x98, 20, 0xA4, 24),
+       PINGROUP(CSUS,  VI,    PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, PLLC_OUT1, 0x14, 6,  0x88, 6,  0xAC, 24),
+       PINGROUP(DAP1,  AUDIO, DAP1,      RSVD,      GMI,       SDIO2,         DAP1,      0x14, 7,  0x88, 20, 0xA0, 10),
+       PINGROUP(DAP2,  AUDIO, DAP2,      TWC,       RSVD,      GMI,           DAP2,      0x14, 8,  0x88, 22, 0xA0, 12),
+       PINGROUP(DAP3,  BB,    DAP3,      RSVD,      RSVD,      RSVD,          DAP3,      0x14, 9,  0x88, 24, 0xA0, 14),
+       PINGROUP(DAP4,  UART,  DAP4,      RSVD,      GMI,       RSVD,          DAP4,      0x14, 10, 0x88, 26, 0xA0, 16),
+       PINGROUP(DDC,   LCD,   I2C2,      RSVD,      RSVD,      RSVD,          RSVD4,     0x18, 31, 0x88, 0,  0xB0, 28),
+       PINGROUP(DTA,   VI,    RSVD,      SDIO2,     VI,        RSVD,          RSVD4,     0x14, 11, 0x84, 20, 0xA0, 18),
+       PINGROUP(DTB,   VI,    RSVD,      RSVD,      VI,        SPI1,          RSVD1,     0x14, 12, 0x84, 22, 0xA0, 20),
+       PINGROUP(DTC,   VI,    RSVD,      RSVD,      VI,        RSVD,          RSVD1,     0x14, 13, 0x84, 26, 0xA0, 22),
+       PINGROUP(DTD,   VI,    RSVD,      SDIO2,     VI,        RSVD,          RSVD1,     0x14, 14, 0x84, 28, 0xA0, 24),
+       PINGROUP(DTE,   VI,    RSVD,      RSVD,      VI,        SPI1,          RSVD1,     0x14, 15, 0x84, 30, 0xA0, 26),
+       PINGROUP(DTF,   VI,    I2C3,      RSVD,      VI,        RSVD,          RSVD4,     0x20, 12, 0x98, 30, 0xA0, 28),
+       PINGROUP(GMA,   NAND,  UARTE,     SPI3,      GMI,       SDIO4,         SPI3,      0x14, 28, 0x84, 0,  0xB0, 20),
+       PINGROUP(GMB,   NAND,  IDE,       NAND,      GMI,       GMI_INT,       GMI,       0x18, 29, 0x88, 28, 0xB0, 22),
+       PINGROUP(GMC,   NAND,  UARTD,     SPI4,      GMI,       SFLASH,        SPI4,      0x14, 29, 0x84, 2,  0xB0, 24),
+       PINGROUP(GMD,   NAND,  RSVD,      NAND,      GMI,       SFLASH,        GMI,       0x18, 30, 0x88, 30, 0xB0, 26),
+       PINGROUP(GME,   NAND,  RSVD,      DAP5,      GMI,       SDIO4,         GMI,       0x18, 0,  0x8C, 0,  0xA8, 24),
+       PINGROUP(GPU,   UART,  PWM,       UARTA,     GMI,       RSVD,          RSVD4,     0x14, 16, 0x8C, 4,  0xA4, 20),
+       PINGROUP(GPU7,  SYS,   RTCK,      RSVD,      RSVD,      RSVD,          RTCK,      0x20, 11, 0x98, 28, 0xA4, 6),
+       PINGROUP(GPV,   SD,    PCIE,      RSVD,      RSVD,      RSVD,          PCIE,      0x14, 17, 0x8C, 2,  0xA0, 30),
+       PINGROUP(HDINT, LCD,   HDMI,      RSVD,      RSVD,      RSVD,          HDMI,      0x1C, 23, 0x84, 4,  0xAC, 22),
+       PINGROUP(I2CP,  SYS,   I2C,       RSVD,      RSVD,      RSVD,          RSVD4,     0x14, 18, 0x88, 8,  0xA4, 2),
+       PINGROUP(IRRX,  UART,  UARTA,     UARTB,     GMI,       SPI4,          UARTB,     0x14, 20, 0x88, 18, 0xA8, 22),
+       PINGROUP(IRTX,  UART,  UARTA,     UARTB,     GMI,       SPI4,          UARTB,     0x14, 19, 0x88, 16, 0xA8, 20),
+       PINGROUP(KBCA,  SYS,   KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, KBC,       0x14, 22, 0x88, 10, 0xA4, 8),
+       PINGROUP(KBCB,  SYS,   KBC,       NAND,      SDIO2,     MIO,           KBC,       0x14, 21, 0x88, 12, 0xA4, 10),
+       PINGROUP(KBCC,  SYS,   KBC,       NAND,      TRACE,     EMC_TEST1_DLL, KBC,       0x18, 26, 0x88, 14, 0xA4, 12),
+       PINGROUP(KBCD,  SYS,   KBC,       NAND,      SDIO2,     MIO,           KBC,       0x20, 10, 0x98, 26, 0xA4, 14),
+       PINGROUP(KBCE,  SYS,   KBC,       NAND,      OWR,       RSVD,          KBC,       0x14, 26, 0x80, 28, 0xB0, 2),
+       PINGROUP(KBCF,  SYS,   KBC,       NAND,      TRACE,     MIO,           KBC,       0x14, 27, 0x80, 26, 0xB0, 0),
+       PINGROUP(LCSN,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          RSVD4,     0x1C, 31, 0x90, 12, 0xAC, 20),
+       PINGROUP(LD0,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 0,  0x94, 0,  0xAC, 12),
+       PINGROUP(LD1,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 1,  0x94, 2,  0xAC, 12),
+       PINGROUP(LD10,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 10, 0x94, 20, 0xAC, 12),
+       PINGROUP(LD11,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 11, 0x94, 22, 0xAC, 12),
+       PINGROUP(LD12,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 12, 0x94, 24, 0xAC, 12),
+       PINGROUP(LD13,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 13, 0x94, 26, 0xAC, 12),
+       PINGROUP(LD14,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 14, 0x94, 28, 0xAC, 12),
+       PINGROUP(LD15,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 15, 0x94, 30, 0xAC, 12),
+       PINGROUP(LD16,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 16, 0x98, 0,  0xAC, 12),
+       PINGROUP(LD17,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 17, 0x98, 2,  0xAC, 12),
+       PINGROUP(LD2,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 2,  0x94, 4,  0xAC, 12),
+       PINGROUP(LD3,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 3,  0x94, 6,  0xAC, 12),
+       PINGROUP(LD4,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 4,  0x94, 8,  0xAC, 12),
+       PINGROUP(LD5,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 5,  0x94, 10, 0xAC, 12),
+       PINGROUP(LD6,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 6,  0x94, 12, 0xAC, 12),
+       PINGROUP(LD7,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 7,  0x94, 14, 0xAC, 12),
+       PINGROUP(LD8,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 8,  0x94, 16, 0xAC, 12),
+       PINGROUP(LD9,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 9,  0x94, 18, 0xAC, 12),
+       PINGROUP(LDC,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 30, 0x90, 14, 0xAC, 20),
+       PINGROUP(LDI,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 6,  0x98, 16, 0xAC, 18),
+       PINGROUP(LHP0,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 18, 0x98, 10, 0xAC, 16),
+       PINGROUP(LHP1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 19, 0x98, 4,  0xAC, 14),
+       PINGROUP(LHP2,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 20, 0x98, 6,  0xAC, 14),
+       PINGROUP(LHS,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x20, 7,  0x90, 22, 0xAC, 22),
+       PINGROUP(LM0,   LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          RSVD4,     0x1C, 24, 0x90, 26, 0xAC, 22),
+       PINGROUP(LM1,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           RSVD3,     0x1C, 25, 0x90, 28, 0xAC, 22),
+       PINGROUP(LPP,   LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 8,  0x98, 14, 0xAC, 18),
+       PINGROUP(LPW0,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 3,  0x90, 0,  0xAC, 20),
+       PINGROUP(LPW1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x20, 4,  0x90, 2,  0xAC, 20),
+       PINGROUP(LPW2,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 5,  0x90, 4,  0xAC, 20),
+       PINGROUP(LSC0,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 27, 0x90, 18, 0xAC, 22),
+       PINGROUP(LSC1,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x1C, 28, 0x90, 20, 0xAC, 20),
+       PINGROUP(LSCK,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x1C, 29, 0x90, 16, 0xAC, 20),
+       PINGROUP(LSDA,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          DISPLAYA,  0x20, 1,  0x90, 8,  0xAC, 20),
+       PINGROUP(LSDI,  LCD,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          DISPLAYA,  0x20, 2,  0x90, 6,  0xAC, 20),
+       PINGROUP(LSPI,  LCD,   DISPLAYA,  DISPLAYB,  XIO,       HDMI,          DISPLAYA,  0x20, 0,  0x90, 10, 0xAC, 22),
+       PINGROUP(LVP0,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 21, 0x90, 30, 0xAC, 22),
+       PINGROUP(LVP1,  LCD,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          RSVD4,     0x1C, 22, 0x98, 8,  0xAC, 16),
+       PINGROUP(LVS,   LCD,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          RSVD4,     0x1C, 26, 0x90, 24, 0xAC, 22),
+       PINGROUP(OWC,   SYS,   OWR,       RSVD,      RSVD,      RSVD,          OWR,       0x14, 31, 0x84, 8,  0xB0, 30),
+       PINGROUP(PMC,   SYS,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          PWR_ON,    0x14, 23, 0x98, 18, -1,   -1),
+       PINGROUP(PTA,   NAND,  I2C2,      HDMI,      GMI,       RSVD,          RSVD4,     0x14, 24, 0x98, 22, 0xA4, 4),
+       PINGROUP(RM,    UART,  I2C,       RSVD,      RSVD,      RSVD,          RSVD4,     0x14, 25, 0x80, 14, 0xA4, 0),
+       PINGROUP(SDB,   SD,    UARTA,     PWM,       SDIO3,     SPI2,          PWM,       0x20, 15, 0x8C, 10, -1,   -1),
+       PINGROUP(SDC,   SD,    PWM,       TWC,       SDIO3,     SPI3,          TWC,       0x18, 1,  0x8C, 12, 0xAC, 28),
+       PINGROUP(SDD,   SD,    UARTA,     PWM,       SDIO3,     SPI3,          PWM,       0x18, 2,  0x8C, 14, 0xAC, 30),
+       PINGROUP(SDIO1, BB,    SDIO1,     RSVD,      UARTE,     UARTA,         RSVD2,     0x14, 30, 0x80, 30, 0xB0, 18),
+       PINGROUP(SLXA,  SD,    PCIE,      SPI4,      SDIO3,     SPI2,          PCIE,      0x18, 3,  0x84, 6,  0xA4, 22),
+       PINGROUP(SLXC,  SD,    SPDIF,     SPI4,      SDIO3,     SPI2,          SPI4,      0x18, 5,  0x84, 10, 0xA4, 26),
+       PINGROUP(SLXD,  SD,    SPDIF,     SPI4,      SDIO3,     SPI2,          SPI4,      0x18, 6,  0x84, 12, 0xA4, 28),
+       PINGROUP(SLXK,  SD,    PCIE,      SPI4,      SDIO3,     SPI2,          PCIE,      0x18, 7,  0x84, 14, 0xA4, 30),
+       PINGROUP(SPDI,  AUDIO, SPDIF,     RSVD,      I2C,       SDIO2,         RSVD2,     0x18, 8,  0x8C, 8,  0xA4, 16),
+       PINGROUP(SPDO,  AUDIO, SPDIF,     RSVD,      I2C,       SDIO2,         RSVD2,     0x18, 9,  0x8C, 6,  0xA4, 18),
+       PINGROUP(SPIA,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 10, 0x8C, 30, 0xA8, 4),
+       PINGROUP(SPIB,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 11, 0x8C, 28, 0xA8, 6),
+       PINGROUP(SPIC,  AUDIO, SPI1,      SPI2,      SPI3,      GMI,           GMI,       0x18, 12, 0x8C, 26, 0xA8, 8),
+       PINGROUP(SPID,  AUDIO, SPI2,      SPI1,      SPI2_ALT,  GMI,           GMI,       0x18, 13, 0x8C, 24, 0xA8, 10),
+       PINGROUP(SPIE,  AUDIO, SPI2,      SPI1,      SPI2_ALT,  GMI,           GMI,       0x18, 14, 0x8C, 22, 0xA8, 12),
+       PINGROUP(SPIF,  AUDIO, SPI3,      SPI1,      SPI2,      RSVD,          RSVD4,     0x18, 15, 0x8C, 20, 0xA8, 14),
+       PINGROUP(SPIG,  AUDIO, SPI3,      SPI2,      SPI2_ALT,  I2C,           SPI2_ALT,  0x18, 16, 0x8C, 18, 0xA8, 16),
+       PINGROUP(SPIH,  AUDIO, SPI3,      SPI2,      SPI2_ALT,  I2C,           SPI2_ALT,  0x18, 17, 0x8C, 16, 0xA8, 18),
+       PINGROUP(UAA,   BB,    SPI3,      MIPI_HS,   UARTA,     ULPI,          MIPI_HS,   0x18, 18, 0x80, 0,  0xAC, 0),
+       PINGROUP(UAB,   BB,    SPI2,      MIPI_HS,   UARTA,     ULPI,          MIPI_HS,   0x18, 19, 0x80, 2,  0xAC, 2),
+       PINGROUP(UAC,   BB,    OWR,       RSVD,      RSVD,      RSVD,          RSVD4,     0x18, 20, 0x80, 4,  0xAC, 4),
+       PINGROUP(UAD,   UART,  IRDA,      SPDIF,     UARTA,     SPI4,          SPDIF,     0x18, 21, 0x80, 6,  0xAC, 6),
+       PINGROUP(UCA,   UART,  UARTC,     RSVD,      GMI,       RSVD,          RSVD4,     0x18, 22, 0x84, 16, 0xAC, 8),
+       PINGROUP(UCB,   UART,  UARTC,     PWM,       GMI,       RSVD,          RSVD4,     0x18, 23, 0x84, 18, 0xAC, 10),
+       PINGROUP(UDA,   BB,    SPI1,      RSVD,      UARTD,     ULPI,          RSVD2,     0x20, 13, 0x80, 8,  0xB0, 16),
+       /* these pin groups only have pullup and pull down control */
+       PINGROUP(CK32,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 14),
+       PINGROUP(DDRC,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xAC, 26),
+       PINGROUP(PMCA,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 4),
+       PINGROUP(PMCB,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 6),
+       PINGROUP(PMCC,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 8),
+       PINGROUP(PMCD,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 10),
+       PINGROUP(PMCE,  SYS,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xB0, 12),
+       PINGROUP(XM2C,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 30),
+       PINGROUP(XM2D,  DDR,   RSVD,      RSVD,      RSVD,      RSVD,          RSVD,      -1,   -1, -1,   -1, 0xA8, 28),
+};
+
+#ifdef CONFIG_PM
+#define TRISTATE_REG_A         0x14
+#define TRISTATE_REG_NUM       4
+#define PIN_MUX_CTL_REG_A      0x80
+#define PIN_MUX_CTL_REG_NUM    8
+#define PULLUPDOWN_REG_A       0xa0
+#define PULLUPDOWN_REG_NUM     5
+
+static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
+                    PULLUPDOWN_REG_NUM];
+
+static inline unsigned long pg_readl(unsigned long offset)
+{
+       return readl(IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+static inline void pg_writel(unsigned long value, unsigned long offset)
+{
+       writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
+}
+
+void tegra_pinmux_suspend(void)
+{
+       unsigned int i;
+       u32 *ctx = pinmux_reg;
+
+       for (i = 0; i < TRISTATE_REG_NUM; i++)
+               *ctx++ = pg_readl(TRISTATE_REG_A + i*4);
+
+       for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
+               *ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
+
+       for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
+               *ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
+}
+
+void tegra_pinmux_resume(void)
+{
+       unsigned int i;
+       u32 *ctx = pinmux_reg;
+
+       for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
+               pg_writel(*ctx++, PIN_MUX_CTL_REG_A + i*4);
+
+       for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
+               pg_writel(*ctx++, PULLUPDOWN_REG_A + i*4);
+
+       for (i = 0; i < TRISTATE_REG_NUM; i++)
+               pg_writel(*ctx++, TRISTATE_REG_A + i*4);
+}
+#endif
index 13ae102..f80d507 100644 (file)
@@ -14,7 +14,8 @@
  *
  */
 
-
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/spinlock.h>
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
 
-
-#define TEGRA_TRI_STATE(x)     (0x14 + (4 * (x)))
-#define TEGRA_PP_MUX_CTL(x)    (0x80 + (4 * (x)))
-#define TEGRA_PP_PU_PD(x)      (0xa0 + (4 * (x)))
-
-#define REG_A 0
-#define REG_B 1
-#define REG_C 2
-#define REG_D 3
-#define REG_E 4
-#define REG_F 5
-#define REG_G 6
-
-#define REG_N -1
-
 #define HSM_EN(reg)    (((reg) >> 2) & 0x1)
 #define SCHMT_EN(reg)  (((reg) >> 3) & 0x1)
 #define LPMD(reg)      (((reg) >> 4) & 0x3)
 #define SLWR(reg)      (((reg) >> 28) & 0x3)
 #define SLWF(reg)      (((reg) >> 30) & 0x3)
 
-struct tegra_pingroup_desc {
-       const char *name;
-       int funcs[4];
-       s8 tri_reg;     /* offset into the TRISTATE_REG_* register bank */
-       s8 tri_bit;     /* offset into the TRISTATE_REG_* register bit */
-       s8 mux_reg;     /* offset into the PIN_MUX_CTL_* register bank */
-       s8 mux_bit;     /* offset into the PIN_MUX_CTL_* register bit */
-       s8 pupd_reg;    /* offset into the PULL_UPDOWN_REG_* register bank */
-       s8 pupd_bit;    /* offset into the PULL_UPDOWN_REG_* register bit */
-};
-
-#define PINGROUP(pg_name, f0, f1, f2, f3,                      \
-                tri_r, tri_b, mux_r, mux_b, pupd_r, pupd_b)    \
-       [TEGRA_PINGROUP_ ## pg_name] = {                        \
-               .name = #pg_name,                               \
-               .funcs = {                                      \
-                       TEGRA_MUX_ ## f0,                       \
-                       TEGRA_MUX_ ## f1,                       \
-                       TEGRA_MUX_ ## f2,                       \
-                       TEGRA_MUX_ ## f3,                       \
-               },                                              \
-               .tri_reg = REG_ ## tri_r,                       \
-               .tri_bit = tri_b,                               \
-               .mux_reg = REG_ ## mux_r,                       \
-               .mux_bit = mux_b,                               \
-               .pupd_reg = REG_ ## pupd_r,                     \
-               .pupd_bit = pupd_b,                             \
-       }
-
-static const struct tegra_pingroup_desc pingroups[TEGRA_MAX_PINGROUP] = {
-       PINGROUP(ATA,   IDE,       NAND,      GMI,       RSVD,          A, 0,  A, 24, A, 0),
-       PINGROUP(ATB,   IDE,       NAND,      GMI,       SDIO4,         A, 1,  A, 16, A, 2),
-       PINGROUP(ATC,   IDE,       NAND,      GMI,       SDIO4,         A, 2,  A, 22, A, 4),
-       PINGROUP(ATD,   IDE,       NAND,      GMI,       SDIO4,         A, 3,  A, 20, A, 6),
-       PINGROUP(ATE,   IDE,       NAND,      GMI,       RSVD,          B, 25, A, 12, A, 8),
-       PINGROUP(CDEV1, OSC,       PLLA_OUT,  PLLM_OUT1, AUDIO_SYNC,    A, 4,  C, 2,  C, 0),
-       PINGROUP(CDEV2, OSC,       AHB_CLK,   APB_CLK,   PLLP_OUT4,     A, 5,  C, 4,  C, 2),
-       PINGROUP(CRTP,  CRT,       RSVD,      RSVD,      RSVD,          D, 14, G, 20, B, 24),
-       PINGROUP(CSUS,  PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, A, 6,  C, 6,  D, 24),
-       PINGROUP(DAP1,  DAP1,      RSVD,      GMI,       SDIO2,         A, 7,  C, 20, A, 10),
-       PINGROUP(DAP2,  DAP2,      TWC,       RSVD,      GMI,           A, 8,  C, 22, A, 12),
-       PINGROUP(DAP3,  DAP3,      RSVD,      RSVD,      RSVD,          A, 9,  C, 24, A, 14),
-       PINGROUP(DAP4,  DAP4,      RSVD,      GMI,       RSVD,          A, 10, C, 26, A, 16),
-       PINGROUP(DDC,   I2C2,      RSVD,      RSVD,      RSVD,          B, 31, C, 0,  E, 28),
-       PINGROUP(DTA,   RSVD,      SDIO2,     VI,        RSVD,          A, 11, B, 20, A, 18),
-       PINGROUP(DTB,   RSVD,      RSVD,      VI,        SPI1,          A, 12, B, 22, A, 20),
-       PINGROUP(DTC,   RSVD,      RSVD,      VI,        RSVD,          A, 13, B, 26, A, 22),
-       PINGROUP(DTD,   RSVD,      SDIO2,     VI,        RSVD,          A, 14, B, 28, A, 24),
-       PINGROUP(DTE,   RSVD,      RSVD,      VI,        SPI1,          A, 15, B, 30, A, 26),
-       PINGROUP(DTF,   I2C3,      RSVD,      VI,        RSVD,          D, 12, G, 30, A, 28),
-       PINGROUP(GMA,   UARTE,     SPI3,      GMI,       SDIO4,         A, 28, B, 0,  E, 20),
-       PINGROUP(GMB,   IDE,       NAND,      GMI,       GMI_INT,       B, 29, C, 28, E, 22),
-       PINGROUP(GMC,   UARTD,     SPI4,      GMI,       SFLASH,        A, 29, B, 2,  E, 24),
-       PINGROUP(GMD,   RSVD,      NAND,      GMI,       SFLASH,        B, 30, C, 30, E, 26),
-       PINGROUP(GME,   RSVD,      DAP5,      GMI,       SDIO4,         B, 0,  D, 0,  C, 24),
-       PINGROUP(GPU,   PWM,       UARTA,     GMI,       RSVD,          A, 16, D, 4,  B, 20),
-       PINGROUP(GPU7,  RTCK,      RSVD,      RSVD,      RSVD,          D, 11, G, 28, B, 6),
-       PINGROUP(GPV,   PCIE,      RSVD,      RSVD,      RSVD,          A, 17, D, 2,  A, 30),
-       PINGROUP(HDINT, HDMI,      RSVD,      RSVD,      RSVD,          C, 23, B, 4,  D, 22),
-       PINGROUP(I2CP,  I2C,       RSVD,      RSVD,      RSVD,          A, 18, C, 8,  B, 2),
-       PINGROUP(IRRX,  UARTA,     UARTB,     GMI,       SPI4,          A, 20, C, 18, C, 22),
-       PINGROUP(IRTX,  UARTA,     UARTB,     GMI,       SPI4,          A, 19, C, 16, C, 20),
-       PINGROUP(KBCA,  KBC,       NAND,      SDIO2,     EMC_TEST0_DLL, A, 22, C, 10, B, 8),
-       PINGROUP(KBCB,  KBC,       NAND,      SDIO2,     MIO,           A, 21, C, 12, B, 10),
-       PINGROUP(KBCC,  KBC,       NAND,      TRACE,     EMC_TEST1_DLL, B, 26, C, 14, B, 12),
-       PINGROUP(KBCD,  KBC,       NAND,      SDIO2,     MIO,           D, 10, G, 26, B, 14),
-       PINGROUP(KBCE,  KBC,       NAND,      OWR,       RSVD,          A, 26, A, 28, E, 2),
-       PINGROUP(KBCF,  KBC,       NAND,      TRACE,     MIO,           A, 27, A, 26, E, 0),
-       PINGROUP(LCSN,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 31, E, 12, D, 20),
-       PINGROUP(LD0,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 0,  F, 0,  D, 12),
-       PINGROUP(LD1,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 1,  F, 2,  D, 12),
-       PINGROUP(LD10,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 10, F, 20, D, 12),
-       PINGROUP(LD11,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 11, F, 22, D, 12),
-       PINGROUP(LD12,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 12, F, 24, D, 12),
-       PINGROUP(LD13,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 13, F, 26, D, 12),
-       PINGROUP(LD14,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 14, F, 28, D, 12),
-       PINGROUP(LD15,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 15, F, 30, D, 12),
-       PINGROUP(LD16,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 16, G, 0,  D, 12),
-       PINGROUP(LD17,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 17, G, 2,  D, 12),
-       PINGROUP(LD2,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 2,  F, 4,  D, 12),
-       PINGROUP(LD3,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 3,  F, 6,  D, 12),
-       PINGROUP(LD4,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 4,  F, 8,  D, 12),
-       PINGROUP(LD5,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 5,  F, 10, D, 12),
-       PINGROUP(LD6,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 6,  F, 12, D, 12),
-       PINGROUP(LD7,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 7,  F, 14, D, 12),
-       PINGROUP(LD8,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 8,  F, 16, D, 12),
-       PINGROUP(LD9,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 9,  F, 18, D, 12),
-       PINGROUP(LDC,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 30, E, 14, D, 20),
-       PINGROUP(LDI,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 6,  G, 16, D, 18),
-       PINGROUP(LHP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 18, G, 10, D, 16),
-       PINGROUP(LHP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 19, G, 4,  D, 14),
-       PINGROUP(LHP2,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 20, G, 6,  D, 14),
-       PINGROUP(LHS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          D, 7,  E, 22, D, 22),
-       PINGROUP(LM0,   DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          C, 24, E, 26, D, 22),
-       PINGROUP(LM1,   DISPLAYA,  DISPLAYB,  RSVD,      CRT,           C, 25, E, 28, D, 22),
-       PINGROUP(LPP,   DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 8,  G, 14, D, 18),
-       PINGROUP(LPW0,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 3,  E, 0,  D, 20),
-       PINGROUP(LPW1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          D, 4,  E, 2,  D, 20),
-       PINGROUP(LPW2,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 5,  E, 4,  D, 20),
-       PINGROUP(LSC0,  DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 27, E, 18, D, 22),
-       PINGROUP(LSC1,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 28, E, 20, D, 20),
-       PINGROUP(LSCK,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          C, 29, E, 16, D, 20),
-       PINGROUP(LSDA,  DISPLAYA,  DISPLAYB,  SPI3,      HDMI,          D, 1,  E, 8,  D, 20),
-       PINGROUP(LSDI,  DISPLAYA,  DISPLAYB,  SPI3,      RSVD,          D, 2,  E, 6,  D, 20),
-       PINGROUP(LSPI,  DISPLAYA,  DISPLAYB,  XIO,       HDMI,          D, 0,  E, 10, D, 22),
-       PINGROUP(LVP0,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 21, E, 30, D, 22),
-       PINGROUP(LVP1,  DISPLAYA,  DISPLAYB,  RSVD,      RSVD,          C, 22, G, 8,  D, 16),
-       PINGROUP(LVS,   DISPLAYA,  DISPLAYB,  XIO,       RSVD,          C, 26, E, 24, D, 22),
-       PINGROUP(OWC,   OWR,       RSVD,      RSVD,      RSVD,          A, 31, B, 8,  E, 30),
-       PINGROUP(PMC,   PWR_ON,    PWR_INTR,  RSVD,      RSVD,          A, 23, G, 18, N, -1),
-       PINGROUP(PTA,   I2C2,      HDMI,      GMI,       RSVD,          A, 24, G, 22, B, 4),
-       PINGROUP(RM,    I2C,       RSVD,      RSVD,      RSVD,          A, 25, A, 14, B, 0),
-       PINGROUP(SDB,   UARTA,     PWM,       SDIO3,     SPI2,          D, 15, D, 10, N, -1),
-       PINGROUP(SDC,   PWM,       TWC,       SDIO3,     SPI3,          B, 1,  D, 12, D, 28),
-       PINGROUP(SDD,   UARTA,     PWM,       SDIO3,     SPI3,          B, 2,  D, 14, D, 30),
-       PINGROUP(SDIO1, SDIO1,     RSVD,      UARTE,     UARTA,         A, 30, A, 30, E, 18),
-       PINGROUP(SLXA,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 3,  B, 6,  B, 22),
-       PINGROUP(SLXC,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 5,  B, 10, B, 26),
-       PINGROUP(SLXD,  SPDIF,     SPI4,      SDIO3,     SPI2,          B, 6,  B, 12, B, 28),
-       PINGROUP(SLXK,  PCIE,      SPI4,      SDIO3,     SPI2,          B, 7,  B, 14, B, 30),
-       PINGROUP(SPDI,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 8,  D, 8,  B, 16),
-       PINGROUP(SPDO,  SPDIF,     RSVD,      I2C,       SDIO2,         B, 9,  D, 6,  B, 18),
-       PINGROUP(SPIA,  SPI1,      SPI2,      SPI3,      GMI,           B, 10, D, 30, C, 4),
-       PINGROUP(SPIB,  SPI1,      SPI2,      SPI3,      GMI,           B, 11, D, 28, C, 6),
-       PINGROUP(SPIC,  SPI1,      SPI2,      SPI3,      GMI,           B, 12, D, 26, C, 8),
-       PINGROUP(SPID,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 13, D, 24, C, 10),
-       PINGROUP(SPIE,  SPI2,      SPI1,      SPI2_ALT,  GMI,           B, 14, D, 22, C, 12),
-       PINGROUP(SPIF,  SPI3,      SPI1,      SPI2,      RSVD,          B, 15, D, 20, C, 14),
-       PINGROUP(SPIG,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 16, D, 18, C, 16),
-       PINGROUP(SPIH,  SPI3,      SPI2,      SPI2_ALT,  I2C,           B, 17, D, 16, C, 18),
-       PINGROUP(UAA,   SPI3,      MIPI_HS,   UARTA,     ULPI,          B, 18, A, 0,  D, 0),
-       PINGROUP(UAB,   SPI2,      MIPI_HS,   UARTA,     ULPI,          B, 19, A, 2,  D, 2),
-       PINGROUP(UAC,   OWR,       RSVD,      RSVD,      RSVD,          B, 20, A, 4,  D, 4),
-       PINGROUP(UAD,   IRDA,      SPDIF,     UARTA,     SPI4,          B, 21, A, 6,  D, 6),
-       PINGROUP(UCA,   UARTC,     RSVD,      GMI,       RSVD,          B, 22, B, 16, D, 8),
-       PINGROUP(UCB,   UARTC,     PWM,       GMI,       RSVD,          B, 23, B, 18, D, 10),
-       PINGROUP(UDA,   SPI1,      RSVD,      UARTD,     ULPI,          D, 13, A, 8,  E, 16),
-       /* these pin groups only have pullup and pull down control */
-       PINGROUP(CK32,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 14),
-       PINGROUP(DDRC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  D, 26),
-       PINGROUP(PMCA,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 4),
-       PINGROUP(PMCB,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 6),
-       PINGROUP(PMCC,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 8),
-       PINGROUP(PMCD,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 10),
-       PINGROUP(PMCE,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  E, 12),
-       PINGROUP(XM2C,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 30),
-       PINGROUP(XM2D,  RSVD,      RSVD,      RSVD,      RSVD,          N, -1,  N, -1,  C, 28),
-};
+static const struct tegra_pingroup_desc *const pingroups = tegra_soc_pingroups;
+static const struct tegra_drive_pingroup_desc *const drive_pingroups = tegra_soc_drive_pingroups;
 
 static char *tegra_mux_names[TEGRA_MAX_MUX] = {
        [TEGRA_MUX_AHB_CLK] = "AHB_CLK",
@@ -256,48 +96,7 @@ static char *tegra_mux_names[TEGRA_MAX_MUX] = {
        [TEGRA_MUX_VI] = "VI",
        [TEGRA_MUX_VI_SENSOR_CLK] = "VI_SENSOR_CLK",
        [TEGRA_MUX_XIO] = "XIO",
-};
-
-struct tegra_drive_pingroup_desc {
-       const char *name;
-       s16 reg;
-};
-
-#define DRIVE_PINGROUP(pg_name, r)                             \
-       [TEGRA_DRIVE_PINGROUP_ ## pg_name] = {                  \
-               .name = #pg_name,                               \
-               .reg = r                                        \
-       }
-
-static const struct tegra_drive_pingroup_desc drive_pingroups[TEGRA_MAX_PINGROUP] = {
-       DRIVE_PINGROUP(AO1,             0x868),
-       DRIVE_PINGROUP(AO2,             0x86c),
-       DRIVE_PINGROUP(AT1,             0x870),
-       DRIVE_PINGROUP(AT2,             0x874),
-       DRIVE_PINGROUP(CDEV1,           0x878),
-       DRIVE_PINGROUP(CDEV2,           0x87c),
-       DRIVE_PINGROUP(CSUS,            0x880),
-       DRIVE_PINGROUP(DAP1,            0x884),
-       DRIVE_PINGROUP(DAP2,            0x888),
-       DRIVE_PINGROUP(DAP3,            0x88c),
-       DRIVE_PINGROUP(DAP4,            0x890),
-       DRIVE_PINGROUP(DBG,             0x894),
-       DRIVE_PINGROUP(LCD1,            0x898),
-       DRIVE_PINGROUP(LCD2,            0x89c),
-       DRIVE_PINGROUP(SDMMC2,  0x8a0),
-       DRIVE_PINGROUP(SDMMC3,  0x8a4),
-       DRIVE_PINGROUP(SPI,             0x8a8),
-       DRIVE_PINGROUP(UAA,             0x8ac),
-       DRIVE_PINGROUP(UAB,             0x8b0),
-       DRIVE_PINGROUP(UART2,           0x8b4),
-       DRIVE_PINGROUP(UART3,           0x8b8),
-       DRIVE_PINGROUP(VI1,             0x8bc),
-       DRIVE_PINGROUP(VI2,             0x8c0),
-       DRIVE_PINGROUP(XM2A,            0x8c4),
-       DRIVE_PINGROUP(XM2C,            0x8c8),
-       DRIVE_PINGROUP(XM2D,            0x8cc),
-       DRIVE_PINGROUP(XM2CLK,  0x8d0),
-       DRIVE_PINGROUP(MEMCOMP, 0x8d4),
+       [TEGRA_MUX_SAFE] = "<safe>",
 };
 
 static const char *tegra_drive_names[TEGRA_MAX_DRIVE] = {
@@ -381,22 +180,27 @@ static inline void pg_writel(unsigned long value, unsigned long offset)
        writel(value, IO_TO_VIRT(TEGRA_APB_MISC_BASE + offset));
 }
 
-int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func)
+static int tegra_pinmux_set_func(const struct tegra_pingroup_config *config)
 {
        int mux = -1;
        int i;
        unsigned long reg;
        unsigned long flags;
+       enum tegra_pingroup pg = config->pingroup;
+       enum tegra_mux_func func = config->func;
 
        if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
                return -ERANGE;
 
-       if (pingroups[pg].mux_reg == REG_N)
+       if (pingroups[pg].mux_reg < 0)
                return -EINVAL;
 
        if (func < 0)
                return -ERANGE;
 
+       if (func == TEGRA_MUX_SAFE)
+               func = pingroups[pg].func_safe;
+
        if (func & TEGRA_MUX_RSVD) {
                mux = func & 0x3;
        } else {
@@ -413,10 +217,10 @@ int tegra_pinmux_set_func(enum tegra_pingroup pg, enum tegra_mux_func func)
 
        spin_lock_irqsave(&mux_lock, flags);
 
-       reg = pg_readl(TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+       reg = pg_readl(pingroups[pg].mux_reg);
        reg &= ~(0x3 << pingroups[pg].mux_bit);
        reg |= mux << pingroups[pg].mux_bit;
-       pg_writel(reg, TEGRA_PP_MUX_CTL(pingroups[pg].mux_reg));
+       pg_writel(reg, pingroups[pg].mux_reg);
 
        spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -432,16 +236,16 @@ int tegra_pinmux_set_tristate(enum tegra_pingroup pg,
        if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
                return -ERANGE;
 
-       if (pingroups[pg].tri_reg == REG_N)
+       if (pingroups[pg].tri_reg < 0)
                return -EINVAL;
 
        spin_lock_irqsave(&mux_lock, flags);
 
-       reg = pg_readl(TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+       reg = pg_readl(pingroups[pg].tri_reg);
        reg &= ~(0x1 << pingroups[pg].tri_bit);
        if (tristate)
                reg |= 1 << pingroups[pg].tri_bit;
-       pg_writel(reg, TEGRA_TRI_STATE(pingroups[pg].tri_reg));
+       pg_writel(reg, pingroups[pg].tri_reg);
 
        spin_unlock_irqrestore(&mux_lock, flags);
 
@@ -457,7 +261,7 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
        if (pg < 0 || pg >=  TEGRA_MAX_PINGROUP)
                return -ERANGE;
 
-       if (pingroups[pg].pupd_reg == REG_N)
+       if (pingroups[pg].pupd_reg < 0)
                return -EINVAL;
 
        if (pupd != TEGRA_PUPD_NORMAL &&
@@ -468,38 +272,39 @@ int tegra_pinmux_set_pullupdown(enum tegra_pingroup pg,
 
        spin_lock_irqsave(&mux_lock, flags);
 
-       reg = pg_readl(TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+       reg = pg_readl(pingroups[pg].pupd_reg);
        reg &= ~(0x3 << pingroups[pg].pupd_bit);
        reg |= pupd << pingroups[pg].pupd_bit;
-       pg_writel(reg, TEGRA_PP_PU_PD(pingroups[pg].pupd_reg));
+       pg_writel(reg, pingroups[pg].pupd_reg);
 
        spin_unlock_irqrestore(&mux_lock, flags);
 
        return 0;
 }
 
-void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
-                                enum tegra_mux_func func,
-                                enum tegra_pullupdown pupd,
-                                enum tegra_tristate tristate)
+static void tegra_pinmux_config_pingroup(const struct tegra_pingroup_config *config)
 {
+       enum tegra_pingroup pingroup = config->pingroup;
+       enum tegra_mux_func func     = config->func;
+       enum tegra_pullupdown pupd   = config->pupd;
+       enum tegra_tristate tristate = config->tristate;
        int err;
 
-       if (pingroups[pingroup].mux_reg != REG_N) {
-               err = tegra_pinmux_set_func(pingroup, func);
+       if (pingroups[pingroup].mux_reg >= 0) {
+               err = tegra_pinmux_set_func(config);
                if (err < 0)
                        pr_err("pinmux: can't set pingroup %s func to %s: %d\n",
                               pingroup_name(pingroup), func_name(func), err);
        }
 
-       if (pingroups[pingroup].pupd_reg != REG_N) {
+       if (pingroups[pingroup].pupd_reg >= 0) {
                err = tegra_pinmux_set_pullupdown(pingroup, pupd);
                if (err < 0)
                        pr_err("pinmux: can't set pingroup %s pullupdown to %s: %d\n",
                               pingroup_name(pingroup), pupd_name(pupd), err);
        }
 
-       if (pingroups[pingroup].tri_reg != REG_N) {
+       if (pingroups[pingroup].tri_reg >= 0) {
                err = tegra_pinmux_set_tristate(pingroup, tristate);
                if (err < 0)
                        pr_err("pinmux: can't set pingroup %s tristate to %s: %d\n",
@@ -507,17 +312,12 @@ void tegra_pinmux_config_pingroup(enum tegra_pingroup pingroup,
        }
 }
 
-
-
-void tegra_pinmux_config_table(struct tegra_pingroup_config *config, int len)
+void tegra_pinmux_config_table(const struct tegra_pingroup_config *config, int len)
 {
        int i;
 
        for (i = 0; i < len; i++)
-               tegra_pinmux_config_pingroup(config[i].pingroup,
-                                            config[i].func,
-                                            config[i].pupd,
-                                            config[i].tristate);
+               tegra_pinmux_config_pingroup(&config[i]);
 }
 
 static const char *drive_pinmux_name(enum tegra_drive_pingroup pg)
@@ -784,6 +584,86 @@ void tegra_drive_pinmux_config_table(struct tegra_drive_pingroup_config *config,
                                                     config[i].slew_falling);
 }
 
+void tegra_pinmux_set_safe_pinmux_table(const struct tegra_pingroup_config *config,
+       int len)
+{
+       int i;
+       struct tegra_pingroup_config c;
+
+       for (i = 0; i < len; i++) {
+               int err;
+               c = config[i];
+               if (c.pingroup < 0 || c.pingroup >= TEGRA_MAX_PINGROUP) {
+                       WARN_ON(1);
+                       continue;
+               }
+               c.func = pingroups[c.pingroup].func_safe;
+               err = tegra_pinmux_set_func(&c);
+               if (err < 0)
+                       pr_err("%s: tegra_pinmux_set_func returned %d setting "
+                              "%s to %s\n", __func__, err,
+                              pingroup_name(c.pingroup), func_name(c.func));
+       }
+}
+
+void tegra_pinmux_config_pinmux_table(const struct tegra_pingroup_config *config,
+       int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++) {
+               int err;
+               if (config[i].pingroup < 0 ||
+                   config[i].pingroup >= TEGRA_MAX_PINGROUP) {
+                       WARN_ON(1);
+                       continue;
+               }
+               err = tegra_pinmux_set_func(&config[i]);
+               if (err < 0)
+                       pr_err("%s: tegra_pinmux_set_func returned %d setting "
+                              "%s to %s\n", __func__, err,
+                              pingroup_name(config[i].pingroup),
+                              func_name(config[i].func));
+       }
+}
+
+void tegra_pinmux_config_tristate_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_tristate tristate)
+{
+       int i;
+       int err;
+       enum tegra_pingroup pingroup;
+
+       for (i = 0; i < len; i++) {
+               pingroup = config[i].pingroup;
+               if (pingroups[pingroup].tri_reg >= 0) {
+                       err = tegra_pinmux_set_tristate(pingroup, tristate);
+                       if (err < 0)
+                               pr_err("pinmux: can't set pingroup %s tristate"
+                                       " to %s: %d\n", pingroup_name(pingroup),
+                                       tri_name(tristate), err);
+               }
+       }
+}
+
+void tegra_pinmux_config_pullupdown_table(const struct tegra_pingroup_config *config,
+       int len, enum tegra_pullupdown pupd)
+{
+       int i;
+       int err;
+       enum tegra_pingroup pingroup;
+
+       for (i = 0; i < len; i++) {
+               pingroup = config[i].pingroup;
+               if (pingroups[pingroup].pupd_reg >= 0) {
+                       err = tegra_pinmux_set_pullupdown(pingroup, pupd);
+                       if (err < 0)
+                               pr_err("pinmux: can't set pingroup %s pullupdown"
+                                       " to %s: %d\n", pingroup_name(pingroup),
+                                       pupd_name(pupd), err);
+               }
+       }
+}
 
 #ifdef CONFIG_DEBUG_FS
 
@@ -812,11 +692,11 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
                len = strlen(pingroups[i].name);
                dbg_pad_field(s, 5 - len);
 
-               if (pingroups[i].mux_reg == REG_N) {
+               if (pingroups[i].mux_reg < 0) {
                        seq_printf(s, "TEGRA_MUX_NONE");
                        len = strlen("NONE");
                } else {
-                       mux = (pg_readl(TEGRA_PP_MUX_CTL(pingroups[i].mux_reg)) >>
+                       mux = (pg_readl(pingroups[i].mux_reg) >>
                               pingroups[i].mux_bit) & 0x3;
                        if (pingroups[i].funcs[mux] == TEGRA_MUX_RSVD) {
                                seq_printf(s, "TEGRA_MUX_RSVD%1lu", mux+1);
@@ -829,21 +709,21 @@ static int dbg_pinmux_show(struct seq_file *s, void *unused)
                }
                dbg_pad_field(s, 13-len);
 
-               if (pingroups[i].mux_reg == REG_N) {
+               if (pingroups[i].pupd_reg < 0) {
                        seq_printf(s, "TEGRA_PUPD_NORMAL");
                        len = strlen("NORMAL");
                } else {
-                       pupd = (pg_readl(TEGRA_PP_PU_PD(pingroups[i].pupd_reg)) >>
+                       pupd = (pg_readl(pingroups[i].pupd_reg) >>
                                pingroups[i].pupd_bit) & 0x3;
                        seq_printf(s, "TEGRA_PUPD_%s", pupd_name(pupd));
                        len = strlen(pupd_name(pupd));
                }
                dbg_pad_field(s, 9 - len);
 
-               if (pingroups[i].tri_reg == REG_N) {
+               if (pingroups[i].tri_reg < 0) {
                        seq_printf(s, "TEGRA_TRI_NORMAL");
                } else {
-                       tri = (pg_readl(TEGRA_TRI_STATE(pingroups[i].tri_reg)) >>
+                       tri = (pg_readl(pingroups[i].tri_reg) >>
                               pingroups[i].tri_bit) & 0x1;
 
                        seq_printf(s, "TEGRA_TRI_%s", tri_name(tri));
index 4261632..ae3b308 100644 (file)
 #include <mach/iomap.h>
 
 #include "clock.h"
+#include "fuse.h"
+#include "tegra2_dvfs.h"
 
 #define RST_DEVICES                    0x004
 #define RST_DEVICES_SET                        0x300
 #define RST_DEVICES_CLR                        0x304
+#define RST_DEVICES_NUM                        3
 
 #define CLK_OUT_ENB                    0x010
 #define CLK_OUT_ENB_SET                        0x320
 #define CLK_OUT_ENB_CLR                        0x324
+#define CLK_OUT_ENB_NUM                        3
+
+#define CLK_MASK_ARM                   0x44
+#define MISC_CLK_ENB                   0x48
 
 #define OSC_CTRL                       0x50
 #define OSC_CTRL_OSC_FREQ_MASK         (3<<30)
@@ -45,6 +52,7 @@
 #define OSC_CTRL_OSC_FREQ_19_2MHZ      (1<<30)
 #define OSC_CTRL_OSC_FREQ_12MHZ                (2<<30)
 #define OSC_CTRL_OSC_FREQ_26MHZ                (3<<30)
+#define OSC_CTRL_MASK                  0x3f2
 
 #define OSC_FREQ_DET                   0x58
 #define OSC_FREQ_DET_TRIG              (1<<31)
 #define OSC_FREQ_DET_BUSY              (1<<31)
 #define OSC_FREQ_DET_CNT_MASK          0xFFFF
 
+#define PERIPH_CLK_SOURCE_I2S1         0x100
+#define PERIPH_CLK_SOURCE_EMC          0x19c
+#define PERIPH_CLK_SOURCE_OSC          0x1fc
+#define PERIPH_CLK_SOURCE_NUM \
+       ((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
+
 #define PERIPH_CLK_SOURCE_MASK         (3<<30)
 #define PERIPH_CLK_SOURCE_SHIFT                30
 #define PERIPH_CLK_SOURCE_ENABLE       (1<<28)
-#define PERIPH_CLK_SOURCE_DIV_MASK     0xFF
+#define PERIPH_CLK_SOURCE_DIVU71_MASK  0xFF
+#define PERIPH_CLK_SOURCE_DIVU16_MASK  0xFFFF
 #define PERIPH_CLK_SOURCE_DIV_SHIFT    0
 
 #define PLL_BASE                       0x0
@@ -79,8 +94,9 @@
 #define PLL_OUT_RESET_DISABLE          (1<<0)
 
 #define PLL_MISC(c)                    (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
+#define PLL_MISC_LOCK_ENABLE(c)                (((c)->flags & PLLU) ? (1<<22) : (1<<18))
+
 #define PLL_MISC_DCCON_SHIFT           20
-#define PLL_MISC_LOCK_ENABLE           (1<<18)
 #define PLL_MISC_CPCON_SHIFT           8
 #define PLL_MISC_CPCON_MASK            (0xF<<PLL_MISC_CPCON_SHIFT)
 #define PLL_MISC_LFCON_SHIFT           4
 #define PLL_MISC_VCOCON_SHIFT          0
 #define PLL_MISC_VCOCON_MASK           (0xF<<PLL_MISC_VCOCON_SHIFT)
 
+#define PLLU_BASE_POST_DIV             (1<<20)
+
 #define PLLD_MISC_CLKENABLE            (1<<30)
 #define PLLD_MISC_DIV_RST              (1<<23)
 #define PLLD_MISC_DCCON_SHIFT          12
 
+#define PLLE_MISC_READY                        (1 << 15)
+
 #define PERIPH_CLK_TO_ENB_REG(c)       ((c->clk_num / 32) * 4)
 #define PERIPH_CLK_TO_ENB_SET_REG(c)   ((c->clk_num / 32) * 8)
 #define PERIPH_CLK_TO_ENB_BIT(c)       (1 << (c->clk_num % 32))
@@ -143,30 +163,37 @@ unsigned long clk_measure_input_freq(void)
        }
 }
 
-static int clk_div71_get_divider(struct clk *c, unsigned long rate)
+static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
 {
-       unsigned long divider_u71;
+       s64 divider_u71 = parent_rate * 2;
+       divider_u71 += rate - 1;
+       do_div(divider_u71, rate);
 
-       divider_u71 = DIV_ROUND_UP(c->rate * 2, rate);
+       if (divider_u71 - 2 < 0)
+               return 0;
 
-       if (divider_u71 - 2 > 255 || divider_u71 - 2 < 0)
+       if (divider_u71 - 2 > 255)
                return -EINVAL;
 
        return divider_u71 - 2;
 }
 
-static unsigned long tegra2_clk_recalculate_rate(struct clk *c)
+static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
 {
-       unsigned long rate;
-       rate = c->parent->rate;
+       s64 divider_u16;
 
-       if (c->mul != 0 && c->div != 0)
-               c->rate = rate * c->mul / c->div;
-       else
-               c->rate = rate;
-       return c->rate;
-}
+       divider_u16 = parent_rate;
+       divider_u16 += rate - 1;
+       do_div(divider_u16, rate);
+
+       if (divider_u16 - 1 < 0)
+               return 0;
 
+       if (divider_u16 - 1 > 255)
+               return -EINVAL;
+
+       return divider_u16 - 1;
+}
 
 /* clk_m functions */
 static unsigned long tegra2_clk_m_autodetect_rate(struct clk *c)
@@ -244,7 +271,6 @@ static void tegra2_super_clk_init(struct clk *c)
        }
        BUG_ON(sel->input == NULL);
        c->parent = sel->input;
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_super_clk_enable(struct clk *c)
@@ -266,6 +292,7 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
        u32 val;
        const struct clk_mux_sel *sel;
        int shift;
+
        val = clk_readl(c->reg + SUPER_CLK_MUX);;
        BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
                ((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
@@ -273,11 +300,18 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p)
                SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
-                       clk_reparent(c, p);
                        val &= ~(SUPER_SOURCE_MASK << shift);
                        val |= sel->value << shift;
+
+                       if (c->refcnt)
+                               clk_enable_locked(p);
+
                        clk_writel(val, c->reg);
-                       c->rate = c->parent->rate;
+
+                       if (c->refcnt && c->parent)
+                               clk_disable_locked(c->parent);
+
+                       clk_reparent(c, p);
                        return 0;
                }
        }
@@ -289,7 +323,61 @@ static struct clk_ops tegra_super_ops = {
        .enable                 = tegra2_super_clk_enable,
        .disable                = tegra2_super_clk_disable,
        .set_parent             = tegra2_super_clk_set_parent,
-       .recalculate_rate       = tegra2_clk_recalculate_rate,
+};
+
+/* virtual cpu clock functions */
+/* some clocks can not be stopped (cpu, memory bus) while the SoC is running.
+   To change the frequency of these clocks, the parent pll may need to be
+   reprogrammed, so the clock must be moved off the pll, the pll reprogrammed,
+   and then the clock moved back to the pll.  To hide this sequence, a virtual
+   clock handles it.
+ */
+static void tegra2_cpu_clk_init(struct clk *c)
+{
+}
+
+static int tegra2_cpu_clk_enable(struct clk *c)
+{
+       return 0;
+}
+
+static void tegra2_cpu_clk_disable(struct clk *c)
+{
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       /* oops - don't disable the CPU clock! */
+       BUG();
+}
+
+static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       int ret;
+       ret = clk_set_parent_locked(c->parent, c->backup);
+       if (ret) {
+               pr_err("Failed to switch cpu to clock %s\n", c->backup->name);
+               return ret;
+       }
+
+       ret = clk_set_rate_locked(c->main, rate);
+       if (ret) {
+               pr_err("Failed to change cpu pll to %lu\n", rate);
+               return ret;
+       }
+
+       ret = clk_set_parent_locked(c->parent, c->main);
+       if (ret) {
+               pr_err("Failed to switch cpu to clock %s\n", c->main->name);
+               return ret;
+       }
+
+       return 0;
+}
+
+static struct clk_ops tegra_cpu_ops = {
+       .init     = tegra2_cpu_clk_init,
+       .enable   = tegra2_cpu_clk_enable,
+       .disable  = tegra2_cpu_clk_disable,
+       .set_rate = tegra2_cpu_clk_set_rate,
 };
 
 /* bus clock functions */
@@ -299,7 +387,6 @@ static void tegra2_bus_clk_init(struct clk *c)
        c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
        c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
        c->mul = 1;
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_bus_clk_enable(struct clk *c)
@@ -340,27 +427,15 @@ static struct clk_ops tegra_bus_ops = {
        .enable                 = tegra2_bus_clk_enable,
        .disable                = tegra2_bus_clk_disable,
        .set_rate               = tegra2_bus_clk_set_rate,
-       .recalculate_rate       = tegra2_clk_recalculate_rate,
 };
 
 /* PLL Functions */
-static unsigned long tegra2_pll_clk_recalculate_rate(struct clk *c)
-{
-       u64 rate;
-       rate = c->parent->rate;
-       rate *= c->n;
-       do_div(rate, c->m);
-       if (c->p == 2)
-               rate >>= 1;
-       c->rate = rate;
-       return c->rate;
-}
-
 static int tegra2_pll_clk_wait_for_lock(struct clk *c)
 {
        ktime_t before;
 
        before = ktime_get();
+
        while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) {
                if (ktime_us_delta(ktime_get(), before) > 5000) {
                        pr_err("Timed out waiting for lock bit on pll %s",
@@ -380,24 +455,19 @@ static void tegra2_pll_clk_init(struct clk *c)
 
        if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
                pr_warning("Clock %s has unknown fixed frequency\n", c->name);
-               c->n = 1;
-               c->m = 0;
-               c->p = 1;
+               c->mul = 1;
+               c->div = 1;
        } else if (val & PLL_BASE_BYPASS) {
-               c->n = 1;
-               c->m = 1;
-               c->p = 1;
+               c->mul = 1;
+               c->div = 1;
        } else {
-               c->n = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
-               c->m = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
-               c->p = (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
+               c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
+               c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
+               if (c->flags & PLLU)
+                       c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
+               else
+                       c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
        }
-
-       val = clk_readl(c->reg + PLL_MISC(c));
-       if (c->flags & PLL_HAS_CPCON)
-               c->cpcon = (val & PLL_MISC_CPCON_MASK) >> PLL_MISC_CPCON_SHIFT;
-
-       tegra2_pll_clk_recalculate_rate(c);
 }
 
 static int tegra2_pll_clk_enable(struct clk *c)
@@ -411,7 +481,7 @@ static int tegra2_pll_clk_enable(struct clk *c)
        clk_writel(val, c->reg + PLL_BASE);
 
        val = clk_readl(c->reg + PLL_MISC(c));
-       val |= PLL_MISC_LOCK_ENABLE;
+       val |= PLL_MISC_LOCK_ENABLE(c);
        clk_writel(val, c->reg + PLL_MISC(c));
 
        tegra2_pll_clk_wait_for_lock(c);
@@ -441,33 +511,36 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate)
        input_rate = c->parent->rate;
        for (sel = c->pll_table; sel->input_rate != 0; sel++) {
                if (sel->input_rate == input_rate && sel->output_rate == rate) {
-                       c->n = sel->n;
-                       c->m = sel->m;
-                       c->p = sel->p;
-                       c->cpcon = sel->cpcon;
+                       c->mul = sel->n;
+                       c->div = sel->m * sel->p;
 
                        val = clk_readl(c->reg + PLL_BASE);
                        if (c->flags & PLL_FIXED)
                                val |= PLL_BASE_OVERRIDE;
                        val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
                                 PLL_BASE_DIVM_MASK);
-                       val |= (c->m << PLL_BASE_DIVM_SHIFT) |
-                               (c->n << PLL_BASE_DIVN_SHIFT);
-                       BUG_ON(c->p > 2);
-                       if (c->p == 2)
-                               val |= 1 << PLL_BASE_DIVP_SHIFT;
+                       val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
+                               (sel->n << PLL_BASE_DIVN_SHIFT);
+                       BUG_ON(sel->p < 1 || sel->p > 2);
+                       if (c->flags & PLLU) {
+                               if (sel->p == 1)
+                                       val |= PLLU_BASE_POST_DIV;
+                       } else {
+                               if (sel->p == 2)
+                                       val |= 1 << PLL_BASE_DIVP_SHIFT;
+                       }
                        clk_writel(val, c->reg + PLL_BASE);
 
                        if (c->flags & PLL_HAS_CPCON) {
-                               val = c->cpcon << PLL_MISC_CPCON_SHIFT;
-                               val |= PLL_MISC_LOCK_ENABLE;
+                               val = clk_readl(c->reg + PLL_MISC(c));
+                               val &= ~PLL_MISC_CPCON_MASK;
+                               val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
                                clk_writel(val, c->reg + PLL_MISC(c));
                        }
 
                        if (c->state == ON)
                                tegra2_pll_clk_enable(c);
 
-                       c->rate = rate;
                        return 0;
                }
        }
@@ -479,7 +552,46 @@ static struct clk_ops tegra_pll_ops = {
        .enable                 = tegra2_pll_clk_enable,
        .disable                = tegra2_pll_clk_disable,
        .set_rate               = tegra2_pll_clk_set_rate,
-       .recalculate_rate       = tegra2_pll_clk_recalculate_rate,
+};
+
+static void tegra2_pllx_clk_init(struct clk *c)
+{
+       tegra2_pll_clk_init(c);
+
+       if (tegra_sku_id() == 7)
+               c->max_rate = 750000000;
+}
+
+static struct clk_ops tegra_pllx_ops = {
+       .init     = tegra2_pllx_clk_init,
+       .enable   = tegra2_pll_clk_enable,
+       .disable  = tegra2_pll_clk_disable,
+       .set_rate = tegra2_pll_clk_set_rate,
+};
+
+static int tegra2_plle_clk_enable(struct clk *c)
+{
+       u32 val;
+
+       pr_debug("%s on clock %s\n", __func__, c->name);
+
+       mdelay(1);
+
+       val = clk_readl(c->reg + PLL_BASE);
+       if (!(val & PLLE_MISC_READY))
+               return -EBUSY;
+
+       val = clk_readl(c->reg + PLL_BASE);
+       val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
+       clk_writel(val, c->reg + PLL_BASE);
+
+       return 0;
+}
+
+static struct clk_ops tegra_plle_ops = {
+       .init       = tegra2_pll_clk_init,
+       .enable     = tegra2_plle_clk_enable,
+       .set_rate   = tegra2_pll_clk_set_rate,
 };
 
 /* Clock divider ops */
@@ -503,8 +615,6 @@ static void tegra2_pll_div_clk_init(struct clk *c)
                c->div = 1;
                c->mul = 1;
        }
-
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_pll_div_clk_enable(struct clk *c)
@@ -565,7 +675,7 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
        int divider_u71;
        pr_debug("%s: %s %lu\n", __func__, c->name, rate);
        if (c->flags & DIV_U71) {
-               divider_u71 = clk_div71_get_divider(c->parent, rate);
+               divider_u71 = clk_div71_get_divider(c->parent->rate, rate);
                if (divider_u71 >= 0) {
                        val = clk_readl(c->reg);
                        new_val = val >> c->reg_shift;
@@ -580,25 +690,37 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate)
                        clk_writel(val, c->reg);
                        c->div = divider_u71 + 2;
                        c->mul = 2;
-                       tegra2_clk_recalculate_rate(c);
                        return 0;
                }
        } else if (c->flags & DIV_2) {
-               if (c->parent->rate == rate * 2) {
-                       c->rate = rate;
+               if (c->parent->rate == rate * 2)
                        return 0;
-               }
        }
        return -EINVAL;
 }
 
+static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
+{
+       int divider;
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+       if (c->flags & DIV_U71) {
+               divider = clk_div71_get_divider(c->parent->rate, rate);
+               if (divider < 0)
+                       return divider;
+               return c->parent->rate * 2 / (divider + 2);
+       } else if (c->flags & DIV_2) {
+               return c->parent->rate / 2;
+       }
+       return -EINVAL;
+}
 
 static struct clk_ops tegra_pll_div_ops = {
        .init                   = tegra2_pll_div_clk_init,
        .enable                 = tegra2_pll_div_clk_enable,
        .disable                = tegra2_pll_div_clk_disable,
        .set_rate               = tegra2_pll_div_clk_set_rate,
-       .recalculate_rate       = tegra2_clk_recalculate_rate,
+       .round_rate             = tegra2_pll_div_clk_round_rate,
 };
 
 /* Periph clk ops */
@@ -621,9 +743,13 @@ static void tegra2_periph_clk_init(struct clk *c)
        }
 
        if (c->flags & DIV_U71) {
-               u32 divu71 = val & PERIPH_CLK_SOURCE_DIV_MASK;
+               u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
                c->div = divu71 + 2;
                c->mul = 2;
+       } else if (c->flags & DIV_U16) {
+               u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
+               c->div = divu16 + 1;
+               c->mul = 1;
        } else {
                c->div = 1;
                c->mul = 1;
@@ -637,7 +763,6 @@ static void tegra2_periph_clk_init(struct clk *c)
                if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
                                PERIPH_CLK_TO_ENB_BIT(c))
                        c->state = OFF;
-       tegra2_clk_recalculate_rate(c);
 }
 
 static int tegra2_periph_clk_enable(struct clk *c)
@@ -692,12 +817,19 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
        pr_debug("%s: %s %s\n", __func__, c->name, p->name);
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
-                       clk_reparent(c, p);
                        val = clk_readl(c->reg);
                        val &= ~PERIPH_CLK_SOURCE_MASK;
                        val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
+
+                       if (c->refcnt)
+                               clk_enable_locked(p);
+
                        clk_writel(val, c->reg);
-                       c->rate = c->parent->rate;
+
+                       if (c->refcnt && c->parent)
+                               clk_disable_locked(c->parent);
+
+                       clk_reparent(c, p);
                        return 0;
                }
        }
@@ -708,20 +840,55 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
 static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate)
 {
        u32 val;
-       int divider_u71;
+       int divider;
        pr_debug("%s: %lu\n", __func__, rate);
        if (c->flags & DIV_U71) {
-               divider_u71 = clk_div71_get_divider(c->parent, rate);
-               if (divider_u71 >= 0) {
+               divider = clk_div71_get_divider(c->parent->rate, rate);
+               if (divider >= 0) {
                        val = clk_readl(c->reg);
-                       val &= ~PERIPH_CLK_SOURCE_DIV_MASK;
-                       val |= divider_u71;
+                       val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
+                       val |= divider;
                        clk_writel(val, c->reg);
-                       c->div = divider_u71 + 2;
+                       c->div = divider + 2;
                        c->mul = 2;
-                       tegra2_clk_recalculate_rate(c);
                        return 0;
                }
+       } else if (c->flags & DIV_U16) {
+               divider = clk_div16_get_divider(c->parent->rate, rate);
+               if (divider >= 0) {
+                       val = clk_readl(c->reg);
+                       val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
+                       val |= divider;
+                       clk_writel(val, c->reg);
+                       c->div = divider + 1;
+                       c->mul = 1;
+                       return 0;
+               }
+       } else if (c->parent->rate <= rate) {
+               c->div = 1;
+               c->mul = 1;
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static long tegra2_periph_clk_round_rate(struct clk *c,
+       unsigned long rate)
+{
+       int divider;
+       pr_debug("%s: %s %lu\n", __func__, c->name, rate);
+
+       if (c->flags & DIV_U71) {
+               divider = clk_div71_get_divider(c->parent->rate, rate);
+               if (divider < 0)
+                       return divider;
+
+               return c->parent->rate * 2 / (divider + 2);
+       } else if (c->flags & DIV_U16) {
+               divider = clk_div16_get_divider(c->parent->rate, rate);
+               if (divider < 0)
+                       return divider;
+               return c->parent->rate / (divider + 1);
        }
        return -EINVAL;
 }
@@ -732,7 +899,7 @@ static struct clk_ops tegra_periph_clk_ops = {
        .disable                = &tegra2_periph_clk_disable,
        .set_parent             = &tegra2_periph_clk_set_parent,
        .set_rate               = &tegra2_periph_clk_set_rate,
-       .recalculate_rate       = &tegra2_clk_recalculate_rate,
+       .round_rate             = &tegra2_periph_clk_round_rate,
 };
 
 /* Clock doubler ops */
@@ -744,21 +911,108 @@ static void tegra2_clk_double_init(struct clk *c)
        if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
                        PERIPH_CLK_TO_ENB_BIT(c)))
                c->state = OFF;
-       tegra2_clk_recalculate_rate(c);
 };
 
+static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate)
+{
+       if (rate != 2 * c->parent->rate)
+               return -EINVAL;
+       c->mul = 2;
+       c->div = 1;
+       return 0;
+}
+
 static struct clk_ops tegra_clk_double_ops = {
        .init                   = &tegra2_clk_double_init,
        .enable                 = &tegra2_periph_clk_enable,
        .disable                = &tegra2_periph_clk_disable,
-       .recalculate_rate       = &tegra2_clk_recalculate_rate,
+       .set_rate               = &tegra2_clk_double_set_rate,
+};
+
+static void tegra2_audio_sync_clk_init(struct clk *c)
+{
+       int source;
+       const struct clk_mux_sel *sel;
+       u32 val = clk_readl(c->reg);
+       c->state = (val & (1<<4)) ? OFF : ON;
+       source = val & 0xf;
+       for (sel = c->inputs; sel->input != NULL; sel++)
+               if (sel->value == source)
+                       break;
+       BUG_ON(sel->input == NULL);
+       c->parent = sel->input;
+}
+
+static int tegra2_audio_sync_clk_enable(struct clk *c)
+{
+       clk_writel(0, c->reg);
+       return 0;
+}
+
+static void tegra2_audio_sync_clk_disable(struct clk *c)
+{
+       clk_writel(1, c->reg);
+}
+
+static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p)
+{
+       u32 val;
+       const struct clk_mux_sel *sel;
+       for (sel = c->inputs; sel->input != NULL; sel++) {
+               if (sel->input == p) {
+                       val = clk_readl(c->reg);
+                       val &= ~0xf;
+                       val |= sel->value;
+
+                       if (c->refcnt)
+                               clk_enable_locked(p);
+
+                       clk_writel(val, c->reg);
+
+                       if (c->refcnt && c->parent)
+                               clk_disable_locked(c->parent);
+
+                       clk_reparent(c, p);
+                       return 0;
+               }
+       }
+
+       return -EINVAL;
+}
+
+static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate)
+{
+       unsigned long parent_rate;
+       if (!c->parent) {
+               pr_err("%s: clock has no parent\n", __func__);
+               return -EINVAL;
+       }
+       parent_rate = c->parent->rate;
+       if (rate != parent_rate) {
+               pr_err("%s: %s/%ld differs from parent %s/%ld\n",
+                       __func__,
+                       c->name, rate,
+                       c->parent->name, parent_rate);
+               return -EINVAL;
+       }
+       c->rate = parent_rate;
+       return 0;
+}
+
+static struct clk_ops tegra_audio_sync_clk_ops = {
+       .init       = tegra2_audio_sync_clk_init,
+       .enable     = tegra2_audio_sync_clk_enable,
+       .disable    = tegra2_audio_sync_clk_disable,
+       .set_rate   = tegra2_audio_sync_clk_set_rate,
+       .set_parent = tegra2_audio_sync_clk_set_parent,
 };
 
 /* Clock definitions */
 static struct clk tegra_clk_32k = {
        .name = "clk_32k",
-       .rate = 32678,
+       .rate = 32768,
        .ops  = NULL,
+       .max_rate = 32768,
 };
 
 static struct clk_pll_table tegra_pll_s_table[] = {
@@ -782,6 +1036,7 @@ static struct clk tegra_pll_s = {
        .vco_min   = 12000000,
        .vco_max   = 26000000,
        .pll_table = tegra_pll_s_table,
+       .max_rate  = 26000000,
 };
 
 static struct clk_mux_sel tegra_clk_m_sel[] = {
@@ -797,6 +1052,7 @@ static struct clk tegra_clk_m = {
        .reg       = 0x1fc,
        .reg_mask  = (1<<28),
        .reg_shift = 28,
+       .max_rate  = 26000000,
 };
 
 static struct clk_pll_table tegra_pll_c_table[] = {
@@ -816,6 +1072,7 @@ static struct clk tegra_pll_c = {
        .vco_min   = 20000000,
        .vco_max   = 1400000000,
        .pll_table = tegra_pll_c_table,
+       .max_rate  = 600000000,
 };
 
 static struct clk tegra_pll_c_out1 = {
@@ -825,9 +1082,18 @@ static struct clk tegra_pll_c_out1 = {
        .parent    = &tegra_pll_c,
        .reg       = 0x84,
        .reg_shift = 0,
+       .max_rate  = 600000000,
 };
 
 static struct clk_pll_table tegra_pll_m_table[] = {
+       { 12000000, 666000000, 666, 12, 1, 8},
+       { 13000000, 666000000, 666, 13, 1, 8},
+       { 19200000, 666000000, 555, 16, 1, 8},
+       { 26000000, 666000000, 666, 26, 1, 8},
+       { 12000000, 600000000, 600, 12, 1, 8},
+       { 13000000, 600000000, 600, 13, 1, 8},
+       { 19200000, 600000000, 375, 12, 1, 6},
+       { 26000000, 600000000, 600, 26, 1, 8},
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -844,6 +1110,7 @@ static struct clk tegra_pll_m = {
        .vco_min   = 20000000,
        .vco_max   = 1200000000,
        .pll_table = tegra_pll_m_table,
+       .max_rate  = 800000000,
 };
 
 static struct clk tegra_pll_m_out1 = {
@@ -853,6 +1120,7 @@ static struct clk tegra_pll_m_out1 = {
        .parent    = &tegra_pll_m,
        .reg       = 0x94,
        .reg_shift = 0,
+       .max_rate  = 600000000,
 };
 
 static struct clk_pll_table tegra_pll_p_table[] = {
@@ -880,6 +1148,7 @@ static struct clk tegra_pll_p = {
        .vco_min   = 20000000,
        .vco_max   = 1400000000,
        .pll_table = tegra_pll_p_table,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out1 = {
@@ -889,6 +1158,7 @@ static struct clk tegra_pll_p_out1 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa4,
        .reg_shift = 0,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out2 = {
@@ -898,6 +1168,7 @@ static struct clk tegra_pll_p_out2 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa4,
        .reg_shift = 16,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out3 = {
@@ -907,6 +1178,7 @@ static struct clk tegra_pll_p_out3 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa8,
        .reg_shift = 0,
+       .max_rate  = 432000000,
 };
 
 static struct clk tegra_pll_p_out4 = {
@@ -916,6 +1188,7 @@ static struct clk tegra_pll_p_out4 = {
        .parent    = &tegra_pll_p,
        .reg       = 0xa8,
        .reg_shift = 16,
+       .max_rate  = 432000000,
 };
 
 static struct clk_pll_table tegra_pll_a_table[] = {
@@ -923,6 +1196,7 @@ static struct clk_pll_table tegra_pll_a_table[] = {
        { 28800000, 73728000, 64, 25, 1, 1},
        { 28800000, 11289600, 49, 25, 1, 1},
        { 28800000, 12288000, 64, 25, 1, 1},
+       { 28800000, 24000000,  5,  6, 1, 1},
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -939,6 +1213,7 @@ static struct clk tegra_pll_a = {
        .vco_min   = 20000000,
        .vco_max   = 1400000000,
        .pll_table = tegra_pll_a_table,
+       .max_rate  = 56448000,
 };
 
 static struct clk tegra_pll_a_out0 = {
@@ -948,6 +1223,7 @@ static struct clk tegra_pll_a_out0 = {
        .parent    = &tegra_pll_a,
        .reg       = 0xb4,
        .reg_shift = 0,
+       .max_rate  = 56448000,
 };
 
 static struct clk_pll_table tegra_pll_d_table[] = {
@@ -971,6 +1247,7 @@ static struct clk tegra_pll_d = {
        .vco_min   = 40000000,
        .vco_max   = 1000000000,
        .pll_table = tegra_pll_d_table,
+       .max_rate  = 1000000000,
 };
 
 static struct clk tegra_pll_d_out0 = {
@@ -978,19 +1255,20 @@ static struct clk tegra_pll_d_out0 = {
        .ops       = &tegra_pll_div_ops,
        .flags     = DIV_2 | PLLD,
        .parent    = &tegra_pll_d,
+       .max_rate  = 500000000,
 };
 
 static struct clk_pll_table tegra_pll_u_table[] = {
-       { 12000000, 480000000, 960, 12, 1, 0},
-       { 13000000, 480000000, 960, 13, 1, 0},
-       { 19200000, 480000000, 200, 4,  1, 0},
-       { 26000000, 480000000, 960, 26, 1, 0},
+       { 12000000, 480000000, 960, 12, 2, 0},
+       { 13000000, 480000000, 960, 13, 2, 0},
+       { 19200000, 480000000, 200, 4,  2, 0},
+       { 26000000, 480000000, 960, 26, 2, 0},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct clk tegra_pll_u = {
        .name      = "pll_u",
-       .flags     = 0,
+       .flags     = PLLU,
        .ops       = &tegra_pll_ops,
        .reg       = 0xc0,
        .input_min = 2000000,
@@ -1001,24 +1279,59 @@ static struct clk tegra_pll_u = {
        .vco_min   = 480000000,
        .vco_max   = 960000000,
        .pll_table = tegra_pll_u_table,
+       .max_rate  = 480000000,
 };
 
 static struct clk_pll_table tegra_pll_x_table[] = {
+       /* 1 GHz */
        { 12000000, 1000000000, 1000, 12, 1, 12},
        { 13000000, 1000000000, 1000, 13, 1, 12},
        { 19200000, 1000000000, 625,  12, 1, 8},
        { 26000000, 1000000000, 1000, 26, 1, 12},
-       { 12000000, 750000000,  750,  12, 1, 12},
-       { 13000000, 750000000,  750,  13, 1, 12},
-       { 19200000, 750000000,  625,  16, 1, 8},
-       { 26000000, 750000000,  750,  26, 1, 12},
+
+       /* 912 MHz */
+       { 12000000, 912000000,  912,  12, 1, 12},
+       { 13000000, 912000000,  912,  13, 1, 12},
+       { 19200000, 912000000,  760,  16, 1, 8},
+       { 26000000, 912000000,  912,  26, 1, 12},
+
+       /* 816 MHz */
+       { 12000000, 816000000,  816,  12, 1, 12},
+       { 13000000, 816000000,  816,  13, 1, 12},
+       { 19200000, 816000000,  680,  16, 1, 8},
+       { 26000000, 816000000,  816,  26, 1, 12},
+
+       /* 760 MHz */
+       { 12000000, 760000000,  760,  12, 1, 12},
+       { 13000000, 760000000,  760,  13, 1, 12},
+       { 19200000, 760000000,  950,  24, 1, 8},
+       { 26000000, 760000000,  760,  26, 1, 12},
+
+       /* 608 MHz */
+       { 12000000, 608000000,  760,  12, 1, 12},
+       { 13000000, 608000000,  760,  13, 1, 12},
+       { 19200000, 608000000,  380,  12, 1, 8},
+       { 26000000, 608000000,  760,  26, 1, 12},
+
+       /* 456 MHz */
+       { 12000000, 456000000,  456,  12, 1, 12},
+       { 13000000, 456000000,  456,  13, 1, 12},
+       { 19200000, 456000000,  380,  16, 1, 8},
+       { 26000000, 456000000,  456,  26, 1, 12},
+
+       /* 312 MHz */
+       { 12000000, 312000000,  312,  12, 1, 12},
+       { 13000000, 312000000,  312,  13, 1, 12},
+       { 19200000, 312000000,  260,  16, 1, 8},
+       { 26000000, 312000000,  312,  26, 1, 12},
+
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct clk tegra_pll_x = {
        .name      = "pll_x",
        .flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
-       .ops       = &tegra_pll_ops,
+       .ops       = &tegra_pllx_ops,
        .reg       = 0xe0,
        .input_min = 2000000,
        .input_max = 31000000,
@@ -1028,6 +1341,24 @@ static struct clk tegra_pll_x = {
        .vco_min   = 20000000,
        .vco_max   = 1200000000,
        .pll_table = tegra_pll_x_table,
+       .max_rate  = 1000000000,
+};
+
+static struct clk_pll_table tegra_pll_e_table[] = {
+       { 12000000, 100000000,  200,  24, 1, 0 },
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct clk tegra_pll_e = {
+       .name      = "pll_e",
+       .flags     = PLL_ALT_MISC_REG,
+       .ops       = &tegra_plle_ops,
+       .input_min = 12000000,
+       .input_max = 12000000,
+       .max_rate  = 100000000,
+       .parent    = &tegra_clk_m,
+       .reg       = 0xe8,
+       .pll_table = tegra_pll_e_table,
 };
 
 static struct clk tegra_clk_d = {
@@ -1038,19 +1369,77 @@ static struct clk tegra_clk_d = {
        .reg       = 0x34,
        .reg_shift = 12,
        .parent    = &tegra_clk_m,
+       .max_rate  = 52000000,
+};
+
+/* initialized before peripheral clocks */
+static struct clk_mux_sel mux_audio_sync_clk[8+1];
+static const struct audio_sources {
+       const char *name;
+       int value;
+} mux_audio_sync_clk_sources[] = {
+       { .name = "spdif_in", .value = 0 },
+       { .name = "i2s1", .value = 1 },
+       { .name = "i2s2", .value = 2 },
+       { .name = "pll_a_out0", .value = 4 },
+#if 0 /* FIXME: not implemented */
+       { .name = "ac97", .value = 3 },
+       { .name = "ext_audio_clk2", .value = 5 },
+       { .name = "ext_audio_clk1", .value = 6 },
+       { .name = "ext_vimclk", .value = 7 },
+#endif
+       { 0, 0 }
+};
+
+static struct clk tegra_clk_audio = {
+       .name      = "audio",
+       .inputs    = mux_audio_sync_clk,
+       .reg       = 0x38,
+       .max_rate  = 24000000,
+       .ops       = &tegra_audio_sync_clk_ops
 };
 
-/* FIXME: need tegra_audio
 static struct clk tegra_clk_audio_2x = {
-       .name      = "clk_d",
+       .name      = "audio_2x",
        .flags     = PERIPH_NO_RESET,
+       .max_rate  = 48000000,
        .ops       = &tegra_clk_double_ops,
        .clk_num   = 89,
        .reg       = 0x34,
        .reg_shift = 8,
-       .parent    = &tegra_audio,
+       .parent    = &tegra_clk_audio,
+};
+
+struct clk_lookup tegra_audio_clk_lookups[] = {
+       { .con_id = "audio", .clk = &tegra_clk_audio },
+       { .con_id = "audio_2x", .clk = &tegra_clk_audio_2x }
+};
+
+/* This is called after peripheral clocks are initialized, as the
+ * audio_sync clock depends on some of the peripheral clocks.
+ */
+
+static void init_audio_sync_clock_mux(void)
+{
+       int i;
+       struct clk_mux_sel *sel = mux_audio_sync_clk;
+       const struct audio_sources *src = mux_audio_sync_clk_sources;
+       struct clk_lookup *lookup;
+
+       for (i = 0; src->name; i++, sel++, src++) {
+               sel->input = tegra_get_clock_by_name(src->name);
+               if (!sel->input)
+                       pr_err("%s: could not find clk %s\n", __func__,
+                               src->name);
+               sel->value = src->value;
+       }
+
+       lookup = tegra_audio_clk_lookups;
+       for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) {
+               clk_init(lookup->clk);
+               clkdev_add(lookup);
+       }
 }
-*/
 
 static struct clk_mux_sel mux_cclk[] = {
        { .input = &tegra_clk_m,        .value = 0},
@@ -1077,27 +1466,40 @@ static struct clk_mux_sel mux_sclk[] = {
        { 0, 0},
 };
 
-static struct clk tegra_clk_cpu = {
-       .name   = "cpu",
+static struct clk tegra_clk_cclk = {
+       .name   = "cclk",
        .inputs = mux_cclk,
        .reg    = 0x20,
        .ops    = &tegra_super_ops,
+       .max_rate = 1000000000,
 };
 
-static struct clk tegra_clk_sys = {
-       .name   = "sys",
+static struct clk tegra_clk_sclk = {
+       .name   = "sclk",
        .inputs = mux_sclk,
        .reg    = 0x28,
        .ops    = &tegra_super_ops,
+       .max_rate = 600000000,
+};
+
+static struct clk tegra_clk_virtual_cpu = {
+       .name      = "cpu",
+       .parent    = &tegra_clk_cclk,
+       .main      = &tegra_pll_x,
+       .backup    = &tegra_clk_m,
+       .ops       = &tegra_cpu_ops,
+       .max_rate  = 1000000000,
+       .dvfs      = &tegra_dvfs_virtual_cpu_dvfs,
 };
 
 static struct clk tegra_clk_hclk = {
        .name           = "hclk",
        .flags          = DIV_BUS,
-       .parent         = &tegra_clk_sys,
+       .parent         = &tegra_clk_sclk,
        .reg            = 0x30,
        .reg_shift      = 4,
        .ops            = &tegra_bus_ops,
+       .max_rate       = 240000000,
 };
 
 static struct clk tegra_clk_pclk = {
@@ -1107,6 +1509,7 @@ static struct clk tegra_clk_pclk = {
        .reg            = 0x30,
        .reg_shift      = 0,
        .ops            = &tegra_bus_ops,
+       .max_rate       = 108000000,
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
@@ -1133,10 +1536,9 @@ static struct clk_mux_sel mux_pllp_pllc_pllm_clkm[] = {
        { 0, 0},
 };
 
-static struct clk_mux_sel mux_plla_audio_pllp_clkm[] = {
-       {.input = &tegra_pll_a, .value = 0},
-       /* FIXME: no mux defined for tegra_audio
-       {.input = &tegra_audio, .value = 1},*/
+static struct clk_mux_sel mux_pllaout0_audio2x_pllp_clkm[] = {
+       {.input = &tegra_pll_a_out0, .value = 0},
+       {.input = &tegra_clk_audio_2x, .value = 1},
        {.input = &tegra_pll_p, .value = 2},
        {.input = &tegra_clk_m, .value = 3},
        { 0, 0},
@@ -1153,8 +1555,7 @@ static struct clk_mux_sel mux_pllp_plld_pllc_clkm[] = {
 static struct clk_mux_sel mux_pllp_pllc_audio_clkm_clk32[] = {
        {.input = &tegra_pll_p,     .value = 0},
        {.input = &tegra_pll_c,     .value = 1},
-       /* FIXME: no mux defined for tegra_audio
-       {.input = &tegra_audio,     .value = 2},*/
+       {.input = &tegra_clk_audio,     .value = 2},
        {.input = &tegra_clk_m,     .value = 3},
        {.input = &tegra_clk_32k,   .value = 4},
        { 0, 0},
@@ -1187,7 +1588,7 @@ static struct clk_mux_sel mux_clk_32k[] = {
        { 0, 0},
 };
 
-#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _inputs, _flags) \
+#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
        {                                               \
                .name      = _name,                     \
                .lookup    = {                          \
@@ -1199,72 +1600,79 @@ static struct clk_mux_sel mux_clk_32k[] = {
                .reg       = _reg,                      \
                .inputs    = _inputs,                   \
                .flags     = _flags,                    \
+               .max_rate  = _max,                      \
        }
 
 struct clk tegra_periph_clks[] = {
-       PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      mux_clk_32k,                    PERIPH_NO_RESET),
-       PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      mux_clk_m,                      0),
-       PERIPH_CLK("i2s1",      "i2s.0",                NULL,   11,     0x100,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
-       PERIPH_CLK("i2s2",      "i2s.1",                NULL,   18,     0x104,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
+       PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET),
+       PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      26000000,  mux_clk_m,                   0),
+       PERIPH_CLK("i2s1",      "i2s.0",                NULL,   11,     0x100,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
+       PERIPH_CLK("i2s2",      "i2s.1",                NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        /* FIXME: spdif has 2 clocks but 1 enable */
-       PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  mux_plla_audio_pllp_clkm,       MUX | DIV_U71),
-       PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  mux_pllp_pllc_pllm,             MUX | DIV_U71),
-       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71),
-       PERIPH_CLK("spi",       "spi",                  NULL,   43,     0x114,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("xio",       "xio",                  NULL,   45,     0x120,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("twc",       "twc",                  NULL,   16,     0x12c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc1",      "spi_tegra.0",          NULL,   41,     0x134,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc2",      "spi_tegra.1",          NULL,   44,     0x118,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc3",      "spi_tegra.2",          NULL,   46,     0x11c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("ide",       "ide",                  NULL,   25,     0x144,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("ndflash",   "tegra_nand",           NULL,   13,     0x160,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  100000000, mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
+       PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  100000000, mux_pllp_pllc_pllm,          MUX | DIV_U71),
+       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  432000000, mux_pllp_pllc_audio_clkm_clk32,      MUX | DIV_U71),
+       PERIPH_CLK("spi",       "spi",                  NULL,   43,     0x114,  40000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("xio",       "xio",                  NULL,   45,     0x120,  150000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("twc",       "twc",                  NULL,   16,     0x12c,  150000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc1",      "spi_tegra.0",          NULL,   41,     0x134,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc2",      "spi_tegra.1",          NULL,   44,     0x118,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc3",      "spi_tegra.2",          NULL,   46,     0x11c,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sbc4",      "spi_tegra.3",          NULL,   68,     0x1b4,  160000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("ide",       "ide",                  NULL,   25,     0x144,  100000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("ndflash",   "tegra_nand",           NULL,   13,     0x160,  164000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
        /* FIXME: vfir shares an enable with uartb */
-       PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x160,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("vde",       "vde",                  NULL,   61,     0x1c8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
+       PERIPH_CLK("vfir",      "vfir",                 NULL,   7,      0x168,  72000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("sdmmc1",    "sdhci-tegra.0",        NULL,   14,     0x150,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc2",    "sdhci-tegra.1",        NULL,   9,      0x154,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc3",    "sdhci-tegra.2",        NULL,   69,     0x1bc,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("sdmmc4",    "sdhci-tegra.3",        NULL,   15,     0x160,  52000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("vde",       "vde",                  NULL,   61,     0x1c8,  250000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("csite",     "csite",                NULL,   73,     0x1d4,  144000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* max rate ??? */
        /* FIXME: what is la? */
-       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("owr",       "owr",                  NULL,   71,     0x1cc,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("nor",       "nor",                  NULL,   42,     0x1d0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("mipi",      "mipi",                 NULL,   50,     0x174,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c1",      "tegra-i2c.0",          NULL,   12,     0x124,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c2",      "tegra-i2c.1",          NULL,   54,     0x198,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c3",      "tegra-i2c.2",          NULL,   67,     0x1b8,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("dvc",       "tegra-i2c.3",          NULL,   47,     0x128,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("i2c1_i2c",  "tegra-i2c.0",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("i2c2_i2c",  "tegra-i2c.1",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("i2c3_i2c",  "tegra-i2c.2",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("dvc_i2c",   "tegra-i2c.3",          "i2c",  0,      0,      mux_pllp_out3,                  0),
-       PERIPH_CLK("uarta",     "uart.0",               NULL,   6,      0x178,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uartb",     "uart.1",               NULL,   7,      0x17c,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uartc",     "uart.2",               NULL,   55,     0x1a0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uartd",     "uart.3",               NULL,   65,     0x1c0,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  mux_pllp_pllc_pllm_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71 | PERIPH_MANUAL_RESET),
-       PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("la",        "la",                   NULL,   76,     0x1f8,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("owr",       "tegra_w1",             NULL,   71,     0x1cc,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
+       PERIPH_CLK("nor",       "nor",                  NULL,   42,     0x1d0,  92000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("mipi",      "mipi",                 NULL,   50,     0x174,  60000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71), /* scales with voltage */
+       PERIPH_CLK("i2c1",      "tegra-i2c.0",          NULL,   12,     0x124,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("i2c2",      "tegra-i2c.1",          NULL,   54,     0x198,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("i2c3",      "tegra-i2c.2",          NULL,   67,     0x1b8,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("dvc",       "tegra-i2c.3",          NULL,   47,     0x128,  26000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U16),
+       PERIPH_CLK("i2c1_i2c",  "tegra-i2c.0",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("i2c2_i2c",  "tegra-i2c.1",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("i2c3_i2c",  "tegra-i2c.2",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("dvc_i2c",   "tegra-i2c.3",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
+       PERIPH_CLK("uarta",     "uart.0",               NULL,   6,      0x178,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartb",     "uart.1",               NULL,   7,      0x17c,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartc",     "uart.2",               NULL,   55,     0x1a0,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartd",     "uart.3",               NULL,   65,     0x1c0,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  216000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
+       PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        /* FIXME: vi and vi_sensor share an enable */
-       PERIPH_CLK("vi",        "vi",                   NULL,   20,     0x148,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("vi_sensor", "vi_sensor",            NULL,   20,     0x1a8,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
-       PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  mux_pllm_pllc_pllp_plla,        MUX | DIV_U71),
+       PERIPH_CLK("vi",        "vi",                   NULL,   20,     0x148,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("vi_sensor", "vi_sensor",            NULL,   20,     0x1a8,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
+       PERIPH_CLK("epp",       "epp",                  NULL,   19,     0x16c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("mpe",       "mpe",                  NULL,   60,     0x170,  250000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("host1x",    "host1x",               NULL,   28,     0x180,  166000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        /* FIXME: cve and tvo share an enable   */
-       PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("tvdac",     "tvdac",                NULL,   53,     0x194,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("disp1",     "tegrafb.0",            NULL,   27,     0x138,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("disp2",     "tegrafb.1",            NULL,   26,     0x13c,  mux_pllp_plld_pllc_clkm,        MUX | DIV_U71),
-       PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      mux_clk_m,                      0),
-       PERIPH_CLK("usb2",      "usb.1",                NULL,   58,     0,      mux_clk_m,                      0),
-       PERIPH_CLK("usb3",      "usb.2",                NULL,   59,     0,      mux_clk_m,                      0),
-       PERIPH_CLK("emc",       "emc",                  NULL,   57,     0x19c,  mux_pllm_pllc_pllp_clkm,        MUX | DIV_U71 | PERIPH_EMC_ENB),
-       PERIPH_CLK("dsi",       "dsi",                  NULL,   48,     0,      mux_plld,                       0),
+       PERIPH_CLK("cve",       "cve",                  NULL,   49,     0x140,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("tvo",       "tvo",                  NULL,   49,     0x188,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("hdmi",      "hdmi",                 NULL,   51,     0x18c,  148500000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("tvdac",     "tvdac",                NULL,   53,     0x194,  250000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* requires min voltage */
+       PERIPH_CLK("disp1",     "tegrafb.0",            NULL,   27,     0x138,  190000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("disp2",     "tegrafb.1",            NULL,   26,     0x13c,  190000000, mux_pllp_plld_pllc_clkm,     MUX | DIV_U71), /* scales with voltage and process_id */
+       PERIPH_CLK("usbd",      "fsl-tegra-udc",        NULL,   22,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("usb2",      "tegra-ehci.1",         NULL,   58,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("usb3",      "tegra-ehci.2",         NULL,   59,     0,      480000000, mux_clk_m,                   0), /* requires min voltage */
+       PERIPH_CLK("emc",       "emc",                  NULL,   57,     0x19c,  800000000, mux_pllm_pllc_pllp_clkm,     MUX | DIV_U71 | PERIPH_EMC_ENB),
+       PERIPH_CLK("dsi",       "dsi",                  NULL,   48,     0,      500000000, mux_plld,                    0), /* scales with voltage */
+       PERIPH_CLK("csi",       "csi",                  NULL,   52,     0,      72000000,  mux_pllp_out3,               0),
+       PERIPH_CLK("isp",       "isp",                  NULL,   23,     0,      150000000, mux_clk_m,                   0), /* same frequency as VI */
+       PERIPH_CLK("csus",      "csus",                 NULL,   92,     0,      150000000, mux_clk_m,                   PERIPH_NO_RESET),
+       PERIPH_CLK("pex",       NULL,                   "pex",  70,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
+       PERIPH_CLK("afi",       NULL,                   "afi",  72,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
+       PERIPH_CLK("pcie_xclk", NULL,             "pcie_xclk",  74,     0,      26000000,  mux_clk_m,                   PERIPH_MANUAL_RESET),
 };
 
 #define CLK_DUPLICATE(_name, _dev, _con)               \
@@ -1286,6 +1694,9 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("uartc",  "tegra_uart.2", NULL),
        CLK_DUPLICATE("uartd",  "tegra_uart.3", NULL),
        CLK_DUPLICATE("uarte",  "tegra_uart.4", NULL),
+       CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"),
+       CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"),
+       CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
 };
 
 #define CLK(dev, con, ck)      \
@@ -1315,11 +1726,13 @@ struct clk_lookup tegra_clk_lookups[] = {
        CLK(NULL,       "pll_d_out0",   &tegra_pll_d_out0),
        CLK(NULL,       "pll_u",        &tegra_pll_u),
        CLK(NULL,       "pll_x",        &tegra_pll_x),
-       CLK(NULL,       "cpu",          &tegra_clk_cpu),
-       CLK(NULL,       "sys",          &tegra_clk_sys),
+       CLK(NULL,       "pll_e",        &tegra_pll_e),
+       CLK(NULL,       "cclk",         &tegra_clk_cclk),
+       CLK(NULL,       "sclk",         &tegra_clk_sclk),
        CLK(NULL,       "hclk",         &tegra_clk_hclk),
        CLK(NULL,       "pclk",         &tegra_clk_pclk),
        CLK(NULL,       "clk_d",        &tegra_clk_d),
+       CLK(NULL,       "cpu",          &tegra_clk_virtual_cpu),
 };
 
 void __init tegra2_init_clocks(void)
@@ -1356,4 +1769,75 @@ void __init tegra2_init_clocks(void)
                                cd->name);
                }
        }
+
+       init_audio_sync_clock_mux();
+}
+
+#ifdef CONFIG_PM
+static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
+                          PERIPH_CLK_SOURCE_NUM + 3];
+
+void tegra_clk_suspend(void)
+{
+       unsigned long off, i;
+       u32 *ctx = clk_rst_suspend;
+
+       *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+
+       for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
+                       off += 4) {
+               if (off == PERIPH_CLK_SOURCE_EMC)
+                       continue;
+               *ctx++ = clk_readl(off);
+       }
+
+       off = RST_DEVICES;
+       for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
+               *ctx++ = clk_readl(off);
+
+       off = CLK_OUT_ENB;
+       for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
+               *ctx++ = clk_readl(off);
+
+       *ctx++ = clk_readl(MISC_CLK_ENB);
+       *ctx++ = clk_readl(CLK_MASK_ARM);
+}
+
+void tegra_clk_resume(void)
+{
+       unsigned long off, i;
+       const u32 *ctx = clk_rst_suspend;
+       u32 val;
+
+       val = clk_readl(OSC_CTRL) & ~OSC_CTRL_MASK;
+       val |= *ctx++;
+       clk_writel(val, OSC_CTRL);
+
+       /* enable all clocks before configuring clock sources */
+       clk_writel(0xbffffff9ul, CLK_OUT_ENB);
+       clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);
+       clk_writel(0x77f01bfful, CLK_OUT_ENB + 8);
+       wmb();
+
+       for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
+                       off += 4) {
+               if (off == PERIPH_CLK_SOURCE_EMC)
+                       continue;
+               clk_writel(*ctx++, off);
+       }
+       wmb();
+
+       off = RST_DEVICES;
+       for (i = 0; i < RST_DEVICES_NUM; i++, off += 4)
+               clk_writel(*ctx++, off);
+       wmb();
+
+       off = CLK_OUT_ENB;
+       for (i = 0; i < CLK_OUT_ENB_NUM; i++, off += 4)
+               clk_writel(*ctx++, off);
+       wmb();
+
+       clk_writel(*ctx++, MISC_CLK_ENB);
+       clk_writel(*ctx++, CLK_MASK_ARM);
 }
+#endif
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c
new file mode 100644 (file)
index 0000000..5529c23
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * arch/arm/mach-tegra/tegra2_dvfs.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+
+#include "clock.h"
+#include "tegra2_dvfs.h"
+
+static struct dvfs_table virtual_cpu_process_0[] = {
+       {314000000,  750},
+       {456000000,  825},
+       {608000000,  900},
+       {760000000,  975},
+       {817000000,  1000},
+       {912000000,  1050},
+       {1000000000, 1100},
+       {0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_1[] = {
+       {314000000,  750},
+       {456000000,  825},
+       {618000000,  900},
+       {770000000,  975},
+       {827000000,  1000},
+       {922000000,  1050},
+       {1000000000, 1100},
+       {0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_2[] = {
+       {494000000,  750},
+       {675000000,  825},
+       {817000000,  875},
+       {922000000,  925},
+       {1000000000, 975},
+       {0, 0},
+};
+
+static struct dvfs_table virtual_cpu_process_3[] = {
+       {730000000,  750},
+       {760000000,  775},
+       {845000000,  800},
+       {1000000000, 875},
+       {0, 0},
+};
+
+struct dvfs tegra_dvfs_virtual_cpu_dvfs = {
+       .reg_id = "vdd_cpu",
+       .process_id_table = {
+               {
+                       .process_id = 0,
+                       .table = virtual_cpu_process_0,
+               },
+               {
+                       .process_id = 1,
+                       .table = virtual_cpu_process_1,
+               },
+               {
+                       .process_id = 2,
+                       .table = virtual_cpu_process_2,
+               },
+               {
+                       .process_id = 3,
+                       .table = virtual_cpu_process_3,
+               },
+       },
+       .process_id_table_length = 4,
+       .cpu = 1,
+};
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.h b/arch/arm/mach-tegra/tegra2_dvfs.h
new file mode 100644 (file)
index 0000000..f8c1adb
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/mach-tegra/tegra2_dvfs.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+extern struct dvfs tegra_dvfs_virtual_cpu_dvfs;
index 8440d95..c493d72 100644 (file)
@@ -89,13 +89,13 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address,
         * open-code the spin-locking.
         */
        ptl = pte_lockptr(vma->vm_mm, pmd);
-       pte = pte_offset_map_nested(pmd, address);
+       pte = pte_offset_map(pmd, address);
        spin_lock(ptl);
 
        ret = do_adjust_pte(vma, address, pfn, pte);
 
        spin_unlock(ptl);
-       pte_unmap_nested(pte);
+       pte_unmap(pte);
 
        return ret;
 }
index 1fbdb55..c00f119 100644 (file)
@@ -36,18 +36,17 @@ void kunmap(struct page *page)
 }
 EXPORT_SYMBOL(kunmap);
 
-void *kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
        unsigned int idx;
        unsigned long vaddr;
        void *kmap;
+       int type;
 
        pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
-       debug_kmap_atomic(type);
-
 #ifdef CONFIG_DEBUG_HIGHMEM
        /*
         * There is no cache coherency issue when non VIVT, so force the
@@ -61,6 +60,8 @@ void *kmap_atomic(struct page *page, enum km_type type)
        if (kmap)
                return kmap;
 
+       type = kmap_atomic_idx_push();
+
        idx = type + KM_TYPE_NR * smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -80,14 +81,17 @@ void *kmap_atomic(struct page *page, enum km_type type)
 
        return (void *)vaddr;
 }
-EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(__kmap_atomic);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       unsigned int idx = type + KM_TYPE_NR * smp_processor_id();
+       int idx, type;
 
        if (kvaddr >= (void *)FIXADDR_START) {
+               type = kmap_atomic_idx_pop();
+               idx = type + KM_TYPE_NR * smp_processor_id();
+
                if (cache_is_vivt())
                        __cpuc_flush_dcache_area((void *)vaddr, PAGE_SIZE);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -103,15 +107,16 @@ void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
        }
        pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-       unsigned int idx;
        unsigned long vaddr;
+       int idx, type;
 
        pagefault_disable();
 
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR * smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
index be5f58e..69bbfc6 100644 (file)
@@ -57,9 +57,9 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
                        goto no_pte;
 
                init_pmd = pmd_offset(init_pgd, 0);
-               init_pte = pte_offset_map_nested(init_pmd, 0);
+               init_pte = pte_offset_map(init_pmd, 0);
                set_pte_ext(new_pte, *init_pte, 0);
-               pte_unmap_nested(init_pte);
+               pte_unmap(init_pte);
                pte_unmap(new_pte);
        }
 
index a92cb49..92c5bb7 100644 (file)
@@ -19,7 +19,7 @@ config ARCH_OMAP2PLUS
        bool "TI OMAP2/3/4"
        select COMMON_CLKDEV
        help
-         "Systems based on omap24xx, omap34xx or omap44xx"
+         "Systems based on OMAP2, OMAP3 or OMAP4"
 
 endchoice
 
index 9405831..a4a1285 100644 (file)
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := common.o sram.o clock.o devices.o dma.o mux.o gpio.o \
-        usb.o fb.o io.o
+        usb.o fb.o io.o counter_32k.o
 obj-m :=
 obj-n :=
 obj-  :=
@@ -31,4 +31,4 @@ obj-y += $(i2c-omap-m) $(i2c-omap-y)
 # OMAP mailbox framework
 obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
 
-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
\ No newline at end of file
+obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
index 7190cbd..fc62fb5 100644 (file)
@@ -60,7 +60,7 @@ void clk_disable(struct clk *clk)
 
        spin_lock_irqsave(&clockfw_lock, flags);
        if (clk->usecount == 0) {
-               printk(KERN_ERR "Trying disable clock %s with 0 usecount\n",
+               pr_err("Trying disable clock %s with 0 usecount\n",
                       clk->name);
                WARN_ON(1);
                goto out;
@@ -397,6 +397,7 @@ static int __init clk_disable_unused(void)
        struct clk *ck;
        unsigned long flags;
 
+       pr_info("clock: disabling unused clocks to save power\n");
        list_for_each_entry(ck, &clocks, node) {
                if (ck->ops == &clkops_null)
                        continue;
@@ -418,7 +419,7 @@ late_initcall(clk_disable_unused);
 int __init clk_init(struct clk_functions * custom_clocks)
 {
        if (!custom_clocks) {
-               printk(KERN_ERR "No custom clock functions registered\n");
+               pr_err("No custom clock functions registered\n");
                BUG();
        }
 
index 3008e71..221a675 100644 (file)
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_8250.h>
-#include <linux/serial_reg.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/omapfb.h>
 
-#include <mach/hardware.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/mach/map.h>
-#include <asm/setup.h>
-
 #include <plat/common.h>
 #include <plat/board.h>
-#include <plat/control.h>
-#include <plat/mux.h>
-#include <plat/fpga.h>
-#include <plat/serial.h>
 #include <plat/vram.h>
 
-#include <plat/clock.h>
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-# include "../mach-omap2/sdrc.h"
-#endif
 
 #define NO_LENGTH_CHECK 0xffffffff
 
@@ -88,270 +65,3 @@ void __init omap_reserve(void)
        omapfb_reserve_sdram_memblock();
        omap_vram_reserve_sdram_memblock();
 }
-
-/*
- * 32KHz clocksource ... always available, on pretty most chips except
- * OMAP 730 and 1510.  Other timers could be used as clocksources, with
- * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
- * but systems won't necessarily want to spend resources that way.
- */
-
-#define OMAP16XX_TIMER_32K_SYNCHRONIZED                0xfffbc410
-
-#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
-
-#include <linux/clocksource.h>
-
-/*
- * offset_32k holds the init time counter value. It is then subtracted
- * from every counter read to achieve a counter that counts time from the
- * kernel boot (needed for sched_clock()).
- */
-static u32 offset_32k __read_mostly;
-
-#ifdef CONFIG_ARCH_OMAP16XX
-static cycle_t omap16xx_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
-}
-#else
-#define omap16xx_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2420
-static cycle_t omap2420_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2420_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP2430
-static cycle_t omap2430_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap2430_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP3
-static cycle_t omap34xx_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap34xx_32k_read      NULL
-#endif
-
-#ifdef CONFIG_ARCH_OMAP4
-static cycle_t omap44xx_32k_read(struct clocksource *cs)
-{
-       return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
-}
-#else
-#define omap44xx_32k_read      NULL
-#endif
-
-/*
- * Kernel assumes that sched_clock can be called early but may not have
- * things ready yet.
- */
-static cycle_t omap_32k_read_dummy(struct clocksource *cs)
-{
-       return 0;
-}
-
-static struct clocksource clocksource_32k = {
-       .name           = "32k_counter",
-       .rating         = 250,
-       .read           = omap_32k_read_dummy,
-       .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 10,
-       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/*
- * Returns current time from boot in nsecs. It's OK for this to wrap
- * around for now, as it's just a relative time stamp.
- */
-unsigned long long sched_clock(void)
-{
-       return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
-                                 clocksource_32k.mult, clocksource_32k.shift);
-}
-
-/**
- * read_persistent_clock -  Return time from a persistent clock.
- *
- * Reads the time from a source which isn't disabled during PM, the
- * 32k sync timer.  Convert the cycles elapsed since last read into
- * nsecs and adds to a monotonically increasing timespec.
- */
-static struct timespec persistent_ts;
-static cycles_t cycles, last_cycles;
-void read_persistent_clock(struct timespec *ts)
-{
-       unsigned long long nsecs;
-       cycles_t delta;
-       struct timespec *tsp = &persistent_ts;
-
-       last_cycles = cycles;
-       cycles = clocksource_32k.read(&clocksource_32k);
-       delta = cycles - last_cycles;
-
-       nsecs = clocksource_cyc2ns(delta,
-                                  clocksource_32k.mult, clocksource_32k.shift);
-
-       timespec_add_ns(tsp, nsecs);
-       *ts = *tsp;
-}
-
-static int __init omap_init_clocksource_32k(void)
-{
-       static char err[] __initdata = KERN_ERR
-                       "%s: can't register clocksource!\n";
-
-       if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
-               struct clk *sync_32k_ick;
-
-               if (cpu_is_omap16xx())
-                       clocksource_32k.read = omap16xx_32k_read;
-               else if (cpu_is_omap2420())
-                       clocksource_32k.read = omap2420_32k_read;
-               else if (cpu_is_omap2430())
-                       clocksource_32k.read = omap2430_32k_read;
-               else if (cpu_is_omap34xx())
-                       clocksource_32k.read = omap34xx_32k_read;
-               else if (cpu_is_omap44xx())
-                       clocksource_32k.read = omap44xx_32k_read;
-               else
-                       return -ENODEV;
-
-               sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
-               if (sync_32k_ick)
-                       clk_enable(sync_32k_ick);
-
-               clocksource_32k.mult = clocksource_hz2mult(32768,
-                                           clocksource_32k.shift);
-
-               offset_32k = clocksource_32k.read(&clocksource_32k);
-
-               if (clocksource_register(&clocksource_32k))
-                       printk(err, clocksource_32k.name);
-       }
-       return 0;
-}
-arch_initcall(omap_init_clocksource_32k);
-
-#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
-
-/* Global address base setup code */
-
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-
-static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
-{
-       omap2_set_globals_tap(omap2_globals);
-       omap2_set_globals_sdrc(omap2_globals);
-       omap2_set_globals_control(omap2_globals);
-       omap2_set_globals_prcm(omap2_globals);
-       omap2_set_globals_uart(omap2_globals);
-}
-
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2420)
-
-static struct omap_globals omap242x_globals = {
-       .class  = OMAP242X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(0x48014000),
-       .sdrc   = OMAP2420_SDRC_BASE,
-       .sms    = OMAP2420_SMS_BASE,
-       .ctrl   = OMAP2420_CTRL_BASE,
-       .prm    = OMAP2420_PRM_BASE,
-       .cm     = OMAP2420_CM_BASE,
-       .uart1_phys     = OMAP2_UART1_BASE,
-       .uart2_phys     = OMAP2_UART2_BASE,
-       .uart3_phys     = OMAP2_UART3_BASE,
-};
-
-void __init omap2_set_globals_242x(void)
-{
-       __omap2_set_globals(&omap242x_globals);
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP2430)
-
-static struct omap_globals omap243x_globals = {
-       .class  = OMAP243X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(0x4900a000),
-       .sdrc   = OMAP243X_SDRC_BASE,
-       .sms    = OMAP243X_SMS_BASE,
-       .ctrl   = OMAP243X_CTRL_BASE,
-       .prm    = OMAP2430_PRM_BASE,
-       .cm     = OMAP2430_CM_BASE,
-       .uart1_phys     = OMAP2_UART1_BASE,
-       .uart2_phys     = OMAP2_UART2_BASE,
-       .uart3_phys     = OMAP2_UART3_BASE,
-};
-
-void __init omap2_set_globals_243x(void)
-{
-       __omap2_set_globals(&omap243x_globals);
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3)
-
-static struct omap_globals omap3_globals = {
-       .class  = OMAP343X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(0x4830A000),
-       .sdrc   = OMAP343X_SDRC_BASE,
-       .sms    = OMAP343X_SMS_BASE,
-       .ctrl   = OMAP343X_CTRL_BASE,
-       .prm    = OMAP3430_PRM_BASE,
-       .cm     = OMAP3430_CM_BASE,
-       .uart1_phys     = OMAP3_UART1_BASE,
-       .uart2_phys     = OMAP3_UART2_BASE,
-       .uart3_phys     = OMAP3_UART3_BASE,
-       .uart4_phys     = OMAP3_UART4_BASE,     /* Only on 3630 */
-};
-
-void __init omap2_set_globals_3xxx(void)
-{
-       __omap2_set_globals(&omap3_globals);
-}
-
-void __init omap3_map_io(void)
-{
-       omap2_set_globals_3xxx();
-       omap34xx_map_common_io();
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP4)
-static struct omap_globals omap4_globals = {
-       .class  = OMAP443X_CLASS,
-       .tap    = OMAP2_L4_IO_ADDRESS(OMAP443X_SCM_BASE),
-       .ctrl   = OMAP443X_CTRL_BASE,
-       .prm    = OMAP4430_PRM_BASE,
-       .cm     = OMAP4430_CM_BASE,
-       .cm2    = OMAP4430_CM2_BASE,
-       .uart1_phys     = OMAP4_UART1_BASE,
-       .uart2_phys     = OMAP4_UART2_BASE,
-       .uart3_phys     = OMAP4_UART3_BASE,
-       .uart4_phys     = OMAP4_UART4_BASE,
-};
-
-void __init omap2_set_globals_443x(void)
-{
-       omap2_set_globals_tap(&omap4_globals);
-       omap2_set_globals_control(&omap4_globals);
-       omap2_set_globals_prcm(&omap4_globals);
-       omap2_set_globals_uart(&omap4_globals);
-}
-#endif
-
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
new file mode 100644 (file)
index 0000000..155fe43
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * OMAP 32ksynctimer/counter_32k-related code
+ *
+ * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2010 Nokia Corporation
+ * Tony Lindgren <tony@atomide.com>
+ * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * NOTE: This timer is not the same timer as the old OMAP1 MPU timer.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+#include <plat/board.h>
+
+#include <plat/clock.h>
+
+
+/*
+ * 32KHz clocksource ... always available, on pretty most chips except
+ * OMAP 730 and 1510.  Other timers could be used as clocksources, with
+ * higher resolution in free-running counter modes (e.g. 12 MHz xtal),
+ * but systems won't necessarily want to spend resources that way.
+ */
+
+#define OMAP16XX_TIMER_32K_SYNCHRONIZED                0xfffbc410
+
+#if !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX))
+
+#include <linux/clocksource.h>
+
+/*
+ * offset_32k holds the init time counter value. It is then subtracted
+ * from every counter read to achieve a counter that counts time from the
+ * kernel boot (needed for sched_clock()).
+ */
+static u32 offset_32k __read_mostly;
+
+#ifdef CONFIG_ARCH_OMAP16XX
+static cycle_t omap16xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
+}
+#else
+#define omap16xx_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2420
+static cycle_t omap2420_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2420_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2430
+static cycle_t omap2430_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2430_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static cycle_t omap34xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap34xx_32k_read      NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static cycle_t omap44xx_32k_read(struct clocksource *cs)
+{
+       return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap44xx_32k_read      NULL
+#endif
+
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t omap_32k_read_dummy(struct clocksource *cs)
+{
+       return 0;
+}
+
+static struct clocksource clocksource_32k = {
+       .name           = "32k_counter",
+       .rating         = 250,
+       .read           = omap_32k_read_dummy,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .shift          = 10,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/*
+ * Returns current time from boot in nsecs. It's OK for this to wrap
+ * around for now, as it's just a relative time stamp.
+ */
+unsigned long long sched_clock(void)
+{
+       return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
+                                 clocksource_32k.mult, clocksource_32k.shift);
+}
+
+/**
+ * read_persistent_clock -  Return time from a persistent clock.
+ *
+ * Reads the time from a source which isn't disabled during PM, the
+ * 32k sync timer.  Convert the cycles elapsed since last read into
+ * nsecs and adds to a monotonically increasing timespec.
+ */
+static struct timespec persistent_ts;
+static cycles_t cycles, last_cycles;
+void read_persistent_clock(struct timespec *ts)
+{
+       unsigned long long nsecs;
+       cycles_t delta;
+       struct timespec *tsp = &persistent_ts;
+
+       last_cycles = cycles;
+       cycles = clocksource_32k.read(&clocksource_32k);
+       delta = cycles - last_cycles;
+
+       nsecs = clocksource_cyc2ns(delta,
+                                  clocksource_32k.mult, clocksource_32k.shift);
+
+       timespec_add_ns(tsp, nsecs);
+       *ts = *tsp;
+}
+
+static int __init omap_init_clocksource_32k(void)
+{
+       static char err[] __initdata = KERN_ERR
+                       "%s: can't register clocksource!\n";
+
+       if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
+               struct clk *sync_32k_ick;
+
+               if (cpu_is_omap16xx())
+                       clocksource_32k.read = omap16xx_32k_read;
+               else if (cpu_is_omap2420())
+                       clocksource_32k.read = omap2420_32k_read;
+               else if (cpu_is_omap2430())
+                       clocksource_32k.read = omap2430_32k_read;
+               else if (cpu_is_omap34xx())
+                       clocksource_32k.read = omap34xx_32k_read;
+               else if (cpu_is_omap44xx())
+                       clocksource_32k.read = omap44xx_32k_read;
+               else
+                       return -ENODEV;
+
+               sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
+               if (sync_32k_ick)
+                       clk_enable(sync_32k_ick);
+
+               clocksource_32k.mult = clocksource_hz2mult(32768,
+                                           clocksource_32k.shift);
+
+               offset_32k = clocksource_32k.read(&clocksource_32k);
+
+               if (clocksource_register(&clocksource_32k))
+                       printk(err, clocksource_32k.name);
+       }
+       return 0;
+}
+arch_initcall(omap_init_clocksource_32k);
+
+#endif /* !(defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP15XX)) */
+
index 6d3d333..11c54ec 100644 (file)
@@ -40,7 +40,7 @@ static struct clk *mpu_clk;
 
 /* TODO: Add support for SDRAM timing changes */
 
-int omap_verify_speed(struct cpufreq_policy *policy)
+static int omap_verify_speed(struct cpufreq_policy *policy)
 {
        if (freq_table)
                return cpufreq_frequency_table_verify(policy, freq_table);
@@ -58,7 +58,7 @@ int omap_verify_speed(struct cpufreq_policy *policy)
        return 0;
 }
 
-unsigned int omap_getspeed(unsigned int cpu)
+static unsigned int omap_getspeed(unsigned int cpu)
 {
        unsigned long rate;
 
index d1920be..1e2383e 100644 (file)
@@ -21,7 +21,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/tc.h>
-#include <plat/control.h>
 #include <plat/board.h>
 #include <plat/mmc.h>
 #include <mach/gpio.h>
@@ -232,46 +231,6 @@ static void omap_init_uwire(void)
 static inline void omap_init_uwire(void) {}
 #endif
 
-/*-------------------------------------------------------------------------*/
-
-#if    defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE)
-
-static struct resource wdt_resources[] = {
-       {
-               .flags          = IORESOURCE_MEM,
-       },
-};
-
-static struct platform_device omap_wdt_device = {
-       .name      = "omap_wdt",
-       .id          = -1,
-       .num_resources  = ARRAY_SIZE(wdt_resources),
-       .resource       = wdt_resources,
-};
-
-static void omap_init_wdt(void)
-{
-       if (cpu_is_omap16xx())
-               wdt_resources[0].start = 0xfffeb000;
-       else if (cpu_is_omap2420())
-               wdt_resources[0].start = 0x48022000; /* WDT2 */
-       else if (cpu_is_omap2430())
-               wdt_resources[0].start = 0x49016000; /* WDT2 */
-       else if (cpu_is_omap343x())
-               wdt_resources[0].start = 0x48314000; /* WDT2 */
-       else if (cpu_is_omap44xx())
-               wdt_resources[0].start = 0x4a314000;
-       else
-               return;
-
-       wdt_resources[0].end = wdt_resources[0].start + 0x4f;
-
-       (void) platform_device_register(&omap_wdt_device);
-}
-#else
-static inline void omap_init_wdt(void) {}
-#endif
-
 /*
  * This gets called after board-specific INIT_MACHINE, and initializes most
  * on-chip peripherals accessible on this board (except for few like USB):
@@ -300,7 +259,6 @@ static int __init omap_init_devices(void)
        omap_init_rng();
        omap_init_mcpdm();
        omap_init_uwire();
-       omap_init_wdt();
        return 0;
 }
 arch_initcall(omap_init_devices);
index ec7eddf..f5c5b8d 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <mach/hardware.h>
@@ -996,11 +997,17 @@ void omap_start_dma(int lch)
        l = dma_read(CCR(lch));
 
        /*
-        * Errata: On ES2.0 BUFFERING disable must be set.
-        * This will always fail on ES1.0
+        * Errata: Inter Frame DMA buffering issue (All OMAP2420 and
+        * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and
+        * bursting is enabled. This might result in data gets stalled in
+        * FIFO at the end of the block.
+        * Workaround: DMA channels must have BUFFERING_DISABLED bit set to
+        * guarantee no data will stay in the DMA FIFO in case inter frame
+        * buffering occurs.
         */
-       if (cpu_is_omap24xx())
-               l |= OMAP_DMA_CCR_EN;
+       if (cpu_is_omap2420() ||
+           (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0)))
+               l |= OMAP_DMA_CCR_BUFFERING_DISABLE;
 
        l |= OMAP_DMA_CCR_EN;
        dma_write(l, CCR(lch));
@@ -1018,8 +1025,39 @@ void omap_stop_dma(int lch)
                dma_write(0, CICR(lch));
 
        l = dma_read(CCR(lch));
-       l &= ~OMAP_DMA_CCR_EN;
-       dma_write(l, CCR(lch));
+       /* OMAP3 Errata i541: sDMA FIFO draining does not finish */
+       if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
+               int i = 0;
+               u32 sys_cf;
+
+               /* Configure No-Standby */
+               l = dma_read(OCP_SYSCONFIG);
+               sys_cf = l;
+               l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+               l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+               dma_write(l , OCP_SYSCONFIG);
+
+               l = dma_read(CCR(lch));
+               l &= ~OMAP_DMA_CCR_EN;
+               dma_write(l, CCR(lch));
+
+               /* Wait for sDMA FIFO drain */
+               l = dma_read(CCR(lch));
+               while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE |
+                                       OMAP_DMA_CCR_WR_ACTIVE))) {
+                       udelay(5);
+                       i++;
+                       l = dma_read(CCR(lch));
+               }
+               if (i >= 100)
+                       printk(KERN_ERR "DMA drain did not complete on "
+                                       "lch %d\n", lch);
+               /* Restore OCP_SYSCONFIG */
+               dma_write(sys_cf, OCP_SYSCONFIG);
+       } else {
+               l &= ~OMAP_DMA_CCR_EN;
+               dma_write(l, CCR(lch));
+       }
 
        if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) {
                int next_lch, cur_lch = lch;
index 44bafda..1d706cf 100644 (file)
@@ -581,7 +581,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
         * When the functional clock disappears, too quick writes seem
         * to cause an abort. XXX Is this still necessary?
         */
-       __delay(150000);
+       __delay(300000);
 
        return ret;
 }
index 7193481..c9e5d72 100644 (file)
@@ -36,6 +36,8 @@
 #include <plat/board.h>
 #include <plat/sram.h>
 
+#include "fb.h"
+
 #if defined(CONFIG_FB_OMAP) || defined(CONFIG_FB_OMAP_MODULE)
 
 static struct omapfb_platform_data omapfb_config;
@@ -94,7 +96,7 @@ static int fbmem_region_reserved(unsigned long start, size_t size)
  * Get the region_idx`th region from board config/ATAG and convert it to
  * our internal format.
  */
-static int get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
+static int __init get_fbmem_region(int region_idx, struct omapfb_mem_region *rg)
 {
        const struct omap_fbmem_config  *conf;
        u32                             paddr;
@@ -126,7 +128,7 @@ static int set_fbmem_region_type(struct omapfb_mem_region *rg, int mem_type,
         * type = 0 && paddr = 0, a default don't care case maps to
         * the SDRAM type.
         */
-       if (rg->type || (!rg->type && !rg->paddr))
+       if (rg->type || !rg->paddr)
                return 0;
        if (ranges_overlap(rg->paddr, rg->size, mem_start, mem_size)) {
                rg->type = mem_type;
@@ -258,7 +260,7 @@ void __init omapfb_reserve_sdram_memblock(void)
  * this point, since the driver built as a module would have problem with
  * freeing / reallocating the regions.
  */
-unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
                                  unsigned long sram_vstart,
                                  unsigned long sram_size,
                                  unsigned long pstart_avail,
@@ -332,7 +334,7 @@ void omapfb_set_ctrl_platform_data(void *data)
        omapfb_config.ctrl_platform_data = data;
 }
 
-static inline int omap_init_fb(void)
+static int __init omap_init_fb(void)
 {
        const struct omap_lcd_config *conf;
 
@@ -377,7 +379,7 @@ void omapfb_set_platform_data(struct omapfb_platform_data *data)
        omapfb_config = *data;
 }
 
-static inline int omap_init_fb(void)
+static int __init omap_init_fb(void)
 {
        return platform_device_register(&omap_fb_device);
 }
@@ -388,7 +390,7 @@ void omapfb_reserve_sdram_memblock(void)
 {
 }
 
-unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
                                  unsigned long sram_vstart,
                                  unsigned long sram_size,
                                  unsigned long start_avail,
@@ -407,7 +409,7 @@ void omapfb_reserve_sdram_memblock(void)
 {
 }
 
-unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+unsigned long __init omapfb_reserve_sram(unsigned long sram_pstart,
                                  unsigned long sram_vstart,
                                  unsigned long sram_size,
                                  unsigned long start_avail,
diff --git a/arch/arm/plat-omap/fb.h b/arch/arm/plat-omap/fb.h
new file mode 100644 (file)
index 0000000..d765d0b
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __PLAT_OMAP_FB_H__
+#define __PLAT_OMAP_FB_H__
+
+extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
+                                        unsigned long sram_vstart,
+                                        unsigned long sram_size,
+                                        unsigned long pstart_avail,
+                                        unsigned long size_avail);
+
+#endif /* __PLAT_OMAP_FB_H__ */
index 7951eef..c05c653 100644 (file)
@@ -2084,9 +2084,10 @@ void omap2_gpio_prepare_for_idle(int power_state)
 
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
-               u32 l1, l2;
+               u32 l1 = 0, l2 = 0;
+               int j;
 
-               if (bank->dbck_enable_mask)
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_disable(bank->dbck);
 
                if (power_state > PWRDM_POWER_OFF)
@@ -2151,9 +2152,10 @@ void omap2_gpio_resume_after_idle(void)
                min = 1;
        for (i = min; i < gpio_bank_count; i++) {
                struct gpio_bank *bank = &gpio_bank[i];
-               u32 l, gen, gen0, gen1;
+               u32 l = 0, gen, gen0, gen1;
+               int j;
 
-               if (bank->dbck_enable_mask)
+               for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++)
                        clk_enable(bank->dbck);
 
                if (!workaround_enabled)
index 9776b41..a9d69a0 100644 (file)
@@ -47,6 +47,7 @@ struct omap_globals {
        unsigned long   sdrc;           /* SDRAM Controller */
        unsigned long   sms;            /* SDRAM Memory Scheduler */
        unsigned long   ctrl;           /* System Control Module */
+       unsigned long   ctrl_pad;       /* PAD Control Module */
        unsigned long   prm;            /* Power and Reset Management */
        unsigned long   cm;             /* Clock Management */
        unsigned long   cm2;
@@ -66,7 +67,6 @@ void omap2_set_globals_tap(struct omap_globals *);
 void omap2_set_globals_sdrc(struct omap_globals *);
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
-void omap2_set_globals_uart(struct omap_globals *);
 
 void omap3_map_io(void);
 
@@ -91,7 +91,8 @@ void omap3_map_io(void);
 })
 
 extern struct device *omap2_get_mpuss_device(void);
-extern struct device *omap2_get_dsp_device(void);
+extern struct device *omap2_get_iva_device(void);
 extern struct device *omap2_get_l3_device(void);
+extern struct device *omap4_get_dsp_device(void);
 
 #endif /* __ARCH_ARM_MACH_OMAP_COMMON_H */
diff --git a/arch/arm/plat-omap/include/plat/control.h b/arch/arm/plat-omap/include/plat/control.h
deleted file mode 100644 (file)
index 131bf40..0000000
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * arch/arm/plat-omap/include/mach/control.h
- *
- * OMAP2/3/4 System Control Module definitions
- *
- * Copyright (C) 2007-2009 Texas Instruments, Inc.
- * Copyright (C) 2007-2008 Nokia Corporation
- *
- * Written by Paul Walmsley
- *
- * 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.
- */
-
-#ifndef __ASM_ARCH_CONTROL_H
-#define __ASM_ARCH_CONTROL_H
-
-#include <mach/io.h>
-
-#ifndef __ASSEMBLY__
-#define OMAP242X_CTRL_REGADDR(reg)                                     \
-               OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
-#define OMAP243X_CTRL_REGADDR(reg)                                     \
-               OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
-#define OMAP343X_CTRL_REGADDR(reg)                                     \
-               OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
-#else
-#define OMAP242X_CTRL_REGADDR(reg)                                     \
-               OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
-#define OMAP243X_CTRL_REGADDR(reg)                                     \
-               OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
-#define OMAP343X_CTRL_REGADDR(reg)                                     \
-               OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
-#endif /* __ASSEMBLY__ */
-
-/*
- * As elsewhere, the "OMAP2_" prefix indicates that the macro is valid for
- * OMAP24XX and OMAP34XX.
- */
-
-/* Control submodule offsets */
-
-#define OMAP2_CONTROL_INTERFACE                0x000
-#define OMAP2_CONTROL_PADCONFS         0x030
-#define OMAP2_CONTROL_GENERAL          0x270
-#define OMAP343X_CONTROL_MEM_WKUP      0x600
-#define OMAP343X_CONTROL_PADCONFS_WKUP 0xa00
-#define OMAP343X_CONTROL_GENERAL_WKUP  0xa60
-
-/* Control register offsets - read/write with omap_ctrl_{read,write}{bwl}() */
-
-#define OMAP2_CONTROL_SYSCONFIG                (OMAP2_CONTROL_INTERFACE + 0x10)
-
-/* CONTROL_GENERAL register offsets common to OMAP2 & 3 */
-#define OMAP2_CONTROL_DEVCONF0         (OMAP2_CONTROL_GENERAL + 0x0004)
-#define OMAP2_CONTROL_MSUSPENDMUX_0    (OMAP2_CONTROL_GENERAL + 0x0020)
-#define OMAP2_CONTROL_MSUSPENDMUX_1    (OMAP2_CONTROL_GENERAL + 0x0024)
-#define OMAP2_CONTROL_MSUSPENDMUX_2    (OMAP2_CONTROL_GENERAL + 0x0028)
-#define OMAP2_CONTROL_MSUSPENDMUX_3    (OMAP2_CONTROL_GENERAL + 0x002c)
-#define OMAP2_CONTROL_MSUSPENDMUX_4    (OMAP2_CONTROL_GENERAL + 0x0030)
-#define OMAP2_CONTROL_MSUSPENDMUX_5    (OMAP2_CONTROL_GENERAL + 0x0034)
-#define OMAP2_CONTROL_SEC_CTRL         (OMAP2_CONTROL_GENERAL + 0x0040)
-#define OMAP2_CONTROL_RPUB_KEY_H_0     (OMAP2_CONTROL_GENERAL + 0x0090)
-#define OMAP2_CONTROL_RPUB_KEY_H_1     (OMAP2_CONTROL_GENERAL + 0x0094)
-#define OMAP2_CONTROL_RPUB_KEY_H_2     (OMAP2_CONTROL_GENERAL + 0x0098)
-#define OMAP2_CONTROL_RPUB_KEY_H_3     (OMAP2_CONTROL_GENERAL + 0x009c)
-
-/* 242x-only CONTROL_GENERAL register offsets */
-#define OMAP242X_CONTROL_DEVCONF       OMAP2_CONTROL_DEVCONF0 /* match TRM */
-#define OMAP242X_CONTROL_OCM_RAM_PERM  (OMAP2_CONTROL_GENERAL + 0x0068)
-
-/* 243x-only CONTROL_GENERAL register offsets */
-/* CONTROL_IVA2_BOOT{ADDR,MOD} are at the same place on 343x - noted below */
-#define OMAP243X_CONTROL_DEVCONF1      (OMAP2_CONTROL_GENERAL + 0x0078)
-#define OMAP243X_CONTROL_CSIRXFE       (OMAP2_CONTROL_GENERAL + 0x007c)
-#define OMAP243X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
-#define OMAP243X_CONTROL_IVA2_BOOTMOD  (OMAP2_CONTROL_GENERAL + 0x0194)
-#define OMAP243X_CONTROL_IVA2_GEMCFG   (OMAP2_CONTROL_GENERAL + 0x0198)
-#define OMAP243X_CONTROL_PBIAS_LITE    (OMAP2_CONTROL_GENERAL + 0x0230)
-
-/* 24xx-only CONTROL_GENERAL register offsets */
-#define OMAP24XX_CONTROL_DEBOBS                (OMAP2_CONTROL_GENERAL + 0x0000)
-#define OMAP24XX_CONTROL_EMU_SUPPORT   (OMAP2_CONTROL_GENERAL + 0x0008)
-#define OMAP24XX_CONTROL_SEC_TEST      (OMAP2_CONTROL_GENERAL + 0x0044)
-#define OMAP24XX_CONTROL_PSA_CTRL      (OMAP2_CONTROL_GENERAL + 0x0048)
-#define OMAP24XX_CONTROL_PSA_CMD       (OMAP2_CONTROL_GENERAL + 0x004c)
-#define OMAP24XX_CONTROL_PSA_VALUE     (OMAP2_CONTROL_GENERAL + 0x0050)
-#define OMAP24XX_CONTROL_SEC_EMU       (OMAP2_CONTROL_GENERAL + 0x0060)
-#define OMAP24XX_CONTROL_SEC_TAP       (OMAP2_CONTROL_GENERAL + 0x0064)
-#define OMAP24XX_CONTROL_OCM_PUB_RAM_ADD       (OMAP2_CONTROL_GENERAL + 0x006c)
-#define OMAP24XX_CONTROL_EXT_SEC_RAM_START_ADD (OMAP2_CONTROL_GENERAL + 0x0070)
-#define OMAP24XX_CONTROL_EXT_SEC_RAM_STOP_ADD  (OMAP2_CONTROL_GENERAL + 0x0074)
-#define OMAP24XX_CONTROL_SEC_STATUS            (OMAP2_CONTROL_GENERAL + 0x0080)
-#define OMAP24XX_CONTROL_SEC_ERR_STATUS                (OMAP2_CONTROL_GENERAL + 0x0084)
-#define OMAP24XX_CONTROL_STATUS                        (OMAP2_CONTROL_GENERAL + 0x0088)
-#define OMAP24XX_CONTROL_GENERAL_PURPOSE_STATUS        (OMAP2_CONTROL_GENERAL + 0x008c)
-#define OMAP24XX_CONTROL_RAND_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00a0)
-#define OMAP24XX_CONTROL_RAND_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00a4)
-#define OMAP24XX_CONTROL_RAND_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00a8)
-#define OMAP24XX_CONTROL_RAND_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00ac)
-#define OMAP24XX_CONTROL_CUST_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00b0)
-#define OMAP24XX_CONTROL_CUST_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00b4)
-#define OMAP24XX_CONTROL_TEST_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00c0)
-#define OMAP24XX_CONTROL_TEST_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00c4)
-#define OMAP24XX_CONTROL_TEST_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00c8)
-#define OMAP24XX_CONTROL_TEST_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00cc)
-#define OMAP24XX_CONTROL_TEST_KEY_4    (OMAP2_CONTROL_GENERAL + 0x00d0)
-#define OMAP24XX_CONTROL_TEST_KEY_5    (OMAP2_CONTROL_GENERAL + 0x00d4)
-#define OMAP24XX_CONTROL_TEST_KEY_6    (OMAP2_CONTROL_GENERAL + 0x00d8)
-#define OMAP24XX_CONTROL_TEST_KEY_7    (OMAP2_CONTROL_GENERAL + 0x00dc)
-#define OMAP24XX_CONTROL_TEST_KEY_8    (OMAP2_CONTROL_GENERAL + 0x00e0)
-#define OMAP24XX_CONTROL_TEST_KEY_9    (OMAP2_CONTROL_GENERAL + 0x00e4)
-
-#define OMAP343X_CONTROL_PADCONF_SYSNIRQ (OMAP2_CONTROL_INTERFACE + 0x01b0)
-
-/* 34xx-only CONTROL_GENERAL register offsets */
-#define OMAP343X_CONTROL_PADCONF_OFF   (OMAP2_CONTROL_GENERAL + 0x0000)
-#define OMAP343X_CONTROL_MEM_DFTRW0    (OMAP2_CONTROL_GENERAL + 0x0008)
-#define OMAP343X_CONTROL_MEM_DFTRW1    (OMAP2_CONTROL_GENERAL + 0x000c)
-#define OMAP343X_CONTROL_DEVCONF1      (OMAP2_CONTROL_GENERAL + 0x0068)
-#define OMAP343X_CONTROL_CSIRXFE               (OMAP2_CONTROL_GENERAL + 0x006c)
-#define OMAP343X_CONTROL_SEC_STATUS            (OMAP2_CONTROL_GENERAL + 0x0070)
-#define OMAP343X_CONTROL_SEC_ERR_STATUS                (OMAP2_CONTROL_GENERAL + 0x0074)
-#define OMAP343X_CONTROL_SEC_ERR_STATUS_DEBUG  (OMAP2_CONTROL_GENERAL + 0x0078)
-#define OMAP343X_CONTROL_STATUS                        (OMAP2_CONTROL_GENERAL + 0x0080)
-#define OMAP343X_CONTROL_GENERAL_PURPOSE_STATUS        (OMAP2_CONTROL_GENERAL + 0x0084)
-#define OMAP343X_CONTROL_RPUB_KEY_H_4  (OMAP2_CONTROL_GENERAL + 0x00a0)
-#define OMAP343X_CONTROL_RAND_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00a8)
-#define OMAP343X_CONTROL_RAND_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00ac)
-#define OMAP343X_CONTROL_RAND_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00b0)
-#define OMAP343X_CONTROL_RAND_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00b4)
-#define OMAP343X_CONTROL_TEST_KEY_0    (OMAP2_CONTROL_GENERAL + 0x00c8)
-#define OMAP343X_CONTROL_TEST_KEY_1    (OMAP2_CONTROL_GENERAL + 0x00cc)
-#define OMAP343X_CONTROL_TEST_KEY_2    (OMAP2_CONTROL_GENERAL + 0x00d0)
-#define OMAP343X_CONTROL_TEST_KEY_3    (OMAP2_CONTROL_GENERAL + 0x00d4)
-#define OMAP343X_CONTROL_TEST_KEY_4    (OMAP2_CONTROL_GENERAL + 0x00d8)
-#define OMAP343X_CONTROL_TEST_KEY_5    (OMAP2_CONTROL_GENERAL + 0x00dc)
-#define OMAP343X_CONTROL_TEST_KEY_6    (OMAP2_CONTROL_GENERAL + 0x00e0)
-#define OMAP343X_CONTROL_TEST_KEY_7    (OMAP2_CONTROL_GENERAL + 0x00e4)
-#define OMAP343X_CONTROL_TEST_KEY_8    (OMAP2_CONTROL_GENERAL + 0x00e8)
-#define OMAP343X_CONTROL_TEST_KEY_9    (OMAP2_CONTROL_GENERAL + 0x00ec)
-#define OMAP343X_CONTROL_TEST_KEY_10   (OMAP2_CONTROL_GENERAL + 0x00f0)
-#define OMAP343X_CONTROL_TEST_KEY_11   (OMAP2_CONTROL_GENERAL + 0x00f4)
-#define OMAP343X_CONTROL_TEST_KEY_12   (OMAP2_CONTROL_GENERAL + 0x00f8)
-#define OMAP343X_CONTROL_TEST_KEY_13   (OMAP2_CONTROL_GENERAL + 0x00fc)
-#define OMAP343X_CONTROL_IVA2_BOOTADDR (OMAP2_CONTROL_GENERAL + 0x0190)
-#define OMAP343X_CONTROL_IVA2_BOOTMOD  (OMAP2_CONTROL_GENERAL + 0x0194)
-#define OMAP343X_CONTROL_DEBOBS(i)     (OMAP2_CONTROL_GENERAL + 0x01B0 \
-                                       + ((i) >> 1) * 4 + (!((i) & 1)) * 2)
-#define OMAP343X_CONTROL_PROG_IO0      (OMAP2_CONTROL_GENERAL + 0x01D4)
-#define OMAP343X_CONTROL_PROG_IO1      (OMAP2_CONTROL_GENERAL + 0x01D8)
-#define OMAP343X_CONTROL_DSS_DPLL_SPREADING    (OMAP2_CONTROL_GENERAL + 0x01E0)
-#define OMAP343X_CONTROL_CORE_DPLL_SPREADING   (OMAP2_CONTROL_GENERAL + 0x01E4)
-#define OMAP343X_CONTROL_PER_DPLL_SPREADING    (OMAP2_CONTROL_GENERAL + 0x01E8)
-#define OMAP343X_CONTROL_USBHOST_DPLL_SPREADING        (OMAP2_CONTROL_GENERAL + 0x01EC)
-#define OMAP343X_CONTROL_PBIAS_LITE    (OMAP2_CONTROL_GENERAL + 0x02B0)
-#define OMAP343X_CONTROL_TEMP_SENSOR   (OMAP2_CONTROL_GENERAL + 0x02B4)
-#define OMAP343X_CONTROL_SRAMLDO4      (OMAP2_CONTROL_GENERAL + 0x02B8)
-#define OMAP343X_CONTROL_SRAMLDO5      (OMAP2_CONTROL_GENERAL + 0x02C0)
-#define OMAP343X_CONTROL_CSI           (OMAP2_CONTROL_GENERAL + 0x02C4)
-
-/* AM35XX only CONTROL_GENERAL register offsets */
-#define AM35XX_CONTROL_MSUSPENDMUX_6    (OMAP2_CONTROL_GENERAL + 0x0038)
-#define AM35XX_CONTROL_DEVCONF2         (OMAP2_CONTROL_GENERAL + 0x0310)
-#define AM35XX_CONTROL_DEVCONF3         (OMAP2_CONTROL_GENERAL + 0x0314)
-#define AM35XX_CONTROL_CBA_PRIORITY     (OMAP2_CONTROL_GENERAL + 0x0320)
-#define AM35XX_CONTROL_LVL_INTR_CLEAR   (OMAP2_CONTROL_GENERAL + 0x0324)
-#define AM35XX_CONTROL_IP_SW_RESET      (OMAP2_CONTROL_GENERAL + 0x0328)
-#define AM35XX_CONTROL_IPSS_CLK_CTRL    (OMAP2_CONTROL_GENERAL + 0x032C)
-
-/* 34xx PADCONF register offsets */
-#define OMAP343X_PADCONF_ETK(i)                (OMAP2_CONTROL_PADCONFS + 0x5a8 + \
-                                               (i)*2)
-#define OMAP343X_PADCONF_ETK_CLK       OMAP343X_PADCONF_ETK(0)
-#define OMAP343X_PADCONF_ETK_CTL       OMAP343X_PADCONF_ETK(1)
-#define OMAP343X_PADCONF_ETK_D0                OMAP343X_PADCONF_ETK(2)
-#define OMAP343X_PADCONF_ETK_D1                OMAP343X_PADCONF_ETK(3)
-#define OMAP343X_PADCONF_ETK_D2                OMAP343X_PADCONF_ETK(4)
-#define OMAP343X_PADCONF_ETK_D3                OMAP343X_PADCONF_ETK(5)
-#define OMAP343X_PADCONF_ETK_D4                OMAP343X_PADCONF_ETK(6)
-#define OMAP343X_PADCONF_ETK_D5                OMAP343X_PADCONF_ETK(7)
-#define OMAP343X_PADCONF_ETK_D6                OMAP343X_PADCONF_ETK(8)
-#define OMAP343X_PADCONF_ETK_D7                OMAP343X_PADCONF_ETK(9)
-#define OMAP343X_PADCONF_ETK_D8                OMAP343X_PADCONF_ETK(10)
-#define OMAP343X_PADCONF_ETK_D9                OMAP343X_PADCONF_ETK(11)
-#define OMAP343X_PADCONF_ETK_D10       OMAP343X_PADCONF_ETK(12)
-#define OMAP343X_PADCONF_ETK_D11       OMAP343X_PADCONF_ETK(13)
-#define OMAP343X_PADCONF_ETK_D12       OMAP343X_PADCONF_ETK(14)
-#define OMAP343X_PADCONF_ETK_D13       OMAP343X_PADCONF_ETK(15)
-#define OMAP343X_PADCONF_ETK_D14       OMAP343X_PADCONF_ETK(16)
-#define OMAP343X_PADCONF_ETK_D15       OMAP343X_PADCONF_ETK(17)
-
-/* 34xx GENERAL_WKUP regist offsets */
-#define OMAP343X_CONTROL_WKUP_DEBOBSMUX(i) (OMAP343X_CONTROL_GENERAL_WKUP + \
-                                               0x008 + (i))
-#define OMAP343X_CONTROL_WKUP_DEBOBS0 (OMAP343X_CONTROL_GENERAL_WKUP + 0x008)
-#define OMAP343X_CONTROL_WKUP_DEBOBS1 (OMAP343X_CONTROL_GENERAL_WKUP + 0x00C)
-#define OMAP343X_CONTROL_WKUP_DEBOBS2 (OMAP343X_CONTROL_GENERAL_WKUP + 0x010)
-#define OMAP343X_CONTROL_WKUP_DEBOBS3 (OMAP343X_CONTROL_GENERAL_WKUP + 0x014)
-#define OMAP343X_CONTROL_WKUP_DEBOBS4 (OMAP343X_CONTROL_GENERAL_WKUP + 0x018)
-
-/* 34xx D2D idle-related pins, handled by PM core */
-#define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
-#define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
-
-/* 44xx control status register offset */
-#define OMAP44XX_CONTROL_STATUS                0x2c4
-
-/* 44xx-only CONTROL_GENERAL register offsets */
-#define OMAP44XX_CONTROL_MMC1                  0x628
-#define OMAP44XX_CONTROL_PBIAS_LITE            0x600
-/*
- * REVISIT: This list of registers is not comprehensive - there are more
- * that should be added.
- */
-
-/*
- * Control module register bit defines - these should eventually go into
- * their own regbits file.  Some of these will be complicated, depending
- * on the device type (general-purpose, emulator, test, secure, bad, other)
- * and the security mode (secure, non-secure, don't care)
- */
-/* CONTROL_DEVCONF0 bits */
-#define OMAP2_MMCSDIO1ADPCLKISEL       (1 << 24) /* MMC1 loop back clock */
-#define OMAP24XX_USBSTANDBYCTRL                (1 << 15)
-#define OMAP2_MCBSP2_CLKS_MASK         (1 << 6)
-#define OMAP2_MCBSP1_CLKS_MASK         (1 << 2)
-
-/* CONTROL_DEVCONF1 bits */
-#define OMAP243X_MMC1_ACTIVE_OVERWRITE (1 << 31)
-#define OMAP2_MMCSDIO2ADPCLKISEL       (1 << 6) /* MMC2 loop back clock */
-#define OMAP2_MCBSP5_CLKS_MASK         (1 << 4) /* > 242x */
-#define OMAP2_MCBSP4_CLKS_MASK         (1 << 2) /* > 242x */
-#define OMAP2_MCBSP3_CLKS_MASK         (1 << 0) /* > 242x */
-
-/* CONTROL_STATUS bits */
-#define OMAP2_DEVICETYPE_MASK          (0x7 << 8)
-#define OMAP2_SYSBOOT_5_MASK           (1 << 5)
-#define OMAP2_SYSBOOT_4_MASK           (1 << 4)
-#define OMAP2_SYSBOOT_3_MASK           (1 << 3)
-#define OMAP2_SYSBOOT_2_MASK           (1 << 2)
-#define OMAP2_SYSBOOT_1_MASK           (1 << 1)
-#define OMAP2_SYSBOOT_0_MASK           (1 << 0)
-
-/* CONTROL_PBIAS_LITE bits */
-#define OMAP343X_PBIASLITESUPPLY_HIGH1 (1 << 15)
-#define OMAP343X_PBIASLITEVMODEERROR1  (1 << 11)
-#define OMAP343X_PBIASSPEEDCTRL1       (1 << 10)
-#define OMAP343X_PBIASLITEPWRDNZ1      (1 << 9)
-#define OMAP343X_PBIASLITEVMODE1       (1 << 8)
-#define OMAP343X_PBIASLITESUPPLY_HIGH0 (1 << 7)
-#define OMAP343X_PBIASLITEVMODEERROR0  (1 << 3)
-#define OMAP2_PBIASSPEEDCTRL0          (1 << 2)
-#define OMAP2_PBIASLITEPWRDNZ0         (1 << 1)
-#define OMAP2_PBIASLITEVMODE0          (1 << 0)
-
-/* CONTROL_PBIAS_LITE bits for OMAP4 */
-#define OMAP4_MMC1_PWRDNZ                      (1 << 26)
-#define OMAP4_MMC1_PBIASLITE_HIZ_MODE          (1 << 25)
-#define OMAP4_MMC1_PBIASLITE_SUPPLY_HI_OUT     (1 << 24)
-#define OMAP4_MMC1_PBIASLITE_VMODE_ERROR       (1 << 23)
-#define OMAP4_MMC1_PBIASLITE_PWRDNZ            (1 << 22)
-#define OMAP4_MMC1_PBIASLITE_VMODE             (1 << 21)
-#define OMAP4_USBC1_ICUSB_PWRDNZ               (1 << 20)
-
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP0    (1 << 31)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP1    (1 << 30)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP2    (1 << 29)
-#define OMAP4_CONTROL_SDMMC1_PUSTRENGTHGRP3    (1 << 28)
-#define OMAP4_CONTROL_SDMMC1_DR0_SPEEDCTRL     (1 << 27)
-#define OMAP4_CONTROL_SDMMC1_DR1_SPEEDCTRL     (1 << 26)
-#define OMAP4_CONTROL_SDMMC1_DR2_SPEEDCTRL     (1 << 25)
-
-/* CONTROL_PROG_IO1 bits */
-#define OMAP3630_PRG_SDMMC1_SPEEDCTRL  (1 << 20)
-
-/* CONTROL_IVA2_BOOTMOD bits */
-#define OMAP3_IVA2_BOOTMOD_SHIFT       0
-#define OMAP3_IVA2_BOOTMOD_MASK                (0xf << 0)
-#define OMAP3_IVA2_BOOTMOD_IDLE                (0x1 << 0)
-
-/* CONTROL_PADCONF_X bits */
-#define OMAP3_PADCONF_WAKEUPEVENT0     (1 << 15)
-#define OMAP3_PADCONF_WAKEUPENABLE0    (1 << 14)
-
-#define OMAP343X_SCRATCHPAD_ROM                (OMAP343X_CTRL_BASE + 0x860)
-#define OMAP343X_SCRATCHPAD            (OMAP343X_CTRL_BASE + 0x910)
-#define OMAP343X_SCRATCHPAD_ROM_OFFSET 0x19C
-
-/* AM35XX_CONTROL_IPSS_CLK_CTRL bits */
-#define AM35XX_USBOTG_VBUSP_CLK_SHIFT   0
-#define AM35XX_CPGMAC_VBUSP_CLK_SHIFT   1
-#define AM35XX_VPFE_VBUSP_CLK_SHIFT     2
-#define AM35XX_HECC_VBUSP_CLK_SHIFT     3
-#define AM35XX_USBOTG_FCLK_SHIFT        8
-#define AM35XX_CPGMAC_FCLK_SHIFT        9
-#define AM35XX_VPFE_FCLK_SHIFT          10
-
-/*AM35XX CONTROL_LVL_INTR_CLEAR bits*/
-#define AM35XX_CPGMAC_C0_MISC_PULSE_CLR        BIT(0)
-#define AM35XX_CPGMAC_C0_RX_PULSE_CLR  BIT(1)
-#define AM35XX_CPGMAC_C0_RX_THRESH_CLR BIT(2)
-#define AM35XX_CPGMAC_C0_TX_PULSE_CLR  BIT(3)
-#define AM35XX_USBOTGSS_INT_CLR                BIT(4)
-#define AM35XX_VPFE_CCDC_VD0_INT_CLR   BIT(5)
-#define AM35XX_VPFE_CCDC_VD1_INT_CLR   BIT(6)
-#define AM35XX_VPFE_CCDC_VD2_INT_CLR   BIT(7)
-
-/*AM35XX CONTROL_IP_SW_RESET bits*/
-#define AM35XX_USBOTGSS_SW_RST         BIT(0)
-#define AM35XX_CPGMACSS_SW_RST         BIT(1)
-#define AM35XX_VPFE_VBUSP_SW_RST       BIT(2)
-#define AM35XX_HECC_SW_RST             BIT(3)
-#define AM35XX_VPFE_PCLK_SW_RST                BIT(4)
-
-/*
- * CONTROL OMAP STATUS register to identify OMAP3 features
- */
-#define OMAP3_CONTROL_OMAP_STATUS      0x044c
-
-#define OMAP3_SGX_SHIFT                        13
-#define OMAP3_SGX_MASK                 (3 << OMAP3_SGX_SHIFT)
-#define                FEAT_SGX_FULL           0
-#define                FEAT_SGX_HALF           1
-#define                FEAT_SGX_NONE           2
-
-#define OMAP3_IVA_SHIFT                        12
-#define OMAP3_IVA_MASK                 (1 << OMAP3_SGX_SHIFT)
-#define                FEAT_IVA                0
-#define                FEAT_IVA_NONE           1
-
-#define OMAP3_L2CACHE_SHIFT            10
-#define OMAP3_L2CACHE_MASK             (3 << OMAP3_L2CACHE_SHIFT)
-#define                FEAT_L2CACHE_NONE       0
-#define                FEAT_L2CACHE_64KB       1
-#define                FEAT_L2CACHE_128KB      2
-#define                FEAT_L2CACHE_256KB      3
-
-#define OMAP3_ISP_SHIFT                        5
-#define OMAP3_ISP_MASK                 (1<< OMAP3_ISP_SHIFT)
-#define                FEAT_ISP                0
-#define                FEAT_ISP_NONE           1
-
-#define OMAP3_NEON_SHIFT               4
-#define OMAP3_NEON_MASK                        (1<< OMAP3_NEON_SHIFT)
-#define                FEAT_NEON               0
-#define                FEAT_NEON_NONE          1
-
-
-#ifndef __ASSEMBLY__
-#ifdef CONFIG_ARCH_OMAP2PLUS
-extern void __iomem *omap_ctrl_base_get(void);
-extern u8 omap_ctrl_readb(u16 offset);
-extern u16 omap_ctrl_readw(u16 offset);
-extern u32 omap_ctrl_readl(u16 offset);
-extern void omap_ctrl_writeb(u8 val, u16 offset);
-extern void omap_ctrl_writew(u16 val, u16 offset);
-extern void omap_ctrl_writel(u32 val, u16 offset);
-
-extern void omap3_save_scratchpad_contents(void);
-extern void omap3_clear_scratchpad_contents(void);
-extern u32 *get_restore_pointer(void);
-extern u32 *get_es3_restore_pointer(void);
-extern u32 omap3_arm_context[128];
-extern void omap3_control_save_context(void);
-extern void omap3_control_restore_context(void);
-
-#else
-#define omap_ctrl_base_get()           0
-#define omap_ctrl_readb(x)             0
-#define omap_ctrl_readw(x)             0
-#define omap_ctrl_readl(x)             0
-#define omap_ctrl_writeb(x, y)         WARN_ON(1)
-#define omap_ctrl_writew(x, y)         WARN_ON(1)
-#define omap_ctrl_writel(x, y)         WARN_ON(1)
-#endif
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_ARCH_CONTROL_H */
-
index 2e2ae53..3fd8b40 100644 (file)
@@ -68,10 +68,9 @@ unsigned int omap_rev(void);
 #define OMAP_REVBITS_00                0x00
 #define OMAP_REVBITS_01                0x01
 #define OMAP_REVBITS_02                0x02
-#define OMAP_REVBITS_10                0x10
-#define OMAP_REVBITS_20                0x20
-#define OMAP_REVBITS_30                0x30
-#define OMAP_REVBITS_40                0x40
+#define OMAP_REVBITS_03                0x03
+#define OMAP_REVBITS_04                0x04
+#define OMAP_REVBITS_05                0x05
 
 /*
  * Get the CPU revision for OMAP devices
@@ -363,23 +362,24 @@ IS_OMAP_TYPE(3517, 0x3517)
 
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS         0x24200024
-#define OMAP2420_REV_ES1_0     0x24200024
-#define OMAP2420_REV_ES2_0     0x24201024
+#define OMAP2420_REV_ES1_0     OMAP242X_CLASS
+#define OMAP2420_REV_ES2_0     (OMAP242X_CLASS | (OMAP_REVBITS_01 << 8))
 
 #define OMAP243X_CLASS         0x24300024
-#define OMAP2430_REV_ES1_0     0x24300024
+#define OMAP2430_REV_ES1_0     OMAP243X_CLASS
 
 #define OMAP343X_CLASS         0x34300034
-#define OMAP3430_REV_ES1_0     0x34300034
-#define OMAP3430_REV_ES2_0     0x34301034
-#define OMAP3430_REV_ES2_1     0x34302034
-#define OMAP3430_REV_ES3_0     0x34303034
-#define OMAP3430_REV_ES3_1     0x34304034
-#define OMAP3430_REV_ES3_1_2   0x34305034
-
-#define OMAP3630_REV_ES1_0     0x36300034
-#define OMAP3630_REV_ES1_1     0x36300134
-#define OMAP3630_REV_ES1_2     0x36300234
+#define OMAP3430_REV_ES1_0     OMAP343X_CLASS
+#define OMAP3430_REV_ES2_0     (OMAP343X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP3430_REV_ES2_1     (OMAP343X_CLASS | (OMAP_REVBITS_02 << 8))
+#define OMAP3430_REV_ES3_0     (OMAP343X_CLASS | (OMAP_REVBITS_03 << 8))
+#define OMAP3430_REV_ES3_1     (OMAP343X_CLASS | (OMAP_REVBITS_04 << 8))
+#define OMAP3430_REV_ES3_1_2   (OMAP343X_CLASS | (OMAP_REVBITS_05 << 8))
+
+#define OMAP363X_CLASS         0x36300034
+#define OMAP3630_REV_ES1_0     OMAP363X_CLASS
+#define OMAP3630_REV_ES1_1     (OMAP363X_CLASS | (OMAP_REVBITS_01 << 8))
+#define OMAP3630_REV_ES1_2     (OMAP363X_CLASS | (OMAP_REVBITS_02 << 8))
 
 #define OMAP35XX_CLASS         0x35000034
 #define OMAP3503_REV(v)                (OMAP35XX_CLASS | (0x3503 << 16) | (v << 8))
@@ -390,7 +390,8 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define OMAP3517_REV(v)                (OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
 
 #define OMAP443X_CLASS         0x44300044
-#define OMAP4430_REV_ES1_0     0x44300044
+#define OMAP4430_REV_ES1_0     OMAP443X_CLASS
+#define OMAP4430_REV_ES2_0     0x44301044
 
 /*
  * omap_chip bits
@@ -417,10 +418,12 @@ IS_OMAP_TYPE(3517, 0x3517)
 #define CHIP_IS_OMAP4430ES1            (1 << 8)
 #define CHIP_IS_OMAP3630ES1_1           (1 << 9)
 #define CHIP_IS_OMAP3630ES1_2           (1 << 10)
+#define CHIP_IS_OMAP4430ES2            (1 << 11)
 
 #define CHIP_IS_OMAP24XX               (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
 
-#define CHIP_IS_OMAP4430               (CHIP_IS_OMAP4430ES1)
+#define CHIP_IS_OMAP4430               (CHIP_IS_OMAP4430ES1 | \
+                                                CHIP_IS_OMAP4430ES2)
 
 /*
  * "GE" here represents "greater than or equal to" in terms of ES
index 8bd15bd..c915a66 100644 (file)
@@ -81,37 +81,6 @@ enum omap_color_mode {
        OMAP_DSS_COLOR_ARGB32   = 1 << 11, /* ARGB32 */
        OMAP_DSS_COLOR_RGBA32   = 1 << 12, /* RGBA32 */
        OMAP_DSS_COLOR_RGBX32   = 1 << 13, /* RGBx32 */
-
-       OMAP_DSS_COLOR_GFX_OMAP2 =
-               OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
-               OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
-               OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
-               OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
-
-       OMAP_DSS_COLOR_VID_OMAP2 =
-               OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-               OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
-               OMAP_DSS_COLOR_UYVY,
-
-       OMAP_DSS_COLOR_GFX_OMAP3 =
-               OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
-               OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
-               OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
-               OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-               OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
-               OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
-
-       OMAP_DSS_COLOR_VID1_OMAP3 =
-               OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
-               OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
-               OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
-
-       OMAP_DSS_COLOR_VID2_OMAP3 =
-               OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
-               OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
-               OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
-               OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
-               OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
 };
 
 enum omap_lcd_display_type {
index af3a039..0cce4ca 100644 (file)
 #define OMAP34XX_DMA_USIM_TX           79      /* S_DMA_78 */
 #define OMAP34XX_DMA_USIM_RX           80      /* S_DMA_79 */
 
+#define OMAP36XX_DMA_UART4_TX          81      /* S_DMA_80 */
+#define OMAP36XX_DMA_UART4_RX          82      /* S_DMA_81 */
 /*----------------------------------------------------------------------------*/
 
 #define OMAP1_DMA_TOUT_IRQ             (1 << 0)
 #define OMAP2_DMA_MISALIGNED_ERR_IRQ   (1 << 11)
 
 #define OMAP_DMA_CCR_EN                        (1 << 7)
+#define OMAP_DMA_CCR_RD_ACTIVE         (1 << 9)
+#define OMAP_DMA_CCR_WR_ACTIVE         (1 << 10)
+#define OMAP_DMA_CCR_SEL_SRC_DST_SYNC  (1 << 24)
+#define OMAP_DMA_CCR_BUFFERING_DISABLE (1 << 25)
 
 #define OMAP_DMA_DATA_TYPE_S8          0x00
 #define OMAP_DMA_DATA_TYPE_S16         0x01
index 20f1054..dfa3aff 100644 (file)
@@ -45,6 +45,8 @@
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE        0x02
 
 struct omap_dm_timer;
+extern struct omap_dm_timer *gptimer_wakeup;
+extern struct sys_timer omap_timer;
 struct clk;
 
 int omap_dm_timer_init(void);
diff --git a/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h b/arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
new file mode 100644 (file)
index 0000000..872de0b
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/plat-omap/include/plat/gpmc-smsc911x.h
+ *
+ * Copyright (C) 2009 Li-Pro.Net
+ * Stephan Linz <linz@li-pro.net>
+ *
+ * Modified from arch/arm/plat-omap/include/plat/gpmc-smc91x.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_OMAP_GPMC_SMSC911X_H__
+
+struct omap_smsc911x_platform_data {
+       int     cs;
+       int     gpio_irq;
+       int     gpio_reset;
+       u32     flags;
+};
+
+#if defined(CONFIG_SMSC911X) || \
+       defined(CONFIG_SMSC911X_MODULE)
+
+extern void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d);
+
+#else
+
+static inline void gpmc_smsc911x_init(struct omap_smsc911x_platform_data *d)
+{
+}
+
+#endif
+#endif
index 87f6bf2..36a0bef 100644 (file)
@@ -18,6 +18,8 @@
  * 02110-1301 USA
  *
  */
+#ifndef __ASM__ARCH_OMAP_I2C_H
+#define __ASM__ARCH_OMAP_I2C_H
 
 #include <linux/i2c.h>
 
@@ -36,3 +38,5 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
 
 void __init omap1_i2c_mux_pins(int bus_id);
 void __init omap2_i2c_mux_pins(int bus_id);
+
+#endif /* __ASM__ARCH_OMAP_I2C_H */
index c01d9f0..65e20a6 100644 (file)
 #define INT_34XX_MMC3_IRQ      94
 #define INT_34XX_GPT12_IRQ     95
 
+#define INT_36XX_UART4_IRQ     80
+
 #define INT_35XX_HECC0_IRQ             24
 #define INT_35XX_HECC1_IRQ             28
 #define INT_35XX_EMAC_C0_RXTHRESH_IRQ  67
index 5b20103..b87d83c 100644 (file)
@@ -319,6 +319,18 @@ static struct platform_device omap_mcbsp##port_nr = {      \
 #define RFSREN                 0x0002
 #define RSYNCERREN             0x0001
 
+/* CLKR signal muxing options */
+#define CLKR_SRC_CLKR          0
+#define CLKR_SRC_CLKX          1
+
+/* FSR signal muxing options */
+#define FSR_SRC_FSR            0
+#define FSR_SRC_FSX            1
+
+/* McBSP functional clock sources */
+#define MCBSP_CLKS_PRCM_SRC    0
+#define MCBSP_CLKS_PAD_SRC     1
+
 /* we don't do multichannel for now */
 struct omap_mcbsp_reg_cfg {
        u16 spcr2;
@@ -405,6 +417,7 @@ struct omap_mcbsp_spi_cfg {
 struct omap_mcbsp_ops {
        void (*request)(unsigned int);
        void (*free)(unsigned int);
+       int (*set_clks_src)(u8, u8);
 };
 
 struct omap_mcbsp_platform_data {
@@ -471,6 +484,9 @@ struct omap_mcbsp {
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count, omap_mcbsp_cache_size;
 
+#define omap_mcbsp_check_valid_id(id)  (id < omap_mcbsp_count)
+#define id_to_mcbsp_ptr(id)            mcbsp_ptr[id];
+
 int omap_mcbsp_init(void);
 void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
                                        int size);
@@ -509,6 +525,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
 int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
 
 
+/* McBSP functional clock source changing function */
+extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
 /* SPI specific API */
 void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
 
@@ -517,6 +535,10 @@ int omap_mcbsp_pollread(unsigned int id, u16 * buf);
 int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
 int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
 
+/* McBSP signal muxing API */
+void omap2_mcbsp1_mux_clkr_src(u8 mux);
+void omap2_mcbsp1_mux_fsr_src(u8 mux);
+
 #ifdef CONFIG_ARCH_OMAP3
 /* Sidetone specific API */
 int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
index 9b89ec6..f57f36a 100644 (file)
@@ -71,12 +71,17 @@ struct omap_mmc_platform_data {
 
        u64 dma_mask;
 
+       /* Register offset deviation */
+       u16 reg_offset;
+
        struct omap_mmc_slot_data {
 
-               /* 4 wire signaling is optional, and is used for SD/SDIO/HSMMC;
-                * 8 wire signaling is also optional, and is used with HSMMC
+               /*
+                * 4/8 wires and any additional host capabilities
+                * need to OR'd all capabilities (ref. linux/mmc/host.h)
                 */
-               u8 wires;
+               u8  wires;      /* Used for the MMC driver on omap1 and 2420 */
+               u32 caps;       /* Used for the MMC driver on 2430 and later */
 
                /*
                 * nomux means "standard" muxing is wrong on this board, and
@@ -104,6 +109,7 @@ struct omap_mmc_platform_data {
 
                /* we can put the features above into this variable */
 #define HSMMC_HAS_PBIAS                (1 << 0)
+#define HSMMC_HAS_UPDATED_RESET        (1 << 1)
                unsigned features;
 
                int switch_pin;                 /* gpio (card detect) */
diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h
new file mode 100644 (file)
index 0000000..c8dae02
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Driver for OMAP-UART controller.
+ * Based on drivers/serial/8250.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Authors:
+ *     Govindraj R     <govindraj.raja@ti.com>
+ *     Thara Gopinath  <thara@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __OMAP_SERIAL_H__
+#define __OMAP_SERIAL_H__
+
+#include <linux/serial_core.h>
+#include <linux/platform_device.h>
+
+#include <plat/mux.h>
+
+#define DRIVER_NAME    "omap-hsuart"
+
+/*
+ * Use tty device name as ttyO, [O -> OMAP]
+ * in bootargs we specify as console=ttyO0 if uart1
+ * is used as console uart.
+ */
+#define OMAP_SERIAL_NAME       "ttyO"
+
+#define OMAP_MDR1_DISABLE      0x07
+#define OMAP_MDR1_MODE13X      0x03
+#define OMAP_MDR1_MODE16X      0x00
+#define OMAP_MODE13X_SPEED     230400
+
+/*
+ * LCR = 0XBF: Switch to Configuration Mode B.
+ * In configuration mode b allow access
+ * to EFR,DLL,DLH.
+ * Reference OMAP TRM Chapter 17
+ * Section: 1.4.3 Mode Selection
+ */
+#define OMAP_UART_LCR_CONF_MDB 0XBF
+
+/* WER = 0x7F
+ * Enable module level wakeup in WER reg
+ */
+#define OMAP_UART_WER_MOD_WKUP 0X7F
+
+/* Enable XON/XOFF flow control on output */
+#define OMAP_UART_SW_TX                0x04
+
+/* Enable XON/XOFF flow control on input */
+#define OMAP_UART_SW_RX                0x04
+
+#define OMAP_UART_SYSC_RESET   0X07
+#define OMAP_UART_TCR_TRIG     0X0F
+#define OMAP_UART_SW_CLR       0XF0
+#define OMAP_UART_FIFO_CLR     0X06
+
+#define OMAP_UART_DMA_CH_FREE  -1
+
+#define RX_TIMEOUT             (3 * HZ)
+#define OMAP_MAX_HSUART_PORTS  4
+
+#define MSR_SAVE_FLAGS         UART_MSR_ANY_DELTA
+
+struct omap_uart_port_info {
+       bool                    dma_enabled;    /* To specify DMA Mode */
+       unsigned int            uartclk;        /* UART clock rate */
+       void __iomem            *membase;       /* ioremap cookie or NULL */
+       resource_size_t         mapbase;        /* resource base */
+       unsigned long           irqflags;       /* request_irq flags */
+       upf_t                   flags;          /* UPF_* flags */
+};
+
+struct uart_omap_dma {
+       u8                      uart_dma_tx;
+       u8                      uart_dma_rx;
+       int                     rx_dma_channel;
+       int                     tx_dma_channel;
+       dma_addr_t              rx_buf_dma_phys;
+       dma_addr_t              tx_buf_dma_phys;
+       unsigned int            uart_base;
+       /*
+        * Buffer for rx dma.It is not required for tx because the buffer
+        * comes from port structure.
+        */
+       unsigned char           *rx_buf;
+       unsigned int            prev_rx_dma_pos;
+       int                     tx_buf_size;
+       int                     tx_dma_used;
+       int                     rx_dma_used;
+       spinlock_t              tx_lock;
+       spinlock_t              rx_lock;
+       /* timer to poll activity on rx dma */
+       struct timer_list       rx_timer;
+       int                     rx_buf_size;
+       int                     rx_timeout;
+};
+
+struct uart_omap_port {
+       struct uart_port        port;
+       struct uart_omap_dma    uart_dma;
+       struct platform_device  *pdev;
+
+       unsigned char           ier;
+       unsigned char           lcr;
+       unsigned char           mcr;
+       unsigned char           fcr;
+       unsigned char           efr;
+
+       int                     use_dma;
+       /*
+        * Some bits in registers are cleared on a read, so they must
+        * be saved whenever the register is read but the bits will not
+        * be immediately processed.
+        */
+       unsigned int            lsr_break_flag;
+       unsigned char           msr_saved_flags;
+       char                    name[20];
+       unsigned long           port_activity;
+};
+
+#endif /* __OMAP_SERIAL_H__ */
index 7055672..92df9e2 100644 (file)
@@ -40,7 +40,7 @@
 #define OMAP24XX_IC_BASE       (L4_24XX_BASE + 0xfe000)
 #define OMAP24XX_IVA_INTC_BASE 0x40000000
 
-#define OMAP2420_CTRL_BASE     L4_24XX_BASE
+#define OMAP242X_CTRL_BASE     L4_24XX_BASE
 #define OMAP2420_32KSYNCT_BASE (L4_24XX_BASE + 0x4000)
 #define OMAP2420_PRCM_BASE     (L4_24XX_BASE + 0x8000)
 #define OMAP2420_CM_BASE       (L4_24XX_BASE + 0x8000)
index 25cd9ac..28e2d1a 100644 (file)
@@ -36,6 +36,8 @@
 
 #include <plat/omap_hwmod.h>
 
+extern struct device omap_device_parent;
+
 /* omap_device._state values */
 #define OMAP_DEVICE_STATE_UNKNOWN      0
 #define OMAP_DEVICE_STATE_ENABLED      1
@@ -62,7 +64,6 @@
  *
  */
 struct omap_device {
-       u32                             magic;
        struct platform_device          pdev;
        struct omap_hwmod               **hwmods;
        struct omap_device_pm_latency   *pm_lats;
@@ -82,7 +83,6 @@ int omap_device_shutdown(struct platform_device *pdev);
 
 /* Core code interface */
 
-bool omap_device_is_valid(struct omap_device *od);
 int omap_device_count_resources(struct omap_device *od);
 int omap_device_fill_resources(struct omap_device *od, struct resource *res);
 
index a4e508d..7eaa8ed 100644 (file)
  *
  * These headers and macros are used to define OMAP on-chip module
  * data and their integration with other OMAP modules and Linux.
- *
- * References:
- * - OMAP2420 Multimedia Processor Silicon Revision 2.1.1, 2.2 (SWPU064)
- * - OMAP2430 Multimedia Device POP Silicon Revision 2.1 (SWPU090)
- * - OMAP34xx Multimedia Device Silicon Revision 3.1 (SWPU108)
- * - OMAP4430 Multimedia Device Silicon Revision 1.0 (SWPU140)
- * - Open Core Protocol Specification 2.2
+ * Copious documentation and references can also be found in the
+ * omap_hwmod code, in arch/arm/mach-omap2/omap_hwmod.c (as of this
+ * writing).
  *
  * To do:
  * - add interconnect error log structures
  * - add pinmuxing
  * - init_conn_id_bit (CONNID_BIT_VECTOR)
  * - implement default hwmod SMS/SDRC flags?
+ * - remove unused fields
  *
  */
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
@@ -35,6 +32,7 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
+#include <linux/mutex.h>
 #include <plat/cpu.h>
 
 struct omap_device;
@@ -96,7 +94,7 @@ struct omap_hwmod_irq_info {
 /**
  * struct omap_hwmod_dma_info - DMA channels used by the hwmod
  * @name: name of the DMA channel (module local name)
- * @dma_ch: DMA channel ID
+ * @dma_req: DMA request ID
  *
  * @name should be something short, e.g., "tx" or "rx".  It is for use
  * by platform_get_resource_byname().  It is defined locally to the
@@ -104,7 +102,20 @@ struct omap_hwmod_irq_info {
  */
 struct omap_hwmod_dma_info {
        const char      *name;
-       u16             dma_ch;
+       u16             dma_req;
+};
+
+/**
+ * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
+ * @name: name of the reset line (module local name)
+ * @rst_shift: Offset of the reset bit
+ *
+ * @name should be something short, e.g., "cpu0" or "rst". It is defined
+ * locally to the hwmod.
+ */
+struct omap_hwmod_rst_info {
+       const char      *name;
+       u8              rst_shift;
 };
 
 /**
@@ -237,8 +248,9 @@ struct omap_hwmod_ocp_if {
 #define SYSC_HAS_CLOCKACTIVITY (1 << 4)
 #define SYSC_HAS_SIDLEMODE     (1 << 5)
 #define SYSC_HAS_MIDLEMODE     (1 << 6)
-#define SYSS_MISSING           (1 << 7)
+#define SYSS_HAS_RESET_STATUS  (1 << 7)
 #define SYSC_NO_CACHE          (1 << 8)  /* XXX SW flag, belongs elsewhere */
+#define SYSC_HAS_RESET_STATUS  (1 << 9)
 
 /* omap_hwmod_sysconfig.clockact flags */
 #define CLOCKACT_TEST_BOTH     0x0
@@ -327,10 +339,12 @@ struct omap_hwmod_omap2_prcm {
 /**
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
  * @clkctrl_reg: PRCM address of the clock control register
+ * @rstctrl_reg: adress of the XXX_RSTCTRL register located in the PRM
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
        void __iomem    *clkctrl_reg;
+       void __iomem    *rstctrl_reg;
        u8              submodule_wkdep_bit;
 };
 
@@ -352,6 +366,11 @@ struct omap_hwmod_omap4_prcm {
  * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
  * HWMOD_NO_IDLEST : this module does not have idle status - this is the case
  *     only for few initiator modules on OMAP2 & 3.
+ * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset.
+ *     This is needed for devices like DSS that require optional clocks enabled
+ *     in order to complete the reset. Optional clocks will be disabled
+ *     again after the reset.
+ * HWMOD_16BIT_REG: Module has 16bit registers
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -360,6 +379,8 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_OCP_AUTOIDLE                  (1 << 4)
 #define HWMOD_SET_DEFAULT_CLOCKACT             (1 << 5)
 #define HWMOD_NO_IDLEST                                (1 << 6)
+#define HWMOD_CONTROL_OPT_CLKS_IN_RESET                (1 << 7)
+#define HWMOD_16BIT_REG                                (1 << 8)
 
 /*
  * omap_hwmod._int_flags definitions
@@ -410,7 +431,7 @@ struct omap_hwmod_class {
  * @class: struct omap_hwmod_class * to the class of this hwmod
  * @od: struct omap_device currently associated with this hwmod (internal use)
  * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
- * @sdma_chs: ptr to an array of SDMA channel IDs (see also sdma_chs_cnt)
+ * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
  * @prcm: PRCM data pertaining to this hwmod
  * @main_clk: main clock: OMAP clock name
  * @_clk: pointer to the main struct clk (filled in at runtime)
@@ -424,7 +445,7 @@ struct omap_hwmod_class {
  * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6)
  * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift
  * @mpu_irqs_cnt: number of @mpu_irqs
- * @sdma_chs_cnt: number of @sdma_chs
+ * @sdma_reqs_cnt: number of @sdma_reqs
  * @opt_clks_cnt: number of @opt_clks
  * @master_cnt: number of @master entries
  * @slaves_cnt: number of @slave entries
@@ -433,6 +454,7 @@ struct omap_hwmod_class {
  * @_state: internal-use hwmod state
  * @flags: hwmod flags (documented below)
  * @omap_chip: OMAP chips this hwmod is present on
+ * @_mutex: mutex serializing operations on this hwmod
  * @node: list node for hwmod list (internal use)
  *
  * @main_clk refers to this module's "main clock," which for our
@@ -448,7 +470,8 @@ struct omap_hwmod {
        struct omap_hwmod_class         *class;
        struct omap_device              *od;
        struct omap_hwmod_irq_info      *mpu_irqs;
-       struct omap_hwmod_dma_info      *sdma_chs;
+       struct omap_hwmod_dma_info      *sdma_reqs;
+       struct omap_hwmod_rst_info      *rst_lines;
        union {
                struct omap_hwmod_omap2_prcm omap2;
                struct omap_hwmod_omap4_prcm omap4;
@@ -461,6 +484,7 @@ struct omap_hwmod {
        void                            *dev_attr;
        u32                             _sysc_cache;
        void __iomem                    *_mpu_rt_va;
+       struct mutex                    _mutex;
        struct list_head                node;
        u16                             flags;
        u8                              _mpu_port_index;
@@ -468,7 +492,8 @@ struct omap_hwmod {
        u8                              msuspendmux_shift;
        u8                              response_lat;
        u8                              mpu_irqs_cnt;
-       u8                              sdma_chs_cnt;
+       u8                              sdma_reqs_cnt;
+       u8                              rst_lines_cnt;
        u8                              opt_clks_cnt;
        u8                              masters_cnt;
        u8                              slaves_cnt;
@@ -492,6 +517,10 @@ int omap_hwmod_idle(struct omap_hwmod *oh);
 int _omap_hwmod_idle(struct omap_hwmod *oh);
 int omap_hwmod_shutdown(struct omap_hwmod *oh);
 
+int omap_hwmod_assert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_deassert_hardreset(struct omap_hwmod *oh, const char *name);
+int omap_hwmod_read_hardreset(struct omap_hwmod *oh, const char *name);
+
 int omap_hwmod_enable_clocks(struct omap_hwmod *oh);
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
@@ -500,8 +529,8 @@ int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
 int omap_hwmod_reset(struct omap_hwmod *oh);
 void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
 
-void omap_hwmod_writel(u32 v, struct omap_hwmod *oh, u16 reg_offs);
-u32 omap_hwmod_readl(struct omap_hwmod *oh, u16 reg_offs);
+void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
+u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
 
 int omap_hwmod_count_resources(struct omap_hwmod *oh);
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
@@ -534,5 +563,6 @@ int omap_hwmod_for_each_by_class(const char *classname,
 extern int omap2420_hwmod_init(void);
 extern int omap2430_hwmod_init(void);
 extern int omap3xxx_hwmod_init(void);
+extern int omap44xx_hwmod_init(void);
 
 #endif
index fb6ec74..9ca420d 100644 (file)
@@ -32,6 +32,7 @@
 
 /* Powerdomain allowable state bitfields */
 #define PWRSTS_ON              (1 << PWRDM_POWER_ON)
+#define PWRSTS_OFF             (1 << PWRDM_POWER_OFF)
 #define PWRSTS_OFF_ON          ((1 << PWRDM_POWER_OFF) | \
                                 (1 << PWRDM_POWER_ON))
 
@@ -161,5 +162,6 @@ int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_clkdm_state_switch(struct clockdomain *clkdm);
 int pwrdm_pre_transition(void);
 int pwrdm_post_transition(void);
+int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 
 #endif
index 9fbd914..ab77442 100644 (file)
@@ -38,6 +38,8 @@ u32 prm_read_mod_reg(s16 module, u16 idx);
 void prm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
 u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask);
+u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask);
+u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg);
 u32 cm_read_mod_reg(s16 module, u16 idx);
 void cm_write_mod_reg(u32 val, s16 module, u16 idx);
 u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx);
index 7b76f50..efd87c8 100644 (file)
@@ -147,6 +147,7 @@ struct memory_timings {
 };
 
 extern void omap2xxx_sdrc_init_params(u32 force_lock_to_unlock_mode);
+struct omap_sdrc_params *rx51_get_sdram_timings(void);
 
 u32 omap2xxx_sdrc_dll_is_unlocked(void);
 u32 omap2xxx_sdrc_reprogram(u32 level, u32 force);
index 16a1b45..5905100 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __ARCH_ARM_OMAP_SRAM_H
 #define __ARCH_ARM_OMAP_SRAM_H
 
-extern int __init omap_sram_init(void);
 extern void * omap_sram_push(void * start, unsigned long size);
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
diff --git a/arch/arm/plat-omap/include/plat/timer-gp.h b/arch/arm/plat-omap/include/plat/timer-gp.h
deleted file mode 100644 (file)
index c88d346..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * OMAP2/3 GPTIMER support.headers
- *
- * Copyright (C) 2009 Nokia Corporation
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
-#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
-
-int __init omap2_gp_clockevent_set_gptimer(u8 id);
-
-#endif
-
index ddf723b..9036e37 100644 (file)
@@ -139,10 +139,14 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
                DEBUG_LL_OMAP2(1, omap3evm);
                DEBUG_LL_OMAP3(1, omap_3430sdp);
                DEBUG_LL_OMAP3(1, omap_3630sdp);
+               DEBUG_LL_OMAP3(1, omap3530_lv_som);
+               DEBUG_LL_OMAP3(1, omap3_torpedo);
 
                /* omap3 based boards using UART3 */
                DEBUG_LL_OMAP3(3, cm_t35);
+               DEBUG_LL_OMAP3(3, cm_t3517);
                DEBUG_LL_OMAP3(3, igep0020);
+               DEBUG_LL_OMAP3(3, igep0030);
                DEBUG_LL_OMAP3(3, nokia_rx51);
                DEBUG_LL_OMAP3(3, omap3517evm);
                DEBUG_LL_OMAP3(3, omap3_beagle);
@@ -153,6 +157,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
 
                /* omap4 based boards using UART3 */
                DEBUG_LL_OMAP4(3, omap_4430sdp);
+               DEBUG_LL_OMAP4(3, omap4_panda);
 
                /* zoom2/3 external uart */
                DEBUG_LL_ZOOM(omap_zoom2);
index 9feddac..59c7fe7 100644 (file)
@@ -105,7 +105,7 @@ static inline void omap1_usb_init(struct omap_usb_config *pdata)
 #if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP_OTG_MODULE)
 void omap2_usbfs_init(struct omap_usb_config *pdata);
 #else
-static inline omap2_usbfs_init(struct omap_usb_config *pdata)
+static inline void omap2_usbfs_init(struct omap_usb_config *pdata)
 {
 }
 #endif
index d8a03ce..3792bde 100644 (file)
@@ -35,6 +35,7 @@ struct vrfb {
        bool yuv_mode;
 };
 
+#ifdef CONFIG_OMAP2_VRFB
 extern int omap_vrfb_request_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_release_ctx(struct vrfb *vrfb);
 extern void omap_vrfb_adjust_size(u16 *width, u16 *height,
@@ -47,4 +48,19 @@ extern void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
 extern int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot);
 extern void omap_vrfb_restore_context(void);
 
+#else
+static inline int omap_vrfb_request_ctx(struct vrfb *vrfb) { return 0; }
+static inline void omap_vrfb_release_ctx(struct vrfb *vrfb) {}
+static inline void omap_vrfb_adjust_size(u16 *width, u16 *height,
+               u8 bytespp) {}
+static inline u32 omap_vrfb_min_phys_size(u16 width, u16 height, u8 bytespp)
+               { return 0; }
+static inline u16 omap_vrfb_max_height(u32 phys_size, u16 width, u8 bytespp)
+               { return 0; }
+static inline void omap_vrfb_setup(struct vrfb *vrfb, unsigned long paddr,
+               u16 width, u16 height, unsigned bytespp, bool yuv_mode) {}
+static inline int omap_vrfb_map_angle(struct vrfb *vrfb, u16 height, u8 rot)
+               { return 0; }
+static inline void omap_vrfb_restore_context(void) {}
+#endif
 #endif /* __VRFB_H */
index 0c8612f..eac4b97 100644 (file)
@@ -33,7 +33,7 @@
 struct omap_mcbsp **mcbsp_ptr;
 int omap_mcbsp_count, omap_mcbsp_cache_size;
 
-void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
        if (cpu_class_is_omap1()) {
                ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val;
@@ -47,7 +47,7 @@ void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
        }
 }
 
-int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
+static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
 {
        if (cpu_class_is_omap1()) {
                return !from_cache ? __raw_readw(mcbsp->io_base + reg) :
@@ -62,12 +62,12 @@ int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
 }
 
 #ifdef CONFIG_ARCH_OMAP3
-void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
 {
        __raw_writel(val, mcbsp->st_data->io_base_st + reg);
 }
 
-int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
+static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 {
        return __raw_readl(mcbsp->st_data->io_base_st + reg);
 }
@@ -80,9 +80,6 @@ int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
 #define MCBSP_READ_CACHE(mcbsp, reg) \
                omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
 
-#define omap_mcbsp_check_valid_id(id)  (id < omap_mcbsp_count)
-#define id_to_mcbsp_ptr(id)            mcbsp_ptr[id];
-
 #define MCBSP_ST_READ(mcbsp, reg) \
                        omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
 #define MCBSP_ST_WRITE(mcbsp, reg, val) \
@@ -878,7 +875,7 @@ EXPORT_SYMBOL(omap_mcbsp_free);
 void omap_mcbsp_start(unsigned int id, int tx, int rx)
 {
        struct omap_mcbsp *mcbsp;
-       int idle;
+       int enable_srg = 0;
        u16 w;
 
        if (!omap_mcbsp_check_valid_id(id)) {
@@ -893,10 +890,13 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
        mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
        mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
 
-       idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
-                       MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
+       /* Only enable SRG, if McBSP is master */
+       w = MCBSP_READ_CACHE(mcbsp, PCR0);
+       if (w & (FSXM | FSRM | CLKXM | CLKRM))
+               enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+                               MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
 
-       if (idle) {
+       if (enable_srg) {
                /* Start the sample generator */
                w = MCBSP_READ_CACHE(mcbsp, SPCR2);
                MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
@@ -919,7 +919,7 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
         */
        udelay(500);
 
-       if (idle) {
+       if (enable_srg) {
                /* Start frame sync */
                w = MCBSP_READ_CACHE(mcbsp, SPCR2);
                MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
@@ -1645,7 +1645,7 @@ static const struct attribute_group sidetone_attr_group = {
        .attrs = (struct attribute **)sidetone_attrs,
 };
 
-int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
 {
        struct omap_mcbsp_platform_data *pdata = mcbsp->pdata;
        struct omap_mcbsp_st_data *st_data;
index d2b1609..abe933c 100644 (file)
@@ -82,6 +82,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clk.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
 #define USE_WAKEUP_LAT                 0
 #define IGNORE_WAKEUP_LAT              1
 
-/*
- * OMAP_DEVICE_MAGIC: used to determine whether a struct omap_device
- * obtained via container_of() is in fact a struct omap_device
- */
-#define OMAP_DEVICE_MAGIC               0xf00dcafe
-
 /* Private functions */
 
 /**
@@ -243,6 +238,44 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
        return container_of(pdev, struct omap_device, pdev);
 }
 
+/**
+ * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * @od: struct omap_device *od
+ *
+ * For every optional clock present per hwmod per omap_device, this function
+ * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
+ * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ *
+ * The function is called from inside omap_device_build_ss(), after
+ * omap_device_register.
+ *
+ * This allows drivers to get a pointer to its optional clocks based on its role
+ * by calling clk_get(<dev*>, <role>).
+ *
+ * No return value.
+ */
+static void _add_optional_clock_alias(struct omap_device *od,
+                                     struct omap_hwmod *oh)
+{
+       int i;
+
+       for (i = 0; i < oh->opt_clks_cnt; i++) {
+               struct omap_hwmod_opt_clk *oc;
+               int r;
+
+               oc = &oh->opt_clks[i];
+
+               if (!oc->_clk)
+                       continue;
+
+               r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
+                                 (char *)oc->clk, &od->pdev.dev);
+               if (r)
+                       pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+                              dev_name(&od->pdev.dev), oc->role);
+       }
+}
+
 
 /* Public functions for use by core code */
 
@@ -257,12 +290,11 @@ static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
  */
 int omap_device_count_resources(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int c = 0;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               c += omap_hwmod_count_resources(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               c += omap_hwmod_count_resources(od->hwmods[i]);
 
        pr_debug("omap_device: %s: counted %d total resources across %d "
                 "hwmods\n", od->pdev.name, c, od->hwmods_cnt);
@@ -289,12 +321,11 @@ int omap_device_count_resources(struct omap_device *od)
  */
 int omap_device_fill_resources(struct omap_device *od, struct resource *res)
 {
-       struct omap_hwmod *oh;
        int c = 0;
        int i, r;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++) {
-               r = omap_hwmod_fill_resources(oh, res);
+       for (i = 0; i < od->hwmods_cnt; i++) {
+               r = omap_hwmod_fill_resources(od->hwmods[i], res);
                res += r;
                c += r;
        }
@@ -414,15 +445,15 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
        od->pm_lats = pm_lats;
        od->pm_lats_cnt = pm_lats_cnt;
 
-       od->magic = OMAP_DEVICE_MAGIC;
-
        if (is_early_device)
                ret = omap_early_device_register(od);
        else
                ret = omap_device_register(od);
 
-       for (i = 0; i < oh_cnt; i++)
+       for (i = 0; i < oh_cnt; i++) {
                hwmods[i]->od = od;
+               _add_optional_clock_alias(od, hwmods[i]);
+       }
 
        if (ret)
                goto odbs_exit4;
@@ -473,6 +504,7 @@ int omap_device_register(struct omap_device *od)
 {
        pr_debug("omap_device: %s: registering\n", od->pdev.name);
 
+       od->pdev.dev.parent = &omap_device_parent;
        return platform_device_register(&od->pdev);
 }
 
@@ -566,7 +598,6 @@ int omap_device_shutdown(struct platform_device *pdev)
 {
        int ret, i;
        struct omap_device *od;
-       struct omap_hwmod *oh;
 
        od = _find_by_pdev(pdev);
 
@@ -579,8 +610,8 @@ int omap_device_shutdown(struct platform_device *pdev)
 
        ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_shutdown(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_shutdown(od->hwmods[i]);
 
        od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
 
@@ -627,18 +658,6 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
 }
 
 /**
- * omap_device_is_valid - Check if pointer is a valid omap_device
- * @od: struct omap_device *
- *
- * Return whether struct omap_device pointer @od points to a valid
- * omap_device.
- */
-bool omap_device_is_valid(struct omap_device *od)
-{
-       return (od && od->magic == OMAP_DEVICE_MAGIC);
-}
-
-/**
  * omap_device_get_pwrdm - return the powerdomain * associated with @od
  * @od: struct omap_device *
  *
@@ -692,11 +711,10 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od)
  */
 int omap_device_enable_hwmods(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_enable(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_enable(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -710,11 +728,10 @@ int omap_device_enable_hwmods(struct omap_device *od)
  */
 int omap_device_idle_hwmods(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_idle(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_idle(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -729,11 +746,10 @@ int omap_device_idle_hwmods(struct omap_device *od)
  */
 int omap_device_disable_clocks(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_disable_clocks(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_disable_clocks(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
@@ -748,12 +764,22 @@ int omap_device_disable_clocks(struct omap_device *od)
  */
 int omap_device_enable_clocks(struct omap_device *od)
 {
-       struct omap_hwmod *oh;
        int i;
 
-       for (i = 0, oh = *od->hwmods; i < od->hwmods_cnt; i++, oh++)
-               omap_hwmod_enable_clocks(oh);
+       for (i = 0; i < od->hwmods_cnt; i++)
+               omap_hwmod_enable_clocks(od->hwmods[i]);
 
        /* XXX pass along return value here? */
        return 0;
 }
+
+struct device omap_device_parent = {
+       .init_name      = "omap",
+       .parent         = &platform_bus,
+};
+
+static int __init omap_device_init(void)
+{
+       return device_register(&omap_device_parent);
+}
+core_initcall(omap_device_init);
index 10b3b4c..e2c8eeb 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/omapfb.h>
 
 #include <asm/tlb.h>
 #include <asm/cacheflush.h>
@@ -30,8 +31,8 @@
 #include <plat/cpu.h>
 #include <plat/vram.h>
 
-#include <plat/control.h>
-
+#include "sram.h"
+#include "fb.h"
 #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 # include "../mach-omap2/prm.h"
 # include "../mach-omap2/cm.h"
@@ -53,7 +54,7 @@
 #define OMAP4_SRAM_PUB_PA      (OMAP4_SRAM_PA + 0x4000)
 #define OMAP4_SRAM_PUB_VA      (OMAP4_SRAM_VA + 0x4000)
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ     0x00
 #else
 #define SRAM_BOOTLOADER_SZ     0x80
@@ -68,7 +69,6 @@
 #define OMAP34XX_VA_WRITEPERM0         OMAP2_L3_IO_ADDRESS(0x68012858)
 #define OMAP34XX_VA_ADDR_MATCH2                OMAP2_L3_IO_ADDRESS(0x68012880)
 #define OMAP34XX_VA_SMS_RG_ATT0                OMAP2_L3_IO_ADDRESS(0x6C000048)
-#define OMAP34XX_VA_CONTROL_STAT       OMAP2_L4_IO_ADDRESS(0x480022F0)
 
 #define GP_DEVICE              0x300
 
@@ -79,12 +79,6 @@ static unsigned long omap_sram_base;
 static unsigned long omap_sram_size;
 static unsigned long omap_sram_ceil;
 
-extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
-                                        unsigned long sram_vstart,
-                                        unsigned long sram_size,
-                                        unsigned long pstart_avail,
-                                        unsigned long size_avail);
-
 /*
  * Depending on the target RAMFS firewall setup, the public usable amount of
  * SRAM varies.  The default accessible size for all device types is 2k. A GP
@@ -93,16 +87,7 @@ extern unsigned long omapfb_reserve_sram(unsigned long sram_pstart,
  */
 static int is_sram_locked(void)
 {
-       int type = 0;
-
-       if (cpu_is_omap44xx())
-               /* Not yet supported */
-               return 0;
-
-       if (cpu_is_omap242x())
-               type = omap_rev() & OMAP2_DEVICETYPE_MASK;
-
-       if (type == GP_DEVICE) {
+       if (OMAP2_DEVICE_TYPE_GP == omap_type()) {
                /* RAMFW: R/W access to all initiators for all qualifier sets */
                if (cpu_is_omap242x()) {
                        __raw_writel(0xFF, OMAP24XX_VA_REQINFOPERM0); /* all q-vects */
@@ -127,7 +112,7 @@ static int is_sram_locked(void)
  * to secure SRAM will hang the system. Also the SRAM is not
  * yet mapped at this point.
  */
-void __init omap_detect_sram(void)
+static void __init omap_detect_sram(void)
 {
        unsigned long reserved;
 
@@ -213,7 +198,7 @@ static struct map_desc omap_sram_io_desc[] __initdata = {
 /*
  * Note that we cannot use ioremap for SRAM, as clock init needs SRAM early.
  */
-void __init omap_map_sram(void)
+static void __init omap_map_sram(void)
 {
        unsigned long base;
 
@@ -330,7 +315,7 @@ u32 omap2_set_prcm(u32 dpll_ctrl_val, u32 sdrc_rfr_val, int bypass)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2420
-int __init omap242x_sram_init(void)
+static int __init omap242x_sram_init(void)
 {
        _omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
                                        omap242x_sram_ddr_init_sz);
@@ -351,7 +336,7 @@ static inline int omap242x_sram_init(void)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2430
-int __init omap243x_sram_init(void)
+static int __init omap243x_sram_init(void)
 {
        _omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
                                        omap243x_sram_ddr_init_sz);
@@ -407,7 +392,7 @@ void omap3_sram_restore_context(void)
 }
 #endif /* CONFIG_PM */
 
-int __init omap34xx_sram_init(void)
+static int __init omap34xx_sram_init(void)
 {
        _omap3_sram_configure_core_dpll =
                omap_sram_push(omap3_sram_configure_core_dpll,
@@ -423,7 +408,7 @@ static inline int omap34xx_sram_init(void)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP4
-int __init omap44xx_sram_init(void)
+static int __init omap44xx_sram_init(void)
 {
        printk(KERN_ERR "FIXME: %s not implemented\n", __func__);
 
diff --git a/arch/arm/plat-omap/sram.h b/arch/arm/plat-omap/sram.h
new file mode 100644 (file)
index 0000000..29b43ef
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __PLAT_OMAP_SRAM_H__
+#define __PLAT_OMAP_SRAM_H__
+
+extern int __init omap_sram_init(void);
+
+#endif /* __PLAT_OMAP_SRAM_H__ */
index a9ae30c..6fbfea6 100644 (file)
@@ -319,9 +319,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define pte_offset_kernel(dir, address)                                        \
        ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
 #define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
-#define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address)
 #define pte_unmap(pte)         do { } while (0)
-#define pte_unmap_nested(pte)  do { } while (0)
 
 struct vm_area_struct;
 extern void update_mmu_cache(struct vm_area_struct * vma,
index d1825cb..acb8379 100644 (file)
@@ -102,17 +102,6 @@ config DEBUG_DOUBLEFAULT_RESET
 
 endchoice
 
-config DEBUG_ICACHE_CHECK
-       bool "Check Instruction cache coherency"
-       depends on DEBUG_KERNEL
-       depends on DEBUG_HWERR
-       help
-         Say Y here if you are getting weird unexplained errors. This will
-         ensure that icache is what SDRAM says it should be by doing a
-         byte wise comparison between SDRAM and instruction cache. This
-         also relocates the irq_panic() function to L1 memory, (which is
-         un-cached).
-
 config DEBUG_HUNT_FOR_ZERO
        bool "Catch NULL pointer reads/writes"
        default y
index 46fac1b..c0b988e 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -114,7 +115,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 8024080..864af5b 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -152,7 +153,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 08c55f6..7b6a337 100644 (file)
@@ -9,6 +9,7 @@ CONFIG_EMBEDDED=y
 # CONFIG_ELF_CORE is not set
 # CONFIG_AIO is not set
 CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -101,5 +102,4 @@ CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
index 4a91255..4faa6b4 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF527=y
 CONFIG_BF_REV_0_2=y
@@ -38,6 +39,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -181,6 +183,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 8ccf3ce..9d893eb 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF527=y
 CONFIG_BF_REV_0_1=y
@@ -37,6 +38,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -173,6 +175,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 92ded5e..97a2767 100644 (file)
@@ -174,7 +174,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC7=m
index c40e0f1..f847743 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BFIN533_EZKIT=y
 CONFIG_TIMER0=11
@@ -107,6 +108,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index aa8c1d7..0e7262c 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_TIMER0=11
 CONFIG_HIGH_RES_TIMERS=y
@@ -121,6 +122,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index f245c0b..4d14a00 100644 (file)
@@ -20,9 +20,9 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF537=y
-CONFIG_IRQ_ERROR=11
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_NOMMU_INITIAL_TRIM_EXCESS=0
 CONFIG_BFIN_GPTIMERS=m
@@ -133,6 +133,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 74a330c..fbee9d7 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF538=y
 CONFIG_IRQ_TIMER0=12
@@ -31,6 +32,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0x99B2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -129,6 +131,5 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 29373cb..05dd11d 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_EBIU_MODEVAL=0x1
 CONFIG_EBIU_FCTLVAL=0x6
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -62,7 +63,7 @@ CONFIG_IRCOMM=m
 CONFIG_IRTTY_SIR=m
 CONFIG_BFIN_SIR=m
 CONFIG_BFIN_SIR3=y
-CONFIG_LIB80211=m
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_FW_LOADER=m
 CONFIG_MTD=y
@@ -92,6 +93,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
index 1f12034..bcb14d1 100644 (file)
@@ -14,6 +14,7 @@ CONFIG_EMBEDDED=y
 # CONFIG_EVENTFD is not set
 # CONFIG_AIO is not set
 CONFIG_SLAB=y
+CONFIG_MMAP_ALLOW_UNINITIALIZED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
@@ -44,6 +45,7 @@ CONFIG_IP_PNP=y
 CONFIG_SYN_COOKIES=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -71,6 +73,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -147,5 +150,4 @@ CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 8913d99..843aaa5 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_C_CDPRIO=y
 CONFIG_BANK_3=0xAAC2
 CONFIG_BINFMT_FLAT=y
 CONFIG_BINFMT_ZFLAT=y
+CONFIG_PM=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
index 0242917..dae7adf 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_INET=y
 CONFIG_IP_PNP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -63,6 +64,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMC91X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_KEYBOARD is not set
@@ -104,5 +106,4 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
index 0512fef..f341424 100644 (file)
@@ -50,6 +50,7 @@ CONFIG_IP_PNP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -70,9 +71,9 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_BFIN_MAC=y
-CONFIG_BFIN_MAC_RMII=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -124,7 +125,6 @@ CONFIG_DEBUG_FS=y
 # CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 05e09be..8c7e08f 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_BINFMT_SHARED_FLAT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -47,6 +48,7 @@ CONFIG_MTD_PHYSMAP=y
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -72,7 +74,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
index d2eb532..bd3cb76 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_IP_PNP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -65,6 +66,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_BFIN_MAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -99,7 +101,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 9d52c44..82224f3 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_INET=y
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -59,6 +60,7 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -90,7 +92,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
index 9de13cf..433598c 100644 (file)
@@ -49,6 +49,7 @@ CONFIG_INET_XFRM_MODE_BEET=m
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
@@ -71,6 +72,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 CONFIG_INPUT_EVBUG=m
@@ -167,7 +169,6 @@ CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=m
index 238353a..ded7d84 100644 (file)
@@ -48,6 +48,7 @@ CONFIG_INET=y
 # CONFIG_INET_LRO is not set
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -67,6 +68,7 @@ CONFIG_MII=y
 CONFIG_SMSC911X=m
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -99,7 +101,6 @@ CONFIG_DEBUG_MMRS=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=m
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
index 0cb524e..700fb70 100644 (file)
@@ -33,6 +33,7 @@ CONFIG_IRLAN=m
 CONFIG_IRCOMM=m
 CONFIG_IRDA_CACHE_LAST_LSAP=y
 CONFIG_IRTTY_SIR=m
+# CONFIG_WIRELESS is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -50,6 +51,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_DM9000=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
@@ -84,4 +86,3 @@ CONFIG_NFS_V3=y
 CONFIG_NLS=m
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
index 2a3411e..b40156d 100644 (file)
@@ -41,6 +41,7 @@ CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_FILTER=y
 CONFIG_IP_NF_TARGET_REJECT=y
 CONFIG_IP_NF_MANGLE=y
+# CONFIG_WIRELESS is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CHAR=y
@@ -60,6 +61,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_DM9000=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -89,5 +91,4 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRC_CCITT=y
index fea3033..be866d9 100644 (file)
@@ -14,6 +14,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_LBDAF is not set
 # CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_BF537=y
 CONFIG_IRQ_TIMER0=12
@@ -107,7 +108,6 @@ CONFIG_SMB_FS=m
 # CONFIG_DEBUG_HUNT_FOR_ZERO is not set
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 # CONFIG_ACCESS_CHECK is not set
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 9811b31..b64bdf7 100644 (file)
@@ -35,6 +35,7 @@ CONFIG_IRLAN=m
 CONFIG_IRCOMM=m
 CONFIG_IRDA_CACHE_LAST_LSAP=y
 CONFIG_IRTTY_SIR=m
+# CONFIG_WIRELESS is not set
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
 CONFIG_MTD_PARTITIONS=y
@@ -51,6 +52,7 @@ CONFIG_EEPROM_AT25=m
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_KEYBOARD is not set
@@ -85,4 +87,3 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE is not set
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
index 412bf79..1bccd9a 100644 (file)
@@ -128,7 +128,6 @@ CONFIG_DEBUG_DOUBLEFAULT=y
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
-CONFIG_SECURITY=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
index 04bf52c..00ce899 100644 (file)
@@ -40,6 +40,7 @@ CONFIG_UNIX=y
 CONFIG_INET=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
@@ -57,6 +58,7 @@ CONFIG_NET_ETHERNET=y
 CONFIG_BFIN_MAC=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
index 0b5136e..5392583 100644 (file)
@@ -60,6 +60,8 @@ struct bfin_spi_regs {
        __BFP(shadow);
 };
 
+#undef __BFP
+
 #define MAX_CTRL_CS          8  /* cs in spi controller */
 
 /* device.platform_data for SSP controller devices */
index 0039008..3be05fa 100644 (file)
@@ -48,4 +48,6 @@ struct bfin_eppi_regs {
        u32 clip;
 };
 
+#undef __BFP
+
 #endif
diff --git a/arch/blackfin/include/asm/bfin_twi.h b/arch/blackfin/include/asm/bfin_twi.h
new file mode 100644 (file)
index 0000000..e767d64
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * bfin_twi.h - interface to Blackfin TWIs
+ *
+ * Copyright 2005-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __ASM_BFIN_TWI_H__
+#define __ASM_BFIN_TWI_H__
+
+#include <linux/types.h>
+
+/*
+ * All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits.  So use a helper macro to streamline this.
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/*
+ * bfin twi registers layout
+ */
+struct bfin_twi_regs {
+       __BFP(clkdiv);
+       __BFP(control);
+       __BFP(slave_ctl);
+       __BFP(slave_stat);
+       __BFP(slave_addr);
+       __BFP(master_ctl);
+       __BFP(master_stat);
+       __BFP(master_addr);
+       __BFP(int_stat);
+       __BFP(int_mask);
+       __BFP(fifo_ctl);
+       __BFP(fifo_stat);
+       u32 __pad[20];
+       __BFP(xmt_data8);
+       __BFP(xmt_data16);
+       __BFP(rcv_data8);
+       __BFP(rcv_data16);
+};
+
+#undef __BFP
+
+#endif
index a1f6817..59af63c 100644 (file)
 #define bfin_write_ITEST_DATA0(val)          bfin_write32(ITEST_DATA0,val)
 #define bfin_write_ITEST_DATA1(val)          bfin_write32(ITEST_DATA1,val)
 
-#if ANOMALY_05000481
+#if !ANOMALY_05000481
 #define bfin_read_ITEST_COMMAND()            bfin_read32(ITEST_COMMAND)
 #define bfin_read_ITEST_DATA0()              bfin_read32(ITEST_DATA0)
 #define bfin_read_ITEST_DATA1()              bfin_read32(ITEST_DATA1)
index a6886f6..4104d57 100644 (file)
 #define        LFLUSH_I_AND_D  0x00000808
 #define        LSIGTRAP        5
 
-/* process bits for task_struct.flags */
-#define        PF_TRACESYS_OFF 3
-#define        PF_TRACESYS_BIT 5
-#define        PF_PTRACED_OFF  3
-#define        PF_PTRACED_BIT  4
-#define        PF_DTRACE_OFF   1
-#define        PF_DTRACE_BIT   5
-
 /*
  * NOTE!  The single-stepping code assumes that all interrupt handlers
  * start by saving SYSCFG on the stack with their first instruction.
index f95e609..b894c8a 100644 (file)
@@ -87,13 +87,55 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = {
+       P_MII0_ETxD0,
+       P_MII0_ETxD1,
+       P_MII0_ETxEN,
+       P_MII0_ERxD0,
+       P_MII0_ERxD1,
+       P_MII0_TxCLK,
+       P_MII0_PHYINT,
+       P_MII0_CRS,
+       P_MII0_MDC,
+       P_MII0_MDIO,
+       0
+};
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+       {
+               .addr = 2,
+               .irq = IRQ_MAC_PHYINT,
+       },
+       {
+               .addr = 3,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 3,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 
 #if defined(CONFIG_NET_DSA_KSZ8893M) || defined(CONFIG_NET_DSA_KSZ8893M_MODULE)
index bead810..e6ce1d7 100644 (file)
@@ -81,13 +81,35 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 38037c7..2c31af7 100644 (file)
@@ -273,13 +273,35 @@ static struct platform_device dm9000_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 6cc64a1..9a736a8 100644 (file)
@@ -193,13 +193,35 @@ static struct platform_device rtc_device = {
 
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index df82723..9222bc0 100644 (file)
@@ -366,13 +366,35 @@ static struct platform_device dm9000_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index ae4130e..9ec5757 100644 (file)
@@ -257,13 +257,35 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index e2e7be4..836698c 100644 (file)
@@ -597,13 +597,35 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 752c833..2a85670 100644 (file)
@@ -562,13 +562,35 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 05d4599..4980051 100644 (file)
@@ -68,13 +68,35 @@ static struct platform_device rtc_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 6b03808..b958078 100644 (file)
@@ -99,13 +99,35 @@ static struct platform_device smc91x_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_RMII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_RMII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index cd2c797..3aa344c 100644 (file)
@@ -327,13 +327,35 @@ static struct platform_device bfin_can_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = PHY_POLL, /* IRQ_MAC_PHYINT */
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index a4d62b5..31498ad 100644 (file)
@@ -564,13 +564,35 @@ static struct platform_device bfin_sport1_uart_device = {
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
+#include <linux/bfin_mac.h>
+static const unsigned short bfin_mac_peripherals[] = P_MII0;
+
+static struct bfin_phydev_platform_data bfin_phydev_data[] = {
+       {
+               .addr = 1,
+               .irq = IRQ_MAC_PHYINT,
+       },
+};
+
+static struct bfin_mii_bus_platform_data bfin_mii_bus_data = {
+       .phydev_number = 1,
+       .phydev_data = bfin_phydev_data,
+       .phy_mode = PHY_INTERFACE_MODE_MII,
+       .mac_peripherals = bfin_mac_peripherals,
+};
+
 static struct platform_device bfin_mii_bus = {
        .name = "bfin_mii_bus",
+       .dev = {
+               .platform_data = &bfin_mii_bus_data,
+       }
 };
 
 static struct platform_device bfin_mac_device = {
        .name = "bfin_mac",
-       .dev.platform_data = &bfin_mii_bus,
+       .dev = {
+               .platform_data = &bfin_mii_bus,
+       }
 };
 #endif
 
index 814cb48..ff299f2 100644 (file)
@@ -11,4 +11,3 @@ obj-$(CONFIG_CPU_FREQ)    += cpufreq.o
 obj-$(CONFIG_CPU_VOLTAGE) += dpmc.o
 obj-$(CONFIG_SMP)         += smp.o
 obj-$(CONFIG_BFIN_KERNEL_CLOCK) += clocks-init.o
-obj-$(CONFIG_DEBUG_ICACHE_CHECK) += irqpanic.o
diff --git a/arch/blackfin/mach-common/irqpanic.c b/arch/blackfin/mach-common/irqpanic.c
deleted file mode 100644 (file)
index c649624..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * panic kernel with dump information
- *
- * Copyright 2005-2009 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/module.h>
-#include <linux/kernel_stat.h>
-#include <linux/sched.h>
-#include <asm/blackfin.h>
-
-#define L1_ICACHE_START 0xffa10000
-#define L1_ICACHE_END   0xffa13fff
-
-/*
- * irq_panic - calls panic with string setup
- */
-__attribute__ ((l1_text))
-asmlinkage void irq_panic(int reason, struct pt_regs *regs)
-{
-       unsigned int cmd, tag, ca, cache_hi, cache_lo, *pa;
-       unsigned short i, j, die;
-       unsigned int bad[10][6];
-
-       /* check entire cache for coherency
-        * Since printk is in cacheable memory,
-        * don't call it until you have checked everything
-       */
-
-       die = 0;
-       i = 0;
-
-       /* check icache */
-
-       for (ca = L1_ICACHE_START; ca <= L1_ICACHE_END && i < 10; ca += 32) {
-
-               /* Grab various address bits for the itest_cmd fields                      */
-               cmd = (((ca & 0x3000) << 4) |   /* ca[13:12] for SBNK[1:0]             */
-                      ((ca & 0x0c00) << 16) |  /* ca[11:10] for WAYSEL[1:0]           */
-                      ((ca & 0x3f8)) | /* ca[09:03] for SET[4:0] and DW[1:0]  */
-                      0);      /* Access Tag, Read access             */
-
-               SSYNC();
-               bfin_write_ITEST_COMMAND(cmd);
-               SSYNC();
-               tag = bfin_read_ITEST_DATA0();
-               SSYNC();
-
-               /* if tag is marked as valid, check it */
-               if (tag & 1) {
-                       /* The icache is arranged in 4 groups of 64-bits */
-                       for (j = 0; j < 32; j += 8) {
-                               cmd = ((((ca + j) & 0x3000) << 4) |     /* ca[13:12] for SBNK[1:0]             */
-                                      (((ca + j) & 0x0c00) << 16) |    /* ca[11:10] for WAYSEL[1:0]           */
-                                      (((ca + j) & 0x3f8)) |   /* ca[09:03] for SET[4:0] and DW[1:0]  */
-                                      4);      /* Access Data, Read access             */
-
-                               SSYNC();
-                               bfin_write_ITEST_COMMAND(cmd);
-                               SSYNC();
-
-                               cache_hi = bfin_read_ITEST_DATA1();
-                               cache_lo = bfin_read_ITEST_DATA0();
-
-                               pa = ((unsigned int *)((tag & 0xffffcc00) |
-                                                      ((ca + j) & ~(0xffffcc00))));
-
-                               /*
-                                * Debugging this, enable
-                                *
-                                * printk("addr: %08x %08x%08x | %08x%08x\n",
-                                *  ((unsigned int *)((tag & 0xffffcc00)  | ((ca+j) & ~(0xffffcc00)))),
-                                *   cache_hi, cache_lo, *(pa+1), *pa);
-                                */
-
-                               if (cache_hi != *(pa + 1) || cache_lo != *pa) {
-                                       /* Since icache is not working, stay out of it, by not printing */
-                                       die = 1;
-                                       bad[i][0] = (ca + j);
-                                       bad[i][1] = cache_hi;
-                                       bad[i][2] = cache_lo;
-                                       bad[i][3] = ((tag & 0xffffcc00) |
-                                               ((ca + j) & ~(0xffffcc00)));
-                                       bad[i][4] = *(pa + 1);
-                                       bad[i][5] = *(pa);
-                                       i++;
-                               }
-                       }
-               }
-       }
-       if (die) {
-               printk(KERN_EMERG "icache coherency error\n");
-               for (j = 0; j <= i; j++) {
-                       printk(KERN_EMERG
-                           "cache address   : %08x  cache value : %08x%08x\n",
-                            bad[j][0], bad[j][1], bad[j][2]);
-                       printk(KERN_EMERG
-                           "physical address: %08x  SDRAM value : %08x%08x\n",
-                            bad[j][3], bad[j][4], bad[j][5]);
-               }
-               panic("icache coherency error");
-       } else
-               printk(KERN_EMERG "icache checked, and OK\n");
-}
index f63d6fc..9eaae21 100644 (file)
@@ -248,10 +248,8 @@ static inline pgd_t * pgd_offset(const struct mm_struct *mm, unsigned long addre
        ((pte_t *) pmd_page_vaddr(*(dir)) +  __pte_offset(address))
 #define pte_offset_map(dir, address) \
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #define pte_pfn(x)             ((unsigned long)(__va((x).pte)) >> PAGE_SHIFT)
 #define pfn_pte(pfn, prot)     __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
 
index cb4c317..a8d6565 100644 (file)
@@ -112,12 +112,11 @@ extern struct page *kmap_atomic_to_page(void *ptr);
        (void *) damlr;                                                                           \
 })
 
-static inline void *kmap_atomic(struct page *page, enum km_type type)
+static inline void *kmap_atomic_primary(struct page *page, enum km_type type)
 {
        unsigned long paddr;
 
        pagefault_disable();
-       debug_kmap_atomic(type);
        paddr = page_to_phys(page);
 
        switch (type) {
@@ -125,14 +124,6 @@ static inline void *kmap_atomic(struct page *page, enum km_type type)
         case 1:                return __kmap_atomic_primary(1, paddr, 3);
         case 2:                return __kmap_atomic_primary(2, paddr, 4);
         case 3:                return __kmap_atomic_primary(3, paddr, 5);
-        case 4:                return __kmap_atomic_primary(4, paddr, 6);
-        case 5:                return __kmap_atomic_primary(5, paddr, 7);
-        case 6:                return __kmap_atomic_primary(6, paddr, 8);
-        case 7:                return __kmap_atomic_primary(7, paddr, 9);
-        case 8:                return __kmap_atomic_primary(8, paddr, 10);
-
-       case 9 ... 9 + NR_TLB_LINES - 1:
-               return __kmap_atomic_secondary(type - 9, paddr);
 
        default:
                BUG();
@@ -152,22 +143,13 @@ do {                                                                      \
        asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory");   \
 } while(0)
 
-static inline void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+static inline void kunmap_atomic_primary(void *kvaddr, enum km_type type)
 {
        switch (type) {
         case 0:                __kunmap_atomic_primary(0, 2);  break;
         case 1:                __kunmap_atomic_primary(1, 3);  break;
         case 2:                __kunmap_atomic_primary(2, 4);  break;
         case 3:                __kunmap_atomic_primary(3, 5);  break;
-        case 4:                __kunmap_atomic_primary(4, 6);  break;
-        case 5:                __kunmap_atomic_primary(5, 7);  break;
-        case 6:                __kunmap_atomic_primary(6, 8);  break;
-        case 7:                __kunmap_atomic_primary(7, 9);  break;
-        case 8:                __kunmap_atomic_primary(8, 10); break;
-
-       case 9 ... 9 + NR_TLB_LINES - 1:
-               __kunmap_atomic_secondary(type - 9, kvaddr);
-               break;
 
        default:
                BUG();
@@ -175,6 +157,9 @@ static inline void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
        pagefault_enable();
 }
 
+void *__kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index c18b0d3..6bc241e 100644 (file)
@@ -451,17 +451,12 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 
 #if defined(CONFIG_HIGHPTE)
 #define pte_offset_map(dir, address) \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE0) + pte_index(address))
-#define pte_offset_map_nested(dir, address) \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)),KM_PTE1) + pte_index(address))
-#define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+       ((pte_t *)kmap_atomic(pmd_page(*(dir))) + pte_index(address))
+#define pte_unmap(pte) kunmap_atomic(pte)
 #else
 #define pte_offset_map(dir, address) \
        ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #endif
 
 /*
index 85d110b..41098a3 100644 (file)
@@ -61,14 +61,14 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
        dampr2 = __get_DAMPR(2);
 
        for (i = 0; i < nents; i++) {
-               vaddr = kmap_atomic(sg_page(&sg[i]), __KM_CACHE);
+               vaddr = kmap_atomic_primary(sg_page(&sg[i]), __KM_CACHE);
 
                frv_dcache_writeback((unsigned long) vaddr,
                                     (unsigned long) vaddr + PAGE_SIZE);
 
        }
 
-       kunmap_atomic(vaddr, __KM_CACHE);
+       kunmap_atomic_primary(vaddr, __KM_CACHE);
        if (dampr2) {
                __set_DAMPR(2, dampr2);
                __set_IAMPR(2, dampr2);
index 0261cbe..b24ade2 100644 (file)
@@ -26,11 +26,11 @@ void flush_dcache_page(struct page *page)
 
        dampr2 = __get_DAMPR(2);
 
-       vaddr = kmap_atomic(page, __KM_CACHE);
+       vaddr = kmap_atomic_primary(page, __KM_CACHE);
 
        frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE);
 
-       kunmap_atomic(vaddr, __KM_CACHE);
+       kunmap_atomic_primary(vaddr, __KM_CACHE);
 
        if (dampr2) {
                __set_DAMPR(2, dampr2);
@@ -54,12 +54,12 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
 
        dampr2 = __get_DAMPR(2);
 
-       vaddr = kmap_atomic(page, __KM_CACHE);
+       vaddr = kmap_atomic_primary(page, __KM_CACHE);
 
        start = (start & ~PAGE_MASK) | (unsigned long) vaddr;
        frv_cache_wback_inv(start, start + len);
 
-       kunmap_atomic(vaddr, __KM_CACHE);
+       kunmap_atomic_primary(vaddr, __KM_CACHE);
 
        if (dampr2) {
                __set_DAMPR(2, dampr2);
index eadd076..61088dc 100644 (file)
@@ -36,3 +36,53 @@ struct page *kmap_atomic_to_page(void *ptr)
 {
        return virt_to_page(ptr);
 }
+
+void *__kmap_atomic(struct page *page)
+{
+       unsigned long paddr;
+       int type;
+
+       pagefault_disable();
+       type = kmap_atomic_idx_push();
+       paddr = page_to_phys(page);
+
+       switch (type) {
+       /*
+        * The first 4 primary maps are reserved for architecture code
+        */
+       case 0:         return __kmap_atomic_primary(4, paddr, 6);
+       case 1:         return __kmap_atomic_primary(5, paddr, 7);
+       case 2:         return __kmap_atomic_primary(6, paddr, 8);
+       case 3:         return __kmap_atomic_primary(7, paddr, 9);
+       case 4:         return __kmap_atomic_primary(8, paddr, 10);
+
+       case 5 ... 5 + NR_TLB_LINES - 1:
+               return __kmap_atomic_secondary(type - 5, paddr);
+
+       default:
+               BUG();
+               return NULL;
+       }
+}
+EXPORT_SYMBOL(__kmap_atomic);
+
+void __kunmap_atomic(void *kvaddr)
+{
+       int type = kmap_atomic_idx_pop();
+       switch (type) {
+       case 0:         __kunmap_atomic_primary(4, 6);  break;
+       case 1:         __kunmap_atomic_primary(5, 7);  break;
+       case 2:         __kunmap_atomic_primary(6, 8);  break;
+       case 3:         __kunmap_atomic_primary(7, 9);  break;
+       case 4:         __kunmap_atomic_primary(8, 10); break;
+
+       case 5 ... 5 + NR_TLB_LINES - 1:
+               __kunmap_atomic_secondary(type - 5, kvaddr);
+               break;
+
+       default:
+               BUG();
+       }
+       pagefault_enable();
+}
+EXPORT_SYMBOL(__kunmap_atomic);
index c3286f4..1a97af3 100644 (file)
@@ -406,9 +406,7 @@ pgd_offset (const struct mm_struct *mm, unsigned long address)
 #define pte_index(addr)                (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
 #define pte_offset_kernel(dir,addr)    ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir,addr)       pte_offset_kernel(dir, addr)
-#define pte_offset_map_nested(dir,addr)        pte_offset_map(dir, addr)
 #define pte_unmap(pte)                 do { } while (0)
-#define pte_unmap_nested(pte)          do { } while (0)
 
 /* atomic versions of the some PTE manipulations: */
 
index 118d429..c8fcaa2 100644 (file)
@@ -62,6 +62,7 @@ typedef struct siginfo {
                        int _imm;               /* immediate value for "break" */
                        unsigned int _flags;    /* see below */
                        unsigned long _isr;     /* isr */
+                       short _addr_lsb;        /* lsb of faulting address */
                } _sigfault;
 
                /* SIGPOLL */
index e6359c5..8a28cfe 100644 (file)
@@ -332,9 +332,7 @@ static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
        ((pte_t *)pmd_page_vaddr(*(dir)) + pte_index(address))
 #define pte_offset_map(dir, address)   \
        ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address)    pte_offset_map(dir, address)
 #define pte_unmap(pte)         do { } while (0)
-#define pte_unmap_nested(pte)  do { } while (0)
 
 /* Encode and de-code a swap entry */
 #define __swp_type(x)                  (((x).val >> 2) & 0x1f)
index e41fea3..73b8c8f 100644 (file)
 
 LFLUSH_I_AND_D = 0x00000808
 
-/* process bits for task_struct.ptrace */
-PT_TRACESYS_OFF = 3
-PT_TRACESYS_BIT = 1
-PT_PTRACED_OFF = 3
-PT_PTRACED_BIT = 0
-PT_DTRACE_OFF = 3
-PT_DTRACE_BIT = 2
-
 #define SAVE_ALL_INT save_all_int
 #define SAVE_ALL_SYS save_all_sys
 #define RESTORE_ALL restore_all
index 80e4149..26be277 100644 (file)
 
 #ifdef __ASSEMBLY__
 
-/* process bits for task_struct.flags */
-PF_TRACESYS_OFF = 3
-PF_TRACESYS_BIT = 5
-PF_PTRACED_OFF = 3
-PF_PTRACED_BIT = 4
-PF_DTRACE_OFF = 1
-PF_DTRACE_BIT = 5
-
-LENOSYS = 38
-
 #define SWITCH_STACK_SIZE (6*4+4)      /* Includes return address */
 
 /*
index 8e9a8a7..45bd3f5 100644 (file)
@@ -221,9 +221,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmdp, unsigned long address)
 }
 
 #define pte_offset_map(pmdp,address) ((pte_t *)__pmd_page(*pmdp) + (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
-#define pte_offset_map_nested(pmdp, address) pte_offset_map(pmdp, address)
 #define pte_unmap(pte)         ((void)0)
-#define pte_unmap_nested(pte)  ((void)0)
 
 /*
  * Allocate and free page tables. The xxx_kernel() versions are
index f847ec7..cf5fad9 100644 (file)
@@ -219,9 +219,7 @@ static inline pte_t pgoff_to_pte(unsigned off)
 #define pte_offset_kernel(pmd, address) ((pte_t *) __pmd_page(*pmd) + pte_index(address))
 /* FIXME: should we bother with kmap() here? */
 #define pte_offset_map(pmd, address) ((pte_t *)kmap(pmd_page(*pmd)) + pte_index(address))
-#define pte_offset_map_nested(pmd, address) pte_offset_map(pmd, address)
 #define pte_unmap(pte) kunmap(pte)
-#define pte_unmap_nested(pte) kunmap(pte)
 
 /* Macros to (de)construct the fake PTEs representing swap pages. */
 #define __swp_type(x)          ((x).val & 0x7F)
index 692fdfc..dad40fc 100644 (file)
@@ -121,6 +121,23 @@ config CMDLINE_FORCE
          Set this to have arguments from the default kernel command string
          override those passed by the boot loader.
 
+config SECCOMP
+       bool "Enable seccomp to safely compute untrusted bytecode"
+       depends on PROC_FS
+       default y
+       help
+         This kernel feature is useful for number crunching applications
+         that may need to compute untrusted bytecode during their
+         execution. By using pipes or other transports made available to
+         the process as file descriptors supporting the read/write
+         syscalls, it's possible to isolate those applications in
+         their own address space using seccomp. Once seccomp is
+         enabled via /proc/<pid>/seccomp, it cannot be disabled
+         and the task is only allowed to execute a few safe syscalls
+         defined by each seccomp mode.
+
+         If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 menu "Advanced setup"
index e6e5e0d..e66e25c 100644 (file)
@@ -10,7 +10,7 @@ source "lib/Kconfig.debug"
 
 config EARLY_PRINTK
        bool "Early printk function for kernel"
-       depends on SERIAL_UARTLITE_CONSOLE
+       depends on SERIAL_UARTLITE_CONSOLE || SERIAL_8250_CONSOLE
        default n
        help
          This option turns on/off early printk messages to console.
index 592c707..15f1f1d 100644 (file)
@@ -42,11 +42,8 @@ KBUILD_CFLAGS += -ffixed-r31 $(CPUFLAGS-1) $(CPUFLAGS-2)
 LDFLAGS                :=
 LDFLAGS_vmlinux        :=
 
-LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
 head-y := arch/microblaze/kernel/head.o
 libs-y += arch/microblaze/lib/
-libs-y += $(LIBGCC)
 core-y += arch/microblaze/kernel/
 core-y += arch/microblaze/mm/
 core-y += arch/microblaze/platform/
@@ -72,12 +69,16 @@ export MMU DTB
 
 all: linux.bin
 
-BOOT_TARGETS = linux.bin linux.bin.gz simpleImage.%
+# With make 3.82 we cannot mix normal and wildcard targets
+BOOT_TARGETS1 = linux.bin linux.bin.gz
+BOOT_TARGETS2 = simpleImage.%
 
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
-$(BOOT_TARGETS): vmlinux
+$(BOOT_TARGETS1): vmlinux
+       $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+$(BOOT_TARGETS2): vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 define archhelp
index ce9c587..3190276 100644 (file)
@@ -1,6 +1,10 @@
 #ifndef _ASM_MICROBLAZE_BYTEORDER_H
 #define _ASM_MICROBLAZE_BYTEORDER_H
 
+#ifdef __MICROBLAZEEL__
+#include <linux/byteorder/little_endian.h>
+#else
 #include <linux/byteorder/big_endian.h>
+#endif
 
 #endif /* _ASM_MICROBLAZE_BYTEORDER_H */
index 128bf03..0185cbe 100644 (file)
@@ -24,8 +24,13 @@ csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
                "addc %0, %0, %3\n\t"
                "addc %0, %0, r0\n\t"
                : "+&d" (sum)
-               : "d" (saddr), "d" (daddr), "d" (len + proto));
-
+               : "d" (saddr), "d" (daddr),
+#ifdef __MICROBLAZEEL__
+       "d" ((len + proto) << 8)
+#else
+       "d" (len + proto)
+#endif
+);
        return sum;
 }
 
index b4f5ca3..cd25753 100644 (file)
@@ -38,6 +38,7 @@ struct cpuinfo {
        u32 use_exc;
        u32 ver_code;
        u32 mmu;
+       u32 endian;
 
        /* CPU caches */
        u32 use_icache;
@@ -76,7 +77,6 @@ struct cpuinfo {
        u32 num_rd_brk;
        u32 num_wr_brk;
        u32 cpu_clock_freq; /* store real freq of cpu */
-       u32 freq_div_hz; /* store freq/HZ */
 
        /* FPGA family */
        u32 fpga_family_code;
@@ -97,7 +97,8 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu);
 static inline unsigned int fcpu(struct device_node *cpu, char *n)
 {
        int *val;
-       return (val = (int *) of_get_property(cpu, n, NULL)) ? *val : 0;
+       return (val = (int *) of_get_property(cpu, n, NULL)) ?
+                                                       be32_to_cpup(val) : 0;
 }
 
 #endif /* _ASM_MICROBLAZE_CPUINFO_H */
index 732caf1..098dfdd 100644 (file)
@@ -71,7 +71,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
-#ifdef __LITTLE_ENDIAN__
+#ifdef __MICROBLAZEEL__
 #define ELF_DATA       ELFDATA2LSB
 #else
 #define ELF_DATA       ELFDATA2MSB
index 2345ac3..2b2c18b 100644 (file)
@@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio)
        return __gpio_cansleep(gpio);
 }
 
-/*
- * Not implemented, yet.
- */
 static inline int gpio_to_irq(unsigned int gpio)
 {
-       return -ENOSYS;
+       return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
index 00b5398..eae3222 100644 (file)
@@ -243,6 +243,8 @@ static inline void __iomem *__ioremap(phys_addr_t address, unsigned long size,
 #define out_8(a, v) __raw_writeb((v), (a))
 #define in_8(a) __raw_readb(a)
 
+#define mmiowb()
+
 #define ioport_map(port, nr)   ((void __iomem *)(port))
 #define ioport_unmap(addr)
 
index cf377d9..ed9d0f6 100644 (file)
@@ -205,9 +205,6 @@ extern int page_is_ram(unsigned long pfn);
 #define TOPHYS(addr)  __virt_to_phys(addr)
 
 #ifdef CONFIG_MMU
-#ifdef CONFIG_CONTIGUOUS_PAGE_ALLOC
-#define WANT_PAGE_VIRTUAL 1 /* page alloc 2 relies on this */
-#endif
 
 #define VM_DATA_DEFAULT_FLAGS  (VM_READ | VM_WRITE | VM_EXEC | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
index 5a388ee..2232ff9 100644 (file)
@@ -165,5 +165,7 @@ extern void __init xilinx_pci_init(void);
 static inline void __init xilinx_pci_init(void) { return; }
 #endif
 
+#include <asm-generic/pci-dma-compat.h>
+
 #endif /* __KERNEL__ */
 #endif /* __ASM_MICROBLAZE_PCI_H */
index c614a89..ebd3579 100644 (file)
@@ -165,7 +165,8 @@ extern inline void pte_free(struct mm_struct *mm, struct page *ptepage)
 
 #define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, (pte))
 
-#define pmd_populate(mm, pmd, pte)     (pmd_val(*(pmd)) = page_address(pte))
+#define pmd_populate(mm, pmd, pte) \
+                       (pmd_val(*(pmd)) = (unsigned long)page_address(pte))
 
 #define pmd_populate_kernel(mm, pmd, pte) \
                (pmd_val(*(pmd)) = (unsigned long) (pte))
index ca2d928..cae268c 100644 (file)
@@ -57,6 +57,13 @@ static inline int pte_file(pte_t pte) { return 0; }
 
 #define pgprot_noncached_wc(prot)      prot
 
+/*
+ * All 32bit addresses are effectively valid for vmalloc...
+ * Sort of meaningless for non-VM targets.
+ */
+#define        VMALLOC_START   0
+#define        VMALLOC_END     0xffffffff
+
 #else /* CONFIG_MMU */
 
 #include <asm-generic/4level-fixup.h>
@@ -497,12 +504,9 @@ static inline pmd_t *pmd_offset(pgd_t *dir, unsigned long address)
 #define pte_offset_kernel(dir, addr)   \
        ((pte_t *) pmd_page_kernel(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir, addr)              \
-       ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
-#define pte_offset_map_nested(dir, addr)       \
-       ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
+       ((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr))
 
-#define pte_unmap(pte)         kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte)  kunmap_atomic(pte, KM_PTE1)
+#define pte_unmap(pte)         kunmap_atomic(pte)
 
 /* Encode and decode a nonlinear file mapping entry */
 #define PTE_FILE_MAX_BITS      29
index 101fa09..bdc3831 100644 (file)
@@ -27,6 +27,7 @@
 
 /* Other Prototypes */
 extern int early_uartlite_console(void);
+extern int early_uart16550_console(void);
 
 #ifdef CONFIG_PCI
 /*
index 9578666..37db96a 100644 (file)
@@ -30,7 +30,9 @@ struct pvr_s {
 #define PVR0_USE_EXC_MASK              0x04000000
 #define PVR0_USE_ICACHE_MASK           0x02000000
 #define PVR0_USE_DCACHE_MASK           0x01000000
-#define PVR0_USE_MMU                   0x00800000      /* new */
+#define PVR0_USE_MMU                   0x00800000
+#define PVR0_USE_BTC                   0x00400000
+#define PVR0_ENDI                      0x00200000
 #define PVR0_VERSION_MASK              0x0000FF00
 #define PVR0_USER1_MASK                        0x000000FF
 
@@ -38,9 +40,9 @@ struct pvr_s {
 #define PVR1_USER2_MASK                        0xFFFFFFFF
 
 /* Configuration PVR masks */
-#define PVR2_D_OPB_MASK                        0x80000000
+#define PVR2_D_OPB_MASK                        0x80000000 /* or AXI */
 #define PVR2_D_LMB_MASK                        0x40000000
-#define PVR2_I_OPB_MASK                        0x20000000
+#define PVR2_I_OPB_MASK                        0x20000000 /* or AXI */
 #define PVR2_I_LMB_MASK                        0x10000000
 #define PVR2_INTERRUPT_IS_EDGE_MASK    0x08000000
 #define PVR2_EDGE_IS_POSITIVE_MASK     0x04000000
@@ -63,8 +65,8 @@ struct pvr_s {
 #define PVR2_OPCODE_0x0_ILL_MASK       0x00000040
 #define PVR2_UNALIGNED_EXC_MASK                0x00000020
 #define PVR2_ILL_OPCODE_EXC_MASK       0x00000010
-#define PVR2_IOPB_BUS_EXC_MASK         0x00000008
-#define PVR2_DOPB_BUS_EXC_MASK         0x00000004
+#define PVR2_IOPB_BUS_EXC_MASK         0x00000008 /* or AXI */
+#define PVR2_DOPB_BUS_EXC_MASK         0x00000004 /* or AXI */
 #define PVR2_DIV_ZERO_EXC_MASK         0x00000002
 #define PVR2_FPU_EXC_MASK              0x00000001
 
@@ -208,6 +210,8 @@ struct pvr_s {
 #define PVR_MMU_TLB_ACCESS(pvr)        (pvr.pvr[11] & PVR11_MMU_TLB_ACCESS)
 #define PVR_MMU_ZONES(pvr)     (pvr.pvr[11] & PVR11_MMU_ZONES)
 
+/* endian */
+#define PVR_ENDIAN(pvr)        (pvr.pvr[0] & PVR0_ENDI)
 
 int cpu_has_pvr(void);
 void get_pvr(struct pvr_s *pvr);
diff --git a/arch/microblaze/include/asm/seccomp.h b/arch/microblaze/include/asm/seccomp.h
new file mode 100644 (file)
index 0000000..0d91275
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef _ASM_MICROBLAZE_SECCOMP_H
+#define _ASM_MICROBLAZE_SECCOMP_H
+
+#include <linux/unistd.h>
+
+#define __NR_seccomp_read              __NR_read
+#define __NR_seccomp_write             __NR_write
+#define __NR_seccomp_exit              __NR_exit
+#define __NR_seccomp_sigreturn         __NR_sigreturn
+
+#define __NR_seccomp_read_32           __NR_read
+#define __NR_seccomp_write_32          __NR_write
+#define __NR_seccomp_exit_32           __NR_exit
+#define __NR_seccomp_sigreturn_32      __NR_sigreturn
+
+#endif /* _ASM_MICROBLAZE_SECCOMP_H */
index 782b5c8..8f39689 100644 (file)
@@ -25,6 +25,12 @@ void early_printk(const char *fmt, ...);
 int setup_early_printk(char *opt);
 void disable_early_printk(void);
 
+#if defined(CONFIG_EARLY_PRINTK)
+#define eprintk early_printk
+#else
+#define eprintk printk
+#endif
+
 void heartbeat(void);
 void setup_heartbeat(void);
 
index 8a8e9fc..b73da2a 100644 (file)
@@ -127,23 +127,19 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SECCOMP            10      /* secure computing */
 #define TIF_FREEZE             14      /* Freezing for suspend */
 
-/* FIXME change in entry.S */
-#define TIF_KERNEL_TRACE       8       /* kernel trace active */
-
 /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_POLLING_NRFLAG     16
 
-#define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
-#define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
-#define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
-#define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
-#define _TIF_IRET              (1<<TIF_IRET)
-#define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
-#define _TIF_FREEZE            (1<<TIF_FREEZE)
+#define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
+#define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
+#define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP                (1 << TIF_SINGLESTEP)
+#define _TIF_IRET              (1 << TIF_IRET)
+#define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE            (1 << TIF_FREEZE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
-#define _TIF_KERNEL_TRACE      (1 << TIF_KERNEL_TRACE)
 
 /* work to do in syscall trace */
 #define _TIF_WORK_SYSCALL_MASK  (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \
index 3658d91..2b97cbe 100644 (file)
 
 # ifdef __KERNEL__
 
-# include <linux/unaligned/be_struct.h>
+# include <linux/unaligned/be_byteshift.h>
 # include <linux/unaligned/le_byteshift.h>
 # include <linux/unaligned/generic.h>
 
-# define get_unaligned __get_unaligned_be
-# define put_unaligned __put_unaligned_be
+
+#  ifdef __MICROBLAZEEL__
+#   define get_unaligned       __get_unaligned_le
+#   define put_unaligned       __put_unaligned_le
+#  else
+#   define get_unaligned       __get_unaligned_be
+#   define put_unaligned       __put_unaligned_be
+#  endif
 
 # endif        /* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNALIGNED_H */
index 2b67e92..d770b00 100644 (file)
 #define __NR_rt_tgsigqueueinfo 365 /* new */
 #define __NR_perf_event_open   366 /* new */
 #define __NR_recvmmsg          367 /* new */
+#define __NR_fanotify_init     368
+#define __NR_fanotify_mark     369
+#define __NR_prlimit64         370
 
-#define __NR_syscalls          368
+#define __NR_syscalls          371
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
index f72dbd6..f70a604 100644 (file)
@@ -72,6 +72,7 @@ void set_cpuinfo_pvr_full(struct cpuinfo *ci, struct device_node *cpu)
        CI(pvr_user2, USER2);
 
        CI(mmu, USE_MMU);
+       CI(endian, ENDIAN);
 
        CI(use_icache, USE_ICACHE);
        CI(icache_tagbits, ICACHE_ADDR_TAG_BITS);
index 6095aa6..b16b994 100644 (file)
@@ -119,6 +119,7 @@ void __init set_cpuinfo_static(struct cpuinfo *ci, struct device_node *cpu)
        ci->pvr_user2 = fcpu(cpu, "xlnx,pvr-user2");
 
        ci->mmu = fcpu(cpu, "xlnx,use-mmu");
+       ci->endian = fcpu(cpu, "xlnx,endianness");
 
        ci->ver_code = 0;
        ci->fpga_family_code = 0;
index 255ef88..87c79fa 100644 (file)
@@ -30,6 +30,8 @@ const struct cpu_ver_key cpu_ver_lookup[] = {
        {"7.20.c", 0x0e},
        {"7.20.d", 0x0f},
        {"7.30.a", 0x10},
+       {"7.30.b", 0x11},
+       {"8.00.a", 0x12},
        {NULL, 0},
 };
 
index 7086e35..b4048af 100644 (file)
@@ -51,11 +51,12 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        count = seq_printf(m,
                        "CPU-Family:    MicroBlaze\n"
                        "FPGA-Arch:     %s\n"
-                       "CPU-Ver:       %s\n"
+                       "CPU-Ver:       %s, %s endian\n"
                        "CPU-MHz:       %d.%02d\n"
                        "BogoMips:      %lu.%02lu\n",
                        fpga_family,
                        cpu_ver,
+                       cpuinfo.endian ? "little" : "big",
                        cpuinfo.cpu_clock_freq /
                        1000000,
                        cpuinfo.cpu_clock_freq %
index 9bee938..e01afa6 100644 (file)
@@ -27,7 +27,7 @@
        register unsigned tmp __asm__("r3");                    \
        tmp = 0x0;      /* Prevent warning about unused */      \
        __asm__ __volatile__ (                                  \
-                       ".byte 0x94,0x60,0xa0, " #pvrid "\n\t"  \
+                       "mfs    %0, rpvr" #pvrid ";"    \
                        : "=r" (tmp) : : "memory");             \
        val = tmp;                                              \
 }
index 7de8492..c3616a0 100644 (file)
@@ -24,7 +24,8 @@
 static u32 early_console_initialized;
 static u32 base_addr;
 
-static void early_printk_putc(char c)
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
+static void early_printk_uartlite_putc(char c)
 {
        /*
         * Limit how many times we'll spin waiting for TX FIFO status.
@@ -45,25 +46,70 @@ static void early_printk_putc(char c)
                out_be32(base_addr + 4, c & 0xff);
 }
 
-static void early_printk_write(struct console *unused,
+static void early_printk_uartlite_write(struct console *unused,
                                        const char *s, unsigned n)
 {
        while (*s && n-- > 0) {
-               early_printk_putc(*s);
+               early_printk_uartlite_putc(*s);
                if (*s == '\n')
-                       early_printk_putc('\r');
+                       early_printk_uartlite_putc('\r');
                s++;
        }
 }
 
-static struct console early_serial_console = {
+static struct console early_serial_uartlite_console = {
        .name = "earlyser",
-       .write = early_printk_write,
+       .write = early_printk_uartlite_write,
        .flags = CON_PRINTBUFFER,
        .index = -1,
 };
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
 
-static struct console *early_console = &early_serial_console;
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static void early_printk_uart16550_putc(char c)
+{
+       /*
+        * Limit how many times we'll spin waiting for TX FIFO status.
+        * This will prevent lockups if the base address is incorrectly
+        * set, or any other issue on the UARTLITE.
+        * This limit is pretty arbitrary, unless we are at about 10 baud
+        * we'll never timeout on a working UART.
+        */
+
+       #define UART_LSR_TEMT   0x40 /* Transmitter empty */
+       #define UART_LSR_THRE   0x20 /* Transmit-hold-register empty */
+       #define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+       unsigned retries = 10000;
+
+       while (--retries &&
+               !((in_be32(base_addr + 0x14) & BOTH_EMPTY) == BOTH_EMPTY))
+               ;
+
+       if (retries)
+               out_be32(base_addr, c & 0xff);
+}
+
+static void early_printk_uart16550_write(struct console *unused,
+                                       const char *s, unsigned n)
+{
+       while (*s && n-- > 0) {
+               early_printk_uart16550_putc(*s);
+               if (*s == '\n')
+                       early_printk_uart16550_putc('\r');
+               s++;
+       }
+}
+
+static struct console early_serial_uart16550_console = {
+       .name = "earlyser",
+       .write = early_printk_uart16550_write,
+       .flags = CON_PRINTBUFFER,
+       .index = -1,
+};
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+static struct console *early_console;
 
 void early_printk(const char *fmt, ...)
 {
@@ -84,20 +130,43 @@ int __init setup_early_printk(char *opt)
        if (early_console_initialized)
                return 1;
 
+#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
        base_addr = early_uartlite_console();
        if (base_addr) {
                early_console_initialized = 1;
 #ifdef CONFIG_MMU
                early_console_reg_tlb_alloc(base_addr);
 #endif
+               early_console = &early_serial_uartlite_console;
                early_printk("early_printk_console is enabled at 0x%08x\n",
                                                        base_addr);
 
                /* register_console(early_console); */
 
                return 0;
-       } else
-               return 1;
+       }
+#endif /* CONFIG_SERIAL_UARTLITE_CONSOLE */
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       base_addr = early_uart16550_console();
+       base_addr &= ~3; /* clear register offset */
+       if (base_addr) {
+               early_console_initialized = 1;
+#ifdef CONFIG_MMU
+               early_console_reg_tlb_alloc(base_addr);
+#endif
+               early_console = &early_serial_uart16550_console;
+
+               early_printk("early_printk_console is enabled at 0x%08x\n",
+                                                       base_addr);
+
+               /* register_console(early_console); */
+
+               return 0;
+       }
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
+
+       return 1;
 }
 
 void __init disable_early_printk(void)
index 304882e..819238b 100644 (file)
        swi     r13, r1, PTO+PT_R13;    /* Save SDA2 */                 \
        swi     r14, r1, PTO+PT_PC;     /* PC, before IRQ/trap */       \
        swi     r15, r1, PTO+PT_R15;    /* Save LP */                   \
+       swi     r16, r1, PTO+PT_R16;                                    \
+       swi     r17, r1, PTO+PT_R17;                                    \
        swi     r18, r1, PTO+PT_R18;    /* Save asm scratch reg */      \
        swi     r19, r1, PTO+PT_R19;                                    \
        swi     r20, r1, PTO+PT_R20;                                    \
        lwi     r13, r1, PTO+PT_R13;    /* restore SDA2 */              \
        lwi     r14, r1, PTO+PT_PC;     /* RESTORE_LINK PC, before IRQ/trap */\
        lwi     r15, r1, PTO+PT_R15;    /* restore LP */                \
+       lwi     r16, r1, PTO+PT_R16;                                    \
+       lwi     r17, r1, PTO+PT_R17;                                    \
        lwi     r18, r1, PTO+PT_R18;    /* restore asm scratch reg */   \
        lwi     r19, r1, PTO+PT_R19;                                    \
        lwi     r20, r1, PTO+PT_R20;                                    \
@@ -295,6 +299,8 @@ C_ENTRY(_user_exception):
        /* addik        r1, r1, -STATE_SAVE_SIZE; */
        addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
        SAVE_REGS
+       swi     r0, r1, PTO + PT_R3
+       swi     r0, r1, PTO + PT_R4
 
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
        swi     r11, r1, PTO+PT_R1;             /* Store user SP.  */
@@ -458,14 +464,8 @@ C_ENTRY(sys_execve):
        addik   r8, r1, PTO;            /* add user context as 4th arg */
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
-       swi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       swi     r4, r1, PTO+PT_R4;
-       brlid   r15, sys_rt_sigreturn   /* Do real work */
+       brid    sys_rt_sigreturn        /* Do real work */
        addik   r5, r1, PTO;            /* add user context as 1st arg */
-       lwi     r3, r1, PTO+PT_R3; /* restore saved r3, r4 registers */
-       lwi     r4, r1, PTO+PT_R4;
-       bri ret_from_trap /* fall through will not work here due to align */
-       nop;
 
 /*
  * HW EXCEPTION rutine start
@@ -765,9 +765,7 @@ C_ENTRY(_debug_exception):
        /* save all regs to pt_reg structure */
        swi     r0, r1, PTO+PT_R0;      /* R0 must be saved too */
        swi     r14, r1, PTO+PT_R14     /* rewrite saved R14 value */
-       swi     r16, r1, PTO+PT_R16
        swi     r16, r1, PTO+PT_PC; /* PC and r16 are the same */
-       swi     r17, r1, PTO+PT_R17
        /* save special purpose registers to pt_regs */
        mfs     r11, rear;
        swi     r11, r1, PTO+PT_EAR;
@@ -801,8 +799,6 @@ C_ENTRY(_debug_exception):
 
        addik   r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
        SAVE_REGS;
-       swi     r17, r1, PTO+PT_R17;
-       swi     r16, r1, PTO+PT_R16;
        swi     r16, r1, PTO+PT_PC;     /* Save LP */
        swi     r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
        lwi     r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
@@ -848,8 +844,6 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
        tophys(r1,r1);
        /* MS: Restore all regs */
        RESTORE_REGS
-       lwi     r17, r1, PTO+PT_R17;
-       lwi     r16, r1, PTO+PT_R16;
        addik   r1, r1, STATE_SAVE_SIZE  /* Clean up stack space */
        lwi     r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
 DBTRAP_return_user: /* MS: Make global symbol for debugging */
@@ -863,7 +857,6 @@ DBTRAP_return_user: /* MS: Make global symbol for debugging */
        RESTORE_REGS
        lwi     r14, r1, PTO+PT_R14;
        lwi     r16, r1, PTO+PT_PC;
-       lwi     r17, r1, PTO+PT_R17;
        addik   r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
        tovirt(r1,r1);
 DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
index b98ee8d..478f294 100644 (file)
@@ -72,7 +72,6 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                                                        int fsr, int addr)
 {
 #ifdef CONFIG_MMU
-       int code;
        addr = regs->pc;
 #endif
 
@@ -86,8 +85,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
        switch (type & 0x1F) {
        case MICROBLAZE_ILL_OPCODE_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Illegal opcode exception " \
-                                                       "in user mode.\n");
+                       pr_debug("Illegal opcode exception in user mode\n");
                        _exception(SIGILL, regs, ILL_ILLOPC, addr);
                        return;
                }
@@ -97,8 +95,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                break;
        case MICROBLAZE_IBUS_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Instruction bus error " \
-                                               "exception in user mode.\n");
+                       pr_debug("Instruction bus error exception in user mode\n");
                        _exception(SIGBUS, regs, BUS_ADRERR, addr);
                        return;
                }
@@ -108,8 +105,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                break;
        case MICROBLAZE_DBUS_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Data bus error exception " \
-                                                       "in user mode.\n");
+                       pr_debug("Data bus error exception in user mode\n");
                        _exception(SIGBUS, regs, BUS_ADRERR, addr);
                        return;
                }
@@ -119,8 +115,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                break;
        case MICROBLAZE_DIV_ZERO_EXCEPTION:
                if (user_mode(regs)) {
-                       pr_debug(KERN_WARNING "Divide by zero exception " \
-                                                       "in user mode\n");
+                       pr_debug("Divide by zero exception in user mode\n");
                        _exception(SIGILL, regs, FPE_INTDIV, addr);
                        return;
                }
@@ -129,7 +124,7 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
                die("Divide by zero exception", regs, SIGBUS);
                break;
        case MICROBLAZE_FPU_EXCEPTION:
-               pr_debug(KERN_WARNING "FPU exception\n");
+               pr_debug("FPU exception\n");
                /* IEEE FP exception */
                /* I removed fsr variable and use code var for storing fsr */
                if (fsr & FSR_IO)
@@ -147,14 +142,8 @@ asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
 
 #ifdef CONFIG_MMU
        case MICROBLAZE_PRIVILEGED_EXCEPTION:
-               pr_debug(KERN_WARNING "Privileged exception\n");
-               /* "brk r0,r0" - used as debug breakpoint - old toolchain */
-               if (get_user(code, (unsigned long *)regs->pc) == 0
-                       && code == 0x980c0000) {
-                       _exception(SIGTRAP, regs, TRAP_BRKPT, addr);
-               } else {
-                       _exception(SIGILL, regs, ILL_PRVOPC, addr);
-               }
+               pr_debug("Privileged exception\n");
+               _exception(SIGILL, regs, ILL_PRVOPC, addr);
                break;
 #endif
        default:
index 5227517..154756f 100644 (file)
@@ -47,11 +47,10 @@ void setup_heartbeat(void)
        struct device_node *gpio = NULL;
        int *prop;
        int j;
-       char *gpio_list[] = {
-                               "xlnx,xps-gpio-1.00.a",
-                               "xlnx,opb-gpio-1.00.a",
-                               NULL
-                       };
+       const char * const gpio_list[] = {
+               "xlnx,xps-gpio-1.00.a",
+               NULL
+       };
 
        for (j = 0; gpio_list[j] != NULL; j++) {
                gpio = of_find_compatible_node(NULL, NULL, gpio_list[j]);
@@ -60,7 +59,7 @@ void setup_heartbeat(void)
        }
 
        if (gpio) {
-               base_addr = *(int *) of_get_property(gpio, "reg", NULL);
+               base_addr = be32_to_cpup(of_get_property(gpio, "reg", NULL));
                base_addr = (unsigned long) ioremap(base_addr, PAGE_SIZE);
                printk(KERN_NOTICE "Heartbeat GPIO at 0x%x\n", base_addr);
 
index 03172c1..d61ea33 100644 (file)
@@ -126,11 +126,8 @@ void __init init_IRQ(void)
                                0
                        };
 #endif
-       static char *intc_list[] = {
+       const char * const intc_list[] = {
                                "xlnx,xps-intc-1.00.a",
-                               "xlnx,opb-intc-1.00.c",
-                               "xlnx,opb-intc-1.00.b",
-                               "xlnx,opb-intc-1.00.a",
                                NULL
                        };
 
@@ -141,12 +138,15 @@ void __init init_IRQ(void)
        }
        BUG_ON(!intc);
 
-       intc_baseaddr = *(int *) of_get_property(intc, "reg", NULL);
+       intc_baseaddr = be32_to_cpup(of_get_property(intc,
+                                                               "reg", NULL));
        intc_baseaddr = (unsigned long) ioremap(intc_baseaddr, PAGE_SIZE);
-       nr_irq = *(int *) of_get_property(intc, "xlnx,num-intr-inputs", NULL);
+       nr_irq = be32_to_cpup(of_get_property(intc,
+                                               "xlnx,num-intr-inputs", NULL));
 
        intr_type =
-               *(int *) of_get_property(intc, "xlnx,kind-of-intr", NULL);
+               be32_to_cpup(of_get_property(intc,
+                                               "xlnx,kind-of-intr", NULL));
        if (intr_type >= (1 << (nr_irq + 1)))
                printk(KERN_INFO " ERROR: Mismatch in kind-of-intr param\n");
 
index bfc006b..09a5e82 100644 (file)
@@ -80,7 +80,7 @@ void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
 void microblaze_kgdb_break(struct pt_regs *regs)
 {
        if (kgdb_handle_exception(1, SIGTRAP, 0, regs) != 0)
-               return 0;
+               return;
 
        /* Jump over the first arch_kgdb_breakpoint which is barrier to
         * get kgdb work. The same solution is used for powerpc */
@@ -114,7 +114,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
 {
        char *ptr;
        unsigned long address;
-       int cpu = smp_processor_id();
 
        switch (remcom_in_buffer[0]) {
        case 'c':
@@ -143,5 +142,9 @@ void kgdb_arch_exit(void)
  * Global data
  */
 struct kgdb_arch arch_kgdb_ops = {
+#ifdef __MICROBLAZEEL__
+       .gdb_bpt_instr = {0x18, 0x00, 0x0c, 0xba}, /* brki r16, 0x18 */
+#else
        .gdb_bpt_instr = {0xba, 0x0c, 0x00, 0x18}, /* brki r16, 0x18 */
+#endif
 };
index ff85f77..5cb0341 100644 (file)
 #include <linux/syscalls.h>
 
 #include <asm/checksum.h>
+#include <asm/cacheflush.h>
 #include <linux/io.h>
 #include <asm/page.h>
 #include <asm/system.h>
 #include <linux/ftrace.h>
 #include <linux/uaccess.h>
 
-/*
- * libgcc functions - functions that are used internally by the
- * compiler... (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-extern void __ashldi3(void);
-EXPORT_SYMBOL(__ashldi3);
-extern void __ashrdi3(void);
-EXPORT_SYMBOL(__ashrdi3);
-extern void __divsi3(void);
-EXPORT_SYMBOL(__divsi3);
-extern void __lshrdi3(void);
-EXPORT_SYMBOL(__lshrdi3);
-extern void __modsi3(void);
-EXPORT_SYMBOL(__modsi3);
-extern void __mulsi3(void);
-EXPORT_SYMBOL(__mulsi3);
-extern void __muldi3(void);
-EXPORT_SYMBOL(__muldi3);
-extern void __ucmpdi2(void);
-EXPORT_SYMBOL(__ucmpdi2);
-extern void __udivsi3(void);
-EXPORT_SYMBOL(__udivsi3);
-extern void __umodsi3(void);
-EXPORT_SYMBOL(__umodsi3);
 extern char *_ebss;
 EXPORT_SYMBOL_GPL(_ebss);
 #ifdef CONFIG_FUNCTION_TRACER
@@ -63,3 +39,9 @@ EXPORT_SYMBOL(__strncpy_user);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memmove);
 #endif
+
+#ifdef CONFIG_MMU
+EXPORT_SYMBOL(empty_zero_page);
+#endif
+
+EXPORT_SYMBOL(mbc);
index bacbd3d..a105301 100644 (file)
@@ -72,11 +72,12 @@ static int __init early_init_dt_scan_serial(unsigned long node,
 /* find compatible node with uartlite */
        p = of_get_flat_dt_prop(node, "compatible", &l);
        if ((strncmp(p, "xlnx,xps-uartlite", 17) != 0) &&
-                       (strncmp(p, "xlnx,opb-uartlite", 17) != 0))
+                       (strncmp(p, "xlnx,opb-uartlite", 17) != 0) &&
+                       (strncmp(p, "xlnx,axi-uartlite", 17) != 0))
                return 0;
 
        addr = of_get_flat_dt_prop(node, "reg", &l);
-       return *addr; /* return address */
+       return be32_to_cpup(addr); /* return address */
 }
 
 /* this function is looking for early uartlite console - Microblaze specific */
@@ -84,6 +85,40 @@ int __init early_uartlite_console(void)
 {
        return of_scan_flat_dt(early_init_dt_scan_serial, NULL);
 }
+
+/* MS this is Microblaze specifig function */
+static int __init early_init_dt_scan_serial_full(unsigned long node,
+                               const char *uname, int depth, void *data)
+{
+       unsigned long l;
+       char *p;
+       unsigned int addr;
+
+       pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
+
+/* find all serial nodes */
+       if (strncmp(uname, "serial", 6) != 0)
+               return 0;
+
+       early_init_dt_check_for_initrd(node);
+
+/* find compatible node with uartlite */
+       p = of_get_flat_dt_prop(node, "compatible", &l);
+
+       if ((strncmp(p, "xlnx,xps-uart16550", 18) != 0) &&
+               (strncmp(p, "xlnx,axi-uart16550", 18) != 0))
+               return 0;
+
+       addr = *(u32 *)of_get_flat_dt_prop(node, "reg", &l);
+       addr += *(u32 *)of_get_flat_dt_prop(node, "reg-offset", &l);
+       return be32_to_cpu(addr); /* return address */
+}
+
+/* this function is looking for early uartlite console - Microblaze specific */
+int __init early_uart16550_console(void)
+{
+       return of_scan_flat_dt(early_init_dt_scan_serial_full, NULL);
+}
 #endif
 
 void __init early_init_devtree(void *params)
index f5f7688..bb1558e 100644 (file)
@@ -92,12 +92,6 @@ inline unsigned get_romfs_len(unsigned *addr)
 }
 #endif /* CONFIG_MTD_UCLINUX_EBSS */
 
-#if defined(CONFIG_EARLY_PRINTK) && defined(CONFIG_SERIAL_UARTLITE_CONSOLE)
-#define eprintk early_printk
-#else
-#define eprintk printk
-#endif
-
 void __init machine_early_init(const char *cmdline, unsigned int ram,
                unsigned int fdt, unsigned int msr)
 {
index 03376dc..e88a930 100644 (file)
@@ -372,3 +372,6 @@ ENTRY(sys_call_table)
        .long sys_rt_tgsigqueueinfo     /* 365 */
        .long sys_perf_event_open
        .long sys_recvmmsg
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64     /* 370 */
index b1380ae..a5aa33d 100644 (file)
@@ -38,6 +38,9 @@ static unsigned int timer_baseaddr;
 #define TIMER_BASE     timer_baseaddr
 #endif
 
+unsigned int freq_div_hz;
+unsigned int timer_clock_freq;
+
 #define TCSR0  (0x00)
 #define TLR0   (0x04)
 #define TCR0   (0x08)
@@ -115,7 +118,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode,
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
                printk(KERN_INFO "%s: periodic\n", __func__);
-               microblaze_timer0_start_periodic(cpuinfo.freq_div_hz);
+               microblaze_timer0_start_periodic(freq_div_hz);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
                printk(KERN_INFO "%s: oneshot\n", __func__);
@@ -168,7 +171,7 @@ static struct irqaction timer_irqaction = {
 static __init void microblaze_clockevent_init(void)
 {
        clockevent_microblaze_timer.mult =
-               div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+               div_sc(timer_clock_freq, NSEC_PER_SEC,
                                clockevent_microblaze_timer.shift);
        clockevent_microblaze_timer.max_delta_ns =
                clockevent_delta2ns((u32)~0, &clockevent_microblaze_timer);
@@ -201,7 +204,7 @@ static struct cyclecounter microblaze_cc = {
 
 int __init init_microblaze_timecounter(void)
 {
-       microblaze_cc.mult = div_sc(cpuinfo.cpu_clock_freq, NSEC_PER_SEC,
+       microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
                                microblaze_cc.shift);
 
        timecounter_init(&microblaze_tc, &microblaze_cc, sched_clock());
@@ -221,7 +224,7 @@ static struct clocksource clocksource_microblaze = {
 static int __init microblaze_clocksource_init(void)
 {
        clocksource_microblaze.mult =
-                       clocksource_hz2mult(cpuinfo.cpu_clock_freq,
+                       clocksource_hz2mult(timer_clock_freq,
                                                clocksource_microblaze.shift);
        if (clocksource_register(&clocksource_microblaze))
                panic("failed to register clocksource");
@@ -247,6 +250,7 @@ void __init time_init(void)
        u32 irq, i = 0;
        u32 timer_num = 1;
        struct device_node *timer = NULL;
+       const void *prop;
 #ifdef CONFIG_SELFMOD_TIMER
        unsigned int timer_baseaddr = 0;
        int arr_func[] = {
@@ -258,12 +262,10 @@ void __init time_init(void)
                                0
                        };
 #endif
-       char *timer_list[] = {
-                               "xlnx,xps-timer-1.00.a",
-                               "xlnx,opb-timer-1.00.b",
-                               "xlnx,opb-timer-1.00.a",
-                               NULL
-                       };
+       const char * const timer_list[] = {
+               "xlnx,xps-timer-1.00.a",
+               NULL
+       };
 
        for (i = 0; timer_list[i] != NULL; i++) {
                timer = of_find_compatible_node(NULL, NULL, timer_list[i]);
@@ -272,13 +274,13 @@ void __init time_init(void)
        }
        BUG_ON(!timer);
 
-       timer_baseaddr = *(int *) of_get_property(timer, "reg", NULL);
+       timer_baseaddr = be32_to_cpup(of_get_property(timer, "reg", NULL));
        timer_baseaddr = (unsigned long) ioremap(timer_baseaddr, PAGE_SIZE);
-       irq = *(int *) of_get_property(timer, "interrupts", NULL);
-       timer_num =
-               *(int *) of_get_property(timer, "xlnx,one-timer-only", NULL);
+       irq = be32_to_cpup(of_get_property(timer, "interrupts", NULL));
+       timer_num = be32_to_cpup(of_get_property(timer,
+                                               "xlnx,one-timer-only", NULL));
        if (timer_num) {
-               printk(KERN_EMERG "Please enable two timers in HW\n");
+               eprintk(KERN_EMERG "Please enable two timers in HW\n");
                BUG();
        }
 
@@ -288,7 +290,14 @@ void __init time_init(void)
        printk(KERN_INFO "%s #0 at 0x%08x, irq=%d\n",
                timer_list[i], timer_baseaddr, irq);
 
-       cpuinfo.freq_div_hz = cpuinfo.cpu_clock_freq / HZ;
+       /* If there is clock-frequency property than use it */
+       prop = of_get_property(timer, "clock-frequency", NULL);
+       if (prop)
+               timer_clock_freq = be32_to_cpup(prop);
+       else
+               timer_clock_freq = cpuinfo.cpu_clock_freq;
+
+       freq_div_hz = timer_clock_freq / HZ;
 
        setup_irq(irq, &timer_irqaction);
 #ifdef CONFIG_HEART_BEAT
index a09f296..96a88c3 100644 (file)
@@ -8,7 +8,6 @@
  * for more details.
  */
 
-OUTPUT_FORMAT("elf32-microblaze", "elf32-microblaze", "elf32-microblaze")
 OUTPUT_ARCH(microblaze)
 ENTRY(microblaze_start)
 
@@ -16,7 +15,11 @@ ENTRY(microblaze_start)
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 
+#ifdef __MICROBLAZEEL__
+jiffies = jiffies_64;
+#else
 jiffies = jiffies_64 + 4;
+#endif
 
 SECTIONS {
        . = CONFIG_KERNEL_START;
index 4dfe47d..f1fcbff 100644 (file)
@@ -11,3 +11,13 @@ lib-y += memcpy.o memmove.o
 endif
 
 lib-y += uaccess_old.o
+
+lib-y += ashldi3.o
+lib-y += ashrdi3.o
+lib-y += divsi3.o
+lib-y += lshrdi3.o
+lib-y += modsi3.o
+lib-y += muldi3.o
+lib-y += mulsi3.o
+lib-y += udivsi3.o
+lib-y += umodsi3.o
diff --git a/arch/microblaze/lib/ashldi3.c b/arch/microblaze/lib/ashldi3.c
new file mode 100644 (file)
index 0000000..beb80f3
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashldi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.low = 0;
+               w.s.high = (unsigned int) uu.s.low << -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.low >> bm;
+
+               w.s.low = (unsigned int) uu.s.low << b;
+               w.s.high = ((unsigned int) uu.s.high << b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/microblaze/lib/ashrdi3.c b/arch/microblaze/lib/ashrdi3.c
new file mode 100644 (file)
index 0000000..c884a91
--- /dev/null
@@ -0,0 +1,31 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __ashrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               /* w.s.high = 1..1 or 0..0 */
+               w.s.high =
+                   uu.s.high >> 31;
+               w.s.low = uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/microblaze/lib/divsi3.S b/arch/microblaze/lib/divsi3.S
new file mode 100644 (file)
index 0000000..595b02d
--- /dev/null
@@ -0,0 +1,73 @@
+#include <linux/linkage.h>
+
+/*
+* Divide operation for 32 bit integers.
+*      Input : Dividend in Reg r5
+*              Divisor in Reg r6
+*      Output: Result in Reg r3
+*/
+       .text
+       .globl  __divsi3
+       .type __divsi3, @function
+       .ent __divsi3
+__divsi3:
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -16
+       swi     r28, r1, 0
+       swi     r29, r1, 4
+       swi     r30, r1, 8
+       swi     r31, r1, 12
+
+       beqi    r6, div_by_zero /* div_by_zero - division error */
+       beqi    r5, result_is_zero /* result is zero */
+       bgeid   r5, r5_pos
+       xor     r28, r5, r6 /* get the sign of the result */
+       rsubi   r5, r5, 0 /* make r5 positive */
+r5_pos:
+       bgei    r6, r6_pos
+       rsubi   r6, r6, 0 /* make r6 positive */
+r6_pos:
+       addik   r30, r0, 0 /* clear mod */
+       addik   r3, r0, 0 /* clear div */
+       addik   r29, r0, 32 /* initialize the loop count */
+
+       /* first part try to find the first '1' in the r5 */
+div0:
+       blti    r5, div2 /* this traps r5 == 0x80000000 */
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgtid   r5, div1
+       addik   r29, r29, -1
+div2:
+       /* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r30, r30, r30 /* move that bit into the mod register */
+       rsub    r31, r6, r30 /* try to subtract (r30 a r6) */
+       blti    r31, mod_too_small
+       /* move the r31 to mod since the result was positive */
+       or      r30, r0, r31
+       addik   r3, r3, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r3, r3, r3 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bgei    r28, return_here
+       brid    return_here
+       rsubi   r3, r3, 0 /* negate the result */
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r28, r1, 0
+       lwi     r29, r1, 4
+       lwi     r30, r1, 8
+       lwi     r31, r1, 12
+       rtsd    r15, 8
+       addik   r1, r1, 16
+
+.size __divsi3, . - __divsi3
+.end __divsi3
diff --git a/arch/microblaze/lib/libgcc.h b/arch/microblaze/lib/libgcc.h
new file mode 100644 (file)
index 0000000..05909d5
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ASM_LIBGCC_H
+#define __ASM_LIBGCC_H
+
+#include <asm/byteorder.h>
+
+typedef int word_type __attribute__ ((mode (__word__)));
+
+#ifdef __BIG_ENDIAN
+struct DWstruct {
+       int high, low;
+};
+#elif defined(__LITTLE_ENDIAN)
+struct DWstruct {
+       int low, high;
+};
+#else
+#error I feel sick.
+#endif
+
+typedef union {
+       struct DWstruct s;
+       long long ll;
+} DWunion;
+
+#endif /* __ASM_LIBGCC_H */
diff --git a/arch/microblaze/lib/lshrdi3.c b/arch/microblaze/lib/lshrdi3.c
new file mode 100644 (file)
index 0000000..dcf8d68
--- /dev/null
@@ -0,0 +1,29 @@
+#include <linux/module.h>
+
+#include "libgcc.h"
+
+long long __lshrdi3(long long u, word_type b)
+{
+       DWunion uu, w;
+       word_type bm;
+
+       if (b == 0)
+               return u;
+
+       uu.ll = u;
+       bm = 32 - b;
+
+       if (bm <= 0) {
+               w.s.high = 0;
+               w.s.low = (unsigned int) uu.s.high >> -bm;
+       } else {
+               const unsigned int carries = (unsigned int) uu.s.high << bm;
+
+               w.s.high = (unsigned int) uu.s.high >> b;
+               w.s.low = ((unsigned int) uu.s.low >> b) | carries;
+       }
+
+       return w.ll;
+}
+
+EXPORT_SYMBOL(__lshrdi3);
index 014bac9..cc495d7 100644 (file)
 #include <asm/system.h>
 
 #ifdef __HAVE_ARCH_MEMCPY
+#ifndef CONFIG_OPT_LIB_FUNCTION
 void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
 {
        const char *src = v_src;
        char *dst = v_dst;
-#ifndef CONFIG_OPT_LIB_FUNCTION
+
        /* Simple, byte oriented memcpy. */
        while (c--)
                *dst++ = *src++;
 
        return v_dst;
-#else
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+       const char *src = v_src;
+       char *dst = v_dst;
+
        /* The following code tries to optimize the copy by using unsigned
         * alignment. This will work fine if both source and destination are
         * aligned on the same boundary. However, if they are aligned on
@@ -86,7 +93,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x1:       /* Unaligned - Off by 1 */
                        /* Word align the source */
                        i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *i_src++ << 8;
 
@@ -95,7 +102,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                                *i_dst++ = buf_hold | value >> 24;
                                buf_hold = value << 8;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*i_src++ & 0xFFFFFF00) >>8;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *i_src++;
+                               *i_dst++ = buf_hold | ((value & 0xFF) << 24);
+                               buf_hold = (value & 0xFFFFFF00) >>8;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src -= 3;
@@ -103,7 +119,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x2:       /* Unaligned - Off by 2 */
                        /* Word align the source */
                        i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *i_src++ << 16;
 
@@ -112,7 +128,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                                *i_dst++ = buf_hold | value >> 16;
                                buf_hold = value << 16;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*i_src++ & 0xFFFF0000 )>>16;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *i_src++;
+                               *i_dst++ = buf_hold | ((value & 0xFFFF)<<16);
+                               buf_hold = (value & 0xFFFF0000) >>16;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src -= 2;
@@ -120,7 +145,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x3:       /* Unaligned - Off by 3 */
                        /* Word align the source */
                        i_src = (const void *) ((unsigned)src & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *i_src++ << 24;
 
@@ -129,7 +154,16 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
                                *i_dst++ = buf_hold | value >> 8;
                                buf_hold = value << 24;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*i_src++ & 0xFF000000) >> 24;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *i_src++;
+                               *i_dst++ = buf_hold | ((value & 0xFFFFFF) << 8);
+                               buf_hold = (value & 0xFF000000) >> 24;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src -= 1;
@@ -150,7 +184,7 @@ void *memcpy(void *v_dst, const void *v_src, __kernel_size_t c)
        }
 
        return v_dst;
-#endif
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memcpy);
 #endif /* __HAVE_ARCH_MEMCPY */
index 0929198..123e361 100644 (file)
 #include <linux/string.h>
 
 #ifdef __HAVE_ARCH_MEMMOVE
+#ifndef CONFIG_OPT_LIB_FUNCTION
 void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
 {
        const char *src = v_src;
        char *dst = v_dst;
 
-#ifdef CONFIG_OPT_LIB_FUNCTION
-       const uint32_t *i_src;
-       uint32_t *i_dst;
-#endif
-
        if (!c)
                return v_dst;
 
@@ -48,7 +44,6 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
        if (v_dst <= v_src)
                return memcpy(v_dst, v_src, c);
 
-#ifndef CONFIG_OPT_LIB_FUNCTION
        /* copy backwards, from end to beginning */
        src += c;
        dst += c;
@@ -58,7 +53,22 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                *--dst = *--src;
 
        return v_dst;
-#else
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
+void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
+{
+       const char *src = v_src;
+       char *dst = v_dst;
+       const uint32_t *i_src;
+       uint32_t *i_dst;
+
+       if (!c)
+               return v_dst;
+
+       /* Use memcpy when source is higher than dest */
+       if (v_dst <= v_src)
+               return memcpy(v_dst, v_src, c);
+
        /* The following code tries to optimize the copy by using unsigned
         * alignment. This will work fine if both source and destination are
         * aligned on the same boundary. However, if they are aligned on
@@ -104,7 +114,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x1:       /* Unaligned - Off by 1 */
                        /* Word align the source */
                        i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *--i_src >> 24;
 
@@ -113,7 +123,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                                *--i_dst = buf_hold << 8 | value;
                                buf_hold = value >> 24;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*--i_src & 0xFF) << 24;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *--i_src;
+                               *--i_dst = buf_hold | ((value & 0xFFFFFF00)>>8);
+                               buf_hold = (value  & 0xFF) << 24;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src += 1;
@@ -121,7 +140,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x2:       /* Unaligned - Off by 2 */
                        /* Word align the source */
                        i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *--i_src >> 16;
 
@@ -130,7 +149,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                                *--i_dst = buf_hold << 16 | value;
                                buf_hold = value >> 16;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*--i_src & 0xFFFF) << 16;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *--i_src;
+                               *--i_dst = buf_hold | ((value & 0xFFFF0000)>>16);
+                               buf_hold = (value & 0xFFFF) << 16;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src += 2;
@@ -138,7 +166,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                case 0x3:       /* Unaligned - Off by 3 */
                        /* Word align the source */
                        i_src = (const void *) (((unsigned)src + 4) & ~3);
-
+#ifndef __MICROBLAZEEL__
                        /* Load the holding buffer */
                        buf_hold = *--i_src >> 8;
 
@@ -147,7 +175,16 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                                *--i_dst = buf_hold << 24 | value;
                                buf_hold = value >> 8;
                        }
+#else
+                       /* Load the holding buffer */
+                       buf_hold = (*--i_src & 0xFFFFFF) << 8;
 
+                       for (; c >= 4; c -= 4) {
+                               value = *--i_src;
+                               *--i_dst = buf_hold | ((value & 0xFF000000)>> 24);
+                               buf_hold = (value & 0xFFFFFF) << 8;;
+                       }
+#endif
                        /* Realign the source */
                        src = (const void *)i_src;
                        src += 3;
@@ -169,7 +206,7 @@ void *memmove(void *v_dst, const void *v_src, __kernel_size_t c)
                *--dst = *--src;
        }
        return v_dst;
-#endif
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memmove);
 #endif /* __HAVE_ARCH_MEMMOVE */
index ecfb663..834565d 100644 (file)
 #include <linux/string.h>
 
 #ifdef __HAVE_ARCH_MEMSET
+#ifndef CONFIG_OPT_LIB_FUNCTION
+void *memset(void *v_src, int c, __kernel_size_t n)
+{
+       char *src = v_src;
+
+       /* Truncate c to 8 bits */
+       c = (c & 0xFF);
+
+       /* Simple, byte oriented memset or the rest of count. */
+       while (n--)
+               *src++ = c;
+
+       return v_src;
+}
+#else /* CONFIG_OPT_LIB_FUNCTION */
 void *memset(void *v_src, int c, __kernel_size_t n)
 {
        char *src = v_src;
-#ifdef CONFIG_OPT_LIB_FUNCTION
        uint32_t *i_src;
        uint32_t w32 = 0;
-#endif
+
        /* Truncate c to 8 bits */
        c = (c & 0xFF);
 
-#ifdef CONFIG_OPT_LIB_FUNCTION
        if (unlikely(c)) {
                /* Make a repeating word out of it */
                w32 = c;
@@ -72,12 +85,13 @@ void *memset(void *v_src, int c, __kernel_size_t n)
 
                src  = (void *)i_src;
        }
-#endif
+
        /* Simple, byte oriented memset or the rest of count. */
        while (n--)
                *src++ = c;
 
        return v_src;
 }
+#endif /* CONFIG_OPT_LIB_FUNCTION */
 EXPORT_SYMBOL(memset);
 #endif /* __HAVE_ARCH_MEMSET */
diff --git a/arch/microblaze/lib/modsi3.S b/arch/microblaze/lib/modsi3.S
new file mode 100644 (file)
index 0000000..84e0bee
--- /dev/null
@@ -0,0 +1,73 @@
+#include <linux/linkage.h>
+
+/*
+* modulo operation for 32 bit integers.
+*      Input : op1 in Reg r5
+*              op2 in Reg r6
+*      Output: op1 mod op2 in Reg r3
+*/
+
+       .text
+       .globl  __modsi3
+       .type __modsi3,  @function
+       .ent __modsi3
+
+__modsi3:
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -16
+       swi     r28, r1, 0
+       swi     r29, r1, 4
+       swi     r30, r1, 8
+       swi     r31, r1, 12
+
+       beqi    r6, div_by_zero /* div_by_zero division error */
+       beqi    r5, result_is_zero /* result is zero */
+       bgeid   r5, r5_pos
+       /* get the sign of the result [ depends only on the first arg] */
+       add     r28, r5, r0
+       rsubi   r5, r5, 0        /* make r5 positive */
+r5_pos:
+       bgei    r6, r6_pos
+       rsubi   r6, r6, 0        /* make r6 positive */
+r6_pos:
+       addik   r3, r0, 0 /* clear mod */
+       addik   r30, r0, 0 /* clear div */
+       addik   r29, r0, 32 /* initialize the loop count */
+/* first part try to find the first '1' in the r5 */
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgeid   r5, div1
+       addik   r29, r29, -1
+div2:
+       /* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r3, r3, r3 /* move that bit into the mod register */
+       rsub    r31, r6, r3 /* try to subtract (r30 a r6) */
+       blti    r31, mod_too_small
+       /* move the r31 to mod since the result was positive */
+       or      r3, r0, r31
+       addik   r30, r30, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r30, r30, r30 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bgei    r28, return_here
+       brid    return_here
+       rsubi   r3, r3, 0 /* negate the result */
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 [both mod as well as div are 0] */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r28, r1, 0
+       lwi     r29, r1, 4
+       lwi     r30, r1, 8
+       lwi     r31, r1, 12
+       rtsd    r15, 8
+       addik   r1, r1, 16
+
+.size __modsi3,  . - __modsi3
+.end __modsi3
diff --git a/arch/microblaze/lib/muldi3.S b/arch/microblaze/lib/muldi3.S
new file mode 100644 (file)
index 0000000..ceeaa8c
--- /dev/null
@@ -0,0 +1,121 @@
+#include <linux/linkage.h>
+
+/*
+ * Multiply operation for 64 bit integers, for devices with hard multiply
+ *     Input : Operand1[H] in Reg r5
+ *             Operand1[L] in Reg r6
+ *             Operand2[H] in Reg r7
+ *             Operand2[L] in Reg r8
+ *     Output: Result[H] in Reg r3
+ *             Result[L] in Reg r4
+ *
+ * Explaination:
+ *
+ *     Both the input numbers are divided into 16 bit number as follows
+ *             op1 = A B C D
+ *             op2 = E F G H
+ *     result = D * H
+ *              + (C * H + D * G) << 16
+ *              + (B * H + C * G + D * F) << 32
+ *              + (A * H + B * G + C * F + D * E) << 48
+ *
+ *     Only 64 bits of the output are considered
+ */
+
+       .text
+       .globl  __muldi3
+       .type __muldi3, @function
+       .ent __muldi3
+
+__muldi3:
+       addi    r1, r1, -40
+
+/* Save the input operands on the caller's stack */
+       swi     r5, r1, 44
+       swi     r6, r1, 48
+       swi     r7, r1, 52
+       swi     r8, r1, 56
+
+/* Store all the callee saved registers */
+       sw      r20, r1, r0
+       swi     r21, r1, 4
+       swi     r22, r1, 8
+       swi     r23, r1, 12
+       swi     r24, r1, 16
+       swi     r25, r1, 20
+       swi     r26, r1, 24
+       swi     r27, r1, 28
+
+/* Load all the 16 bit values for A thru H */
+       lhui    r20, r1, 44 /* A */
+       lhui    r21, r1, 46 /* B */
+       lhui    r22, r1, 48 /* C */
+       lhui    r23, r1, 50 /* D */
+       lhui    r24, r1, 52 /* E */
+       lhui    r25, r1, 54 /* F */
+       lhui    r26, r1, 56 /* G */
+       lhui    r27, r1, 58 /* H */
+
+/* D * H ==> LSB of the result on stack ==> Store1 */
+       mul     r9, r23, r27
+       swi     r9, r1, 36 /* Pos2 and Pos3 */
+
+/* Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2 */
+/* Store the carry generated in position 2 for Pos 3 */
+       lhui    r11, r1, 36 /* Pos2 */
+       mul     r9, r22, r27 /* C * H */
+       mul     r10, r23, r26 /* D * G */
+       add     r9, r9, r10
+       addc    r12, r0, r0
+       add     r9, r9, r11
+       addc    r12, r12, r0 /* Store the Carry */
+       shi     r9, r1, 36 /* Store Pos2 */
+       swi     r9, r1, 32
+       lhui    r11, r1, 32
+       shi     r11, r1, 34 /* Store Pos1 */
+
+/* Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1 */
+       mul     r9, r21, r27 /* B * H */
+       mul     r10, r22, r26 /* C * G */
+       mul     r7, r23, r25 /* D * F */
+       add     r9, r9, r11
+       add     r9, r9, r10
+       add     r9, r9, r7
+       swi     r9, r1, 32 /* Pos0 and Pos1 */
+
+/* Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0 */
+       lhui    r11, r1, 32 /* Pos0 */
+       mul     r9, r20, r27 /* A * H */
+       mul     r10, r21, r26 /* B * G */
+       mul     r7, r22, r25 /* C * F */
+       mul     r8, r23, r24 /* D * E */
+       add     r9, r9, r11
+       add     r9, r9, r10
+       add     r9, r9, r7
+       add     r9, r9, r8
+       sext16  r9, r9 /* Sign extend the MSB */
+       shi     r9, r1, 32
+
+/* Move results to r3 and r4 */
+       lhui    r3, r1, 32
+       add     r3, r3, r12
+       shi     r3, r1, 32
+       lwi     r3, r1, 32 /* Hi Part */
+       lwi     r4, r1, 36 /* Lo Part */
+
+/* Restore Callee saved registers */
+       lw      r20, r1, r0
+       lwi     r21, r1, 4
+       lwi     r22, r1, 8
+       lwi     r23, r1, 12
+       lwi     r24, r1, 16
+       lwi     r25, r1, 20
+       lwi     r26, r1, 24
+       lwi     r27, r1, 28
+
+/* Restore Frame and return */
+       rtsd    r15, 8
+       addi    r1, r1, 40
+
+.size __muldi3, . - __muldi3
+.end __muldi3
diff --git a/arch/microblaze/lib/mulsi3.S b/arch/microblaze/lib/mulsi3.S
new file mode 100644 (file)
index 0000000..90bd7b9
--- /dev/null
@@ -0,0 +1,46 @@
+#include <linux/linkage.h>
+
+/*
+ * Multiply operation for 32 bit integers.
+ *     Input : Operand1 in Reg r5
+ *             Operand2 in Reg r6
+ *     Output: Result [op1 * op2] in Reg r3
+ */
+       .text
+       .globl  __mulsi3
+       .type __mulsi3,  @function
+       .ent __mulsi3
+
+__mulsi3:
+       .frame  r1, 0, r15
+       add     r3, r0, r0
+       beqi    r5, result_is_zero /* multiply by zero */
+       beqi    r6, result_is_zero /* multiply by zero */
+       bgeid   r5, r5_pos
+       xor     r4, r5, r6 /* get the sign of the result */
+       rsubi   r5, r5, 0 /* make r5 positive */
+r5_pos:
+       bgei    r6, r6_pos
+       rsubi   r6, r6, 0 /* make r6 positive */
+r6_pos:
+       bri     l1
+l2:
+       add     r5, r5, r5
+l1:
+       srl     r6, r6
+       addc    r7, r0, r0
+       beqi    r7, l2
+       bneid   r6, l2
+       add     r3, r3, r5
+       blti    r4, negateresult
+       rtsd    r15, 8
+       nop
+negateresult:
+       rtsd    r15, 8
+       rsub    r3, r3, r0
+result_is_zero:
+       rtsd    r15, 8
+       addi    r3, r0, 0
+
+.size __mulsi3,  . - __mulsi3
+.end __mulsi3
diff --git a/arch/microblaze/lib/udivsi3.S b/arch/microblaze/lib/udivsi3.S
new file mode 100644 (file)
index 0000000..64cf57e
--- /dev/null
@@ -0,0 +1,84 @@
+#include <linux/linkage.h>
+
+/*
+* Unsigned divide operation.
+*      Input : Divisor in Reg r5
+*              Dividend in Reg r6
+*      Output: Result in Reg r3
+*/
+
+       .text
+       .globl  __udivsi3
+       .type __udivsi3, @function
+       .ent __udivsi3
+
+__udivsi3:
+
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -12
+       swi     r29, r1, 0
+       swi     r30, r1, 4
+       swi     r31, r1, 8
+
+       beqi    r6, div_by_zero /* div_by_zero /* division error */
+       beqid   r5, result_is_zero /* result is zero */
+       addik   r30, r0, 0 /* clear mod */
+       addik   r29, r0, 32 /* initialize the loop count */
+
+/* check if r6 and r5 are equal - if yes, return 1 */
+       rsub    r18, r5, r6
+       beqid   r18, return_here
+       addik   r3, r0, 1
+
+/* check if (uns)r6 is greater than (uns)r5. in that case, just return 0 */
+       xor     r18, r5, r6
+       bgeid   r18, 16
+       add     r3, r0, r0 /* we would anyways clear r3 */
+       blti    r6, return_here /* r6[bit 31 = 1] hence is greater */
+       bri     checkr6
+       rsub    r18, r6, r5 /* microblazecmp */
+       blti    r18, return_here
+
+/* if r6 [bit 31] is set, then return result as 1 */
+checkr6:
+       bgti    r6, div0
+       brid    return_here
+       addik   r3, r0, 1
+
+/* first part try to find the first '1' in the r5 */
+div0:
+       blti    r5, div2
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgtid   r5, div1
+       addik   r29, r29, -1
+div2:
+/* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r30, r30, r30 /* move that bit into the mod register */
+       rsub    r31, r6, r30 /* try to subtract (r30 a r6) */
+       blti    r31, mod_too_small
+/* move the r31 to mod since the result was positive */
+       or      r30, r0, r31
+       addik   r3, r3, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r3, r3, r3 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bri     return_here
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r29, r1, 0
+       lwi     r30, r1, 4
+       lwi     r31, r1, 8
+       rtsd    r15, 8
+       addik   r1, r1, 12
+
+.size __udivsi3, . - __udivsi3
+.end __udivsi3
diff --git a/arch/microblaze/lib/umodsi3.S b/arch/microblaze/lib/umodsi3.S
new file mode 100644 (file)
index 0000000..17d16ba
--- /dev/null
@@ -0,0 +1,86 @@
+#include <linux/linkage.h>
+
+/*
+ * Unsigned modulo operation for 32 bit integers.
+ *     Input : op1 in Reg r5
+ *             op2 in Reg r6
+ *     Output: op1 mod op2 in Reg r3
+ */
+
+       .text
+       .globl  __umodsi3
+       .type __umodsi3, @function
+       .ent __umodsi3
+
+__umodsi3:
+       .frame  r1, 0, r15
+
+       addik   r1, r1, -12
+       swi     r29, r1, 0
+       swi     r30, r1, 4
+       swi     r31, r1, 8
+
+       beqi    r6, div_by_zero /* div_by_zero - division error */
+       beqid   r5, result_is_zero /* result is zero */
+       addik   r3, r0, 0 /* clear div */
+       addik   r30, r0, 0 /* clear mod */
+       addik   r29, r0, 32 /* initialize the loop count */
+
+/* check if r6 and r5 are equal /* if yes, return 0 */
+       rsub    r18, r5, r6
+       beqi    r18, return_here
+
+/* check if (uns)r6 is greater than (uns)r5. in that case, just return r5 */
+       xor     r18, r5, r6
+       bgeid   r18, 16
+       addik   r3, r5, 0
+       blti    r6, return_here
+       bri     $lcheckr6
+       rsub    r18, r5, r6 /* microblazecmp */
+       bgti    r18, return_here
+
+/* if r6 [bit 31] is set, then return result as r5-r6 */
+$lcheckr6:
+       bgtid   r6, div0
+       addik   r3, r0, 0
+       addik   r18, r0, 0x7fffffff
+       and     r5, r5, r18
+       and     r6, r6, r18
+       brid    return_here
+       rsub    r3, r6, r5
+/* first part: try to find the first '1' in the r5 */
+div0:
+       blti    r5, div2
+div1:
+       add     r5, r5, r5 /* left shift logical r5 */
+       bgeid   r5, div1
+       addik   r29, r29, -1
+div2:
+       /* left shift logical r5 get the '1' into the carry */
+       add     r5, r5, r5
+       addc    r3, r3, r3 /* move that bit into the mod register */
+       rsub    r31, r6, r3 /* try to subtract (r3 a r6) */
+       blti    r31, mod_too_small
+       /* move the r31 to mod since the result was positive */
+       or      r3, r0, r31
+       addik   r30, r30, 1
+mod_too_small:
+       addik   r29, r29, -1
+       beqi    r29, loop_end
+       add     r30, r30, r30 /* shift in the '1' into div */
+       bri     div2 /* div2 */
+loop_end:
+       bri     return_here
+div_by_zero:
+result_is_zero:
+       or      r3, r0, r0 /* set result to 0 */
+return_here:
+/* restore values of csrs and that of r3 and the divisor and the dividend */
+       lwi     r29, r1, 0
+       lwi     r30, r1, 4
+       lwi     r31, r1, 8
+       rtsd    r15, 8
+       addik   r1, r1, 12
+
+.size __umodsi3, . - __umodsi3
+.end __umodsi3
index 55ef532..e363615 100644 (file)
@@ -60,21 +60,6 @@ struct dma_map_ops *get_pci_dma_ops(void)
 }
 EXPORT_SYMBOL(get_pci_dma_ops);
 
-int pci_set_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       return dma_set_mask(&dev->dev, mask);
-}
-
-int pci_set_consistent_dma_mask(struct pci_dev *dev, u64 mask)
-{
-       int rc;
-
-       rc = dma_set_mask(&dev->dev, mask);
-       dev->dev.coherent_dma_mask = dev->dma_mask;
-
-       return rc;
-}
-
 struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
 {
        struct pci_controller *phb;
@@ -1075,8 +1060,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
                 bus->number, bus->self ? pci_name(bus->self) : "PHB");
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
-               struct dev_archdata *sd = &dev->dev.archdata;
-
                /* Setup OF node pointer in archdata */
                dev->dev.of_node = pci_device_to_OF_node(dev);
 
@@ -1086,8 +1069,8 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus)
                set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
 
                /* Hook up default DMA ops */
-               sd->dma_ops = pci_dma_ops;
-               sd->dma_data = (void *)PCI_DRAM_OFFSET;
+               set_dma_ops(&dev->dev, pci_dma_ops);
+               dev->dev.archdata.dma_data = (void *)PCI_DRAM_OFFSET;
 
                /* Read default IRQs and fixup if necessary */
                pci_read_irq_line(dev);
index 2d5c417..3f85df2 100644 (file)
@@ -85,6 +85,7 @@
                        xlnx,dynamic-bus-sizing = <0x1>;
                        xlnx,edge-is-positive = <0x1>;
                        xlnx,family = "virtex5";
+                       xlnx,endianness = <0x1>;
                        xlnx,fpu-exception = <0x1>;
                        xlnx,fsl-data-size = <0x20>;
                        xlnx,fsl-exception = <0x0>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "xlnx,compound";
+                       ranges ;
                        ethernet@81c00000 {
                                compatible = "xlnx,xps-ll-temac-1.01.b", "xlnx,xps-ll-temac-1.00.a";
                                device_type = "network";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        compatible = "xlnx,mpmc-4.02.a";
+                       ranges ;
                        PIM3: sdma@84600180 {
                                compatible = "xlnx,ll-dma-1.00.a";
                                interrupt-parent = <&xps_intc_0>;
index 5b89b58..b9529ca 100644 (file)
@@ -17,9 +17,6 @@
 
 static struct of_device_id xilinx_of_bus_ids[] __initdata = {
        { .compatible = "simple-bus", },
-       { .compatible = "xlnx,plb-v46-1.00.a", },
-       { .compatible = "xlnx,opb-v20-1.10.c", },
-       { .compatible = "xlnx,opb-v20-1.10.b", },
        { .compatible = "xlnx,compound", },
        {}
 };
index 75753ca..77e6440 100644 (file)
@@ -45,18 +45,12 @@ extern pte_t *pkmap_page_table;
 extern void * kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
 
-extern void *__kmap(struct page *page);
-extern void __kunmap(struct page *page);
-extern void *__kmap_atomic(struct page *page, enum km_type type);
-extern void __kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-extern void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
-extern struct page *__kmap_atomic_to_page(void *ptr);
-
-#define kmap                   __kmap
-#define kunmap                 __kunmap
-#define kmap_atomic            __kmap_atomic
-#define kunmap_atomic_notypecheck              __kunmap_atomic_notypecheck
-#define kmap_atomic_to_page    __kmap_atomic_to_page
+extern void *kmap(struct page *page);
+extern void kunmap(struct page *page);
+extern void *__kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
+extern void *kmap_atomic_pfn(unsigned long pfn);
+extern struct page *kmap_atomic_to_page(void *ptr);
 
 #define flush_cache_kmaps()    flush_cache_all()
 
index ae90412..8a153d2 100644 (file)
@@ -154,10 +154,7 @@ pfn_pte(unsigned long pfn, pgprot_t prot)
 
 #define pte_offset_map(dir, address)                                    \
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address)                             \
-       ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
 #define pte_unmap(pte) ((void)(pte))
-#define pte_unmap_nested(pte) ((void)(pte))
 
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
 
index 1be4b0f..f008960 100644 (file)
@@ -257,10 +257,7 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address)
        ((pte_t *) pmd_page_vaddr(*(dir)) + __pte_offset(address))
 #define pte_offset_map(dir, address)                                   \
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address)                            \
-       ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
 #define pte_unmap(pte) ((void)(pte))
-#define pte_unmap_nested(pte) ((void)(pte))
 
 /*
  * Initialize a new pgd / pmd table with invalid pointers.
index 6a2b1bf..1e69b1f 100644 (file)
@@ -9,7 +9,7 @@ static pte_t *kmap_pte;
 
 unsigned long highstart_pfn, highend_pfn;
 
-void *__kmap(struct page *page)
+void *kmap(struct page *page)
 {
        void *addr;
 
@@ -21,16 +21,16 @@ void *__kmap(struct page *page)
 
        return addr;
 }
-EXPORT_SYMBOL(__kmap);
+EXPORT_SYMBOL(kmap);
 
-void __kunmap(struct page *page)
+void kunmap(struct page *page)
 {
        BUG_ON(in_interrupt());
        if (!PageHighMem(page))
                return;
        kunmap_high(page);
 }
-EXPORT_SYMBOL(__kunmap);
+EXPORT_SYMBOL(kunmap);
 
 /*
  * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
@@ -41,17 +41,17 @@ EXPORT_SYMBOL(__kunmap);
  * kmaps are appropriate for short, tight code paths only.
  */
 
-void *__kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
-       enum fixed_addresses idx;
        unsigned long vaddr;
+       int idx, type;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
        pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
-       debug_kmap_atomic(type);
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -64,43 +64,47 @@ void *__kmap_atomic(struct page *page, enum km_type type)
 }
 EXPORT_SYMBOL(__kmap_atomic);
 
-void __kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+       int type;
 
        if (vaddr < FIXADDR_START) { // FIXME
                pagefault_enable();
                return;
        }
 
-       BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+       type = kmap_atomic_idx_pop();
+#ifdef CONFIG_DEBUG_HIGHMEM
+       {
+               int idx = type + KM_TYPE_NR * smp_processor_id();
 
-       /*
-        * force other mappings to Oops if they'll try to access
-        * this pte without first remap it
-        */
-       pte_clear(&init_mm, vaddr, kmap_pte-idx);
-       local_flush_tlb_one(vaddr);
-#endif
+               BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
 
+               /*
+                * force other mappings to Oops if they'll try to access
+                * this pte without first remap it
+                */
+               pte_clear(&init_mm, vaddr, kmap_pte-idx);
+               local_flush_tlb_one(vaddr);
+       }
+#endif
        pagefault_enable();
 }
-EXPORT_SYMBOL(__kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
 /*
  * This is the same as kmap_atomic() but can map memory that doesn't
  * have a struct page associated with it.
  */
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-       enum fixed_addresses idx;
        unsigned long vaddr;
+       int idx, type;
 
        pagefault_disable();
 
-       debug_kmap_atomic(type);
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
        set_pte(kmap_pte-idx, pfn_pte(pfn, PAGE_KERNEL));
@@ -109,7 +113,7 @@ void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
        return (void*) vaddr;
 }
 
-struct page *__kmap_atomic_to_page(void *ptr)
+struct page *kmap_atomic_to_page(void *ptr)
 {
        unsigned long idx, vaddr = (unsigned long)ptr;
        pte_t *pte;
index b0b187a..f577ba2 100644 (file)
@@ -70,15 +70,16 @@ static inline void kunmap(struct page *page)
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-static inline unsigned long kmap_atomic(struct page *page, enum km_type type)
+static inline unsigned long __kmap_atomic(struct page *page)
 {
-       enum fixed_addresses idx;
        unsigned long vaddr;
+       int idx, type;
 
+       pagefault_disable();
        if (page < highmem_start_page)
                return page_address(page);
 
-       debug_kmap_atomic(type);
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR * smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #if HIGHMEM_DEBUG
@@ -91,26 +92,35 @@ static inline unsigned long kmap_atomic(struct page *page, enum km_type type)
        return vaddr;
 }
 
-static inline void kunmap_atomic_notypecheck(unsigned long vaddr, enum km_type type)
+static inline void __kunmap_atomic(unsigned long vaddr)
 {
-#if HIGHMEM_DEBUG
-       enum fixed_addresses idx = type + KM_TYPE_NR * smp_processor_id();
+       int type;
 
-       if (vaddr < FIXADDR_START) /* FIXME */
+       if (vaddr < FIXADDR_START) { /* FIXME */
+               pagefault_enable();
                return;
+       }
 
-       if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx))
-               BUG();
+       type = kmap_atomic_idx_pop();
 
-       /*
-        * force other mappings to Oops if they'll try to access
-        * this pte without first remap it
-        */
-       pte_clear(kmap_pte - idx);
-       __flush_tlb_one(vaddr);
+#if HIGHMEM_DEBUG
+       {
+               unsigned int idx;
+               idx = type + KM_TYPE_NR * smp_processor_id();
+
+               if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx))
+                       BUG();
+
+               /*
+                * force other mappings to Oops if they'll try to access
+                * this pte without first remap it
+                */
+               pte_clear(kmap_pte - idx);
+               __flush_tlb_one(vaddr);
+       }
 #endif
+       pagefault_enable();
 }
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_HIGHMEM_H */
index 16d8857..b049a8b 100644 (file)
@@ -457,9 +457,7 @@ static inline int set_kernel_exec(unsigned long vaddr, int enable)
 
 #define pte_offset_map(dir, address) \
        ((pte_t *) page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte)         do {} while (0)
-#define pte_unmap_nested(pte)  do {} while (0)
 
 /*
  * The MN10300 has external MMU info in the form of a TLB: this is adapted from
index 10549dc..febbeee 100644 (file)
@@ -70,7 +70,7 @@ SECTIONS
        .exit.text : { EXIT_TEXT; }
        .exit.data : { EXIT_DATA; }
 
-  PERCPU(32)
+  PERCPU(PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
index 01c1503..865f37a 100644 (file)
@@ -397,9 +397,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define pte_offset_kernel(pmd, address) \
        ((pte_t *) pmd_page_vaddr(*(pmd)) + pte_index(address))
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
-#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 
 #define pte_unmap(pte)                 do { } while (0)
 #define pte_unmap_nested(pte)          do { } while (0)
index d10d64a..dbc2640 100644 (file)
@@ -60,9 +60,8 @@ extern pte_t *pkmap_page_table;
 
 extern void *kmap_high(struct page *page);
 extern void kunmap_high(struct page *page);
-extern void *kmap_atomic_prot(struct page *page, enum km_type type,
-                             pgprot_t prot);
-extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
+extern void *kmap_atomic_prot(struct page *page, pgprot_t prot);
+extern void __kunmap_atomic(void *kvaddr);
 
 static inline void *kmap(struct page *page)
 {
@@ -80,9 +79,9 @@ static inline void kunmap(struct page *page)
        kunmap_high(page);
 }
 
-static inline void *kmap_atomic(struct page *page, enum km_type type)
+static inline void *__kmap_atomic(struct page *page)
 {
-       return kmap_atomic_prot(page, type, kmap_prot);
+       return kmap_atomic_prot(page, kmap_prot);
 }
 
 static inline struct page *kmap_atomic_to_page(void *ptr)
index a7db96f..47edde8 100644 (file)
@@ -308,12 +308,8 @@ static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry)
 #define pte_offset_kernel(dir, addr)   \
        ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir, addr)              \
-       ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE0) + pte_index(addr))
-#define pte_offset_map_nested(dir, addr)       \
-       ((pte_t *) kmap_atomic(pmd_page(*(dir)), KM_PTE1) + pte_index(addr))
-
-#define pte_unmap(pte)         kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte)  kunmap_atomic(pte, KM_PTE1)
+       ((pte_t *) kmap_atomic(pmd_page(*(dir))) + pte_index(addr))
+#define pte_unmap(pte)         kunmap_atomic(pte)
 
 /*
  * Encode and decode a swap entry.
index 4986504..2b09cd5 100644 (file)
   (((pte_t *) pmd_page_vaddr(*(dir))) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
 
 #define pte_offset_map(dir,addr)       pte_offset_kernel((dir), (addr))
-#define pte_offset_map_nested(dir,addr)        pte_offset_kernel((dir), (addr))
 #define pte_unmap(pte)                 do { } while(0)
-#define pte_unmap_nested(pte)          do { } while(0)
 
 /* to find an entry in a kernel page-table-directory */
 /* This now only contains the vmalloc pages */
index d692989..441d2a7 100644 (file)
@@ -238,9 +238,7 @@ static inline void vio_cmo_dealloc(struct vio_dev *viodev, size_t size)
         * memory in this pool does not change.
         */
        if (spare_needed && reserve_freed) {
-               tmp = min(spare_needed, min(reserve_freed,
-                                           (viodev->cmo.entitled -
-                                            VIO_CMO_MIN_ENT)));
+               tmp = min3(spare_needed, reserve_freed, (viodev->cmo.entitled - VIO_CMO_MIN_ENT));
 
                vio_cmo.spare += tmp;
                viodev->cmo.entitled -= tmp;
index 857d417..b0848b4 100644 (file)
  * be used in IRQ contexts, so in some (very limited) cases we need
  * it.
  */
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 {
-       unsigned int idx;
        unsigned long vaddr;
+       int idx, type;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
        pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
-       debug_kmap_atomic(type);
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 #ifdef CONFIG_DEBUG_HIGHMEM
@@ -52,26 +52,33 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
 }
 EXPORT_SYMBOL(kmap_atomic_prot);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
+       int type;
 
        if (vaddr < __fix_to_virt(FIX_KMAP_END)) {
                pagefault_enable();
                return;
        }
 
-       BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+       type = kmap_atomic_idx_pop();
 
-       /*
-        * force other mappings to Oops if they'll try to access
-        * this pte without first remap it
-        */
-       pte_clear(&init_mm, vaddr, kmap_pte-idx);
-       local_flush_tlb_page(NULL, vaddr);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       {
+               unsigned int idx;
+
+               idx = type + KM_TYPE_NR * smp_processor_id();
+               BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+
+               /*
+                * force other mappings to Oops if they'll try to access
+                * this pte without first remap it
+                */
+               pte_clear(&init_mm, vaddr, kmap_pte-idx);
+               local_flush_tlb_page(NULL, vaddr);
+       }
 #endif
        pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
index 986dc94..02ace34 100644 (file)
@@ -1094,9 +1094,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long address)
 #define pte_offset(pmd, addr) ((pte_t *) pmd_deref(*(pmd)) + pte_index(addr))
 #define pte_offset_kernel(pmd, address) pte_offset(pmd,address)
 #define pte_offset_map(pmd, address) pte_offset_kernel(pmd, address)
-#define pte_offset_map_nested(pmd, address) pte_offset_kernel(pmd, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 
 /*
  * 31 bit swap entry format:
index ccf38f0..2fd4698 100644 (file)
@@ -88,10 +88,7 @@ static inline void pmd_clear(pmd_t *pmdp)
 
 #define pte_offset_map(dir, address)   \
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
-#define pte_offset_map_nested(dir, address)    \
-       ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset(address))
 #define pte_unmap(pte) ((void)(pte))
-#define pte_unmap_nested(pte) ((void)(pte))
 
 /*
  * Bits 9(_PAGE_PRESENT) and 10(_PAGE_FILE)are taken,
index e172d69..69fdfbf 100644 (file)
@@ -429,10 +429,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 #define pte_offset_kernel(dir, address) \
        ((pte_t *) pmd_page_vaddr(*(dir)) + pte_index(address))
 #define pte_offset_map(dir, address)           pte_offset_kernel(dir, address)
-#define pte_offset_map_nested(dir, address)    pte_offset_kernel(dir, address)
-
 #define pte_unmap(pte)         do { } while (0)
-#define pte_unmap_nested(pte)  do { } while (0)
 
 #ifdef CONFIG_X2TLB
 #define pte_ERROR(e) \
index 0ee4677..10a4811 100644 (file)
@@ -84,9 +84,7 @@ static __inline__ void set_pte(pte_t *pteptr, pte_t pteval)
                ((pte_t *) ((pmd_val(*(dir))) & PAGE_MASK) + pte_index((addr)))
 
 #define pte_offset_map(dir,addr)       pte_offset_kernel(dir, addr)
-#define pte_offset_map_nested(dir,addr)        pte_offset_kernel(dir, addr)
 #define pte_unmap(pte)         do { } while (0)
-#define pte_unmap_nested(pte)  do { } while (0)
 
 #ifndef __ASSEMBLY__
 #define IOBASE_VADDR   0xff000000
index ec23b0a..3d7afbb 100644 (file)
@@ -70,8 +70,8 @@ static inline void kunmap(struct page *page)
        kunmap_high(page);
 }
 
-extern void *kmap_atomic(struct page *page, enum km_type type);
-extern void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
+extern void *__kmap_atomic(struct page *page);
+extern void __kunmap_atomic(void *kvaddr);
 extern struct page *kmap_atomic_to_page(void *vaddr);
 
 #define flush_cache_kmaps()    flush_cache_all()
index 0ece77f..303bd4d 100644 (file)
@@ -304,10 +304,7 @@ BTFIXUPDEF_CALL(pte_t *, pte_offset_kernel, pmd_t *, unsigned long)
  * and sun4c is guaranteed to have no highmem anyway.
  */
 #define pte_offset_map(d, a)           pte_offset_kernel(d,a)
-#define pte_offset_map_nested(d, a)    pte_offset_kernel(d,a)
-
 #define pte_unmap(pte)         do{}while(0)
-#define pte_unmap_nested(pte)  do{}while(0)
 
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
index f5b5fa7..f8dddb7 100644 (file)
@@ -652,9 +652,7 @@ static inline int pte_special(pte_t pte)
         ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
 #define pte_offset_kernel              pte_index
 #define pte_offset_map                 pte_index
-#define pte_offset_map_nested          pte_index
 #define pte_unmap(pte)                 do { } while (0)
-#define pte_unmap_nested(pte)          do { } while (0)
 
 /* Actual page table PTE updates.  */
 extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig);
index e139e9c..5e50c09 100644 (file)
 #include <asm/tlbflush.h>
 #include <asm/fixmap.h>
 
-void *kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
-       unsigned long idx;
        unsigned long vaddr;
+       long idx, type;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
        pagefault_disable();
        if (!PageHighMem(page))
                return page_address(page);
 
-       debug_kmap_atomic(type);
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
 
@@ -63,44 +63,50 @@ void *kmap_atomic(struct page *page, enum km_type type)
 
        return (void*) vaddr;
 }
-EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(__kmap_atomic);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
-#ifdef CONFIG_DEBUG_HIGHMEM
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       unsigned long idx = type + KM_TYPE_NR*smp_processor_id();
+       int type;
 
        if (vaddr < FIXADDR_START) { // FIXME
                pagefault_enable();
                return;
        }
 
-       BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
+       type = kmap_atomic_idx_pop();
 
-/* XXX Fix - Anton */
+#ifdef CONFIG_DEBUG_HIGHMEM
+       {
+               unsigned long idx;
+
+               idx = type + KM_TYPE_NR * smp_processor_id();
+               BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx));
+
+               /* XXX Fix - Anton */
 #if 0
-       __flush_cache_one(vaddr);
+               __flush_cache_one(vaddr);
 #else
-       flush_cache_all();
+               flush_cache_all();
 #endif
 
-       /*
-        * force other mappings to Oops if they'll try to access
-        * this pte without first remap it
-        */
-       pte_clear(&init_mm, vaddr, kmap_pte-idx);
-/* XXX Fix - Anton */
+               /*
+                * force other mappings to Oops if they'll try to access
+                * this pte without first remap it
+                */
+               pte_clear(&init_mm, vaddr, kmap_pte-idx);
+               /* XXX Fix - Anton */
 #if 0
-       __flush_tlb_one(vaddr);
+               __flush_tlb_one(vaddr);
 #else
-       flush_tlb_all();
+               flush_tlb_all();
 #endif
+       }
 #endif
-
        pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
 /* We may be fed a pagetable here by ptep_to_xxx and others. */
 struct page *kmap_atomic_to_page(void *ptr)
index 1eb308c..89cfee0 100644 (file)
@@ -96,6 +96,7 @@ config HVC_TILE
 
 config TILE
        def_bool y
+       select HAVE_KVM if !TILEGX
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_FIND_NEXT_BIT
        select USE_GENERIC_SMP_HELPERS
@@ -236,9 +237,9 @@ choice
          If you are not absolutely sure what you are doing, leave this
          option alone!
 
-       config VMSPLIT_375G
+       config VMSPLIT_3_75G
                bool "3.75G/0.25G user/kernel split (no kernel networking)"
-       config VMSPLIT_35G
+       config VMSPLIT_3_5G
                bool "3.5G/0.5G user/kernel split"
        config VMSPLIT_3G
                bool "3G/1G user/kernel split"
@@ -252,8 +253,8 @@ endchoice
 
 config PAGE_OFFSET
        hex
-       default 0xF0000000 if VMSPLIT_375G
-       default 0xE0000000 if VMSPLIT_35G
+       default 0xF0000000 if VMSPLIT_3_75G
+       default 0xE0000000 if VMSPLIT_3_5G
        default 0xB0000000 if VMSPLIT_3G_OPT
        default 0x80000000 if VMSPLIT_2G
        default 0x40000000 if VMSPLIT_1G
@@ -314,6 +315,15 @@ config HARDWALL
        bool "Hardwall support to allow access to user dynamic network"
        default y
 
+config KERNEL_PL
+       int "Processor protection level for kernel"
+       range 1 2
+       default "1"
+       ---help---
+         This setting determines the processor protection level the
+         kernel will be built to run at.  Generally you should use
+         the default value here.
+
 endmenu  # Tilera-specific configuration
 
 menu "Bus options"
@@ -354,3 +364,5 @@ source "security/Kconfig"
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+source "arch/tile/kvm/Kconfig"
index fd8f6bb..17acce7 100644 (file)
@@ -26,8 +26,9 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH))
   endif
 endif
 
-
+ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"")
 KBUILD_CFLAGS   += $(CONFIG_DEBUG_EXTRA_FLAGS)
+endif
 
 LIBGCC_PATH     := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
@@ -49,6 +50,20 @@ head-y               := arch/tile/kernel/head_$(BITS).o
 libs-y         += arch/tile/lib/
 libs-y         += $(LIBGCC_PATH)
 
-
 # See arch/tile/Kbuild for content of core part of the kernel
 core-y         += arch/tile/
+
+core-$(CONFIG_KVM) += arch/tile/kvm/
+
+ifdef TILERA_ROOT
+INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
+endif
+
+install:
+       install -D -m 755 vmlinux $(INSTALL_PATH)/vmlinux-$(KERNELRELEASE)
+       install -D -m 644 .config $(INSTALL_PATH)/config-$(KERNELRELEASE)
+       install -D -m 644 System.map $(INSTALL_PATH)/System.map-$(KERNELRELEASE)
+
+define archhelp
+       echo '  install         - install kernel into $(INSTALL_PATH)'
+endef
diff --git a/arch/tile/include/arch/sim.h b/arch/tile/include/arch/sim.h
new file mode 100644 (file)
index 0000000..74b7c16
--- /dev/null
@@ -0,0 +1,619 @@
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ *
+ * Provides an API for controlling the simulator at runtime.
+ */
+
+/**
+ * @addtogroup arch_sim
+ * @{
+ *
+ * An API for controlling the simulator at runtime.
+ *
+ * The simulator's behavior can be modified while it is running.
+ * For example, human-readable trace output can be enabled and disabled
+ * around code of interest.
+ *
+ * There are two ways to modify simulator behavior:
+ * programmatically, by calling various sim_* functions, and
+ * interactively, by entering commands like "sim set functional true"
+ * at the tile-monitor prompt.  Typing "sim help" at that prompt provides
+ * a list of interactive commands.
+ *
+ * All interactive commands can also be executed programmatically by
+ * passing a string to the sim_command function.
+ */
+
+#ifndef __ARCH_SIM_H__
+#define __ARCH_SIM_H__
+
+#include <arch/sim_def.h>
+#include <arch/abi.h>
+
+#ifndef __ASSEMBLER__
+
+#include <arch/spr_def.h>
+
+
+/**
+ * Return true if the current program is running under a simulator,
+ * rather than on real hardware.  If running on hardware, other "sim_xxx()"
+ * calls have no useful effect.
+ */
+static inline int
+sim_is_simulator(void)
+{
+  return __insn_mfspr(SPR_SIM_CONTROL) != 0;
+}
+
+
+/**
+ * Checkpoint the simulator state to a checkpoint file.
+ *
+ * The checkpoint file name is either the default or the name specified
+ * on the command line with "--checkpoint-file".
+ */
+static __inline void
+sim_checkpoint(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_CHECKPOINT);
+}
+
+
+/**
+ * Report whether or not various kinds of simulator tracing are enabled.
+ *
+ * @return The bitwise OR of these values:
+ *
+ * SIM_TRACE_CYCLES (--trace-cycles),
+ * SIM_TRACE_ROUTER (--trace-router),
+ * SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
+ * SIM_TRACE_DISASM (--trace-disasm),
+ * SIM_TRACE_STALL_INFO (--trace-stall-info)
+ * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
+ * SIM_TRACE_L2_CACHE (--trace-l2)
+ * SIM_TRACE_LINES (--trace-lines)
+ */
+static __inline unsigned int
+sim_get_tracing(void)
+{
+  return __insn_mfspr(SPR_SIM_CONTROL) & SIM_TRACE_FLAG_MASK;
+}
+
+
+/**
+ * Turn on or off different kinds of simulator tracing.
+ *
+ * @param mask Either one of these special values:
+ *
+ * SIM_TRACE_NONE (turns off tracing),
+ * SIM_TRACE_ALL (turns on all possible tracing).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_TRACE_CYCLES (--trace-cycles),
+ * SIM_TRACE_ROUTER (--trace-router),
+ * SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
+ * SIM_TRACE_DISASM (--trace-disasm),
+ * SIM_TRACE_STALL_INFO (--trace-stall-info)
+ * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
+ * SIM_TRACE_L2_CACHE (--trace-l2)
+ * SIM_TRACE_LINES (--trace-lines)
+ */
+static __inline void
+sim_set_tracing(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_TRACE_SPR_ARG(mask));
+}
+
+
+/**
+ * Request dumping of different kinds of simulator state.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_DUMP_ALL (dump all known state)
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_DUMP_REGS (the register file),
+ * SIM_DUMP_SPRS (the SPRs),
+ * SIM_DUMP_ITLB (the iTLB),
+ * SIM_DUMP_DTLB (the dTLB),
+ * SIM_DUMP_L1I (the L1 I-cache),
+ * SIM_DUMP_L1D (the L1 D-cache),
+ * SIM_DUMP_L2 (the L2 cache),
+ * SIM_DUMP_SNREGS (the switch register file),
+ * SIM_DUMP_SNITLB (the switch iTLB),
+ * SIM_DUMP_SNL1I (the switch L1 I-cache),
+ * SIM_DUMP_BACKTRACE (the current backtrace)
+ */
+static __inline void
+sim_dump(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_DUMP_SPR_ARG(mask));
+}
+
+
+/**
+ * Print a string to the simulator stdout.
+ *
+ * @param str The string to be written; a newline is automatically added.
+ */
+static __inline void
+sim_print_string(const char* str)
+{
+  int i;
+  for (i = 0; str[i] != 0; i++)
+  {
+    __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+                 (str[i] << _SIM_CONTROL_OPERATOR_BITS));
+  }
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+               (SIM_PUTC_FLUSH_STRING << _SIM_CONTROL_OPERATOR_BITS));
+}
+
+
+/**
+ * Execute a simulator command string.
+ *
+ * Type 'sim help' at the tile-monitor prompt to learn what commands
+ * are available.  Note the use of the tile-monitor "sim" command to
+ * pass commands to the simulator.
+ *
+ * The argument to sim_command() does not include the leading "sim"
+ * prefix used at the tile-monitor prompt; for example, you might call
+ * sim_command("trace disasm").
+ */
+static __inline void
+sim_command(const char* str)
+{
+  int c;
+  do
+  {
+    c = *str++;
+    __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_COMMAND |
+                 (c << _SIM_CONTROL_OPERATOR_BITS));
+  }
+  while (c);
+}
+
+
+
+#ifndef __DOXYGEN__
+
+/**
+ * The underlying implementation of "_sim_syscall()".
+ *
+ * We use extra "and" instructions to ensure that all the values
+ * we are passing to the simulator are actually valid in the registers
+ * (i.e. returned from memory) prior to the SIM_CONTROL spr.
+ */
+static __inline int _sim_syscall0(int val)
+{
+  long result;
+  __asm__ __volatile__ ("mtspr SIM_CONTROL, r0"
+                        : "=R00" (result) : "R00" (val));
+  return result;
+}
+
+static __inline int _sim_syscall1(int val, long arg1)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result) : "R00" (val), "R01" (arg1));
+  return result;
+}
+
+static __inline int _sim_syscall2(int val, long arg1, long arg2)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2));
+  return result;
+}
+
+/* Note that _sim_syscall3() and higher are technically at risk of
+   receiving an interrupt right before the mtspr bundle, in which case
+   the register values for arguments 3 and up may still be in flight
+   to the core from a stack frame reload. */
+
+static __inline int _sim_syscall3(int val, long arg1, long arg2, long arg3)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r3, r3 };"
+                        "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2),
+                          "R03" (arg3));
+  return result;
+}
+
+static __inline int _sim_syscall4(int val, long arg1, long arg2, long arg3,
+                                  long arg4)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r3, r4 };"
+                        "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2),
+                          "R03" (arg3), "R04" (arg4));
+  return result;
+}
+
+static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3,
+                                  long arg4, long arg5)
+{
+  long result;
+  __asm__ __volatile__ ("{ and zero, r3, r4; and zero, r5, r5 };"
+                        "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (result)
+                        : "R00" (val), "R01" (arg1), "R02" (arg2),
+                          "R03" (arg3), "R04" (arg4), "R05" (arg5));
+  return result;
+}
+
+
+/**
+ * Make a special syscall to the simulator itself, if running under
+ * simulation. This is used as the implementation of other functions
+ * and should not be used outside this file.
+ *
+ * @param syscall_num The simulator syscall number.
+ * @param nr The number of additional arguments provided.
+ *
+ * @return Varies by syscall.
+ */
+#define _sim_syscall(syscall_num, nr, args...) \
+  _sim_syscall##nr( \
+    ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, args)
+
+
+/* Values for the "access_mask" parameters below. */
+#define SIM_WATCHPOINT_READ    1
+#define SIM_WATCHPOINT_WRITE   2
+#define SIM_WATCHPOINT_EXECUTE 4
+
+
+static __inline int
+sim_add_watchpoint(unsigned int process_id,
+                   unsigned long address,
+                   unsigned long size,
+                   unsigned int access_mask,
+                   unsigned long user_data)
+{
+  return _sim_syscall(SIM_SYSCALL_ADD_WATCHPOINT, 5, process_id,
+                     address, size, access_mask, user_data);
+}
+
+
+static __inline int
+sim_remove_watchpoint(unsigned int process_id,
+                      unsigned long address,
+                      unsigned long size,
+                      unsigned int access_mask,
+                      unsigned long user_data)
+{
+  return _sim_syscall(SIM_SYSCALL_REMOVE_WATCHPOINT, 5, process_id,
+                     address, size, access_mask, user_data);
+}
+
+
+/**
+ * Return value from sim_query_watchpoint.
+ */
+struct SimQueryWatchpointStatus
+{
+  /**
+   * 0 if a watchpoint fired, 1 if no watchpoint fired, or -1 for
+   * error (meaning a bad process_id).
+   */
+  int syscall_status;
+
+  /**
+   * The address of the watchpoint that fired (this is the address
+   * passed to sim_add_watchpoint, not an address within that range
+   * that actually triggered the watchpoint).
+   */
+  unsigned long address;
+
+  /** The arbitrary user_data installed by sim_add_watchpoint. */
+  unsigned long user_data;
+};
+
+
+static __inline struct SimQueryWatchpointStatus
+sim_query_watchpoint(unsigned int process_id)
+{
+  struct SimQueryWatchpointStatus status;
+  long val = SIM_CONTROL_SYSCALL |
+    (SIM_SYSCALL_QUERY_WATCHPOINT << _SIM_CONTROL_OPERATOR_BITS);
+  __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
+                        : "=R00" (status.syscall_status),
+                          "=R01" (status.address),
+                          "=R02" (status.user_data)
+                        : "R00" (val), "R01" (process_id));
+  return status;
+}
+
+
+/* On the simulator, confirm lines have been evicted everywhere. */
+static __inline void
+sim_validate_lines_evicted(unsigned long long pa, unsigned long length)
+{
+#ifdef __LP64__
+  _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 2, pa, length);
+#else
+  _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 4,
+               0 /* dummy */, (long)(pa), (long)(pa >> 32), length);
+#endif
+}
+
+
+#endif /* !__DOXYGEN__ */
+
+
+
+
+/**
+ * Modify the shaping parameters of a shim.
+ *
+ * @param shim The shim to modify. One of:
+ *   SIM_CONTROL_SHAPING_GBE_0
+ *   SIM_CONTROL_SHAPING_GBE_1
+ *   SIM_CONTROL_SHAPING_GBE_2
+ *   SIM_CONTROL_SHAPING_GBE_3
+ *   SIM_CONTROL_SHAPING_XGBE_0
+ *   SIM_CONTROL_SHAPING_XGBE_1
+ *
+ * @param type The type of shaping. This should be the same type of
+ * shaping that is already in place on the shim. One of:
+ *   SIM_CONTROL_SHAPING_MULTIPLIER
+ *   SIM_CONTROL_SHAPING_PPS
+ *   SIM_CONTROL_SHAPING_BPS
+ *
+ * @param units The magnitude of the rate. One of:
+ *   SIM_CONTROL_SHAPING_UNITS_SINGLE
+ *   SIM_CONTROL_SHAPING_UNITS_KILO
+ *   SIM_CONTROL_SHAPING_UNITS_MEGA
+ *   SIM_CONTROL_SHAPING_UNITS_GIGA
+ *
+ * @param rate The rate to which to change it. This must fit in
+ * SIM_CONTROL_SHAPING_RATE_BITS bits or a warning is issued and
+ * the shaping is not changed.
+ *
+ * @return 0 if no problems were detected in the arguments to sim_set_shaping
+ * or 1 if problems were detected (for example, rate does not fit in 17 bits).
+ */
+static __inline int
+sim_set_shaping(unsigned shim,
+                unsigned type,
+                unsigned units,
+                unsigned rate)
+{
+  if ((rate & ~((1 << SIM_CONTROL_SHAPING_RATE_BITS) - 1)) != 0)
+    return 1;
+
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_SHAPING_SPR_ARG(shim, type, units, rate));
+  return 0;
+}
+
+#ifdef __tilegx__
+
+/** Enable a set of mPIPE links.  Pass a -1 link_mask to enable all links. */
+static __inline void
+sim_enable_mpipe_links(unsigned mpipe, unsigned long link_mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL,
+               (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
+                (mpipe << 8) | (1 << 16) | ((uint_reg_t)link_mask << 32)));
+}
+
+/** Disable a set of mPIPE links.  Pass a -1 link_mask to disable all links. */
+static __inline void
+sim_disable_mpipe_links(unsigned mpipe, unsigned long link_mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL,
+               (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
+                (mpipe << 8) | (0 << 16) | ((uint_reg_t)link_mask << 32)));
+}
+
+#endif /* __tilegx__ */
+
+
+/*
+ * An API for changing "functional" mode.
+ */
+
+#ifndef __DOXYGEN__
+
+#define sim_enable_functional() \
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_ENABLE_FUNCTIONAL)
+
+#define sim_disable_functional() \
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_DISABLE_FUNCTIONAL)
+
+#endif /* __DOXYGEN__ */
+
+
+/*
+ * Profiler support.
+ */
+
+/**
+ * Turn profiling on for the current task.
+ *
+ * Note that this has no effect if run in an environment without
+ * profiling support (thus, the proper flags to the simulator must
+ * be supplied).
+ */
+static __inline void
+sim_profiler_enable(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_ENABLE);
+}
+
+
+/** Turn profiling off for the current task. */
+static __inline void
+sim_profiler_disable(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_DISABLE);
+}
+
+
+/**
+ * Turn profiling on or off for the current task.
+ *
+ * @param enabled If true, turns on profiling. If false, turns it off.
+ *
+ * Note that this has no effect if run in an environment without
+ * profiling support (thus, the proper flags to the simulator must
+ * be supplied).
+ */
+static __inline void
+sim_profiler_set_enabled(int enabled)
+{
+  int val =
+    enabled ? SIM_CONTROL_PROFILER_ENABLE : SIM_CONTROL_PROFILER_DISABLE;
+  __insn_mtspr(SPR_SIM_CONTROL, val);
+}
+
+
+/**
+ * Return true if and only if profiling is currently enabled
+ * for the current task.
+ *
+ * This returns false even if sim_profiler_enable() was called
+ * if the current execution environment does not support profiling.
+ */
+static __inline int
+sim_profiler_is_enabled(void)
+{
+  return ((__insn_mfspr(SPR_SIM_CONTROL) & SIM_PROFILER_ENABLED_MASK) != 0);
+}
+
+
+/**
+ * Reset profiling counters to zero for the current task.
+ *
+ * Resetting can be done while profiling is enabled.  It does not affect
+ * the chip-wide profiling counters.
+ */
+static __inline void
+sim_profiler_clear(void)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_CLEAR);
+}
+
+
+/**
+ * Enable specified chip-level profiling counters.
+ *
+ * Does not affect the per-task profiling counters.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_CHIP_ALL (enables all chip-level components).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_CHIP_MEMCTL (enable all memory controllers)
+ * SIM_CHIP_XAUI (enable all XAUI controllers)
+ * SIM_CHIP_MPIPE (enable all MPIPE controllers)
+ */
+static __inline void
+sim_profiler_chip_enable(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask));
+}
+
+
+/**
+ * Disable specified chip-level profiling counters.
+ *
+ * Does not affect the per-task profiling counters.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_CHIP_ALL (disables all chip-level components).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_CHIP_MEMCTL (disable all memory controllers)
+ * SIM_CHIP_XAUI (disable all XAUI controllers)
+ * SIM_CHIP_MPIPE (disable all MPIPE controllers)
+ */
+static __inline void
+sim_profiler_chip_disable(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask));
+}
+
+
+/**
+ * Reset specified chip-level profiling counters to zero.
+ *
+ * Does not affect the per-task profiling counters.
+ *
+ * @param mask Either this special value:
+ *
+ * SIM_CHIP_ALL (clears all chip-level components).
+ *
+ * or the bitwise OR of these values:
+ *
+ * SIM_CHIP_MEMCTL (clear all memory controllers)
+ * SIM_CHIP_XAUI (clear all XAUI controllers)
+ * SIM_CHIP_MPIPE (clear all MPIPE controllers)
+ */
+static __inline void
+sim_profiler_chip_clear(unsigned int mask)
+{
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask));
+}
+
+
+/*
+ * Event support.
+ */
+
+#ifndef __DOXYGEN__
+
+static __inline void
+sim_event_begin(unsigned int x)
+{
+#if defined(__tile__) && !defined(__NO_EVENT_SPR__)
+  __insn_mtspr(SPR_EVENT_BEGIN, x);
+#endif
+}
+
+static __inline void
+sim_event_end(unsigned int x)
+{
+#if defined(__tile__) && !defined(__NO_EVENT_SPR__)
+  __insn_mtspr(SPR_EVENT_END, x);
+#endif
+}
+
+#endif /* !__DOXYGEN__ */
+
+#endif /* !__ASSEMBLER__ */
+
+#endif /* !__ARCH_SIM_H__ */
+
+/** @} */
index 6418fbd..7a17082 100644 (file)
-// 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.
-
-//! @file
-//!
-//! Some low-level simulator definitions.
-//!
+/*
+ * 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.
+ */
+
+/**
+ * @file
+ *
+ * Some low-level simulator definitions.
+ */
 
 #ifndef __ARCH_SIM_DEF_H__
 #define __ARCH_SIM_DEF_H__
 
 
-//! Internal: the low bits of the SIM_CONTROL_* SPR values specify
-//! the operation to perform, and the remaining bits are
-//! an operation-specific parameter (often unused).
-//!
+/**
+ * Internal: the low bits of the SIM_CONTROL_* SPR values specify
+ * the operation to perform, and the remaining bits are
+ * an operation-specific parameter (often unused).
+ */
 #define _SIM_CONTROL_OPERATOR_BITS 8
 
 
-//== Values which can be written to SPR_SIM_CONTROL.
+/*
+ * Values which can be written to SPR_SIM_CONTROL.
+ */
 
-//! If written to SPR_SIM_CONTROL, stops profiling.
-//!
+/** If written to SPR_SIM_CONTROL, stops profiling. */
 #define SIM_CONTROL_PROFILER_DISABLE 0
 
-//! If written to SPR_SIM_CONTROL, starts profiling.
-//!
+/** If written to SPR_SIM_CONTROL, starts profiling. */
 #define SIM_CONTROL_PROFILER_ENABLE 1
 
-//! If written to SPR_SIM_CONTROL, clears profiling counters.
-//!
+/** If written to SPR_SIM_CONTROL, clears profiling counters. */
 #define SIM_CONTROL_PROFILER_CLEAR 2
 
-//! If written to SPR_SIM_CONTROL, checkpoints the simulator.
-//!
+/** If written to SPR_SIM_CONTROL, checkpoints the simulator. */
 #define SIM_CONTROL_CHECKPOINT 3
 
-//! If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
-//! sets the tracing mask to the given mask. See "sim_set_tracing()".
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
+ * sets the tracing mask to the given mask. See "sim_set_tracing()".
+ */
 #define SIM_CONTROL_SET_TRACING 4
 
-//! If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
-//! dumps the requested items of machine state to the log.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mask (shifted by 8),
+ * dumps the requested items of machine state to the log.
+ */
 #define SIM_CONTROL_DUMP 5
 
-//! If written to SPR_SIM_CONTROL, clears chip-level profiling counters.
-//!
+/** If written to SPR_SIM_CONTROL, clears chip-level profiling counters. */
 #define SIM_CONTROL_PROFILER_CHIP_CLEAR 6
 
-//! If written to SPR_SIM_CONTROL, disables chip-level profiling.
-//!
+/** If written to SPR_SIM_CONTROL, disables chip-level profiling. */
 #define SIM_CONTROL_PROFILER_CHIP_DISABLE 7
 
-//! If written to SPR_SIM_CONTROL, enables chip-level profiling.
-//!
+/** If written to SPR_SIM_CONTROL, enables chip-level profiling. */
 #define SIM_CONTROL_PROFILER_CHIP_ENABLE 8
 
-//! If written to SPR_SIM_CONTROL, enables chip-level functional mode
-//!
+/** If written to SPR_SIM_CONTROL, enables chip-level functional mode */
 #define SIM_CONTROL_ENABLE_FUNCTIONAL 9
 
-//! If written to SPR_SIM_CONTROL, disables chip-level functional mode.
-//!
+/** If written to SPR_SIM_CONTROL, disables chip-level functional mode. */
 #define SIM_CONTROL_DISABLE_FUNCTIONAL 10
 
-//! If written to SPR_SIM_CONTROL, enables chip-level functional mode.
-//! All tiles must perform this write for functional mode to be enabled.
-//! Ignored in naked boot mode unless --functional is specified.
-//! WARNING: Only the hypervisor startup code should use this!
-//!
+/**
+ * If written to SPR_SIM_CONTROL, enables chip-level functional mode.
+ * All tiles must perform this write for functional mode to be enabled.
+ * Ignored in naked boot mode unless --functional is specified.
+ * WARNING: Only the hypervisor startup code should use this!
+ */
 #define SIM_CONTROL_ENABLE_FUNCTIONAL_BARRIER 11
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! writes a string directly to the simulator output.  Written to once for
-//! each character in the string, plus a final NUL.  Instead of NUL,
-//! you can also use "SIM_PUTC_FLUSH_STRING" or "SIM_PUTC_FLUSH_BINARY".
-//!
-// ISSUE: Document the meaning of "newline", and the handling of NUL.
-//
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * writes a string directly to the simulator output.  Written to once for
+ * each character in the string, plus a final NUL.  Instead of NUL,
+ * you can also use "SIM_PUTC_FLUSH_STRING" or "SIM_PUTC_FLUSH_BINARY".
+ */
+/* ISSUE: Document the meaning of "newline", and the handling of NUL. */
 #define SIM_CONTROL_PUTC 12
 
-//! If written to SPR_SIM_CONTROL, clears the --grind-coherence state for
-//! this core.  This is intended to be used before a loop that will
-//! invalidate the cache by loading new data and evicting all current data.
-//! Generally speaking, this API should only be used by system code.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, clears the --grind-coherence state for
+ * this core.  This is intended to be used before a loop that will
+ * invalidate the cache by loading new data and evicting all current data.
+ * Generally speaking, this API should only be used by system code.
+ */
 #define SIM_CONTROL_GRINDER_CLEAR 13
 
-//! If written to SPR_SIM_CONTROL, shuts down the simulator.
-//!
+/** If written to SPR_SIM_CONTROL, shuts down the simulator. */
 #define SIM_CONTROL_SHUTDOWN 14
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! indicates that a fork syscall just created the given process.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * indicates that a fork syscall just created the given process.
+ */
 #define SIM_CONTROL_OS_FORK 15
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! indicates that an exit syscall was just executed by the given process.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * indicates that an exit syscall was just executed by the given process.
+ */
 #define SIM_CONTROL_OS_EXIT 16
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! indicates that the OS just switched to the given process.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * indicates that the OS just switched to the given process.
+ */
 #define SIM_CONTROL_OS_SWITCH 17
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that an exec syscall was just executed. Written to once for
-//! each character in the executable name, plus a final NUL.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that an exec syscall was just executed. Written to once for
+ * each character in the executable name, plus a final NUL.
+ */
 #define SIM_CONTROL_OS_EXEC 18
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that an interpreter (PT_INTERP) was loaded.  Written to once
-//! for each character in "ADDR:PATH", plus a final NUL, where "ADDR" is a
-//! hex load address starting with "0x", and "PATH" is the executable name.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that an interpreter (PT_INTERP) was loaded.  Written to once
+ * for each character in "ADDR:PATH", plus a final NUL, where "ADDR" is a
+ * hex load address starting with "0x", and "PATH" is the executable name.
+ */
 #define SIM_CONTROL_OS_INTERP 19
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that a dll was loaded.  Written to once for each character
-//! in "ADDR:PATH", plus a final NUL, where "ADDR" is a hexadecimal load
-//! address starting with "0x", and "PATH" is the executable name.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that a dll was loaded.  Written to once for each character
+ * in "ADDR:PATH", plus a final NUL, where "ADDR" is a hexadecimal load
+ * address starting with "0x", and "PATH" is the executable name.
+ */
 #define SIM_CONTROL_DLOPEN 20
 
-//! If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
-//! indicates that a dll was unloaded.  Written to once for each character
-//! in "ADDR", plus a final NUL, where "ADDR" is a hexadecimal load
-//! address starting with "0x".
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a character (shifted by 8),
+ * indicates that a dll was unloaded.  Written to once for each character
+ * in "ADDR", plus a final NUL, where "ADDR" is a hexadecimal load
+ * address starting with "0x".
+ */
 #define SIM_CONTROL_DLCLOSE 21
 
-//! If written to SPR_SIM_CONTROL, combined with a flag (shifted by 8),
-//! indicates whether to allow data reads to remotely-cached
-//! dirty cache lines to be cached locally without grinder warnings or
-//! assertions (used by Linux kernel fast memcpy).
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a flag (shifted by 8),
+ * indicates whether to allow data reads to remotely-cached
+ * dirty cache lines to be cached locally without grinder warnings or
+ * assertions (used by Linux kernel fast memcpy).
+ */
 #define SIM_CONTROL_ALLOW_MULTIPLE_CACHING 22
 
-//! If written to SPR_SIM_CONTROL, enables memory tracing.
-//!
+/** If written to SPR_SIM_CONTROL, enables memory tracing. */
 #define SIM_CONTROL_ENABLE_MEM_LOGGING 23
 
-//! If written to SPR_SIM_CONTROL, disables memory tracing.
-//!
+/** If written to SPR_SIM_CONTROL, disables memory tracing. */
 #define SIM_CONTROL_DISABLE_MEM_LOGGING 24
 
-//! If written to SPR_SIM_CONTROL, changes the shaping parameters of one of
-//! the gbe or xgbe shims. Must specify the shim id, the type, the units, and
-//! the rate, as defined in SIM_SHAPING_SPR_ARG.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, changes the shaping parameters of one of
+ * the gbe or xgbe shims. Must specify the shim id, the type, the units, and
+ * the rate, as defined in SIM_SHAPING_SPR_ARG.
+ */
 #define SIM_CONTROL_SHAPING 25
 
-//! If written to SPR_SIM_CONTROL, combined with character (shifted by 8),
-//! requests that a simulator command be executed.  Written to once for each
-//! character in the command, plus a final NUL.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with character (shifted by 8),
+ * requests that a simulator command be executed.  Written to once for each
+ * character in the command, plus a final NUL.
+ */
 #define SIM_CONTROL_COMMAND 26
 
-//! If written to SPR_SIM_CONTROL, indicates that the simulated system
-//! is panicking, to allow debugging via --debug-on-panic.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, indicates that the simulated system
+ * is panicking, to allow debugging via --debug-on-panic.
+ */
 #define SIM_CONTROL_PANIC 27
 
-//! If written to SPR_SIM_CONTROL, triggers a simulator syscall.
-//! See "sim_syscall()" for more info.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, triggers a simulator syscall.
+ * See "sim_syscall()" for more info.
+ */
 #define SIM_CONTROL_SYSCALL 32
 
-//! If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
-//! provides the pid that subsequent SIM_CONTROL_OS_FORK writes should
-//! use as the pid, rather than the default previous SIM_CONTROL_OS_SWITCH.
-//!
+/**
+ * If written to SPR_SIM_CONTROL, combined with a pid (shifted by 8),
+ * provides the pid that subsequent SIM_CONTROL_OS_FORK writes should
+ * use as the pid, rather than the default previous SIM_CONTROL_OS_SWITCH.
+ */
 #define SIM_CONTROL_OS_FORK_PARENT 33
 
-//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
-//! (shifted by 8), clears the pending magic data section.  The cleared
-//! pending magic data section and any subsequently appended magic bytes
-//! will only take effect when the classifier blast programmer is run.
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
+ * (shifted by 8), clears the pending magic data section.  The cleared
+ * pending magic data section and any subsequently appended magic bytes
+ * will only take effect when the classifier blast programmer is run.
+ */
 #define SIM_CONTROL_CLEAR_MPIPE_MAGIC_BYTES 34
 
-//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
-//! (shifted by 8) and a byte of data (shifted by 16), appends that byte
-//! to the shim's pending magic data section.  The pending magic data
-//! section takes effect when the classifier blast programmer is run.
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
+ * (shifted by 8) and a byte of data (shifted by 16), appends that byte
+ * to the shim's pending magic data section.  The pending magic data
+ * section takes effect when the classifier blast programmer is run.
+ */
 #define SIM_CONTROL_APPEND_MPIPE_MAGIC_BYTE 35
 
-//! If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
-//! (shifted by 8), an enable=1/disable=0 bit (shifted by 16), and a
-//! mask of links (shifted by 32), enable or disable the corresponding
-//! mPIPE links.
+/**
+ * If written to SPR_SIM_CONTROL, combined with a mPIPE shim number
+ * (shifted by 8), an enable=1/disable=0 bit (shifted by 16), and a
+ * mask of links (shifted by 32), enable or disable the corresponding
+ * mPIPE links.
+ */
 #define SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE 36
 
-//== Syscall numbers for use with "sim_syscall()".
 
-//! Syscall number for sim_add_watchpoint().
-//!
+/*
+ * Syscall numbers for use with "sim_syscall()".
+ */
+
+/** Syscall number for sim_add_watchpoint(). */
 #define SIM_SYSCALL_ADD_WATCHPOINT 2
 
-//! Syscall number for sim_remove_watchpoint().
-//!
+/** Syscall number for sim_remove_watchpoint(). */
 #define SIM_SYSCALL_REMOVE_WATCHPOINT 3
 
-//! Syscall number for sim_query_watchpoint().
-//!
+/** Syscall number for sim_query_watchpoint(). */
 #define SIM_SYSCALL_QUERY_WATCHPOINT 4
 
-//! Syscall number that asserts that the cache lines whose 64-bit PA
-//! is passed as the second argument to sim_syscall(), and over a
-//! range passed as the third argument, are no longer in cache.
-//! The simulator raises an error if this is not the case.
-//!
+/**
+ * Syscall number that asserts that the cache lines whose 64-bit PA
+ * is passed as the second argument to sim_syscall(), and over a
+ * range passed as the third argument, are no longer in cache.
+ * The simulator raises an error if this is not the case.
+ */
 #define SIM_SYSCALL_VALIDATE_LINES_EVICTED 5
 
 
-//== Bit masks which can be shifted by 8, combined with
-//== SIM_CONTROL_SET_TRACING, and written to SPR_SIM_CONTROL.
+/*
+ * Bit masks which can be shifted by 8, combined with
+ * SIM_CONTROL_SET_TRACING, and written to SPR_SIM_CONTROL.
+ */
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Enable --trace-cycle when passed to simulator_set_tracing().
-//!
+/** Enable --trace-cycle when passed to simulator_set_tracing(). */
 #define SIM_TRACE_CYCLES          0x01
 
-//! Enable --trace-router when passed to simulator_set_tracing().
-//!
+/** Enable --trace-router when passed to simulator_set_tracing(). */
 #define SIM_TRACE_ROUTER          0x02
 
-//! Enable --trace-register-writes when passed to simulator_set_tracing().
-//!
+/** Enable --trace-register-writes when passed to simulator_set_tracing(). */
 #define SIM_TRACE_REGISTER_WRITES 0x04
 
-//! Enable --trace-disasm when passed to simulator_set_tracing().
-//!
+/** Enable --trace-disasm when passed to simulator_set_tracing(). */
 #define SIM_TRACE_DISASM          0x08
 
-//! Enable --trace-stall-info when passed to simulator_set_tracing().
-//!
+/** Enable --trace-stall-info when passed to simulator_set_tracing(). */
 #define SIM_TRACE_STALL_INFO      0x10
 
-//! Enable --trace-memory-controller when passed to simulator_set_tracing().
-//!
+/** Enable --trace-memory-controller when passed to simulator_set_tracing(). */
 #define SIM_TRACE_MEMORY_CONTROLLER 0x20
 
-//! Enable --trace-l2 when passed to simulator_set_tracing().
-//!
+/** Enable --trace-l2 when passed to simulator_set_tracing(). */
 #define SIM_TRACE_L2_CACHE 0x40
 
-//! Enable --trace-lines when passed to simulator_set_tracing().
-//!
+/** Enable --trace-lines when passed to simulator_set_tracing(). */
 #define SIM_TRACE_LINES 0x80
 
-//! Turn off all tracing when passed to simulator_set_tracing().
-//!
+/** Turn off all tracing when passed to simulator_set_tracing(). */
 #define SIM_TRACE_NONE 0
 
-//! Turn on all tracing when passed to simulator_set_tracing().
-//!
+/** Turn on all tracing when passed to simulator_set_tracing(). */
 #define SIM_TRACE_ALL (-1)
 
-//! @}
+/** @} */
 
-//! Computes the value to write to SPR_SIM_CONTROL to set tracing flags.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to set tracing flags. */
 #define SIM_TRACE_SPR_ARG(mask) \
   (SIM_CONTROL_SET_TRACING | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
 
-//== Bit masks which can be shifted by 8, combined with
-//== SIM_CONTROL_DUMP, and written to SPR_SIM_CONTROL.
+/*
+ * Bit masks which can be shifted by 8, combined with
+ * SIM_CONTROL_DUMP, and written to SPR_SIM_CONTROL.
+ */
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Dump the general-purpose registers.
-//!
+/** Dump the general-purpose registers. */
 #define SIM_DUMP_REGS          0x001
 
-//! Dump the SPRs.
-//!
+/** Dump the SPRs. */
 #define SIM_DUMP_SPRS          0x002
 
-//! Dump the ITLB.
-//!
+/** Dump the ITLB. */
 #define SIM_DUMP_ITLB          0x004
 
-//! Dump the DTLB.
-//!
+/** Dump the DTLB. */
 #define SIM_DUMP_DTLB          0x008
 
-//! Dump the L1 I-cache.
-//!
+/** Dump the L1 I-cache. */
 #define SIM_DUMP_L1I           0x010
 
-//! Dump the L1 D-cache.
-//!
+/** Dump the L1 D-cache. */
 #define SIM_DUMP_L1D           0x020
 
-//! Dump the L2 cache.
-//!
+/** Dump the L2 cache. */
 #define SIM_DUMP_L2            0x040
 
-//! Dump the switch registers.
-//!
+/** Dump the switch registers. */
 #define SIM_DUMP_SNREGS        0x080
 
-//! Dump the switch ITLB.
-//!
+/** Dump the switch ITLB. */
 #define SIM_DUMP_SNITLB        0x100
 
-//! Dump the switch L1 I-cache.
-//!
+/** Dump the switch L1 I-cache. */
 #define SIM_DUMP_SNL1I         0x200
 
-//! Dump the current backtrace.
-//!
+/** Dump the current backtrace. */
 #define SIM_DUMP_BACKTRACE     0x400
 
-//! Only dump valid lines in caches.
-//!
+/** Only dump valid lines in caches. */
 #define SIM_DUMP_VALID_LINES   0x800
 
-//! Dump everything that is dumpable.
-//!
+/** Dump everything that is dumpable. */
 #define SIM_DUMP_ALL (-1 & ~SIM_DUMP_VALID_LINES)
 
-// @}
+/** @} */
 
-//! Computes the value to write to SPR_SIM_CONTROL to dump machine state.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to dump machine state. */
 #define SIM_DUMP_SPR_ARG(mask) \
   (SIM_CONTROL_DUMP | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
 
-//== Bit masks which can be shifted by 8, combined with
-//== SIM_CONTROL_PROFILER_CHIP_xxx, and written to SPR_SIM_CONTROL.
+/*
+ * Bit masks which can be shifted by 8, combined with
+ * SIM_CONTROL_PROFILER_CHIP_xxx, and written to SPR_SIM_CONTROL.
+ */
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the memory controllers.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the memory controllers. */
 #define SIM_CHIP_MEMCTL        0x001
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the XAUI interface.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the XAUI interface. */
 #define SIM_CHIP_XAUI          0x002
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the PCIe interface.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the PCIe interface. */
 #define SIM_CHIP_PCIE          0x004
 
-//! Use with with SIM_PROFILER_CHIP_xxx to control the MPIPE interface.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the MPIPE interface. */
 #define SIM_CHIP_MPIPE         0x008
 
-//! Reference all chip devices.
-//!
+/** Use with with SIM_PROFILER_CHIP_xxx to control the TRIO interface. */
+#define SIM_CHIP_TRIO          0x010
+
+/** Reference all chip devices. */
 #define SIM_CHIP_ALL (-1)
 
-//! @}
+/** @} */
 
-//! Computes the value to write to SPR_SIM_CONTROL to clear chip statistics.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to clear chip statistics. */
 #define SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask) \
   (SIM_CONTROL_PROFILER_CHIP_CLEAR | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
-//! Computes the value to write to SPR_SIM_CONTROL to disable chip statistics.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to disable chip statistics.*/
 #define SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask) \
   (SIM_CONTROL_PROFILER_CHIP_DISABLE | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
-//! Computes the value to write to SPR_SIM_CONTROL to enable chip statistics.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to enable chip statistics. */
 #define SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask) \
   (SIM_CONTROL_PROFILER_CHIP_ENABLE | ((mask) << _SIM_CONTROL_OPERATOR_BITS))
 
 
 
-// Shim bitrate controls.
+/* Shim bitrate controls. */
 
-//! The number of bits used to store the shim id.
-//!
+/** The number of bits used to store the shim id. */
 #define SIM_CONTROL_SHAPING_SHIM_ID_BITS 3
 
-//! @addtogroup arch_sim
-//! @{
+/**
+ * @addtogroup arch_sim
+ * @{
+ */
 
-//! Change the gbe 0 bitrate.
-//!
+/** Change the gbe 0 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_0 0x0
 
-//! Change the gbe 1 bitrate.
-//!
+/** Change the gbe 1 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_1 0x1
 
-//! Change the gbe 2 bitrate.
-//!
+/** Change the gbe 2 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_2 0x2
 
-//! Change the gbe 3 bitrate.
-//!
+/** Change the gbe 3 bitrate. */
 #define SIM_CONTROL_SHAPING_GBE_3 0x3
 
-//! Change the xgbe 0 bitrate.
-//!
+/** Change the xgbe 0 bitrate. */
 #define SIM_CONTROL_SHAPING_XGBE_0 0x4
 
-//! Change the xgbe 1 bitrate.
-//!
+/** Change the xgbe 1 bitrate. */
 #define SIM_CONTROL_SHAPING_XGBE_1 0x5
 
-//! The type of shaping to do.
-//!
+/** The type of shaping to do. */
 #define SIM_CONTROL_SHAPING_TYPE_BITS 2
 
-//! Control the multiplier.
-//!
+/** Control the multiplier. */
 #define SIM_CONTROL_SHAPING_MULTIPLIER 0
 
-//! Control the PPS.
-//!
+/** Control the PPS. */
 #define SIM_CONTROL_SHAPING_PPS 1
 
-//! Control the BPS.
-//!
+/** Control the BPS. */
 #define SIM_CONTROL_SHAPING_BPS 2
 
-//! The number of bits for the units for the shaping parameter.
-//!
+/** The number of bits for the units for the shaping parameter. */
 #define SIM_CONTROL_SHAPING_UNITS_BITS 2
 
-//! Provide a number in single units.
-//!
+/** Provide a number in single units. */
 #define SIM_CONTROL_SHAPING_UNITS_SINGLE 0
 
-//! Provide a number in kilo units.
-//!
+/** Provide a number in kilo units. */
 #define SIM_CONTROL_SHAPING_UNITS_KILO 1
 
-//! Provide a number in mega units.
-//!
+/** Provide a number in mega units. */
 #define SIM_CONTROL_SHAPING_UNITS_MEGA 2
 
-//! Provide a number in giga units.
-//!
+/** Provide a number in giga units. */
 #define SIM_CONTROL_SHAPING_UNITS_GIGA 3
 
-// @}
+/** @} */
 
-//! How many bits are available for the rate.
-//!
+/** How many bits are available for the rate. */
 #define SIM_CONTROL_SHAPING_RATE_BITS \
   (32 - (_SIM_CONTROL_OPERATOR_BITS + \
          SIM_CONTROL_SHAPING_SHIM_ID_BITS + \
          SIM_CONTROL_SHAPING_TYPE_BITS + \
          SIM_CONTROL_SHAPING_UNITS_BITS))
 
-//! Computes the value to write to SPR_SIM_CONTROL to change a bitrate.
-//!
+/** Computes the value to write to SPR_SIM_CONTROL to change a bitrate. */
 #define SIM_SHAPING_SPR_ARG(shim, type, units, rate) \
   (SIM_CONTROL_SHAPING | \
    ((shim) | \
                SIM_CONTROL_SHAPING_UNITS_BITS))) << _SIM_CONTROL_OPERATOR_BITS)
 
 
-//== Values returned when reading SPR_SIM_CONTROL.
-// ISSUE: These names should share a longer common prefix.
+/*
+ * Values returned when reading SPR_SIM_CONTROL.
+ * ISSUE: These names should share a longer common prefix.
+ */
 
-//! When reading SPR_SIM_CONTROL, the mask of simulator tracing bits
-//! (SIM_TRACE_xxx values).
-//!
+/**
+ * When reading SPR_SIM_CONTROL, the mask of simulator tracing bits
+ * (SIM_TRACE_xxx values).
+ */
 #define SIM_TRACE_FLAG_MASK 0xFFFF
 
-//! When reading SPR_SIM_CONTROL, the mask for whether profiling is enabled.
-//!
+/** When reading SPR_SIM_CONTROL, the mask for whether profiling is enabled. */
 #define SIM_PROFILER_ENABLED_MASK 0x10000
 
 
-//== Special arguments for "SIM_CONTROL_PUTC".
+/*
+ * Special arguments for "SIM_CONTROL_PUTC".
+ */
 
-//! Flag value for forcing a PUTC string-flush, including
-//! coordinate/cycle prefix and newline.
-//!
+/**
+ * Flag value for forcing a PUTC string-flush, including
+ * coordinate/cycle prefix and newline.
+ */
 #define SIM_PUTC_FLUSH_STRING 0x100
 
-//! Flag value for forcing a PUTC binary-data-flush, which skips the
-//! prefix and does not append a newline.
-//!
+/**
+ * Flag value for forcing a PUTC binary-data-flush, which skips the
+ * prefix and does not append a newline.
+ */
 #define SIM_PUTC_FLUSH_BINARY 0x101
 
 
-#endif //__ARCH_SIM_DEF_H__
+#endif /* __ARCH_SIM_DEF_H__ */
index c8fdbd9..442fcba 100644 (file)
  *   more details.
  */
 
+/*
+ * In addition to including the proper base SPR definition file, depending
+ * on machine architecture, this file defines several macros which allow
+ * kernel code to use protection-level dependent SPRs without worrying
+ * about which PL it's running at.  In these macros, the PL that the SPR
+ * or interrupt number applies to is replaced by K.
+ */
+
+#if CONFIG_KERNEL_PL != 1 && CONFIG_KERNEL_PL != 2
+#error CONFIG_KERNEL_PL must be 1 or 2
+#endif
+
+/* Concatenate 4 strings. */
+#define __concat4(a, b, c, d) a ## b ## c ## d
+#define _concat4(a, b, c, d)  __concat4(a, b, c, d)
+
 #ifdef __tilegx__
 #include <arch/spr_def_64.h>
+
+/* TILE-Gx dependent, protection-level dependent SPRs. */
+
+#define SPR_INTERRUPT_MASK_K \
+       _concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL,,)
+#define SPR_INTERRUPT_MASK_SET_K \
+       _concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define SPR_INTERRUPT_MASK_RESET_K \
+       _concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL,,)
+#define SPR_INTERRUPT_VECTOR_BASE_K \
+       _concat4(SPR_INTERRUPT_VECTOR_BASE_, CONFIG_KERNEL_PL,,)
+
+#define SPR_IPI_MASK_K \
+       _concat4(SPR_IPI_MASK_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_MASK_RESET_K \
+       _concat4(SPR_IPI_MASK_RESET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_MASK_SET_K \
+       _concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_EVENT_K \
+       _concat4(SPR_IPI_EVENT_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_EVENT_RESET_K \
+       _concat4(SPR_IPI_EVENT_RESET_, CONFIG_KERNEL_PL,,)
+#define SPR_IPI_MASK_SET_K \
+       _concat4(SPR_IPI_MASK_SET_, CONFIG_KERNEL_PL,,)
+#define INT_IPI_K \
+       _concat4(INT_IPI_, CONFIG_KERNEL_PL,,)
+
+#define SPR_SINGLE_STEP_CONTROL_K \
+       _concat4(SPR_SINGLE_STEP_CONTROL_, CONFIG_KERNEL_PL,,)
+#define SPR_SINGLE_STEP_EN_K_K \
+       _concat4(SPR_SINGLE_STEP_EN_, CONFIG_KERNEL_PL, _, CONFIG_KERNEL_PL)
+#define INT_SINGLE_STEP_K \
+       _concat4(INT_SINGLE_STEP_, CONFIG_KERNEL_PL,,)
+
 #else
 #include <arch/spr_def_32.h>
+
+/* TILEPro dependent, protection-level dependent SPRs. */
+
+#define SPR_INTERRUPT_MASK_K_0 \
+       _concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL, _0,)
+#define SPR_INTERRUPT_MASK_K_1 \
+       _concat4(SPR_INTERRUPT_MASK_, CONFIG_KERNEL_PL, _1,)
+#define SPR_INTERRUPT_MASK_SET_K_0 \
+       _concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL, _0,)
+#define SPR_INTERRUPT_MASK_SET_K_1 \
+       _concat4(SPR_INTERRUPT_MASK_SET_, CONFIG_KERNEL_PL, _1,)
+#define SPR_INTERRUPT_MASK_RESET_K_0 \
+       _concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL, _0,)
+#define SPR_INTERRUPT_MASK_RESET_K_1 \
+       _concat4(SPR_INTERRUPT_MASK_RESET_, CONFIG_KERNEL_PL, _1,)
+
 #endif
+
+/* Generic protection-level dependent SPRs. */
+
+#define SPR_SYSTEM_SAVE_K_0 \
+       _concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _0,)
+#define SPR_SYSTEM_SAVE_K_1 \
+       _concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _1,)
+#define SPR_SYSTEM_SAVE_K_2 \
+       _concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _2,)
+#define SPR_SYSTEM_SAVE_K_3 \
+       _concat4(SPR_SYSTEM_SAVE_, CONFIG_KERNEL_PL, _3,)
+#define SPR_EX_CONTEXT_K_0 \
+       _concat4(SPR_EX_CONTEXT_, CONFIG_KERNEL_PL, _0,)
+#define SPR_EX_CONTEXT_K_1 \
+       _concat4(SPR_EX_CONTEXT_, CONFIG_KERNEL_PL, _1,)
+#define SPR_INTCTRL_K_STATUS \
+       _concat4(SPR_INTCTRL_, CONFIG_KERNEL_PL, _STATUS,)
+#define INT_INTCTRL_K \
+       _concat4(INT_INTCTRL_, CONFIG_KERNEL_PL,,)
index b4fc068..bbc1f4c 100644 (file)
 #define SPR_EX_CONTEXT_1_1__ICS_SHIFT 2
 #define SPR_EX_CONTEXT_1_1__ICS_RMASK 0x1
 #define SPR_EX_CONTEXT_1_1__ICS_MASK  0x4
+#define SPR_EX_CONTEXT_2_0 0x4605
+#define SPR_EX_CONTEXT_2_1 0x4606
+#define SPR_EX_CONTEXT_2_1__PL_SHIFT 0
+#define SPR_EX_CONTEXT_2_1__PL_RMASK 0x3
+#define SPR_EX_CONTEXT_2_1__PL_MASK  0x3
+#define SPR_EX_CONTEXT_2_1__ICS_SHIFT 2
+#define SPR_EX_CONTEXT_2_1__ICS_RMASK 0x1
+#define SPR_EX_CONTEXT_2_1__ICS_MASK  0x4
 #define SPR_FAIL 0x4e09
 #define SPR_INTCTRL_0_STATUS 0x4a07
 #define SPR_INTCTRL_1_STATUS 0x4807
+#define SPR_INTCTRL_2_STATUS 0x4607
 #define SPR_INTERRUPT_CRITICAL_SECTION 0x4e0a
 #define SPR_INTERRUPT_MASK_0_0 0x4a08
 #define SPR_INTERRUPT_MASK_0_1 0x4a09
 #define SPR_INTERRUPT_MASK_1_0 0x4809
 #define SPR_INTERRUPT_MASK_1_1 0x480a
+#define SPR_INTERRUPT_MASK_2_0 0x4608
+#define SPR_INTERRUPT_MASK_2_1 0x4609
 #define SPR_INTERRUPT_MASK_RESET_0_0 0x4a0a
 #define SPR_INTERRUPT_MASK_RESET_0_1 0x4a0b
 #define SPR_INTERRUPT_MASK_RESET_1_0 0x480b
 #define SPR_INTERRUPT_MASK_RESET_1_1 0x480c
+#define SPR_INTERRUPT_MASK_RESET_2_0 0x460a
+#define SPR_INTERRUPT_MASK_RESET_2_1 0x460b
 #define SPR_INTERRUPT_MASK_SET_0_0 0x4a0c
 #define SPR_INTERRUPT_MASK_SET_0_1 0x4a0d
 #define SPR_INTERRUPT_MASK_SET_1_0 0x480d
 #define SPR_INTERRUPT_MASK_SET_1_1 0x480e
+#define SPR_INTERRUPT_MASK_SET_2_0 0x460c
+#define SPR_INTERRUPT_MASK_SET_2_1 0x460d
 #define SPR_MPL_DMA_CPL_SET_0 0x5800
 #define SPR_MPL_DMA_CPL_SET_1 0x5801
+#define SPR_MPL_DMA_CPL_SET_2 0x5802
 #define SPR_MPL_DMA_NOTIFY_SET_0 0x3800
 #define SPR_MPL_DMA_NOTIFY_SET_1 0x3801
+#define SPR_MPL_DMA_NOTIFY_SET_2 0x3802
 #define SPR_MPL_INTCTRL_0_SET_0 0x4a00
 #define SPR_MPL_INTCTRL_0_SET_1 0x4a01
+#define SPR_MPL_INTCTRL_0_SET_2 0x4a02
 #define SPR_MPL_INTCTRL_1_SET_0 0x4800
 #define SPR_MPL_INTCTRL_1_SET_1 0x4801
+#define SPR_MPL_INTCTRL_1_SET_2 0x4802
+#define SPR_MPL_INTCTRL_2_SET_0 0x4600
+#define SPR_MPL_INTCTRL_2_SET_1 0x4601
+#define SPR_MPL_INTCTRL_2_SET_2 0x4602
 #define SPR_MPL_SN_ACCESS_SET_0 0x0800
 #define SPR_MPL_SN_ACCESS_SET_1 0x0801
+#define SPR_MPL_SN_ACCESS_SET_2 0x0802
 #define SPR_MPL_SN_CPL_SET_0 0x5a00
 #define SPR_MPL_SN_CPL_SET_1 0x5a01
+#define SPR_MPL_SN_CPL_SET_2 0x5a02
 #define SPR_MPL_SN_FIREWALL_SET_0 0x2c00
 #define SPR_MPL_SN_FIREWALL_SET_1 0x2c01
+#define SPR_MPL_SN_FIREWALL_SET_2 0x2c02
 #define SPR_MPL_SN_NOTIFY_SET_0 0x2a00
 #define SPR_MPL_SN_NOTIFY_SET_1 0x2a01
+#define SPR_MPL_SN_NOTIFY_SET_2 0x2a02
 #define SPR_MPL_UDN_ACCESS_SET_0 0x0c00
 #define SPR_MPL_UDN_ACCESS_SET_1 0x0c01
+#define SPR_MPL_UDN_ACCESS_SET_2 0x0c02
 #define SPR_MPL_UDN_AVAIL_SET_0 0x4000
 #define SPR_MPL_UDN_AVAIL_SET_1 0x4001
+#define SPR_MPL_UDN_AVAIL_SET_2 0x4002
 #define SPR_MPL_UDN_CA_SET_0 0x3c00
 #define SPR_MPL_UDN_CA_SET_1 0x3c01
+#define SPR_MPL_UDN_CA_SET_2 0x3c02
 #define SPR_MPL_UDN_COMPLETE_SET_0 0x1400
 #define SPR_MPL_UDN_COMPLETE_SET_1 0x1401
+#define SPR_MPL_UDN_COMPLETE_SET_2 0x1402
 #define SPR_MPL_UDN_FIREWALL_SET_0 0x3000
 #define SPR_MPL_UDN_FIREWALL_SET_1 0x3001
+#define SPR_MPL_UDN_FIREWALL_SET_2 0x3002
 #define SPR_MPL_UDN_REFILL_SET_0 0x1000
 #define SPR_MPL_UDN_REFILL_SET_1 0x1001
+#define SPR_MPL_UDN_REFILL_SET_2 0x1002
 #define SPR_MPL_UDN_TIMER_SET_0 0x3600
 #define SPR_MPL_UDN_TIMER_SET_1 0x3601
+#define SPR_MPL_UDN_TIMER_SET_2 0x3602
 #define SPR_MPL_WORLD_ACCESS_SET_0 0x4e00
 #define SPR_MPL_WORLD_ACCESS_SET_1 0x4e01
+#define SPR_MPL_WORLD_ACCESS_SET_2 0x4e02
 #define SPR_PASS 0x4e0b
 #define SPR_PERF_COUNT_0 0x4205
 #define SPR_PERF_COUNT_1 0x4206
 #define SPR_PERF_COUNT_CTL 0x4207
+#define SPR_PERF_COUNT_DN_CTL 0x4210
 #define SPR_PERF_COUNT_STS 0x4208
 #define SPR_PROC_STATUS 0x4f00
 #define SPR_SIM_CONTROL 0x4e0c
 #define SPR_SYSTEM_SAVE_1_1 0x4901
 #define SPR_SYSTEM_SAVE_1_2 0x4902
 #define SPR_SYSTEM_SAVE_1_3 0x4903
+#define SPR_SYSTEM_SAVE_2_0 0x4700
+#define SPR_SYSTEM_SAVE_2_1 0x4701
+#define SPR_SYSTEM_SAVE_2_2 0x4702
+#define SPR_SYSTEM_SAVE_2_3 0x4703
 #define SPR_TILE_COORD 0x4c17
 #define SPR_TILE_RTF_HWM 0x4e10
 #define SPR_TILE_TIMER_CONTROL 0x3205
index 758ca46..f18887d 100644 (file)
@@ -146,7 +146,10 @@ enum {
 
        CALLER_SP_IN_R52_BASE = 4,
 
-       CALLER_SP_OFFSET_BASE = 8
+       CALLER_SP_OFFSET_BASE = 8,
+
+       /* Marks the entry point of certain functions. */
+       ENTRY_POINT_INFO_OP = 16
 };
 
 
index 8b60ec8..c3ae570 100644 (file)
@@ -216,15 +216,16 @@ struct compat_siginfo;
 struct compat_sigaltstack;
 long compat_sys_execve(const char __user *path,
                       const compat_uptr_t __user *argv,
-                      const compat_uptr_t __user *envp);
+                      const compat_uptr_t __user *envp, struct pt_regs *);
 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
                             struct compat_sigaction __user *oact,
                             size_t sigsetsize);
 long compat_sys_rt_sigqueueinfo(int pid, int sig,
                                struct compat_siginfo __user *uinfo);
-long compat_sys_rt_sigreturn(void);
+long compat_sys_rt_sigreturn(struct pt_regs *);
 long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-                           struct compat_sigaltstack __user *uoss_ptr);
+                           struct compat_sigaltstack __user *uoss_ptr,
+                           struct pt_regs *);
 long compat_sys_truncate64(char __user *filename, u32 dummy, u32 low, u32 high);
 long compat_sys_ftruncate64(unsigned int fd, u32 dummy, u32 low, u32 high);
 long compat_sys_pread64(unsigned int fd, char __user *ubuf, size_t count,
@@ -255,4 +256,12 @@ long tile_compat_sys_ptrace(compat_long_t request, compat_long_t pid,
 /* Tilera Linux syscalls that don't have "compat" versions. */
 #define compat_sys_flush_cache sys_flush_cache
 
+/* These are the intvec_64.S trampolines. */
+long _compat_sys_execve(const char __user *path,
+                       const compat_uptr_t __user *argv,
+                       const compat_uptr_t __user *envp);
+long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
+                           struct compat_sigaltstack __user *uoss_ptr);
+long _compat_sys_rt_sigreturn(void);
+
 #endif /* _ASM_TILE_COMPAT_H */
index d155db6..e0f7ee1 100644 (file)
@@ -60,12 +60,12 @@ void *kmap_fix_kpte(struct page *page, int finished);
 /* This macro is used only in map_new_virtual() to map "page". */
 #define kmap_prot page_to_kpgprot(page)
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+void *__kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+void *kmap_atomic_pfn(unsigned long pfn);
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
 struct page *kmap_atomic_to_page(void *ptr);
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot);
-void *kmap_atomic(struct page *page, enum km_type type);
+void *kmap_atomic_prot(struct page *page, pgprot_t prot);
 void kmap_atomic_fix_kpte(struct page *page, int finished);
 
 #define flush_cache_kmaps()    do { } while (0)
index a11d483..641e4ff 100644 (file)
        int __n = (n); \
        int __mask = 1 << (__n & 0x1f); \
        if (__n < 32) \
-               __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, __mask); \
+               __insn_mtspr(SPR_INTERRUPT_MASK_SET_K_0, __mask); \
        else \
-               __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, __mask); \
+               __insn_mtspr(SPR_INTERRUPT_MASK_SET_K_1, __mask); \
 } while (0)
 #define interrupt_mask_reset(n) do { \
        int __n = (n); \
        int __mask = 1 << (__n & 0x1f); \
        if (__n < 32) \
-               __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, __mask); \
+               __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, __mask); \
        else \
-               __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, __mask); \
+               __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, __mask); \
 } while (0)
 #define interrupt_mask_check(n) ({ \
        int __n = (n); \
        (((__n < 32) ? \
-        __insn_mfspr(SPR_INTERRUPT_MASK_1_0) : \
-        __insn_mfspr(SPR_INTERRUPT_MASK_1_1)) \
+        __insn_mfspr(SPR_INTERRUPT_MASK_K_0) : \
+        __insn_mfspr(SPR_INTERRUPT_MASK_K_1)) \
          >> (__n & 0x1f)) & 1; \
 })
 #define interrupt_mask_set_mask(mask) do { \
        unsigned long long __m = (mask); \
-       __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_0, (unsigned long)(__m)); \
-       __insn_mtspr(SPR_INTERRUPT_MASK_SET_1_1, (unsigned long)(__m>>32)); \
+       __insn_mtspr(SPR_INTERRUPT_MASK_SET_K_0, (unsigned long)(__m)); \
+       __insn_mtspr(SPR_INTERRUPT_MASK_SET_K_1, (unsigned long)(__m>>32)); \
 } while (0)
 #define interrupt_mask_reset_mask(mask) do { \
        unsigned long long __m = (mask); \
-       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_0, (unsigned long)(__m)); \
-       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1_1, (unsigned long)(__m>>32)); \
+       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_0, (unsigned long)(__m)); \
+       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K_1, (unsigned long)(__m>>32)); \
 } while (0)
 #else
 #define interrupt_mask_set(n) \
-       __insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (1UL << (n)))
+       __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (1UL << (n)))
 #define interrupt_mask_reset(n) \
-       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (1UL << (n)))
+       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (1UL << (n)))
 #define interrupt_mask_check(n) \
-       ((__insn_mfspr(SPR_INTERRUPT_MASK_1) >> (n)) & 1)
+       ((__insn_mfspr(SPR_INTERRUPT_MASK_K) >> (n)) & 1)
 #define interrupt_mask_set_mask(mask) \
-       __insn_mtspr(SPR_INTERRUPT_MASK_SET_1, (mask))
+       __insn_mtspr(SPR_INTERRUPT_MASK_SET_K, (mask))
 #define interrupt_mask_reset_mask(mask) \
-       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_1, (mask))
+       __insn_mtspr(SPR_INTERRUPT_MASK_RESET_K, (mask))
 #endif
 
 /*
  * The set of interrupts we want active if irqs are enabled.
  * Note that in particular, the tile timer interrupt comes and goes
  * from this set, since we have no other way to turn off the timer.
- * Likewise, INTCTRL_1 is removed and re-added during device
+ * Likewise, INTCTRL_K is removed and re-added during device
  * interrupts, as is the the hardwall UDN_FIREWALL interrupt.
  * We use a low bit (MEM_ERROR) as our sentinel value and make sure it
  * is always claimed as an "active interrupt" so we can query that bit
@@ -170,14 +170,14 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
 
 /* Return 0 or 1 to indicate whether interrupts are currently disabled. */
 #define IRQS_DISABLED(tmp)                                     \
-       mfspr   tmp, INTERRUPT_MASK_1;                          \
+       mfspr   tmp, SPR_INTERRUPT_MASK_K;                      \
        andi    tmp, tmp, 1
 
 /* Load up a pointer to &interrupts_enabled_mask. */
 #define GET_INTERRUPTS_ENABLED_MASK_PTR(reg)                   \
-       moveli reg, hw2_last(interrupts_enabled_mask); \
-       shl16insli reg, reg, hw1(interrupts_enabled_mask); \
-       shl16insli reg, reg, hw0(interrupts_enabled_mask); \
+       moveli reg, hw2_last(interrupts_enabled_mask);          \
+       shl16insli reg, reg, hw1(interrupts_enabled_mask);      \
+       shl16insli reg, reg, hw0(interrupts_enabled_mask);      \
        add     reg, reg, tp
 
 /* Disable interrupts. */
@@ -185,18 +185,18 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
        moveli  tmp0, hw2_last(LINUX_MASKABLE_INTERRUPTS);      \
        shl16insli tmp0, tmp0, hw1(LINUX_MASKABLE_INTERRUPTS);  \
        shl16insli tmp0, tmp0, hw0(LINUX_MASKABLE_INTERRUPTS);  \
-       mtspr   INTERRUPT_MASK_SET_1, tmp0
+       mtspr   SPR_INTERRUPT_MASK_SET_K, tmp0
 
 /* Disable ALL synchronous interrupts (used by NMI entry). */
 #define IRQ_DISABLE_ALL(tmp)                                   \
        movei   tmp, -1;                                        \
-       mtspr   INTERRUPT_MASK_SET_1, tmp
+       mtspr   SPR_INTERRUPT_MASK_SET_K, tmp
 
 /* Enable interrupts. */
 #define IRQ_ENABLE(tmp0, tmp1)                                 \
        GET_INTERRUPTS_ENABLED_MASK_PTR(tmp0);                  \
        ld      tmp0, tmp0;                                     \
-       mtspr   INTERRUPT_MASK_RESET_1, tmp0
+       mtspr   SPR_INTERRUPT_MASK_RESET_K, tmp0
 
 #else /* !__tilegx__ */
 
@@ -210,14 +210,14 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
  * (making the original code's write of the "high" mask word idempotent).
  */
 #define IRQS_DISABLED(tmp)                                     \
-       mfspr   tmp, INTERRUPT_MASK_1_0;                        \
+       mfspr   tmp, SPR_INTERRUPT_MASK_K_0;                    \
        shri    tmp, tmp, INT_MEM_ERROR;                        \
        andi    tmp, tmp, 1
 
 /* Load up a pointer to &interrupts_enabled_mask. */
 #define GET_INTERRUPTS_ENABLED_MASK_PTR(reg)                   \
-       moveli  reg, lo16(interrupts_enabled_mask);     \
-       auli    reg, reg, ha16(interrupts_enabled_mask);\
+       moveli  reg, lo16(interrupts_enabled_mask);             \
+       auli    reg, reg, ha16(interrupts_enabled_mask);        \
        add     reg, reg, tp
 
 /* Disable interrupts. */
@@ -227,16 +227,16 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
         moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS)           \
        };                                                      \
        {                                                       \
-        mtspr  INTERRUPT_MASK_SET_1_0, tmp0;                   \
+        mtspr  SPR_INTERRUPT_MASK_SET_K_0, tmp0;               \
         auli   tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS)     \
        };                                                      \
-       mtspr   INTERRUPT_MASK_SET_1_1, tmp1
+       mtspr   SPR_INTERRUPT_MASK_SET_K_1, tmp1
 
 /* Disable ALL synchronous interrupts (used by NMI entry). */
 #define IRQ_DISABLE_ALL(tmp)                                   \
        movei   tmp, -1;                                        \
-       mtspr   INTERRUPT_MASK_SET_1_0, tmp;                    \
-       mtspr   INTERRUPT_MASK_SET_1_1, tmp
+       mtspr   SPR_INTERRUPT_MASK_SET_K_0, tmp;                \
+       mtspr   SPR_INTERRUPT_MASK_SET_K_1, tmp
 
 /* Enable interrupts. */
 #define IRQ_ENABLE(tmp0, tmp1)                                 \
@@ -246,8 +246,8 @@ DECLARE_PER_CPU(unsigned long long, interrupts_enabled_mask);
         addi   tmp1, tmp0, 4                                   \
        };                                                      \
        lw      tmp1, tmp1;                                     \
-       mtspr   INTERRUPT_MASK_RESET_1_0, tmp0;                 \
-       mtspr   INTERRUPT_MASK_RESET_1_1, tmp1
+       mtspr   SPR_INTERRUPT_MASK_RESET_K_0, tmp0;             \
+       mtspr   SPR_INTERRUPT_MASK_RESET_K_1, tmp1
 #endif
 
 /*
index 4c6811e..81b8fc3 100644 (file)
@@ -23,6 +23,7 @@
 #define MAP_POPULATE   0x0040          /* populate (prefault) pagetables */
 #define MAP_NONBLOCK   0x0080          /* do not block on IO */
 #define MAP_GROWSDOWN  0x0100          /* stack-like segment */
+#define MAP_STACK      MAP_GROWSDOWN   /* provide convenience alias */
 #define MAP_LOCKED     0x0200          /* pages are locked */
 #define MAP_NORESERVE  0x0400          /* don't check for reservations */
 #define MAP_DENYWRITE  0x0800          /* ETXTBSY */
index 7d90641..7979a45 100644 (file)
@@ -199,17 +199,17 @@ static inline __attribute_const__ int get_order(unsigned long size)
  * If you want more physical memory than this then see the CONFIG_HIGHMEM
  * option in the kernel configuration.
  *
- * The top two 16MB chunks in the table below (VIRT and HV) are
- * unavailable to Linux.  Since the kernel interrupt vectors must live
- * at 0xfd000000, we map all of the bottom of RAM at this address with
- * a huge page table entry to minimize its ITLB footprint (as well as
- * at PAGE_OFFSET).  The last architected requirement is that user
- * interrupt vectors live at 0xfc000000, so we make that range of
- * memory available to user processes.  The remaining regions are sized
- * as shown; after the first four addresses, we show "typical" values,
- * since the actual addresses depend on kernel #defines.
+ * The top 16MB chunk in the table below is unavailable to Linux.  Since
+ * the kernel interrupt vectors must live at ether 0xfe000000 or 0xfd000000
+ * (depending on whether the kernel is at PL2 or Pl1), we map all of the
+ * bottom of RAM at this address with a huge page table entry to minimize
+ * its ITLB footprint (as well as at PAGE_OFFSET).  The last architected
+ * requirement is that user interrupt vectors live at 0xfc000000, so we
+ * make that range of memory available to user processes.  The remaining
+ * regions are sized as shown; the first four addresses use the PL 1
+ * values, and after that, we show "typical" values, since the actual
+ * addresses depend on kernel #defines.
  *
- * MEM_VIRT_INTRPT                 0xff000000
  * MEM_HV_INTRPT                   0xfe000000
  * MEM_SV_INTRPT (kernel code)     0xfd000000
  * MEM_USER_INTRPT (user vector)   0xfc000000
@@ -221,9 +221,14 @@ static inline __attribute_const__ int get_order(unsigned long size)
  */
 
 #define MEM_USER_INTRPT                _AC(0xfc000000, UL)
+#if CONFIG_KERNEL_PL == 1
 #define MEM_SV_INTRPT          _AC(0xfd000000, UL)
 #define MEM_HV_INTRPT          _AC(0xfe000000, UL)
-#define MEM_VIRT_INTRPT                _AC(0xff000000, UL)
+#else
+#define MEM_GUEST_INTRPT       _AC(0xfd000000, UL)
+#define MEM_SV_INTRPT          _AC(0xfe000000, UL)
+#define MEM_HV_INTRPT          _AC(0xff000000, UL)
+#endif
 
 #define INTRPT_SIZE            0x4000
 
index b336737..dc4ccdd 100644 (file)
@@ -347,15 +347,10 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 extern pte_t *_pte_offset_map(pmd_t *, unsigned long address, enum km_type);
 #define pte_offset_map(dir, address) \
        _pte_offset_map(dir, address, KM_PTE0)
-#define pte_offset_map_nested(dir, address) \
-       _pte_offset_map(dir, address, KM_PTE1)
 #define pte_unmap(pte) kunmap_atomic(pte, KM_PTE0)
-#define pte_unmap_nested(pte) kunmap_atomic(pte, KM_PTE1)
 #else
 #define pte_offset_map(dir, address) pte_offset_kernel(dir, address)
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #endif
 
 /* Clear a non-executable kernel PTE and flush it from the TLB. */
index ccd5f84..1747ff3 100644 (file)
@@ -328,18 +328,21 @@ extern int kdata_huge;
  * Note that assembly code assumes that USER_PL is zero.
  */
 #define USER_PL 0
-#define KERNEL_PL 1
+#if CONFIG_KERNEL_PL == 2
+#define GUEST_PL 1
+#endif
+#define KERNEL_PL CONFIG_KERNEL_PL
 
-/* SYSTEM_SAVE_1_0 holds the current cpu number ORed with ksp0. */
+/* SYSTEM_SAVE_K_0 holds the current cpu number ORed with ksp0. */
 #define CPU_LOG_MASK_VALUE 12
 #define CPU_MASK_VALUE ((1 << CPU_LOG_MASK_VALUE) - 1)
 #if CONFIG_NR_CPUS > CPU_MASK_VALUE
 # error Too many cpus!
 #endif
 #define raw_smp_processor_id() \
-       ((int)__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & CPU_MASK_VALUE)
+       ((int)__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & CPU_MASK_VALUE)
 #define get_current_ksp0() \
-       (__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & ~CPU_MASK_VALUE)
+       (__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & ~CPU_MASK_VALUE)
 #define next_current_ksp0(task) ({ \
        unsigned long __ksp0 = task_ksp0(task); \
        int __cpu = raw_smp_processor_id(); \
index 4a02bb0..ac6d343 100644 (file)
@@ -62,8 +62,8 @@ struct pt_regs {
        pt_reg_t lr;            /* aliases regs[TREG_LR] */
 
        /* Saved special registers. */
-       pt_reg_t pc;            /* stored in EX_CONTEXT_1_0 */
-       pt_reg_t ex1;           /* stored in EX_CONTEXT_1_1 (PL and ICS bit) */
+       pt_reg_t pc;            /* stored in EX_CONTEXT_K_0 */
+       pt_reg_t ex1;           /* stored in EX_CONTEXT_K_1 (PL and ICS bit) */
        pt_reg_t faultnum;      /* fault number (INT_SWINT_1 for syscall) */
        pt_reg_t orig_r0;       /* r0 at syscall entry, else zero */
        pt_reg_t flags;         /* flags (see below) */
index ce99ffe..3b5507c 100644 (file)
@@ -32,8 +32,9 @@ extern void *compat_sys_call_table[];
 
 /*
  * Note that by convention, any syscall which requires the current
- * register set takes an additional "struct pt_regs *" pointer; the
- * sys_xxx() function just adds the pointer and tail-calls to _sys_xxx().
+ * register set takes an additional "struct pt_regs *" pointer; a
+ * _sys_xxx() trampoline in intvec*.S just sets up the pointer and
+ * jumps to sys_xxx().
  */
 
 /* kernel/sys.c */
@@ -43,66 +44,17 @@ long sys32_fadvise64(int fd, u32 offset_lo, u32 offset_hi,
 int sys32_fadvise64_64(int fd, u32 offset_lo, u32 offset_hi,
                       u32 len_lo, u32 len_hi, int advice);
 long sys_flush_cache(void);
-long sys_mmap2(unsigned long addr, unsigned long len,
-              unsigned long prot, unsigned long flags,
-              unsigned long fd, unsigned long pgoff);
-#ifdef __tilegx__
-long sys_mmap(unsigned long addr, unsigned long len,
-             unsigned long prot, unsigned long flags,
-             unsigned long fd, off_t pgoff);
+#ifndef __tilegx__  /* No mmap() in the 32-bit kernel. */
+#define sys_mmap sys_mmap
 #endif
 
-/* kernel/process.c */
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-              void __user *parent_tid, void __user *child_tid);
-long _sys_clone(unsigned long clone_flags, unsigned long newsp,
-               void __user *parent_tid, void __user *child_tid,
-               struct pt_regs *regs);
-long sys_fork(void);
-long _sys_fork(struct pt_regs *regs);
-long sys_vfork(void);
-long _sys_vfork(struct pt_regs *regs);
-long sys_execve(const char __user *filename,
-               const char __user *const __user *argv,
-               const char __user *const __user *envp);
-long _sys_execve(const char __user *filename,
-                const char __user *const __user *argv,
-                const char __user *const __user *envp, struct pt_regs *regs);
-
-/* kernel/signal.c */
-long sys_sigaltstack(const stack_t __user *, stack_t __user *);
-long _sys_sigaltstack(const stack_t __user *, stack_t __user *,
-                     struct pt_regs *);
-long sys_rt_sigreturn(void);
-long _sys_rt_sigreturn(struct pt_regs *regs);
-
-/* platform-independent functions */
-long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize);
-long sys_rt_sigaction(int sig, const struct sigaction __user *act,
-                     struct sigaction __user *oact, size_t sigsetsize);
-
 #ifndef __tilegx__
 /* mm/fault.c */
-int sys_cmpxchg_badaddr(unsigned long address);
-int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
+long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);
+long _sys_cmpxchg_badaddr(unsigned long address);
 #endif
 
 #ifdef CONFIG_COMPAT
-long compat_sys_execve(const char __user *path,
-                      const compat_uptr_t __user *argv,
-                      const compat_uptr_t __user *envp);
-long _compat_sys_execve(const char __user *path,
-                       const compat_uptr_t __user *argv,
-                       const compat_uptr_t __user *envp,
-                       struct pt_regs *regs);
-long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-                           struct compat_sigaltstack __user *uoss_ptr);
-long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-                            struct compat_sigaltstack __user *uoss_ptr,
-                            struct pt_regs *regs);
-long compat_sys_rt_sigreturn(void);
-long _compat_sys_rt_sigreturn(struct pt_regs *regs);
-
 /* These four are not defined for 64-bit, but serve as "compat" syscalls. */
 long sys_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg);
 long sys_fstat64(unsigned long fd, struct stat64 __user *statbuf);
@@ -110,4 +62,15 @@ long sys_truncate64(const char __user *path, loff_t length);
 long sys_ftruncate64(unsigned int fd, loff_t length);
 #endif
 
+/* These are the intvec*.S trampolines. */
+long _sys_sigaltstack(const stack_t __user *, stack_t __user *);
+long _sys_rt_sigreturn(void);
+long _sys_clone(unsigned long clone_flags, unsigned long newsp,
+               void __user *parent_tid, void __user *child_tid);
+long _sys_execve(const char __user *filename,
+                const char __user *const __user *argv,
+                const char __user *const __user *envp);
+
+#include <asm-generic/syscalls.h>
+
 #endif /* _ASM_TILE_SYSCALLS_H */
index f749be3..5388850 100644 (file)
 #define get_cycles_low() __insn_mfspr(SPR_CYCLE)   /* just get all 64 bits */
 #endif
 
+#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
+int __mb_incoherent(void);  /* Helper routine for mb_incoherent(). */
+#endif
+
 /* Fence to guarantee visibility of stores to incoherent memory. */
 static inline void
 mb_incoherent(void)
@@ -97,7 +101,6 @@ mb_incoherent(void)
 
 #if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
        {
-               int __mb_incoherent(void);
 #if CHIP_HAS_TILE_WRITE_PENDING()
                const unsigned long WRITE_TIMEOUT_CYCLES = 400;
                unsigned long start = get_cycles_low();
@@ -161,7 +164,7 @@ extern struct task_struct *_switch_to(struct task_struct *prev,
 /* Helper function for _switch_to(). */
 extern struct task_struct *__switch_to(struct task_struct *prev,
                                       struct task_struct *next,
-                                      unsigned long new_system_save_1_0);
+                                      unsigned long new_system_save_k_0);
 
 /* Address that switched-away from tasks are at. */
 extern unsigned long get_switch_to_pc(void);
@@ -214,13 +217,6 @@ int hardwall_deactivate(struct task_struct *task);
 } while (0)
 #endif
 
-/* Invoke the simulator "syscall" mechanism (see arch/tile/kernel/entry.S). */
-extern int _sim_syscall(int syscall_num, ...);
-#define sim_syscall(syscall_num, ...) \
-       _sim_syscall(SIM_CONTROL_SYSCALL + \
-               ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS), \
-               ## __VA_ARGS__)
-
 /*
  * Kernel threads can check to see if they need to migrate their
  * stack whenever they return from a context switch; for user
index 432a9c1..d06e35f 100644 (file)
@@ -59,4 +59,8 @@ void do_hardwall_trap(struct pt_regs *, int fault_num);
 void do_breakpoint(struct pt_regs *, int fault_num);
 
 
+#ifdef __tilegx__
+void gx_singlestep_handle(struct pt_regs *, int fault_num);
+#endif
+
 #endif /* _ASM_TILE_SYSCALLS_H */
index 9bd303a..f672544 100644 (file)
@@ -1003,37 +1003,37 @@ int hv_console_write(HV_VirtAddr bytes, int len);
  *  when these occur in a client's interrupt critical section, they must
  *  be delivered through the downcall mechanism.
  *
- *  A downcall is initially delivered to the client as an INTCTRL_1
- *  interrupt.  Upon entry to the INTCTRL_1 vector, the client must
- *  immediately invoke the hv_downcall_dispatch service.  This service
- *  will not return; instead it will cause one of the client's actual
- *  downcall-handling interrupt vectors to be entered.  The EX_CONTEXT
- *  registers in the client will be set so that when the client irets,
- *  it will return to the code which was interrupted by the INTCTRL_1
- *  interrupt.
- *
- *  Under some circumstances, the firing of INTCTRL_1 can race with
+ *  A downcall is initially delivered to the client as an INTCTRL_CL
+ *  interrupt, where CL is the client's PL.  Upon entry to the INTCTRL_CL
+ *  vector, the client must immediately invoke the hv_downcall_dispatch
+ *  service.  This service will not return; instead it will cause one of
+ *  the client's actual downcall-handling interrupt vectors to be entered.
+ *  The EX_CONTEXT registers in the client will be set so that when the
+ *  client irets, it will return to the code which was interrupted by the
+ *  INTCTRL_CL interrupt.
+ *
+ *  Under some circumstances, the firing of INTCTRL_CL can race with
  *  the lowering of a device interrupt.  In such a case, the
  *  hv_downcall_dispatch service may issue an iret instruction instead
  *  of entering one of the client's actual downcall-handling interrupt
  *  vectors.  This will return execution to the location that was
- *  interrupted by INTCTRL_1.
+ *  interrupted by INTCTRL_CL.
  *
  *  Any saving of registers should be done by the actual handling
- *  vectors; no registers should be changed by the INTCTRL_1 handler.
+ *  vectors; no registers should be changed by the INTCTRL_CL handler.
  *  In particular, the client should not use a jal instruction to invoke
  *  the hv_downcall_dispatch service, as that would overwrite the client's
  *  lr register.  Note that the hv_downcall_dispatch service may overwrite
  *  one or more of the client's system save registers.
  *
- *  The client must not modify the INTCTRL_1_STATUS SPR.  The hypervisor
+ *  The client must not modify the INTCTRL_CL_STATUS SPR.  The hypervisor
  *  will set this register to cause a downcall to happen, and will clear
  *  it when no further downcalls are pending.
  *
- *  When a downcall vector is entered, the INTCTRL_1 interrupt will be
+ *  When a downcall vector is entered, the INTCTRL_CL interrupt will be
  *  masked.  When the client is done processing a downcall, and is ready
  *  to accept another, it must unmask this interrupt; if more downcalls
- *  are pending, this will cause the INTCTRL_1 vector to be reentered.
+ *  are pending, this will cause the INTCTRL_CL vector to be reentered.
  *  Currently the following interrupt vectors can be entered through a
  *  downcall:
  *
index d3c41c1..55a6a74 100644 (file)
@@ -369,6 +369,10 @@ static void find_caller_pc_and_caller_sp(CallerLocation *location,
                                        /* Weird; reserved value, ignore it. */
                                        continue;
                                }
+                               if (info_operand & ENTRY_POINT_INFO_OP) {
+                                       /* This info op is ignored by the backtracer. */
+                                       continue;
+                               }
 
                                /* Skip info ops which are not in the
                                 * "one_ago" mode we want right now.
index b1e06d0..77739cd 100644 (file)
@@ -154,8 +154,14 @@ long tile_compat_sys_msgrcv(int msqid,
 #define compat_sys_fstat64 sys_newfstat
 #define compat_sys_fstatat64 sys_newfstatat
 
-/* Pass full 64-bit values through ptrace. */
-#define compat_sys_ptrace tile_compat_sys_ptrace
+/* The native sys_ptrace dynamically handles compat binaries. */
+#define compat_sys_ptrace sys_ptrace
+
+/* Call the trampolines to manage pt_regs where necessary. */
+#define compat_sys_execve _compat_sys_execve
+#define compat_sys_sigaltstack _compat_sys_sigaltstack
+#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn
+#define sys_clone _sys_clone
 
 /*
  * Note that we can't include <linux/unistd.h> here since the header
index 9c710db..fb64b99 100644 (file)
@@ -256,9 +256,9 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
        return err;
 }
 
-long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
-                            struct compat_sigaltstack __user *uoss_ptr,
-                            struct pt_regs *regs)
+long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
+                           struct compat_sigaltstack __user *uoss_ptr,
+                           struct pt_regs *regs)
 {
        stack_t uss, uoss;
        int ret;
@@ -291,7 +291,7 @@ long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
        return ret;
 }
 
-long _compat_sys_rt_sigreturn(struct pt_regs *regs)
+long compat_sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct compat_rt_sigframe __user *frame =
                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
@@ -312,7 +312,7 @@ long _compat_sys_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
                goto badframe;
 
-       if (_compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
+       if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
                goto badframe;
 
        return r0;
index 3d01383..fd8dc42 100644 (file)
@@ -15,7 +15,9 @@
 #include <linux/linkage.h>
 #include <linux/unistd.h>
 #include <asm/irqflags.h>
+#include <asm/processor.h>
 #include <arch/abi.h>
+#include <arch/spr_def.h>
 
 #ifdef __tilegx__
 #define bnzt bnezt
@@ -25,28 +27,6 @@ STD_ENTRY(current_text_addr)
        { move r0, lr; jrp lr }
        STD_ENDPROC(current_text_addr)
 
-STD_ENTRY(_sim_syscall)
-       /*
-        * Wait for r0-r9 to be ready (and lr on the off chance we
-        * want the syscall to locate its caller), then make a magic
-        * simulator syscall.
-        *
-        * We carefully stall until the registers are readable in case they
-        * are the target of a slow load, etc. so that tile-sim will
-        * definitely be able to read all of them inside the magic syscall.
-        *
-        * Technically this is wrong for r3-r9 and lr, since an interrupt
-        * could come in and restore the registers with a slow load right
-        * before executing the mtspr. We may need to modify tile-sim to
-        * explicitly stall for this case, but we do not yet have
-        * a way to implement such a stall.
-        */
-       { and zero, lr, r9 ; and zero, r8, r7 }
-       { and zero, r6, r5 ; and zero, r4, r3 }
-       { and zero, r2, r1 ; mtspr SIM_CONTROL, r0 }
-       { jrp lr }
-       STD_ENDPROC(_sim_syscall)
-
 /*
  * Implement execve().  The i386 code has a note that forking from kernel
  * space results in no copy on write until the execve, so we should be
@@ -102,7 +82,7 @@ STD_ENTRY(KBacktraceIterator_init_current)
 STD_ENTRY(cpu_idle_on_new_stack)
        {
         move sp, r1
-        mtspr SYSTEM_SAVE_1_0, r2
+        mtspr SPR_SYSTEM_SAVE_K_0, r2
        }
        jal free_thread_info
        j cpu_idle
@@ -124,15 +104,15 @@ STD_ENTRY(smp_nap)
 STD_ENTRY(_cpu_idle)
        {
         lnk r0
-        movei r1, 1
+        movei r1, KERNEL_PL
        }
        {
         addli r0, r0, _cpu_idle_nap - .
         mtspr INTERRUPT_CRITICAL_SECTION, r1
        }
-       IRQ_ENABLE(r2, r3)         /* unmask, but still with ICS set */
-       mtspr EX_CONTEXT_1_1, r1   /* PL1, ICS clear */
-       mtspr EX_CONTEXT_1_0, r0
+       IRQ_ENABLE(r2, r3)             /* unmask, but still with ICS set */
+       mtspr SPR_EX_CONTEXT_K_1, r1   /* Kernel PL, ICS clear */
+       mtspr SPR_EX_CONTEXT_K_0, r0
        iret
        .global _cpu_idle_nap
 _cpu_idle_nap:
index 2b4f6c0..90e7c44 100644 (file)
@@ -23,6 +23,7 @@
 #include <asm/asm-offsets.h>
 #include <hv/hypervisor.h>
 #include <arch/chip.h>
+#include <arch/spr_def.h>
 
 /*
  * This module contains the entry code for kernel images. It performs the
@@ -76,7 +77,7 @@ ENTRY(_start)
        }
 1:
 
-       /* Get our processor number and save it away in SAVE_1_0. */
+       /* Get our processor number and save it away in SAVE_K_0. */
        jal hv_inquire_topology
        mulll_uu r4, r1, r2        /* r1 == y, r2 == width */
        add r4, r4, r0             /* r0 == x, so r4 == cpu == y*width + x */
@@ -124,7 +125,7 @@ ENTRY(_start)
        lw r0, r0
        lw sp, r1
        or r4, sp, r4
-       mtspr SYSTEM_SAVE_1_0, r4  /* save ksp0 + cpu */
+       mtspr SPR_SYSTEM_SAVE_K_0, r4  /* save ksp0 + cpu */
        addi sp, sp, -STACK_TOP_DELTA
        {
          move lr, zero   /* stop backtraces in the called function */
index 8f58bdf..f582162 100644 (file)
@@ -32,8 +32,8 @@
 # error "No support for kernel preemption currently"
 #endif
 
-#if INT_INTCTRL_1 < 32 || INT_INTCTRL_1 >= 48
-# error INT_INTCTRL_1 coded to set high interrupt mask
+#if INT_INTCTRL_K < 32 || INT_INTCTRL_K >= 48
+# error INT_INTCTRL_K coded to set high interrupt mask
 #endif
 
 #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg)
@@ -132,8 +132,8 @@ intvec_\vecname:
 
        /* Temporarily save a register so we have somewhere to work. */
 
-       mtspr   SYSTEM_SAVE_1_1, r0
-       mfspr   r0, EX_CONTEXT_1_1
+       mtspr   SPR_SYSTEM_SAVE_K_1, r0
+       mfspr   r0, SPR_EX_CONTEXT_K_1
 
        /* The cmpxchg code clears sp to force us to reset it here on fault. */
        {
@@ -167,18 +167,18 @@ intvec_\vecname:
         * The page_fault handler may be downcalled directly by the
         * hypervisor even when Linux is running and has ICS set.
         *
-        * In this case the contents of EX_CONTEXT_1_1 reflect the
+        * In this case the contents of EX_CONTEXT_K_1 reflect the
         * previous fault and can't be relied on to choose whether or
         * not to reinitialize the stack pointer.  So we add a test
-        * to see whether SYSTEM_SAVE_1_2 has the high bit set,
+        * to see whether SYSTEM_SAVE_K_2 has the high bit set,
         * and if so we don't reinitialize sp, since we must be coming
         * from Linux.  (In fact the precise case is !(val & ~1),
         * but any Linux PC has to have the high bit set.)
         *
-        * Note that the hypervisor *always* sets SYSTEM_SAVE_1_2 for
+        * Note that the hypervisor *always* sets SYSTEM_SAVE_K_2 for
         * any path that turns into a downcall to one of our TLB handlers.
         */
-       mfspr   r0, SYSTEM_SAVE_1_2
+       mfspr   r0, SPR_SYSTEM_SAVE_K_2
        {
         blz    r0, 0f    /* high bit in S_S_1_2 is for a PC to use */
         move   r0, sp
@@ -187,12 +187,12 @@ intvec_\vecname:
 
 2:
        /*
-        * SYSTEM_SAVE_1_0 holds the cpu number in the low bits, and
+        * SYSTEM_SAVE_K_0 holds the cpu number in the low bits, and
         * the current stack top in the higher bits.  So we recover
         * our stack top by just masking off the low bits, then
         * point sp at the top aligned address on the actual stack page.
         */
-       mfspr   r0, SYSTEM_SAVE_1_0
+       mfspr   r0, SPR_SYSTEM_SAVE_K_0
        mm      r0, r0, zero, LOG2_THREAD_SIZE, 31
 
 0:
@@ -254,7 +254,7 @@ intvec_\vecname:
         sw     sp, r3
         addli  sp, sp, PTREGS_OFFSET_PC - PTREGS_OFFSET_REG(3)
        }
-       mfspr   r0, EX_CONTEXT_1_0
+       mfspr   r0, SPR_EX_CONTEXT_K_0
        .ifc \processing,handle_syscall
        /*
         * Bump the saved PC by one bundle so that when we return, we won't
@@ -267,7 +267,7 @@ intvec_\vecname:
         sw     sp, r0
         addli  sp, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC
        }
-       mfspr   r0, EX_CONTEXT_1_1
+       mfspr   r0, SPR_EX_CONTEXT_K_1
        {
         sw     sp, r0
         addi   sp, sp, PTREGS_OFFSET_FAULTNUM - PTREGS_OFFSET_EX1
@@ -289,7 +289,7 @@ intvec_\vecname:
         .endif
         addli  sp, sp, PTREGS_OFFSET_REG(0) - PTREGS_OFFSET_FAULTNUM
        }
-       mfspr   r0, SYSTEM_SAVE_1_1    /* Original r0 */
+       mfspr   r0, SPR_SYSTEM_SAVE_K_1    /* Original r0 */
        {
         sw     sp, r0
         addi   sp, sp, -PTREGS_OFFSET_REG(0) - 4
@@ -309,12 +309,12 @@ intvec_\vecname:
         * See discussion below at "finish_interrupt_save".
         */
        .ifc \c_routine, do_page_fault
-       mfspr   r2, SYSTEM_SAVE_1_3   /* address of page fault */
-       mfspr   r3, SYSTEM_SAVE_1_2   /* info about page fault */
+       mfspr   r2, SPR_SYSTEM_SAVE_K_3   /* address of page fault */
+       mfspr   r3, SPR_SYSTEM_SAVE_K_2   /* info about page fault */
        .else
        .ifc \vecnum, INT_DOUBLE_FAULT
        {
-        mfspr  r2, SYSTEM_SAVE_1_2   /* double fault info from HV */
+        mfspr  r2, SPR_SYSTEM_SAVE_K_2   /* double fault info from HV */
         movei  r3, 0
        }
        .else
@@ -467,7 +467,7 @@ intvec_\vecname:
        /* Load tp with our per-cpu offset. */
 #ifdef CONFIG_SMP
        {
-        mfspr  r20, SYSTEM_SAVE_1_0
+        mfspr  r20, SPR_SYSTEM_SAVE_K_0
         moveli r21, lo16(__per_cpu_offset)
        }
        {
@@ -487,7 +487,7 @@ intvec_\vecname:
         * We load flags in r32 here so we can jump to .Lrestore_regs
         * directly after do_page_fault_ics() if necessary.
         */
-       mfspr   r32, EX_CONTEXT_1_1
+       mfspr   r32, SPR_EX_CONTEXT_K_1
        {
         andi   r32, r32, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
         PTREGS_PTR(r21, PTREGS_OFFSET_FLAGS)
@@ -957,11 +957,11 @@ STD_ENTRY(interrupt_return)
        pop_reg_zero r21, r3, sp, PTREGS_OFFSET_EX1 - PTREGS_OFFSET_PC
        pop_reg_zero lr, r4, sp, PTREGS_OFFSET_REG(52) - PTREGS_OFFSET_EX1
        {
-        mtspr  EX_CONTEXT_1_0, r21
+        mtspr  SPR_EX_CONTEXT_K_0, r21
         move   r5, zero
        }
        {
-        mtspr  EX_CONTEXT_1_1, lr
+        mtspr  SPR_EX_CONTEXT_K_1, lr
         andi   lr, lr, SPR_EX_CONTEXT_1_1__PL_MASK  /* mask off ICS */
        }
 
@@ -1020,7 +1020,7 @@ STD_ENTRY(interrupt_return)
 
        /* Set r1 to errno if we are returning an error, otherwise zero. */
        {
-        moveli r29, 1024
+        moveli r29, 4096
         sub    r1, zero, r0
        }
        slt_u   r29, r1, r29
@@ -1199,7 +1199,7 @@ STD_ENTRY(interrupt_return)
        STD_ENDPROC(interrupt_return)
 
        /*
-        * This interrupt variant clears the INT_INTCTRL_1 interrupt mask bit
+        * This interrupt variant clears the INT_INTCTRL_K interrupt mask bit
         * before returning, so we can properly get more downcalls.
         */
        .pushsection .text.handle_interrupt_downcall,"ax"
@@ -1208,11 +1208,11 @@ handle_interrupt_downcall:
        check_single_stepping normal, .Ldispatch_downcall
 .Ldispatch_downcall:
 
-       /* Clear INTCTRL_1 from the set of interrupts we ever enable. */
+       /* Clear INTCTRL_K from the set of interrupts we ever enable. */
        GET_INTERRUPTS_ENABLED_MASK_PTR(r30)
        {
         addi   r30, r30, 4
-        movei  r31, INT_MASK(INT_INTCTRL_1)
+        movei  r31, INT_MASK(INT_INTCTRL_K)
        }
        {
         lw     r20, r30
@@ -1227,7 +1227,7 @@ handle_interrupt_downcall:
        }
        FEEDBACK_REENTER(handle_interrupt_downcall)
 
-       /* Allow INTCTRL_1 to be enabled next time we enable interrupts. */
+       /* Allow INTCTRL_K to be enabled next time we enable interrupts. */
        lw      r20, r30
        or      r20, r20, r31
        sw      r30, r20
@@ -1472,7 +1472,12 @@ handle_ill:
        lw      r26, r24
        sw      r28, r26
 
-       /* Clear TIF_SINGLESTEP */
+       /*
+        * Clear TIF_SINGLESTEP to prevent recursion if we execute an ill.
+        * The normal non-arch flow redundantly clears TIF_SINGLESTEP, but we
+        * need to clear it here and can't really impose on all other arches.
+        * So what's another write between friends?
+        */
        GET_THREAD_INFO(r0)
 
        addi    r1, r0, THREAD_INFO_FLAGS_OFFSET
@@ -1509,7 +1514,7 @@ handle_ill:
 /* Various stub interrupt handlers and syscall handlers */
 
 STD_ENTRY_LOCAL(_kernel_double_fault)
-       mfspr   r1, EX_CONTEXT_1_0
+       mfspr   r1, SPR_EX_CONTEXT_K_0
        move    r2, lr
        move    r3, sp
        move    r4, r52
@@ -1518,34 +1523,29 @@ STD_ENTRY_LOCAL(_kernel_double_fault)
        STD_ENDPROC(_kernel_double_fault)
 
 STD_ENTRY_LOCAL(bad_intr)
-       mfspr   r2, EX_CONTEXT_1_0
+       mfspr   r2, SPR_EX_CONTEXT_K_0
        panic   "Unhandled interrupt %#x: PC %#lx"
        STD_ENDPROC(bad_intr)
 
 /* Put address of pt_regs in reg and jump. */
 #define PTREGS_SYSCALL(x, reg)                          \
-       STD_ENTRY(x);                                   \
+       STD_ENTRY(_##x);                                \
        {                                               \
         PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
-        j      _##x                                    \
+        j      x                                       \
        };                                              \
-       STD_ENDPROC(x)
+       STD_ENDPROC(_##x)
 
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
 PTREGS_SYSCALL(sys_rt_sigreturn, r0)
+PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
-/* Save additional callee-saves to pt_regs, put address in reg and jump. */
-#define PTREGS_SYSCALL_ALL_REGS(x, reg)                 \
-       STD_ENTRY(x);                                   \
-       push_extra_callee_saves reg;                    \
-       j       _##x;                                   \
-       STD_ENDPROC(x)
-
-PTREGS_SYSCALL_ALL_REGS(sys_fork, r0)
-PTREGS_SYSCALL_ALL_REGS(sys_vfork, r0)
-PTREGS_SYSCALL_ALL_REGS(sys_clone, r4)
-PTREGS_SYSCALL_ALL_REGS(sys_cmpxchg_badaddr, r1)
+/* Save additional callee-saves to pt_regs, put address in r4 and jump. */
+STD_ENTRY(_sys_clone)
+       push_extra_callee_saves r4
+       j       sys_clone
+       STD_ENDPROC(_sys_clone)
 
 /*
  * This entrypoint is taken for the cmpxchg and atomic_update fast
@@ -1558,12 +1558,14 @@ PTREGS_SYSCALL_ALL_REGS(sys_cmpxchg_badaddr, r1)
  * to be available to it on entry.  It does not modify any callee-save
  * registers (including "lr").  It does not check what PL it is being
  * called at, so you'd better not call it other than at PL0.
+ * The <atomic.h> wrapper assumes it only clobbers r20-r29, so if
+ * it ever is necessary to use more registers, be aware.
  *
  * It does not use the stack, but since it might be re-interrupted by
  * a page fault which would assume the stack was valid, it does
  * save/restore the stack pointer and zero it out to make sure it gets reset.
  * Since we always keep interrupts disabled, the hypervisor won't
- * clobber our EX_CONTEXT_1_x registers, so we don't save/restore them
+ * clobber our EX_CONTEXT_K_x registers, so we don't save/restore them
  * (other than to advance the PC on return).
  *
  * We have to manually validate the user vs kernel address range
@@ -1769,7 +1771,7 @@ ENTRY(sys_cmpxchg)
        /* Do slow mtspr here so the following "mf" waits less. */
        {
         move   sp, r27
-        mtspr  EX_CONTEXT_1_0, r28
+        mtspr  SPR_EX_CONTEXT_K_0, r28
        }
        mf
 
@@ -1788,7 +1790,7 @@ ENTRY(sys_cmpxchg)
        }
        {
         move   sp, r27
-        mtspr  EX_CONTEXT_1_0, r28
+        mtspr  SPR_EX_CONTEXT_K_0, r28
        }
        iret
 
@@ -1816,7 +1818,7 @@ ENTRY(sys_cmpxchg)
 #endif
 
        /* Issue the slow SPR here while the tns result is in flight. */
-       mfspr   r28, EX_CONTEXT_1_0
+       mfspr   r28, SPR_EX_CONTEXT_K_0
 
        {
         addi   r28, r28, 8    /* return to the instruction after the swint1 */
@@ -1904,7 +1906,7 @@ ENTRY(sys_cmpxchg)
 .Lcmpxchg64_mismatch:
        {
         move   sp, r27
-        mtspr  EX_CONTEXT_1_0, r28
+        mtspr  SPR_EX_CONTEXT_K_0, r28
        }
        mf
        {
@@ -1985,8 +1987,13 @@ int_unalign:
        int_hand     INT_PERF_COUNT, PERF_COUNT, \
                     op_handle_perf_interrupt, handle_nmi
        int_hand     INT_INTCTRL_3, INTCTRL_3, bad_intr
+#if CONFIG_KERNEL_PL == 2
+       dc_dispatch  INT_INTCTRL_2, INTCTRL_2
+       int_hand     INT_INTCTRL_1, INTCTRL_1, bad_intr
+#else
        int_hand     INT_INTCTRL_2, INTCTRL_2, bad_intr
        dc_dispatch  INT_INTCTRL_1, INTCTRL_1
+#endif
        int_hand     INT_INTCTRL_0, INTCTRL_0, bad_intr
        int_hand     INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \
                     hv_message_intr, handle_interrupt_downcall
index 9a27d56..e639176 100644 (file)
@@ -61,9 +61,9 @@ static DEFINE_SPINLOCK(available_irqs_lock);
 
 #if CHIP_HAS_IPI()
 /* Use SPRs to manipulate device interrupts. */
-#define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_1, irq_mask)
-#define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_1, irq_mask)
-#define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_1, irq_mask)
+#define mask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_SET_K, irq_mask)
+#define unmask_irqs(irq_mask) __insn_mtspr(SPR_IPI_MASK_RESET_K, irq_mask)
+#define clear_irqs(irq_mask) __insn_mtspr(SPR_IPI_EVENT_RESET_K, irq_mask)
 #else
 /* Use HV to manipulate device interrupts. */
 #define mask_irqs(irq_mask) hv_disable_intr(irq_mask)
@@ -89,16 +89,16 @@ void tile_dev_intr(struct pt_regs *regs, int intnum)
         * masked by a previous interrupt.  Then, mask out the ones
         * we're going to handle.
         */
-       unsigned long masked = __insn_mfspr(SPR_IPI_MASK_1);
-       original_irqs = __insn_mfspr(SPR_IPI_EVENT_1) & ~masked;
-       __insn_mtspr(SPR_IPI_MASK_SET_1, original_irqs);
+       unsigned long masked = __insn_mfspr(SPR_IPI_MASK_K);
+       original_irqs = __insn_mfspr(SPR_IPI_EVENT_K) & ~masked;
+       __insn_mtspr(SPR_IPI_MASK_SET_K, original_irqs);
 #else
        /*
         * Hypervisor performs the equivalent of the Gx code above and
         * then puts the pending interrupt mask into a system save reg
         * for us to find.
         */
-       original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_1_3);
+       original_irqs = __insn_mfspr(SPR_SYSTEM_SAVE_K_3);
 #endif
        remaining_irqs = original_irqs;
 
@@ -225,7 +225,7 @@ void __cpuinit setup_irq_regs(void)
        /* Enable interrupt delivery. */
        unmask_irqs(~0UL);
 #if CHIP_HAS_IPI()
-       raw_local_irq_unmask(INT_IPI_1);
+       raw_local_irq_unmask(INT_IPI_K);
 #endif
 }
 
index 6d23ed2..997e393 100644 (file)
@@ -34,7 +34,7 @@ void __cpuinit init_messaging(void)
                panic("hv_register_message_state: error %d", rc);
 
        /* Make sure downcall interrupts will be enabled. */
-       raw_local_irq_unmask(INT_INTCTRL_1);
+       raw_local_irq_unmask(INT_INTCTRL_K);
 }
 
 void hv_message_intr(struct pt_regs *regs, int intnum)
index 84c2911..8430f45 100644 (file)
@@ -214,9 +214,10 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        /*
         * Copy the callee-saved registers from the passed pt_regs struct
         * into the context-switch callee-saved registers area.
-        * We have to restore the callee-saved registers since we may
-        * be cloning a userspace task with userspace register state,
-        * and we won't be unwinding the same kernel frames to restore them.
+        * This way when we start the interrupt-return sequence, the
+        * callee-save registers will be correctly in registers, which
+        * is how we assume the compiler leaves them as we start doing
+        * the normal return-from-interrupt path after calling C code.
         * Zero out the C ABI save area to mark the top of the stack.
         */
        ksp = (unsigned long) childregs;
@@ -304,15 +305,25 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 /* Allow user processes to access the DMA SPRs */
 void grant_dma_mpls(void)
 {
+#if CONFIG_KERNEL_PL == 2
+       __insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1);
+       __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1);
+#else
        __insn_mtspr(SPR_MPL_DMA_CPL_SET_0, 1);
        __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_0, 1);
+#endif
 }
 
 /* Forbid user processes from accessing the DMA SPRs */
 void restrict_dma_mpls(void)
 {
+#if CONFIG_KERNEL_PL == 2
+       __insn_mtspr(SPR_MPL_DMA_CPL_SET_2, 1);
+       __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_2, 1);
+#else
        __insn_mtspr(SPR_MPL_DMA_CPL_SET_1, 1);
        __insn_mtspr(SPR_MPL_DMA_NOTIFY_SET_1, 1);
+#endif
 }
 
 /* Pause the DMA engine, then save off its state registers. */
@@ -523,19 +534,14 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
         * Switch kernel SP, PC, and callee-saved registers.
         * In the context of the new task, return the old task pointer
         * (i.e. the task that actually called __switch_to).
-        * Pass the value to use for SYSTEM_SAVE_1_0 when we reset our sp.
+        * Pass the value to use for SYSTEM_SAVE_K_0 when we reset our sp.
         */
        return __switch_to(prev, next, next_current_ksp0(next));
 }
 
-long _sys_fork(struct pt_regs *regs)
-{
-       return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
-}
-
-long _sys_clone(unsigned long clone_flags, unsigned long newsp,
-               void __user *parent_tidptr, void __user *child_tidptr,
-               struct pt_regs *regs)
+SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
+               void __user *, parent_tidptr, void __user *, child_tidptr,
+               struct pt_regs *, regs)
 {
        if (!newsp)
                newsp = regs->sp;
@@ -543,18 +549,13 @@ long _sys_clone(unsigned long clone_flags, unsigned long newsp,
                       parent_tidptr, child_tidptr);
 }
 
-long _sys_vfork(struct pt_regs *regs)
-{
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp,
-                      regs, 0, NULL, NULL);
-}
-
 /*
  * sys_execve() executes a new program.
  */
-long _sys_execve(const char __user *path,
-                const char __user *const __user *argv,
-                const char __user *const __user *envp, struct pt_regs *regs)
+SYSCALL_DEFINE4(execve, const char __user *, path,
+               const char __user *const __user *, argv,
+               const char __user *const __user *, envp,
+               struct pt_regs *, regs)
 {
        long error;
        char *filename;
@@ -570,9 +571,10 @@ out:
 }
 
 #ifdef CONFIG_COMPAT
-long _compat_sys_execve(const char __user *path,
-                       const compat_uptr_t __user *argv,
-                       const compat_uptr_t __user *envp, struct pt_regs *regs)
+long compat_sys_execve(const char __user *path,
+                      const compat_uptr_t __user *argv,
+                      const compat_uptr_t __user *envp,
+                      struct pt_regs *regs)
 {
        long error;
        char *filename;
index 7161bd0..5b20c28 100644 (file)
@@ -32,25 +32,6 @@ void user_disable_single_step(struct task_struct *child)
 }
 
 /*
- * This routine will put a word on the process's privileged stack.
- */
-static void putreg(struct task_struct *task,
-                  unsigned long addr, unsigned long value)
-{
-       unsigned int regno = addr / sizeof(unsigned long);
-       struct pt_regs *childregs = task_pt_regs(task);
-       childregs->regs[regno] = value;
-       childregs->flags |= PT_FLAGS_RESTORE_REGS;
-}
-
-static unsigned long getreg(struct task_struct *task, unsigned long addr)
-{
-       unsigned int regno = addr / sizeof(unsigned long);
-       struct pt_regs *childregs = task_pt_regs(task);
-       return childregs->regs[regno];
-}
-
-/*
  * Called by kernel/ptrace.c when detaching..
  */
 void ptrace_disable(struct task_struct *child)
@@ -66,59 +47,72 @@ void ptrace_disable(struct task_struct *child)
 
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
-       unsigned long __user *datap;
+       unsigned long __user *datap = (long __user __force *)data;
        unsigned long tmp;
        int i;
        long ret = -EIO;
-
-#ifdef CONFIG_COMPAT
-       if (task_thread_info(current)->status & TS_COMPAT)
-               data = (u32)data;
-       if (task_thread_info(child)->status & TS_COMPAT)
-               addr = (u32)addr;
-#endif
-       datap = (unsigned long __user __force *)data;
+       unsigned long *childregs;
+       char *childreg;
 
        switch (request) {
 
        case PTRACE_PEEKUSR:  /* Read register from pt_regs. */
-               if (addr & (sizeof(data)-1))
-                       break;
                if (addr < 0 || addr >= PTREGS_SIZE)
                        break;
-               tmp = getreg(child, addr);   /* Read register */
-               ret = put_user(tmp, datap);
+               childreg = (char *)task_pt_regs(child) + addr;
+#ifdef CONFIG_COMPAT
+               if (is_compat_task()) {
+                       if (addr & (sizeof(compat_long_t)-1))
+                               break;
+                       ret = put_user(*(compat_long_t *)childreg,
+                                      (compat_long_t __user *)datap);
+               } else
+#endif
+               {
+                       if (addr & (sizeof(long)-1))
+                               break;
+                       ret = put_user(*(long *)childreg, datap);
+               }
                break;
 
        case PTRACE_POKEUSR:  /* Write register in pt_regs. */
-               if (addr & (sizeof(data)-1))
-                       break;
                if (addr < 0 || addr >= PTREGS_SIZE)
                        break;
-               putreg(child, addr, data);   /* Write register */
+               childreg = (char *)task_pt_regs(child) + addr;
+#ifdef CONFIG_COMPAT
+               if (is_compat_task()) {
+                       if (addr & (sizeof(compat_long_t)-1))
+                               break;
+                       *(compat_long_t *)childreg = data;
+               } else
+#endif
+               {
+                       if (addr & (sizeof(long)-1))
+                               break;
+                       *(long *)childreg = data;
+               }
                ret = 0;
                break;
 
        case PTRACE_GETREGS:  /* Get all registers from the child. */
                if (!access_ok(VERIFY_WRITE, datap, PTREGS_SIZE))
                        break;
-               for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) {
-                       ret = __put_user(getreg(child, i), datap);
+               childregs = (long *)task_pt_regs(child);
+               for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
+                       ret = __put_user(childregs[i], &datap[i]);
                        if (ret != 0)
                                break;
-                       datap++;
                }
                break;
 
        case PTRACE_SETREGS:  /* Set all registers in the child. */
                if (!access_ok(VERIFY_READ, datap, PTREGS_SIZE))
                        break;
-               for (i = 0; i < PTREGS_SIZE; i += sizeof(long)) {
-                       ret = __get_user(tmp, datap);
+               childregs = (long *)task_pt_regs(child);
+               for (i = 0; i < sizeof(struct pt_regs)/sizeof(long); ++i) {
+                       ret = __get_user(childregs[i], &datap[i]);
                        if (ret != 0)
                                break;
-                       putreg(child, i, tmp);
-                       datap++;
                }
                break;
 
index e88d6e1..caa1310 100644 (file)
@@ -85,7 +85,7 @@ STD_ENTRY_SECTION(__switch_to, .sched.text)
        {
          /* Update sp and ksp0 simultaneously to avoid backtracer warnings. */
          move sp, r13
-         mtspr SYSTEM_SAVE_1_0, r2
+         mtspr SPR_SYSTEM_SAVE_K_0, r2
        }
        FOR_EACH_CALLEE_SAVED_REG(LOAD_REG)
 .L__switch_to_pc:
index e7d54c7..f3a50e7 100644 (file)
@@ -187,11 +187,11 @@ early_param("vmalloc", parse_vmalloc);
 
 #ifdef CONFIG_HIGHMEM
 /*
- * Determine for each controller where its lowmem is mapped and how
- * much of it is mapped there.  On controller zero, the first few
- * megabytes are mapped at 0xfd000000 as code, so in principle we
- * could start our data mappings higher up, but for now we don't
- * bother, to avoid additional confusion.
+ * Determine for each controller where its lowmem is mapped and how much of
+ * it is mapped there.  On controller zero, the first few megabytes are
+ * already mapped in as code at MEM_SV_INTRPT, so in principle we could
+ * start our data mappings higher up, but for now we don't bother, to avoid
+ * additional confusion.
  *
  * One question is whether, on systems with more than 768 Mb and
  * controllers of different sizes, to map in a proportionate amount of
@@ -311,7 +311,7 @@ static void __init setup_memory(void)
 #endif
 
        /* We are using a char to hold the cpu_2_node[] mapping */
-       BUG_ON(MAX_NUMNODES > 127);
+       BUILD_BUG_ON(MAX_NUMNODES > 127);
 
        /* Discover the ranges of memory available to us */
        for (i = 0; ; ++i) {
@@ -876,6 +876,9 @@ void __cpuinit setup_cpu(int boot)
 #if CHIP_HAS_SN_PROC()
        raw_local_irq_unmask(INT_SNITLB_MISS);
 #endif
+#ifdef __tilegx__
+       raw_local_irq_unmask(INT_SINGLE_STEP_K);
+#endif
 
        /*
         * Allow user access to many generic SPRs, like the cycle
@@ -893,11 +896,12 @@ void __cpuinit setup_cpu(int boot)
 #endif
 
        /*
-        * Set the MPL for interrupt control 0 to user level.
-        * This includes access to the SYSTEM_SAVE and EX_CONTEXT SPRs,
-        * as well as the PL 0 interrupt mask.
+        * Set the MPL for interrupt control 0 & 1 to the corresponding
+        * values.  This includes access to the SYSTEM_SAVE and EX_CONTEXT
+        * SPRs, as well as the interrupt mask.
         */
        __insn_mtspr(SPR_MPL_INTCTRL_0_SET_0, 1);
+       __insn_mtspr(SPR_MPL_INTCTRL_1_SET_1, 1);
 
        /* Initialize IRQ support for this cpu. */
        setup_irq_regs();
@@ -1033,7 +1037,7 @@ static void __init validate_va(void)
         * In addition, make sure we CAN'T use the end of memory, since
         * we use the last chunk of each pgd for the pgd_list.
         */
-       int i, fc_fd_ok = 0;
+       int i, user_kernel_ok = 0;
        unsigned long max_va = 0;
        unsigned long list_va =
                ((PGD_LIST_OFFSET / sizeof(pgd_t)) << PGDIR_SHIFT);
@@ -1044,13 +1048,13 @@ static void __init validate_va(void)
                        break;
                if (range.start <= MEM_USER_INTRPT &&
                    range.start + range.size >= MEM_HV_INTRPT)
-                       fc_fd_ok = 1;
+                       user_kernel_ok = 1;
                if (range.start == 0)
                        max_va = range.size;
                BUG_ON(range.start + range.size > list_va);
        }
-       if (!fc_fd_ok)
-               early_panic("Hypervisor not configured for VAs 0xfc/0xfd\n");
+       if (!user_kernel_ok)
+               early_panic("Hypervisor not configured for user/kernel VAs\n");
        if (max_va == 0)
                early_panic("Hypervisor not configured for low VAs\n");
        if (max_va < KERNEL_HIGH_VADDR)
@@ -1334,6 +1338,10 @@ static void __init pcpu_fc_populate_pte(unsigned long addr)
        pte_t *pte;
 
        BUG_ON(pgd_addr_invalid(addr));
+       if (addr < VMALLOC_START || addr >= VMALLOC_END)
+               panic("PCPU addr %#lx outside vmalloc range %#lx..%#lx;"
+                     " try increasing CONFIG_VMALLOC_RESERVE\n",
+                     addr, VMALLOC_START, VMALLOC_END);
 
        pgd = swapper_pg_dir + pgd_index(addr);
        pud = pud_offset(pgd, addr);
index ce183aa..fb28e85 100644 (file)
@@ -41,8 +41,8 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
-long _sys_sigaltstack(const stack_t __user *uss,
-                     stack_t __user *uoss, struct pt_regs *regs)
+SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
+               stack_t __user *, uoss, struct pt_regs *, regs)
 {
        return do_sigaltstack(uss, uoss, regs->sp);
 }
@@ -78,7 +78,7 @@ int restore_sigcontext(struct pt_regs *regs,
 }
 
 /* sigreturn() returns long since it restores r0 in the interrupted code. */
-long _sys_rt_sigreturn(struct pt_regs *regs)
+SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 {
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(regs->sp);
index 5ec4b9c..1eb3b39 100644 (file)
@@ -15,7 +15,7 @@
  * Derived from iLib's single-stepping code.
  */
 
-#ifndef __tilegx__   /* No support for single-step yet. */
+#ifndef __tilegx__   /* Hardware support for single step unavailable. */
 
 /* These functions are only used on the TILE platform */
 #include <linux/slab.h>
@@ -660,4 +660,75 @@ void single_step_once(struct pt_regs *regs)
                regs->pc += 8;
 }
 
+#else
+#include <linux/smp.h>
+#include <linux/ptrace.h>
+#include <arch/spr_def.h>
+
+static DEFINE_PER_CPU(unsigned long, ss_saved_pc);
+
+
+/*
+ * Called directly on the occasion of an interrupt.
+ *
+ * If the process doesn't have single step set, then we use this as an
+ * opportunity to turn single step off.
+ *
+ * It has been mentioned that we could conditionally turn off single stepping
+ * on each entry into the kernel and rely on single_step_once to turn it
+ * on for the processes that matter (as we already do), but this
+ * implementation is somewhat more efficient in that we muck with registers
+ * once on a bum interrupt rather than on every entry into the kernel.
+ *
+ * If SINGLE_STEP_CONTROL_K has CANCELED set, then an interrupt occurred,
+ * so we have to run through this process again before we can say that an
+ * instruction has executed.
+ *
+ * swint will set CANCELED, but it's a legitimate instruction.  Fortunately
+ * it changes the PC.  If it hasn't changed, then we know that the interrupt
+ * wasn't generated by swint and we'll need to run this process again before
+ * we can say an instruction has executed.
+ *
+ * If either CANCELED == 0 or the PC's changed, we send out SIGTRAPs and get
+ * on with our lives.
+ */
+
+void gx_singlestep_handle(struct pt_regs *regs, int fault_num)
+{
+       unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
+       struct thread_info *info = (void *)current_thread_info();
+       int is_single_step = test_ti_thread_flag(info, TIF_SINGLESTEP);
+       unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);
+
+       if (is_single_step == 0) {
+               __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 0);
+
+       } else if ((*ss_pc != regs->pc) ||
+                  (!(control & SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK))) {
+
+               ptrace_notify(SIGTRAP);
+               control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
+               control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
+               __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
+       }
+}
+
+
+/*
+ * Called from need_singlestep.  Set up the control registers and the enable
+ * register, then return back.
+ */
+
+void single_step_once(struct pt_regs *regs)
+{
+       unsigned long *ss_pc = &__get_cpu_var(ss_saved_pc);
+       unsigned long control = __insn_mfspr(SPR_SINGLE_STEP_CONTROL_K);
+
+       *ss_pc = regs->pc;
+       control |= SPR_SINGLE_STEP_CONTROL_1__CANCELED_MASK;
+       control |= SPR_SINGLE_STEP_CONTROL_1__INHIBIT_MASK;
+       __insn_mtspr(SPR_SINGLE_STEP_CONTROL_K, control);
+       __insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL);
+}
+
 #endif /* !__tilegx__ */
index 1cb5ec7..75255d9 100644 (file)
@@ -212,7 +212,7 @@ void __init ipi_init(void)
 
                tile.x = cpu_x(cpu);
                tile.y = cpu_y(cpu);
-               if (hv_get_ipi_pte(tile, 1, &pte) != 0)
+               if (hv_get_ipi_pte(tile, KERNEL_PL, &pte) != 0)
                        panic("Failed to initialize IPI for cpu %d\n", cpu);
 
                offset = hv_pte_get_pfn(pte) << PAGE_SHIFT;
index ea2e0ce..0d54106 100644 (file)
 #include <arch/abi.h>
 #include <arch/interrupts.h>
 
+#define KBT_ONGOING    0  /* Backtrace still ongoing */
+#define KBT_DONE       1  /* Backtrace cleanly completed */
+#define KBT_RUNNING    2  /* Can't run backtrace on a running task */
+#define KBT_LOOP       3  /* Backtrace entered a loop */
 
 /* Is address on the specified kernel stack? */
 static int in_kernel_stack(struct KBacktraceIterator *kbt, VirtualAddress sp)
@@ -207,11 +211,11 @@ static int KBacktraceIterator_next_item_inclusive(
        for (;;) {
                do {
                        if (!KBacktraceIterator_is_sigreturn(kbt))
-                               return 1;
+                               return KBT_ONGOING;
                } while (backtrace_next(&kbt->it));
 
                if (!KBacktraceIterator_restart(kbt))
-                       return 0;
+                       return KBT_DONE;
        }
 }
 
@@ -264,7 +268,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
        kbt->pgtable = NULL;
        kbt->verbose = 0;   /* override in caller if desired */
        kbt->profile = 0;   /* override in caller if desired */
-       kbt->end = 0;
+       kbt->end = KBT_ONGOING;
        kbt->new_context = 0;
        if (is_current) {
                HV_PhysAddr pgdir_pa = hv_inquire_context().page_table;
@@ -290,7 +294,7 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
        if (regs == NULL) {
                if (is_current || t->state == TASK_RUNNING) {
                        /* Can't do this; we need registers */
-                       kbt->end = 1;
+                       kbt->end = KBT_RUNNING;
                        return;
                }
                pc = get_switch_to_pc();
@@ -305,26 +309,29 @@ void KBacktraceIterator_init(struct KBacktraceIterator *kbt,
        }
 
        backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52);
-       kbt->end = !KBacktraceIterator_next_item_inclusive(kbt);
+       kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
 }
 EXPORT_SYMBOL(KBacktraceIterator_init);
 
 int KBacktraceIterator_end(struct KBacktraceIterator *kbt)
 {
-       return kbt->end;
+       return kbt->end != KBT_ONGOING;
 }
 EXPORT_SYMBOL(KBacktraceIterator_end);
 
 void KBacktraceIterator_next(struct KBacktraceIterator *kbt)
 {
+       VirtualAddress old_pc = kbt->it.pc, old_sp = kbt->it.sp;
        kbt->new_context = 0;
-       if (!backtrace_next(&kbt->it) &&
-           !KBacktraceIterator_restart(kbt)) {
-                       kbt->end = 1;
-                       return;
-               }
-
-       kbt->end = !KBacktraceIterator_next_item_inclusive(kbt);
+       if (!backtrace_next(&kbt->it) && !KBacktraceIterator_restart(kbt)) {
+               kbt->end = KBT_DONE;
+               return;
+       }
+       kbt->end = KBacktraceIterator_next_item_inclusive(kbt);
+       if (old_pc == kbt->it.pc && old_sp == kbt->it.sp) {
+               /* Trapped in a loop; give up. */
+               kbt->end = KBT_LOOP;
+       }
 }
 EXPORT_SYMBOL(KBacktraceIterator_next);
 
@@ -387,6 +394,8 @@ void tile_show_stack(struct KBacktraceIterator *kbt, int headers)
                        break;
                }
        }
+       if (kbt->end == KBT_LOOP)
+               pr_err("Stack dump stopped; next frame identical to this one\n");
        if (headers)
                pr_err("Stack dump complete\n");
 }
index f0f87ea..7e76466 100644 (file)
@@ -110,6 +110,15 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
 #define sys_sync_file_range sys_sync_file_range2
 #endif
 
+/* Call the trampolines to manage pt_regs where necessary. */
+#define sys_execve _sys_execve
+#define sys_sigaltstack _sys_sigaltstack
+#define sys_rt_sigreturn _sys_rt_sigreturn
+#define sys_clone _sys_clone
+#ifndef __tilegx__
+#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr
+#endif
+
 /*
  * Note that we can't include <linux/unistd.h> here since the header
  * guard will defeat us; <asm/unistd.h> checks for __SYSCALL as well.
index 0f362dc..5474fc2 100644 (file)
@@ -260,7 +260,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
                address = regs->pc;
                break;
        case INT_UNALIGN_DATA:
-#ifndef __tilegx__  /* FIXME: GX: no single-step yet */
+#ifndef __tilegx__  /* Emulated support for single step debugging */
                if (unaligned_fixup >= 0) {
                        struct single_step_state *state =
                                current_thread_info()->step_state;
@@ -278,7 +278,7 @@ void __kprobes do_trap(struct pt_regs *regs, int fault_num,
        case INT_DOUBLE_FAULT:
                /*
                 * For double fault, "reason" is actually passed as
-                * SYSTEM_SAVE_1_2, the hypervisor's double-fault info, so
+                * SYSTEM_SAVE_K_2, the hypervisor's double-fault info, so
                 * we can provide the original fault number rather than
                 * the uninteresting "INT_DOUBLE_FAULT" so the user can
                 * learn what actually struck while PL0 ICS was set.
diff --git a/arch/tile/kvm/Kconfig b/arch/tile/kvm/Kconfig
new file mode 100644 (file)
index 0000000..b88f9c0
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# KVM configuration
+#
+
+source "virt/kvm/Kconfig"
+
+menuconfig VIRTUALIZATION
+       bool "Virtualization"
+       ---help---
+         Say Y here to get to see options for using your Linux host to run
+         other operating systems inside virtual machines (guests).
+         This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and
+         disabled.
+
+if VIRTUALIZATION
+
+config KVM
+       tristate "Kernel-based Virtual Machine (KVM) support"
+       depends on HAVE_KVM && MODULES && EXPERIMENTAL
+       select PREEMPT_NOTIFIERS
+       select ANON_INODES
+       ---help---
+         Support hosting paravirtualized guest machines.
+
+         This module provides access to the hardware capabilities through
+         a character device node named /dev/kvm.
+
+         To compile this as a module, choose M here: the module
+         will be called kvm.
+
+         If unsure, say N.
+
+source drivers/vhost/Kconfig
+source drivers/virtio/Kconfig
+
+endif # VIRTUALIZATION
index 746dc81..93122d5 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 lib-y = cacheflush.o checksum.o cpumask.o delay.o \
-       mb_incoherent.o uaccess.o \
-       memcpy_$(BITS).o memchr_$(BITS).o memmove_$(BITS).o memset_$(BITS).o \
+       mb_incoherent.o uaccess.o memmove.o \
+       memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
        strchr_$(BITS).o strlen_$(BITS).o
 
 ifeq ($(CONFIG_TILEGX),y)
index 8040b42..7a5cc70 100644 (file)
@@ -300,7 +300,7 @@ void __init __init_atomic_per_cpu(void)
 #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
        /* Validate power-of-two and "bigger than cpus" assumption */
-       BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1));
+       BUILD_BUG_ON(ATOMIC_HASH_SIZE & (ATOMIC_HASH_SIZE-1));
        BUG_ON(ATOMIC_HASH_SIZE < nr_cpu_ids);
 
        /*
@@ -314,17 +314,17 @@ void __init __init_atomic_per_cpu(void)
        BUG_ON((unsigned long)atomic_locks % PAGE_SIZE != 0);
 
        /* The locks must all fit on one page. */
-       BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE);
+       BUILD_BUG_ON(ATOMIC_HASH_SIZE * sizeof(int) > PAGE_SIZE);
 
        /*
         * We use the page offset of the atomic value's address as
         * an index into atomic_locks, excluding the low 3 bits.
         * That should not produce more indices than ATOMIC_HASH_SIZE.
         */
-       BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
+       BUILD_BUG_ON((PAGE_SIZE >> 3) > ATOMIC_HASH_SIZE);
 
 #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
        /* The futex code makes this assumption, so we validate it here. */
-       BUG_ON(sizeof(atomic_t) != sizeof(int));
+       BUILD_BUG_ON(sizeof(atomic_t) != sizeof(int));
 }
index ce5dbf5..1509c55 100644 (file)
@@ -45,6 +45,9 @@ EXPORT_SYMBOL(__copy_from_user_zeroing);
 EXPORT_SYMBOL(__copy_in_user_inatomic);
 #endif
 
+/* arch/tile/lib/mb_incoherent.S */
+EXPORT_SYMBOL(__mb_incoherent);
+
 /* hypervisor glue */
 #include <hv/hypervisor.h>
 EXPORT_SYMBOL(hv_dev_open);
index 30c3b7e..2a419a6 100644 (file)
  *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  *   NON INFRINGEMENT.  See the GNU General Public License for
  *   more details.
- *
- * This file shares the implementation of the userspace memcpy and
- * the kernel's memcpy, copy_to_user and copy_from_user.
  */
 
 #include <arch/chip.h>
 
 
+/*
+ * This file shares the implementation of the userspace memcpy and
+ * the kernel's memcpy, copy_to_user and copy_from_user.
+ */
+
 #include <linux/linkage.h>
 
 /* On TILE64, we wrap these functions via arch/tile/lib/memcpy_tile64.c */
@@ -53,9 +55,9 @@
  */
 ENTRY(__copy_from_user_inatomic)
 .type __copy_from_user_inatomic, @function
-        FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \
+       FEEDBACK_ENTER_EXPLICIT(__copy_from_user_inatomic, \
          .text.memcpy_common, \
-          .Lend_memcpy_common - __copy_from_user_inatomic)
+         .Lend_memcpy_common - __copy_from_user_inatomic)
        { movei r29, IS_COPY_FROM_USER; j memcpy_common }
        .size __copy_from_user_inatomic, . - __copy_from_user_inatomic
 
@@ -64,7 +66,7 @@ ENTRY(__copy_from_user_inatomic)
  */
 ENTRY(__copy_from_user_zeroing)
 .type __copy_from_user_zeroing, @function
-        FEEDBACK_REENTER(__copy_from_user_inatomic)
+       FEEDBACK_REENTER(__copy_from_user_inatomic)
        { movei r29, IS_COPY_FROM_USER_ZEROING; j memcpy_common }
        .size __copy_from_user_zeroing, . - __copy_from_user_zeroing
 
@@ -74,13 +76,13 @@ ENTRY(__copy_from_user_zeroing)
  */
 ENTRY(__copy_to_user_inatomic)
 .type __copy_to_user_inatomic, @function
-        FEEDBACK_REENTER(__copy_from_user_inatomic)
+       FEEDBACK_REENTER(__copy_from_user_inatomic)
        { movei r29, IS_COPY_TO_USER; j memcpy_common }
        .size __copy_to_user_inatomic, . - __copy_to_user_inatomic
 
 ENTRY(memcpy)
 .type memcpy, @function
-        FEEDBACK_REENTER(__copy_from_user_inatomic)
+       FEEDBACK_REENTER(__copy_from_user_inatomic)
        { movei r29, IS_MEMCPY }
        .size memcpy, . - memcpy
        /* Fall through */
@@ -157,35 +159,35 @@ EX:       { sw r0, r3; addi r0, r0, 4; addi r2, r2, -4 }
        { addi r3, r1, 60; andi r9, r9, -64 }
 
 #if CHIP_HAS_WH64()
-        /* No need to prefetch dst, we'll just do the wh64
-         * right before we copy a line.
+       /* No need to prefetch dst, we'll just do the wh64
+        * right before we copy a line.
         */
 #endif
 
 EX:    { lw r5, r3; addi r3, r3, 64; movei r4, 1 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, .; move r27, lr }
+       /* Intentionally stall for a few cycles to leave L2 cache alone. */
+       { bnzt zero, .; move r27, lr }
 EX:    { lw r6, r3; addi r3, r3, 64 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
+       /* Intentionally stall for a few cycles to leave L2 cache alone. */
+       { bnzt zero, . }
 EX:    { lw r7, r3; addi r3, r3, 64 }
 #if !CHIP_HAS_WH64()
-        /* Prefetch the dest */
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
-        /* Use a real load to cause a TLB miss if necessary.  We aren't using
-         * r28, so this should be fine.
-         */
+       /* Prefetch the dest */
+       /* Intentionally stall for a few cycles to leave L2 cache alone. */
+       { bnzt zero, . }
+       /* Use a real load to cause a TLB miss if necessary.  We aren't using
+        * r28, so this should be fine.
+        */
 EX:    { lw r28, r9; addi r9, r9, 64 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
-        { prefetch r9; addi r9, r9, 64 }
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bnzt zero, . }
-        { prefetch r9; addi r9, r9, 64 }
+       /* Intentionally stall for a few cycles to leave L2 cache alone. */
+       { bnzt zero, . }
+       { prefetch r9; addi r9, r9, 64 }
+       /* Intentionally stall for a few cycles to leave L2 cache alone. */
+       { bnzt zero, . }
+       { prefetch r9; addi r9, r9, 64 }
 #endif
-        /* Intentionally stall for a few cycles to leave L2 cache alone. */
-        { bz zero, .Lbig_loop2 }
+       /* Intentionally stall for a few cycles to leave L2 cache alone. */
+       { bz zero, .Lbig_loop2 }
 
        /* On entry to this loop:
         * - r0 points to the start of dst line 0
@@ -197,7 +199,7 @@ EX: { lw r28, r9; addi r9, r9, 64 }
         *   to some "safe" recently loaded address.
         * - r5 contains *(r1 + 60)       [i.e. last word of source line 0]
         * - r6 contains *(r1 + 64 + 60)  [i.e. last word of source line 1]
-         * - r9 contains ((r0 + 63) & -64)
+        * - r9 contains ((r0 + 63) & -64)
         *     [start of next dst cache line.]
         */
 
@@ -208,137 +210,137 @@ EX:     { lw r28, r9; addi r9, r9, 64 }
        /* Copy line 0, first stalling until r5 is ready. */
 EX:    { move r12, r5; lw r16, r1 }
        { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
-        /* Prefetch several lines ahead. */
+       /* Prefetch several lines ahead. */
 EX:    { lw r5, r3; addi r3, r3, 64 }
-        { jal .Lcopy_line }
+       { jal .Lcopy_line }
 
        /* Copy line 1, first stalling until r6 is ready. */
 EX:    { move r12, r6; lw r16, r1 }
        { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
-        /* Prefetch several lines ahead. */
+       /* Prefetch several lines ahead. */
 EX:    { lw r6, r3; addi r3, r3, 64 }
        { jal .Lcopy_line }
 
        /* Copy line 2, first stalling until r7 is ready. */
 EX:    { move r12, r7; lw r16, r1 }
        { bz r4, .Lcopy_8_check; slti_u r8, r2, 8 }
-        /* Prefetch several lines ahead. */
+       /* Prefetch several lines ahead. */
 EX:    { lw r7, r3; addi r3, r3, 64 }
-        /* Use up a caches-busy cycle by jumping back to the top of the
-         * loop. Might as well get it out of the way now.
-         */
-        { j .Lbig_loop }
+       /* Use up a caches-busy cycle by jumping back to the top of the
+        * loop. Might as well get it out of the way now.
+        */
+       { j .Lbig_loop }
 
 
        /* On entry:
         * - r0 points to the destination line.
         * - r1 points to the source line.
-         * - r3 is the next prefetch address.
+        * - r3 is the next prefetch address.
         * - r9 holds the last address used for wh64.
         * - r12 = WORD_15
-         * - r16 = WORD_0.
-         * - r17 == r1 + 16.
-         * - r27 holds saved lr to restore.
+        * - r16 = WORD_0.
+        * - r17 == r1 + 16.
+        * - r27 holds saved lr to restore.
         *
         * On exit:
         * - r0 is incremented by 64.
         * - r1 is incremented by 64, unless that would point to a word
-         *   beyond the end of the source array, in which case it is redirected
-         *   to point to an arbitrary word already in the cache.
+        *   beyond the end of the source array, in which case it is redirected
+        *   to point to an arbitrary word already in the cache.
         * - r2 is decremented by 64.
-         * - r3 is unchanged, unless it points to a word beyond the
-         *   end of the source array, in which case it is redirected
-         *   to point to an arbitrary word already in the cache.
-         *   Redirecting is OK since if we are that close to the end
-         *   of the array we will not come back to this subroutine
-         *   and use the contents of the prefetched address.
+        * - r3 is unchanged, unless it points to a word beyond the
+        *   end of the source array, in which case it is redirected
+        *   to point to an arbitrary word already in the cache.
+        *   Redirecting is OK since if we are that close to the end
+        *   of the array we will not come back to this subroutine
+        *   and use the contents of the prefetched address.
         * - r4 is nonzero iff r2 >= 64.
-         * - r9 is incremented by 64, unless it points beyond the
-         *   end of the last full destination cache line, in which
-         *   case it is redirected to a "safe address" that can be
-         *   clobbered (sp - 64)
+        * - r9 is incremented by 64, unless it points beyond the
+        *   end of the last full destination cache line, in which
+        *   case it is redirected to a "safe address" that can be
+        *   clobbered (sp - 64)
         * - lr contains the value in r27.
         */
 
 /* r26 unused */
 
 .Lcopy_line:
-        /* TODO: when r3 goes past the end, we would like to redirect it
-         * to prefetch the last partial cache line (if any) just once, for the
-         * benefit of the final cleanup loop. But we don't want to
-         * prefetch that line more than once, or subsequent prefetches
-         * will go into the RTF. But then .Lbig_loop should unconditionally
-         * branch to top of loop to execute final prefetch, and its
-         * nop should become a conditional branch.
-         */
-
-        /* We need two non-memory cycles here to cover the resources
-         * used by the loads initiated by the caller.
-         */
-        { add r15, r1, r2 }
+       /* TODO: when r3 goes past the end, we would like to redirect it
+        * to prefetch the last partial cache line (if any) just once, for the
+        * benefit of the final cleanup loop. But we don't want to
+        * prefetch that line more than once, or subsequent prefetches
+        * will go into the RTF. But then .Lbig_loop should unconditionally
+        * branch to top of loop to execute final prefetch, and its
+        * nop should become a conditional branch.
+        */
+
+       /* We need two non-memory cycles here to cover the resources
+        * used by the loads initiated by the caller.
+        */
+       { add r15, r1, r2 }
 .Lcopy_line2:
-        { slt_u r13, r3, r15; addi r17, r1, 16 }
+       { slt_u r13, r3, r15; addi r17, r1, 16 }
 
-        /* NOTE: this will stall for one cycle as L1 is busy. */
+       /* NOTE: this will stall for one cycle as L1 is busy. */
 
-        /* Fill second L1D line. */
+       /* Fill second L1D line. */
 EX:    { lw r17, r17; addi r1, r1, 48; mvz r3, r13, r1 } /* r17 = WORD_4 */
 
 #if CHIP_HAS_WH64()
-        /* Prepare destination line for writing. */
+       /* Prepare destination line for writing. */
 EX:    { wh64 r9; addi r9, r9, 64 }
 #else
-        /* Prefetch dest line */
+       /* Prefetch dest line */
        { prefetch r9; addi r9, r9, 64 }
 #endif
-        /* Load seven words that are L1D hits to cover wh64 L2 usage. */
+       /* Load seven words that are L1D hits to cover wh64 L2 usage. */
 
-        /* Load the three remaining words from the last L1D line, which
-         * we know has already filled the L1D.
-         */
+       /* Load the three remaining words from the last L1D line, which
+        * we know has already filled the L1D.
+        */
 EX:    { lw r4, r1;  addi r1, r1, 4;   addi r20, r1, 16 }   /* r4 = WORD_12 */
 EX:    { lw r8, r1;  addi r1, r1, 4;   slt_u r13, r20, r15 }/* r8 = WORD_13 */
 EX:    { lw r11, r1; addi r1, r1, -52; mvz r20, r13, r1 }  /* r11 = WORD_14 */
 
-        /* Load the three remaining words from the first L1D line, first
-         * stalling until it has filled by "looking at" r16.
-         */
+       /* Load the three remaining words from the first L1D line, first
+        * stalling until it has filled by "looking at" r16.
+        */
 EX:    { lw r13, r1; addi r1, r1, 4; move zero, r16 }   /* r13 = WORD_1 */
 EX:    { lw r14, r1; addi r1, r1, 4 }                   /* r14 = WORD_2 */
 EX:    { lw r15, r1; addi r1, r1, 8; addi r10, r0, 60 } /* r15 = WORD_3 */
 
-        /* Load second word from the second L1D line, first
-         * stalling until it has filled by "looking at" r17.
-         */
+       /* Load second word from the second L1D line, first
+        * stalling until it has filled by "looking at" r17.
+        */
 EX:    { lw r19, r1; addi r1, r1, 4; move zero, r17 }  /* r19 = WORD_5 */
 
-        /* Store last word to the destination line, potentially dirtying it
-         * for the first time, which keeps the L2 busy for two cycles.
-         */
+       /* Store last word to the destination line, potentially dirtying it
+        * for the first time, which keeps the L2 busy for two cycles.
+        */
 EX:    { sw r10, r12 }                                 /* store(WORD_15) */
 
-        /* Use two L1D hits to cover the sw L2 access above. */
+       /* Use two L1D hits to cover the sw L2 access above. */
 EX:    { lw r10, r1; addi r1, r1, 4 }                  /* r10 = WORD_6 */
 EX:    { lw r12, r1; addi r1, r1, 4 }                  /* r12 = WORD_7 */
 
-        /* Fill third L1D line. */
+       /* Fill third L1D line. */
 EX:    { lw r18, r1; addi r1, r1, 4 }                  /* r18 = WORD_8 */
 
-        /* Store first L1D line. */
+       /* Store first L1D line. */
 EX:    { sw r0, r16; addi r0, r0, 4; add r16, r0, r2 } /* store(WORD_0) */
 EX:    { sw r0, r13; addi r0, r0, 4; andi r16, r16, -64 } /* store(WORD_1) */
 EX:    { sw r0, r14; addi r0, r0, 4; slt_u r16, r9, r16 } /* store(WORD_2) */
 #if CHIP_HAS_WH64()
 EX:    { sw r0, r15; addi r0, r0, 4; addi r13, sp, -64 } /* store(WORD_3) */
 #else
-        /* Back up the r9 to a cache line we are already storing to
+       /* Back up the r9 to a cache line we are already storing to
         * if it gets past the end of the dest vector.  Strictly speaking,
         * we don't need to back up to the start of a cache line, but it's free
         * and tidy, so why not?
-         */
+        */
 EX:    { sw r0, r15; addi r0, r0, 4; andi r13, r0, -64 } /* store(WORD_3) */
 #endif
-        /* Store second L1D line. */
+       /* Store second L1D line. */
 EX:    { sw r0, r17; addi r0, r0, 4; mvz r9, r16, r13 }/* store(WORD_4) */
 EX:    { sw r0, r19; addi r0, r0, 4 }                  /* store(WORD_5) */
 EX:    { sw r0, r10; addi r0, r0, 4 }                  /* store(WORD_6) */
@@ -348,30 +350,30 @@ EX:       { lw r13, r1; addi r1, r1, 4; move zero, r18 }  /* r13 = WORD_9 */
 EX:    { lw r14, r1; addi r1, r1, 4 }                  /* r14 = WORD_10 */
 EX:    { lw r15, r1; move r1, r20   }                  /* r15 = WORD_11 */
 
-        /* Store third L1D line. */
+       /* Store third L1D line. */
 EX:    { sw r0, r18; addi r0, r0, 4 }                  /* store(WORD_8) */
 EX:    { sw r0, r13; addi r0, r0, 4 }                  /* store(WORD_9) */
 EX:    { sw r0, r14; addi r0, r0, 4 }                  /* store(WORD_10) */
 EX:    { sw r0, r15; addi r0, r0, 4 }                  /* store(WORD_11) */
 
-        /* Store rest of fourth L1D line. */
+       /* Store rest of fourth L1D line. */
 EX:    { sw r0, r4;  addi r0, r0, 4 }                  /* store(WORD_12) */
-        {
+       {
 EX:    sw r0, r8                                       /* store(WORD_13) */
-        addi r0, r0, 4
+       addi r0, r0, 4
        /* Will r2 be > 64 after we subtract 64 below? */
-        shri r4, r2, 7
-        }
-        {
+       shri r4, r2, 7
+       }
+       {
 EX:    sw r0, r11                                      /* store(WORD_14) */
-        addi r0, r0, 8
-        /* Record 64 bytes successfully copied. */
-        addi r2, r2, -64
-        }
+       addi r0, r0, 8
+       /* Record 64 bytes successfully copied. */
+       addi r2, r2, -64
+       }
 
        { jrp lr; move lr, r27 }
 
-        /* Convey to the backtrace library that the stack frame is size
+       /* Convey to the backtrace library that the stack frame is size
         * zero, and the real return address is on the stack rather than
         * in 'lr'.
         */
diff --git a/arch/tile/lib/memmove.c b/arch/tile/lib/memmove.c
new file mode 100644 (file)
index 0000000..fd615ae
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+       if ((const char *)src >= (char *)dest + n
+           || (char *)dest >= (const char *)src + n) {
+               /* We found no overlap, so let memcpy do all the heavy
+                * lifting (prefetching, etc.)
+                */
+               return memcpy(dest, src, n);
+       }
+
+       if (n != 0) {
+               const uint8_t *in;
+               uint8_t x;
+               uint8_t *out;
+               int stride;
+
+               if (src < dest) {
+                       /* copy backwards */
+                       in = (const uint8_t *)src + n - 1;
+                       out = (uint8_t *)dest + n - 1;
+                       stride = -1;
+               } else {
+                       /* copy forwards */
+                       in = (const uint8_t *)src;
+                       out = (uint8_t *)dest;
+                       stride = 1;
+               }
+
+               /* Manually software-pipeline this loop. */
+               x = *in;
+               in += stride;
+
+               while (--n != 0) {
+                       *out = x;
+                       out += stride;
+                       x = *in;
+                       in += stride;
+               }
+
+               *out = x;
+       }
+
+       return dest;
+}
+EXPORT_SYMBOL(memmove);
diff --git a/arch/tile/lib/memmove_32.c b/arch/tile/lib/memmove_32.c
deleted file mode 100644 (file)
index fd615ae..0000000
+++ /dev/null
@@ -1,63 +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.
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/module.h>
-
-void *memmove(void *dest, const void *src, size_t n)
-{
-       if ((const char *)src >= (char *)dest + n
-           || (char *)dest >= (const char *)src + n) {
-               /* We found no overlap, so let memcpy do all the heavy
-                * lifting (prefetching, etc.)
-                */
-               return memcpy(dest, src, n);
-       }
-
-       if (n != 0) {
-               const uint8_t *in;
-               uint8_t x;
-               uint8_t *out;
-               int stride;
-
-               if (src < dest) {
-                       /* copy backwards */
-                       in = (const uint8_t *)src + n - 1;
-                       out = (uint8_t *)dest + n - 1;
-                       stride = -1;
-               } else {
-                       /* copy forwards */
-                       in = (const uint8_t *)src;
-                       out = (uint8_t *)dest;
-                       stride = 1;
-               }
-
-               /* Manually software-pipeline this loop. */
-               x = *in;
-               in += stride;
-
-               while (--n != 0) {
-                       *out = x;
-                       out += stride;
-                       x = *in;
-                       in += stride;
-               }
-
-               *out = x;
-       }
-
-       return dest;
-}
-EXPORT_SYMBOL(memmove);
index d014c1f..57dbb3a 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
+#undef memset
 
 void *memset(void *s, int c, size_t n)
 {
index f26f88e..4974292 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/string.h>
 #include <linux/module.h>
 
+#undef strlen
+
 size_t strlen(const char *s)
 {
        /* Get an aligned pointer. */
index 704f3e8..f295b4a 100644 (file)
@@ -66,10 +66,10 @@ static noinline void force_sig_info_fault(int si_signo, int si_code,
 #ifndef __tilegx__
 /*
  * Synthesize the fault a PL0 process would get by doing a word-load of
- * an unaligned address or a high kernel address.  Called indirectly
- * from sys_cmpxchg() in kernel/intvec.S.
+ * an unaligned address or a high kernel address.
  */
-int _sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *regs)
+SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address,
+               struct pt_regs *, regs)
 {
        if (address >= PAGE_OFFSET)
                force_sig_info_fault(SIGSEGV, SEGV_MAPERR, address,
@@ -563,10 +563,10 @@ do_sigbus:
 /*
  * When we take an ITLB or DTLB fault or access violation in the
  * supervisor while the critical section bit is set, the hypervisor is
- * reluctant to write new values into the EX_CONTEXT_1_x registers,
+ * reluctant to write new values into the EX_CONTEXT_K_x registers,
  * since that might indicate we have not yet squirreled the SPR
  * contents away and can thus safely take a recursive interrupt.
- * Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_1_2.
+ * Accordingly, the hypervisor passes us the PC via SYSTEM_SAVE_K_2.
  *
  * Note that this routine is called before homecache_tlb_defer_enter(),
  * which means that we can properly unlock any atomics that might
@@ -610,7 +610,7 @@ struct intvec_state do_page_fault_ics(struct pt_regs *regs, int fault_num,
         * fault.  We didn't set up a kernel stack on initial entry to
         * sys_cmpxchg, but instead had one set up by the fault, which
         * (because sys_cmpxchg never releases ICS) came to us via the
-        * SYSTEM_SAVE_1_2 mechanism, and thus EX_CONTEXT_1_[01] are
+        * SYSTEM_SAVE_K_2 mechanism, and thus EX_CONTEXT_K_[01] are
         * still referencing the original user code.  We release the
         * atomic lock and rewrite pt_regs so that it appears that we
         * came from user-space directly, and after we finish the
index 12ab137..8ef6595 100644 (file)
@@ -56,50 +56,6 @@ void kunmap(struct page *page)
 }
 EXPORT_SYMBOL(kunmap);
 
-static void debug_kmap_atomic_prot(enum km_type type)
-{
-#ifdef CONFIG_DEBUG_HIGHMEM
-       static unsigned warn_count = 10;
-
-       if (unlikely(warn_count == 0))
-               return;
-
-       if (unlikely(in_interrupt())) {
-               if (in_irq()) {
-                       if (type != KM_IRQ0 && type != KM_IRQ1 &&
-                           type != KM_BIO_SRC_IRQ &&
-                           /* type != KM_BIO_DST_IRQ && */
-                           type != KM_BOUNCE_READ) {
-                               WARN_ON(1);
-                               warn_count--;
-                       }
-               } else if (!irqs_disabled()) {  /* softirq */
-                       if (type != KM_IRQ0 && type != KM_IRQ1 &&
-                           type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 &&
-                           type != KM_SKB_SUNRPC_DATA &&
-                           type != KM_SKB_DATA_SOFTIRQ &&
-                           type != KM_BOUNCE_READ) {
-                               WARN_ON(1);
-                               warn_count--;
-                       }
-               }
-       }
-
-       if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ ||
-           type == KM_BIO_SRC_IRQ /* || type == KM_BIO_DST_IRQ */) {
-               if (!irqs_disabled()) {
-                       WARN_ON(1);
-                       warn_count--;
-               }
-       } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) {
-               if (irq_count() == 0 && !irqs_disabled()) {
-                       WARN_ON(1);
-                       warn_count--;
-               }
-       }
-#endif
-}
-
 /*
  * Describe a single atomic mapping of a page on a given cpu at a
  * given address, and allow it to be linked into a list.
@@ -240,10 +196,10 @@ void kmap_atomic_fix_kpte(struct page *page, int finished)
  * When holding an atomic kmap is is not legal to sleep, so atomic
  * kmaps are appropriate for short, tight code paths only.
  */
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 {
-       enum fixed_addresses idx;
        unsigned long vaddr;
+       int idx, type;
        pte_t *pte;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
@@ -255,8 +211,7 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
        if (!PageHighMem(page))
                return page_address(page);
 
-       debug_kmap_atomic_prot(type);
-
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
        pte = kmap_get_pte(vaddr);
@@ -269,25 +224,31 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
 }
 EXPORT_SYMBOL(kmap_atomic_prot);
 
-void *kmap_atomic(struct page *page, enum km_type type)
+void *__kmap_atomic(struct page *page)
 {
        /* PAGE_NONE is a magic value that tells us to check immutability. */
        return kmap_atomic_prot(page, type, PAGE_NONE);
 }
-EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(__kmap_atomic);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-       /*
-        * Force other mappings to Oops if they try to access this pte without
-        * first remapping it.  Keeping stale mappings around is a bad idea.
-        */
-       if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) {
+       if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
+           vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
                pte_t *pte = kmap_get_pte(vaddr);
                pte_t pteval = *pte;
+               int idx, type;
+
+               type = kmap_atomic_idx_pop();
+               idx = type + KM_TYPE_NR*smp_processor_id();
+
+               /*
+                * Force other mappings to Oops if they try to access this pte
+                * without first remapping it.  Keeping stale mappings around
+                * is a bad idea.
+                */
                BUG_ON(!pte_present(pteval) && !pte_migrating(pteval));
                kmap_atomic_unregister(pte_page(pteval), vaddr);
                kpte_clear_flush(pte, vaddr);
@@ -300,19 +261,19 @@ void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
        arch_flush_lazy_mmu_mode();
        pagefault_enable();
 }
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
+EXPORT_SYMBOL(__kunmap_atomic);
 
 /*
  * This API is supposed to allow us to map memory without a "struct page".
  * Currently we don't support this, though this may change in the future.
  */
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-       return kmap_atomic(pfn_to_page(pfn), type);
+       return kmap_atomic(pfn_to_page(pfn));
 }
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 {
-       return kmap_atomic_prot(pfn_to_page(pfn), type, prot);
+       return kmap_atomic_prot(pfn_to_page(pfn), prot);
 }
 
 struct page *kmap_atomic_to_page(void *ptr)
index fb3b4a5..d78df3a 100644 (file)
@@ -37,6 +37,8 @@
 #include <asm/pgalloc.h>
 #include <asm/homecache.h>
 
+#include <arch/sim.h>
+
 #include "migrate.h"
 
 
@@ -217,13 +219,6 @@ static unsigned long cache_flush_length(unsigned long length)
        return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length;
 }
 
-/* On the simulator, confirm lines have been evicted everywhere. */
-static void validate_lines_evicted(unsigned long pfn, size_t length)
-{
-       sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED,
-                   (HV_PhysAddr)pfn << PAGE_SHIFT, length);
-}
-
 /* Flush a page out of whatever cache(s) it is in. */
 void homecache_flush_cache(struct page *page, int order)
 {
@@ -234,7 +229,7 @@ void homecache_flush_cache(struct page *page, int order)
 
        homecache_mask(page, pages, &home_mask);
        flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0);
-       validate_lines_evicted(pfn, pages * PAGE_SIZE);
+       sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE);
 }
 
 
index d89c9ea..78e1982 100644 (file)
@@ -1060,7 +1060,7 @@ void free_initmem(void)
 
        /*
         * Free the pages mapped from 0xc0000000 that correspond to code
-        * pages from 0xfd000000 that we won't use again after init.
+        * pages from MEM_SV_INTRPT that we won't use again after init.
         */
        free_init_pages("unused kernel text",
                        (unsigned long)_sinittext - text_delta,
index ec2b8da..50d6aa2 100644 (file)
@@ -120,6 +120,9 @@ config SMP
 
          If you don't know what to do, say N.
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       def_bool y
+
 config NR_CPUS
        int "Maximum number of CPUs (2-32)"
        range 2 32
@@ -147,3 +150,6 @@ config KERNEL_STACK_ORDER
          This option determines the size of UML kernel stacks.  They will
          be 1 << order pages.  The default is OK unless you're running Valgrind
          on UML, in which case, set this to 3.
+
+config NO_DMA
+       def_bool y
index 6bd456f..564f3de 100644 (file)
@@ -566,7 +566,6 @@ CONFIG_CRC32=m
 # CONFIG_CRC7 is not set
 # CONFIG_LIBCRC32C is not set
 CONFIG_PLIST=y
-CONFIG_HAS_DMA=y
 
 #
 # SCSI device support
diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h
deleted file mode 100644 (file)
index 1f469e8..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-#ifndef _ASM_DMA_MAPPING_H
-#define _ASM_DMA_MAPPING_H
-
-#include <asm/scatterlist.h>
-
-static inline int
-dma_supported(struct device *dev, u64 mask)
-{
-       BUG();
-       return(0);
-}
-
-static inline int
-dma_set_mask(struct device *dev, u64 dma_mask)
-{
-       BUG();
-       return(0);
-}
-
-static inline void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-                  gfp_t flag)
-{
-       BUG();
-       return((void *) 0);
-}
-
-static inline void
-dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-                 dma_addr_t dma_handle)
-{
-       BUG();
-}
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *cpu_addr, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG();
-       return(0);
-}
-
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-                enum dma_data_direction direction)
-{
-       BUG();
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page,
-            unsigned long offset, size_t size,
-            enum dma_data_direction direction)
-{
-       BUG();
-       return(0);
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG();
-}
-
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-          enum dma_data_direction direction)
-{
-       BUG();
-       return(0);
-}
-
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-            enum dma_data_direction direction)
-{
-       BUG();
-}
-
-static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-               enum dma_data_direction direction)
-{
-       BUG();
-}
-
-static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-           enum dma_data_direction direction)
-{
-       BUG();
-}
-
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-static inline void
-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-              enum dma_data_direction direction)
-{
-       BUG();
-}
-
-static inline int
-dma_mapping_error(struct device *dev, dma_addr_t dma_handle)
-{
-       BUG();
-       return 0;
-}
-
-#endif
index a9f7251..41474fb 100644 (file)
@@ -338,9 +338,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
        ((pte_t *) pmd_page_vaddr(*(dir)) +  pte_index(address))
 #define pte_offset_map(dir, address) \
        ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
-#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 
 struct mm_struct;
 extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
index 93af1cf..68a90ec 100644 (file)
@@ -8,23 +8,38 @@ extern int set_signals(int enable);
 extern void block_signals(void);
 extern void unblock_signals(void);
 
-#define local_save_flags(flags) do { typecheck(unsigned long, flags); \
-                                    (flags) = get_signals(); } while(0)
-#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \
-                                     set_signals(flags); } while(0)
-
-#define local_irq_save(flags) do { local_save_flags(flags); \
-                                   local_irq_disable(); } while(0)
-
-#define local_irq_enable() unblock_signals()
-#define local_irq_disable() block_signals()
-
-#define irqs_disabled()                 \
-({                                      \
-        unsigned long flags;            \
-        local_save_flags(flags);        \
-        (flags == 0);                   \
-})
+static inline unsigned long arch_local_save_flags(void)
+{
+       return get_signals();
+}
+
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+       set_signals(flags);
+}
+
+static inline void arch_local_irq_enable(void)
+{
+       unblock_signals();
+}
+
+static inline void arch_local_irq_disable(void)
+{
+       block_signals();
+}
+
+static inline unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       flags = arch_local_save_flags();
+       arch_local_irq_disable();
+       return flags;
+}
+
+static inline bool arch_irqs_disabled(void)
+{
+       return arch_local_save_flags() == 0;
+}
 
 extern void *_switch_to(void *prev, void *next, void *last);
 #define switch_to(prev, next, last) prev = _switch_to(prev, next, last)
index 6926801..a3cab6d 100644 (file)
@@ -50,8 +50,18 @@ SECTIONS
   .rela.got       : { *(.rela.got) }
   .rel.bss        : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
   .rela.bss       : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
-  .rel.plt        : { *(.rel.plt) }
-  .rela.plt       : { *(.rela.plt) }
+  .rel.plt : {
+       *(.rel.plt)
+       PROVIDE_HIDDEN(__rel_iplt_start = .);
+       *(.rel.iplt)
+       PROVIDE_HIDDEN(__rel_iplt_end = .);
+  }
+  .rela.plt : {
+       *(.rela.plt)
+       PROVIDE_HIDDEN(__rela_iplt_start = .);
+       *(.rela.iplt)
+       PROVIDE_HIDDEN(__rela_iplt_end = .);
+  }
   .init           : {
     KEEP (*(.init))
   } =0x90909090
index a746e30..3f0ac9e 100644 (file)
@@ -334,7 +334,7 @@ unsigned int do_IRQ(int irq, struct uml_pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs((struct pt_regs *)regs);
        irq_enter();
-       __do_IRQ(irq);
+       generic_handle_irq(irq);
        irq_exit();
        set_irq_regs(old_regs);
        return 1;
@@ -391,17 +391,10 @@ void __init init_IRQ(void)
 {
        int i;
 
-       irq_desc[TIMER_IRQ].status = IRQ_DISABLED;
-       irq_desc[TIMER_IRQ].action = NULL;
-       irq_desc[TIMER_IRQ].depth = 1;
-       irq_desc[TIMER_IRQ].chip = &SIGVTALRM_irq_type;
-       enable_irq(TIMER_IRQ);
+       set_irq_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq);
+
        for (i = 1; i < NR_IRQS; i++) {
-               irq_desc[i].status = IRQ_DISABLED;
-               irq_desc[i].action = NULL;
-               irq_desc[i].depth = 1;
-               irq_desc[i].chip = &normal_irq_type;
-               enable_irq(i);
+               set_irq_chip_and_handler(i, &normal_irq_type, handle_edge_irq);
        }
 }
 
index ec63785..fbd9940 100644 (file)
@@ -22,7 +22,7 @@ SECTIONS
   _text = .;
   _stext = .;
   __init_begin = .;
-  INIT_TEXT_SECTION(PAGE_SIZE)
+  INIT_TEXT_SECTION(0)
   . = ALIGN(PAGE_SIZE);
 
   .text      :
@@ -43,6 +43,23 @@ SECTIONS
        __syscall_stub_end = .;
   }
 
+  /*
+   * These are needed even in a static link, even if they wind up being empty.
+   * Newer glibc needs these __rel{,a}_iplt_{start,end} symbols.
+   */
+  .rel.plt : {
+       *(.rel.plt)
+       PROVIDE_HIDDEN(__rel_iplt_start = .);
+       *(.rel.iplt)
+       PROVIDE_HIDDEN(__rel_iplt_end = .);
+  }
+  .rela.plt : {
+       *(.rela.plt)
+       PROVIDE_HIDDEN(__rela_iplt_start = .);
+       *(.rela.iplt)
+       PROVIDE_HIDDEN(__rela_iplt_end = .);
+  }
+
   #include "asm/common.lds.S"
 
   init.data : { INIT_DATA }
index dec5678..6e3359d 100644 (file)
@@ -60,7 +60,7 @@ static inline long long timeval_to_ns(const struct timeval *tv)
 long long disable_timer(void)
 {
        struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } });
-       int remain, max = UM_NSEC_PER_SEC / UM_HZ;
+       long long remain, max = UM_NSEC_PER_SEC / UM_HZ;
 
        if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0)
                printk(UM_KERN_ERR "disable_timer - setitimer failed, "
index 8caac76..3bd0402 100644 (file)
@@ -59,11 +59,12 @@ extern void kunmap_high(struct page *page);
 
 void *kmap(struct page *page);
 void kunmap(struct page *page);
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot);
-void *kmap_atomic(struct page *page, enum km_type type);
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type);
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type);
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+
+void *kmap_atomic_prot(struct page *page, pgprot_t prot);
+void *__kmap_atomic(struct page *page);
+void __kunmap_atomic(void *kvaddr);
+void *kmap_atomic_pfn(unsigned long pfn);
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
 struct page *kmap_atomic_to_page(void *ptr);
 
 #define flush_cache_kmaps()    do { } while (0)
index c4191b3..363e33e 100644 (file)
 #include <asm/tlbflush.h>
 
 void __iomem *
-iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot);
+iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot);
 
 void
-iounmap_atomic(void __iomem *kvaddr, enum km_type type);
+iounmap_atomic(void __iomem *kvaddr);
 
 int
 iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot);
index 8abde9e..0c92113 100644 (file)
@@ -49,24 +49,14 @@ extern void set_pmd_pfn(unsigned long, unsigned long, pgprot_t);
 #endif
 
 #if defined(CONFIG_HIGHPTE)
-#define __KM_PTE                       \
-       (in_nmi() ? KM_NMI_PTE :        \
-        in_irq() ? KM_IRQ_PTE :        \
-        KM_PTE0)
 #define pte_offset_map(dir, address)                                   \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)), __KM_PTE) +             \
+       ((pte_t *)kmap_atomic(pmd_page(*(dir))) +               \
         pte_index((address)))
-#define pte_offset_map_nested(dir, address)                            \
-       ((pte_t *)kmap_atomic(pmd_page(*(dir)), KM_PTE1) +              \
-        pte_index((address)))
-#define pte_unmap(pte) kunmap_atomic((pte), __KM_PTE)
-#define pte_unmap_nested(pte) kunmap_atomic((pte), KM_PTE1)
+#define pte_unmap(pte) kunmap_atomic((pte))
 #else
 #define pte_offset_map(dir, address)                                   \
        ((pte_t *)page_address(pmd_page(*(dir))) + pte_index((address)))
-#define pte_offset_map_nested(dir, address) pte_offset_map((dir), (address))
 #define pte_unmap(pte) do { } while (0)
-#define pte_unmap_nested(pte) do { } while (0)
 #endif
 
 /* Clear a kernel PTE and flush it from the TLB */
index f96ac9b..f86da20 100644 (file)
@@ -127,9 +127,7 @@ static inline int pgd_large(pgd_t pgd) { return 0; }
 
 /* x86-64 always has all page tables mapped. */
 #define pte_offset_map(dir, address) pte_offset_kernel((dir), (address))
-#define pte_offset_map_nested(dir, address) pte_offset_kernel((dir), (address))
 #define pte_unmap(pte) ((void)(pte))/* NOP */
-#define pte_unmap_nested(pte) ((void)(pte)) /* NOP */
 
 #define update_mmu_cache(vma, address, ptep) do { } while (0)
 
index cd8da24..a2baafb 100644 (file)
@@ -701,6 +701,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
                per_cpu(acfreq_data, policy->cpu) = NULL;
                acpi_processor_unregister_performance(data->acpi_data,
                                                      policy->cpu);
+               kfree(data->freq_table);
                kfree(data);
        }
 
index 733093d..141abeb 100644 (file)
@@ -393,7 +393,7 @@ static struct cpufreq_driver nforce2_driver = {
  * Detects nForce2 A2 and C1 stepping
  *
  */
-static unsigned int nforce2_detect_chipset(void)
+static int nforce2_detect_chipset(void)
 {
        nforce2_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
                                        PCI_DEVICE_ID_NVIDIA_NFORCE2,
index fc09f14..d9f5136 100644 (file)
@@ -35,7 +35,7 @@ static unsigned int longrun_low_freq, longrun_high_freq;
  * Reads the current LongRun policy by access to MSR_TMTA_LONGRUN_FLAGS
  * and MSR_TMTA_LONGRUN_CTRL
  */
-static void __init longrun_get_policy(struct cpufreq_policy *policy)
+static void __cpuinit longrun_get_policy(struct cpufreq_policy *policy)
 {
        u32 msr_lo, msr_hi;
 
@@ -165,7 +165,7 @@ static unsigned int longrun_get(unsigned int cpu)
  * TMTA rules:
  * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq)
  */
-static unsigned int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
+static int __cpuinit longrun_determine_freqs(unsigned int *low_freq,
                                                      unsigned int *high_freq)
 {
        u32 msr_lo, msr_hi;
index 12cd823..17ad033 100644 (file)
@@ -327,6 +327,7 @@ static void __cpuinit amd_calc_l3_indices(struct amd_l3_cache *l3)
        l3->subcaches[3] = sc3 = !(val & BIT(12)) + !(val & BIT(13));
 
        l3->indices = (max(max(max(sc0, sc1), sc2), sc3) << 10) - 1;
+       l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1;
 }
 
 static struct amd_l3_cache * __cpuinit amd_init_l3_cache(int node)
index fe73c18..c1e8c7a 100644 (file)
@@ -49,7 +49,6 @@ static unsigned long
 copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
 {
        unsigned long offset, addr = (unsigned long)from;
-       int type = in_nmi() ? KM_NMI : KM_IRQ0;
        unsigned long size, len = 0;
        struct page *page;
        void *map;
@@ -63,9 +62,9 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
                offset = addr & (PAGE_SIZE - 1);
                size = min(PAGE_SIZE - offset, n - len);
 
-               map = kmap_atomic(page, type);
+               map = kmap_atomic(page);
                memcpy(to, map+offset, size);
-               kunmap_atomic(map, type);
+               kunmap_atomic(map);
                put_page(page);
 
                len  += size;
index 6741455..d5cd139 100644 (file)
@@ -61,7 +61,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
        if (!is_crashed_pfn_valid(pfn))
                return -EFAULT;
 
-       vaddr = kmap_atomic_pfn(pfn, KM_PTE0);
+       vaddr = kmap_atomic_pfn(pfn);
 
        if (!userbuf) {
                memcpy(buf, (vaddr + offset), csize);
index aff0b3c..ae03cab 100644 (file)
@@ -713,7 +713,7 @@ static int hpet_cpuhp_notify(struct notifier_block *n,
 
        switch (action & 0xf) {
        case CPU_ONLINE:
-               INIT_DELAYED_WORK_ON_STACK(&work.work, hpet_work);
+               INIT_DELAYED_WORK_ONSTACK(&work.work, hpet_work);
                init_completion(&work.complete);
                /* FIXME: add schedule_work_on() */
                schedule_delayed_work_on(cpu, &work.work, 0);
index 6af1185..6c7faec 100644 (file)
@@ -747,7 +747,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu)
                .done   = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
        };
 
-       INIT_WORK_ON_STACK(&c_idle.work, do_fork_idle);
+       INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
 
        alternatives_smp_switch(1);
 
index 79b0b37..7d90ceb 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kprobes.h>             /* __kprobes, ...               */
 #include <linux/mmiotrace.h>           /* kmmio_handler, ...           */
 #include <linux/perf_event.h>          /* perf_sw_event                */
+#include <linux/hugetlb.h>             /* hstate_index_to_shift        */
 
 #include <asm/traps.h>                 /* dotraplinkage, ...           */
 #include <asm/pgalloc.h>               /* pgd_*(), ...                 */
@@ -160,15 +161,20 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
 
 static void
 force_sig_info_fault(int si_signo, int si_code, unsigned long address,
-                    struct task_struct *tsk)
+                    struct task_struct *tsk, int fault)
 {
+       unsigned lsb = 0;
        siginfo_t info;
 
        info.si_signo   = si_signo;
        info.si_errno   = 0;
        info.si_code    = si_code;
        info.si_addr    = (void __user *)address;
-       info.si_addr_lsb = si_code == BUS_MCEERR_AR ? PAGE_SHIFT : 0;
+       if (fault & VM_FAULT_HWPOISON_LARGE)
+               lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); 
+       if (fault & VM_FAULT_HWPOISON)
+               lsb = PAGE_SHIFT;
+       info.si_addr_lsb = lsb;
 
        force_sig_info(si_signo, &info, tsk);
 }
@@ -722,7 +728,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
                tsk->thread.error_code  = error_code | (address >= TASK_SIZE);
                tsk->thread.trap_no     = 14;
 
-               force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+               force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0);
 
                return;
        }
@@ -807,14 +813,14 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
        tsk->thread.trap_no     = 14;
 
 #ifdef CONFIG_MEMORY_FAILURE
-       if (fault & VM_FAULT_HWPOISON) {
+       if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
                printk(KERN_ERR
        "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n",
                        tsk->comm, tsk->pid, address);
                code = BUS_MCEERR_AR;
        }
 #endif
-       force_sig_info_fault(SIGBUS, code, address, tsk);
+       force_sig_info_fault(SIGBUS, code, address, tsk, fault);
 }
 
 static noinline void
@@ -824,7 +830,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
        if (fault & VM_FAULT_OOM) {
                out_of_memory(regs, error_code, address);
        } else {
-               if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON))
+               if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON|
+                            VM_FAULT_HWPOISON_LARGE))
                        do_sigbus(regs, error_code, address, fault);
                else
                        BUG();
@@ -912,9 +919,9 @@ spurious_fault(unsigned long error_code, unsigned long address)
 int show_unhandled_signals = 1;
 
 static inline int
-access_error(unsigned long error_code, int write, struct vm_area_struct *vma)
+access_error(unsigned long error_code, struct vm_area_struct *vma)
 {
-       if (write) {
+       if (error_code & PF_WRITE) {
                /* write, present and write, not present: */
                if (unlikely(!(vma->vm_flags & VM_WRITE)))
                        return 1;
@@ -949,8 +956,10 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
        struct task_struct *tsk;
        unsigned long address;
        struct mm_struct *mm;
-       int write;
        int fault;
+       int write = error_code & PF_WRITE;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY |
+                                       (write ? FAULT_FLAG_WRITE : 0);
 
        tsk = current;
        mm = tsk->mm;
@@ -1061,6 +1070,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
                        bad_area_nosemaphore(regs, error_code, address);
                        return;
                }
+retry:
                down_read(&mm->mmap_sem);
        } else {
                /*
@@ -1104,9 +1114,7 @@ do_page_fault(struct pt_regs *regs, unsigned long error_code)
         * we can handle it..
         */
 good_area:
-       write = error_code & PF_WRITE;
-
-       if (unlikely(access_error(error_code, write, vma))) {
+       if (unlikely(access_error(error_code, vma))) {
                bad_area_access_error(regs, error_code, address);
                return;
        }
@@ -1116,21 +1124,34 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault:
         */
-       fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0);
+       fault = handle_mm_fault(mm, vma, address, flags);
 
        if (unlikely(fault & VM_FAULT_ERROR)) {
                mm_fault_error(regs, error_code, address, fault);
                return;
        }
 
-       if (fault & VM_FAULT_MAJOR) {
-               tsk->maj_flt++;
-               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
-                                    regs, address);
-       } else {
-               tsk->min_flt++;
-               perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
-                                    regs, address);
+       /*
+        * Major/minor page fault accounting is only done on the
+        * initial attempt. If we go through a retry, it is extremely
+        * likely that the page will be found in page cache at that point.
+        */
+       if (flags & FAULT_FLAG_ALLOW_RETRY) {
+               if (fault & VM_FAULT_MAJOR) {
+                       tsk->maj_flt++;
+                       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, 0,
+                                     regs, address);
+               } else {
+                       tsk->min_flt++;
+                       perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, 0,
+                                     regs, address);
+               }
+               if (fault & VM_FAULT_RETRY) {
+                       /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+                        * of starvation. */
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       goto retry;
+               }
        }
 
        check_v8086_mode(regs, address, tsk);
index 5e8fa12..d723e36 100644 (file)
@@ -9,6 +9,7 @@ void *kmap(struct page *page)
                return page_address(page);
        return kmap_high(page);
 }
+EXPORT_SYMBOL(kmap);
 
 void kunmap(struct page *page)
 {
@@ -18,6 +19,7 @@ void kunmap(struct page *page)
                return;
        kunmap_high(page);
 }
+EXPORT_SYMBOL(kunmap);
 
 /*
  * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
@@ -27,10 +29,10 @@ void kunmap(struct page *page)
  * However when holding an atomic kmap it is not legal to sleep, so atomic
  * kmaps are appropriate for short, tight code paths only.
  */
-void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot(struct page *page, pgprot_t prot)
 {
-       enum fixed_addresses idx;
        unsigned long vaddr;
+       int idx, type;
 
        /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */
        pagefault_disable();
@@ -38,8 +40,7 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
        if (!PageHighMem(page))
                return page_address(page);
 
-       debug_kmap_atomic(type);
-
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR*smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
        BUG_ON(!pte_none(*(kmap_pte-idx)));
@@ -47,44 +48,56 @@ void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot)
 
        return (void *)vaddr;
 }
+EXPORT_SYMBOL(kmap_atomic_prot);
+
+void *__kmap_atomic(struct page *page)
+{
+       return kmap_atomic_prot(page, kmap_prot);
+}
+EXPORT_SYMBOL(__kmap_atomic);
 
-void *kmap_atomic(struct page *page, enum km_type type)
+/*
+ * This is the same as kmap_atomic() but can map memory that doesn't
+ * have a struct page associated with it.
+ */
+void *kmap_atomic_pfn(unsigned long pfn)
 {
-       return kmap_atomic_prot(page, type, kmap_prot);
+       return kmap_atomic_prot_pfn(pfn, kmap_prot);
 }
+EXPORT_SYMBOL_GPL(kmap_atomic_pfn);
 
-void kunmap_atomic_notypecheck(void *kvaddr, enum km_type type)
+void __kunmap_atomic(void *kvaddr)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
-
-       /*
-        * Force other mappings to Oops if they'll try to access this pte
-        * without first remap it.  Keeping stale mappings around is a bad idea
-        * also, in case the page changes cacheability attributes or becomes
-        * a protected page in a hypervisor.
-        */
-       if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+
+       if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
+           vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
+               int idx, type;
+
+               type = kmap_atomic_idx_pop();
+               idx = type + KM_TYPE_NR * smp_processor_id();
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+               WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+#endif
+               /*
+                * Force other mappings to Oops if they'll try to access this
+                * pte without first remap it.  Keeping stale mappings around
+                * is a bad idea also, in case the page changes cacheability
+                * attributes or becomes a protected page in a hypervisor.
+                */
                kpte_clear_flush(kmap_pte-idx, vaddr);
-       else {
+       }
 #ifdef CONFIG_DEBUG_HIGHMEM
+       else {
                BUG_ON(vaddr < PAGE_OFFSET);
                BUG_ON(vaddr >= (unsigned long)high_memory);
-#endif
        }
+#endif
 
        pagefault_enable();
 }
-
-/*
- * This is the same as kmap_atomic() but can map memory that doesn't
- * have a struct page associated with it.
- */
-void *kmap_atomic_pfn(unsigned long pfn, enum km_type type)
-{
-       return kmap_atomic_prot_pfn(pfn, type, kmap_prot);
-}
-EXPORT_SYMBOL_GPL(kmap_atomic_pfn); /* temporarily in use by i915 GEM until vmap */
+EXPORT_SYMBOL(__kunmap_atomic);
 
 struct page *kmap_atomic_to_page(void *ptr)
 {
@@ -98,12 +111,6 @@ struct page *kmap_atomic_to_page(void *ptr)
        pte = kmap_pte - (idx - FIX_KMAP_BEGIN);
        return pte_page(*pte);
 }
-
-EXPORT_SYMBOL(kmap);
-EXPORT_SYMBOL(kunmap);
-EXPORT_SYMBOL(kmap_atomic);
-EXPORT_SYMBOL(kunmap_atomic_notypecheck);
-EXPORT_SYMBOL(kmap_atomic_prot);
 EXPORT_SYMBOL(kmap_atomic_to_page);
 
 void __init set_highmem_pages_init(void)
index 72fc70c..75a3d7f 100644 (file)
@@ -48,21 +48,20 @@ int iomap_create_wc(resource_size_t base, unsigned long size, pgprot_t *prot)
 }
 EXPORT_SYMBOL_GPL(iomap_create_wc);
 
-void
-iomap_free(resource_size_t base, unsigned long size)
+void iomap_free(resource_size_t base, unsigned long size)
 {
        io_free_memtype(base, base + size);
 }
 EXPORT_SYMBOL_GPL(iomap_free);
 
-void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+void *kmap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 {
-       enum fixed_addresses idx;
        unsigned long vaddr;
+       int idx, type;
 
        pagefault_disable();
 
-       debug_kmap_atomic(type);
+       type = kmap_atomic_idx_push();
        idx = type + KM_TYPE_NR * smp_processor_id();
        vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
        set_pte(kmap_pte - idx, pfn_pte(pfn, prot));
@@ -72,10 +71,10 @@ void *kmap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
 }
 
 /*
- * Map 'pfn' using fixed map 'type' and protections 'prot'
+ * Map 'pfn' using protections 'prot'
  */
 void __iomem *
-iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
+iomap_atomic_prot_pfn(unsigned long pfn, pgprot_t prot)
 {
        /*
         * For non-PAT systems, promote PAGE_KERNEL_WC to PAGE_KERNEL_UC_MINUS.
@@ -86,24 +85,33 @@ iomap_atomic_prot_pfn(unsigned long pfn, enum km_type type, pgprot_t prot)
        if (!pat_enabled && pgprot_val(prot) == pgprot_val(PAGE_KERNEL_WC))
                prot = PAGE_KERNEL_UC_MINUS;
 
-       return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, type, prot);
+       return (void __force __iomem *) kmap_atomic_prot_pfn(pfn, prot);
 }
 EXPORT_SYMBOL_GPL(iomap_atomic_prot_pfn);
 
 void
-iounmap_atomic(void __iomem *kvaddr, enum km_type type)
+iounmap_atomic(void __iomem *kvaddr)
 {
        unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK;
-       enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
 
-       /*
-        * Force other mappings to Oops if they'll try to access this pte
-        * without first remap it.  Keeping stale mappings around is a bad idea
-        * also, in case the page changes cacheability attributes or becomes
-        * a protected page in a hypervisor.
-        */
-       if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx))
+       if (vaddr >= __fix_to_virt(FIX_KMAP_END) &&
+           vaddr <= __fix_to_virt(FIX_KMAP_BEGIN)) {
+               int idx, type;
+
+               type = kmap_atomic_idx_pop();
+               idx = type + KM_TYPE_NR * smp_processor_id();
+
+#ifdef CONFIG_DEBUG_HIGHMEM
+               WARN_ON_ONCE(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx));
+#endif
+               /*
+                * Force other mappings to Oops if they'll try to access this
+                * pte without first remap it.  Keeping stale mappings around
+                * is a bad idea also, in case the page changes cacheability
+                * attributes or becomes a protected page in a hypervisor.
+                */
                kpte_clear_flush(kmap_pte-idx, vaddr);
+       }
 
        pagefault_enable();
 }
index 76bf355..b03c043 100644 (file)
@@ -324,10 +324,7 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 #define pte_offset_kernel(dir,addr)                                    \
        ((pte_t*) pmd_page_vaddr(*(dir)) + pte_index(addr))
 #define pte_offset_map(dir,addr)       pte_offset_kernel((dir),(addr))
-#define pte_offset_map_nested(dir,addr)        pte_offset_kernel((dir),(addr))
-
 #define pte_unmap(pte)         do { } while (0)
-#define pte_unmap_nested(pte)  do { } while (0)
 
 
 /*
index 0ec1fb6..518c22b 100644 (file)
@@ -83,8 +83,8 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
 
                memcpy(dest_buf, src_buf, len);
 
-               kunmap_atomic(dest_buf, KM_USER0);
                kunmap_atomic(src_buf, KM_USER1);
+               kunmap_atomic(dest_buf, KM_USER0);
 
                async_tx_sync_epilog(submit);
        }
index 90d26c9..7a72192 100644 (file)
@@ -89,9 +89,9 @@ static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk,
                memcpy(walk->dst.virt.addr, walk->page, n);
                blkcipher_unmap_dst(walk);
        } else if (!(walk->flags & BLKCIPHER_WALK_PHYS)) {
-               blkcipher_unmap_src(walk);
                if (walk->flags & BLKCIPHER_WALK_DIFF)
                        blkcipher_unmap_dst(walk);
+               blkcipher_unmap_src(walk);
        }
 
        scatterwalk_advance(&walk->in, n);
index 88681ac..3f3489c 100644 (file)
@@ -9,7 +9,6 @@ menuconfig ACPI
        depends on PCI
        depends on PM
        select PNP
-       select CPU_IDLE
        default y
        help
          Advanced Configuration and Power Interface (ACPI) support for 
@@ -66,7 +65,6 @@ config ACPI_PROCFS
 config ACPI_PROCFS_POWER
        bool "Deprecated power /proc/acpi directories"
        depends on PROC_FS
-       default y
        help
          For backwards compatibility, this option allows
           deprecated power /proc/acpi/ directories to exist, even when
@@ -90,13 +88,6 @@ config ACPI_POWER_METER
          To compile this driver as a module, choose M here:
          the module will be called power-meter.
 
-config ACPI_SYSFS_POWER
-       bool "Future power /sys interface"
-       select POWER_SUPPLY
-       default y
-       help
-         Say N to disable power /sys interface
-
 config ACPI_EC_DEBUGFS
        tristate "EC read/write access through /sys/kernel/debug/ec"
        default n
@@ -136,6 +127,7 @@ config ACPI_PROC_EVENT
 config ACPI_AC
        tristate "AC Adapter"
        depends on X86
+       select POWER_SUPPLY
        default y
        help
          This driver supports the AC Adapter object, which indicates
@@ -148,6 +140,7 @@ config ACPI_AC
 config ACPI_BATTERY
        tristate "Battery"
        depends on X86
+       select POWER_SUPPLY
        default y
        help
          This driver adds support for battery information through
@@ -206,6 +199,7 @@ config ACPI_DOCK
 config ACPI_PROCESSOR
        tristate "Processor"
        select THERMAL
+       select CPU_IDLE
        default y
        help
          This driver installs ACPI as the idle handler for Linux and uses
@@ -364,6 +358,7 @@ config ACPI_HOTPLUG_MEMORY
 config ACPI_SBS
        tristate "Smart Battery System"
        depends on X86
+       select POWER_SUPPLY
        help
          This driver supports the Smart Battery System, another
          type of access to battery information, found on some laptops.
index 56205a0..ba9afea 100644 (file)
@@ -32,9 +32,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 #include <linux/power_supply.h>
-#endif
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
@@ -86,9 +84,7 @@ static struct acpi_driver acpi_ac_driver = {
 };
 
 struct acpi_ac {
-#ifdef CONFIG_ACPI_SYSFS_POWER
        struct power_supply charger;
-#endif
        struct acpi_device * device;
        unsigned long long state;
 };
@@ -104,7 +100,6 @@ static const struct file_operations acpi_ac_fops = {
        .release = single_release,
 };
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static int get_ac_property(struct power_supply *psy,
                           enum power_supply_property psp,
                           union power_supply_propval *val)
@@ -123,7 +118,6 @@ static int get_ac_property(struct power_supply *psy,
 static enum power_supply_property ac_props[] = {
        POWER_SUPPLY_PROP_ONLINE,
 };
-#endif
 /* --------------------------------------------------------------------------
                                AC Adapter Management
    -------------------------------------------------------------------------- */
@@ -247,9 +241,7 @@ static void acpi_ac_notify(struct acpi_device *device, u32 event)
                                                  dev_name(&device->dev), event,
                                                  (u32) ac->state);
                acpi_notifier_call_chain(device, event, (u32) ac->state);
-#ifdef CONFIG_ACPI_SYSFS_POWER
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
-#endif
        }
 
        return;
@@ -282,14 +274,12 @@ static int acpi_ac_add(struct acpi_device *device)
 #endif
        if (result)
                goto end;
-#ifdef CONFIG_ACPI_SYSFS_POWER
        ac->charger.name = acpi_device_bid(device);
        ac->charger.type = POWER_SUPPLY_TYPE_MAINS;
        ac->charger.properties = ac_props;
        ac->charger.num_properties = ARRAY_SIZE(ac_props);
        ac->charger.get_property = get_ac_property;
        power_supply_register(&ac->device->dev, &ac->charger);
-#endif
 
        printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
               acpi_device_name(device), acpi_device_bid(device),
@@ -316,10 +306,8 @@ static int acpi_ac_resume(struct acpi_device *device)
        old_state = ac->state;
        if (acpi_ac_get_state(ac))
                return 0;
-#ifdef CONFIG_ACPI_SYSFS_POWER
        if (old_state != ac->state)
                kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE);
-#endif
        return 0;
 }
 
@@ -333,10 +321,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type)
 
        ac = acpi_driver_data(device);
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
        if (ac->charger.dev)
                power_supply_unregister(&ac->charger);
-#endif
 #ifdef CONFIG_ACPI_PROCFS_POWER
        acpi_ac_remove_fs(device);
 #endif
index d93cc06..a7e1d1a 100644 (file)
@@ -21,7 +21,7 @@ acpi-y += exconfig.o  exfield.o  exnames.o   exoparg6.o  exresolv.o  exstorob.o\
         excreate.o  exmisc.o   exoparg2.o  exregion.o  exstore.o   exutils.o \
         exdump.o    exmutex.o  exoparg3.o  exresnte.o  exstoren.o  exdebug.o
 
-acpi-y += hwacpi.o  hwgpe.o  hwregs.o  hwsleep.o hwxface.o hwvalid.o
+acpi-y += hwacpi.o  hwgpe.o  hwregs.o  hwsleep.o hwxface.o hwvalid.o hwpci.o
 
 acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o
 
@@ -44,4 +44,5 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o
 
 acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
                utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
-               utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o
+               utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
+               utosi.o utxferror.o
index 48faf3e..72e9d5e 100644 (file)
@@ -105,6 +105,8 @@ void acpi_db_set_method_data(char *type_arg, char *index_arg, char *value_arg);
 acpi_status
 acpi_db_display_objects(char *obj_type_arg, char *display_count_arg);
 
+void acpi_db_display_interfaces(char *action_arg, char *interface_name_arg);
+
 acpi_status acpi_db_find_name_in_namespace(char *name_arg);
 
 void acpi_db_set_scope(char *name);
index 36867cd..a6f99cc 100644 (file)
@@ -105,8 +105,9 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
                         struct acpi_gpe_block_info **return_gpe_block);
 
 acpi_status
-acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
-                            struct acpi_gpe_block_info *gpe_block);
+acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+                            struct acpi_gpe_block_info *gpe_block,
+                            void *ignored);
 
 acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block);
 
index 1d19214..ad88fca 100644 (file)
@@ -132,6 +132,7 @@ struct acpi_table_fadt acpi_gbl_FADT;
 u32 acpi_current_gpe_count;
 u32 acpi_gbl_trace_flags;
 acpi_name acpi_gbl_trace_method_name;
+u8 acpi_gbl_system_awake_and_running;
 
 #endif
 
@@ -187,6 +188,10 @@ ACPI_EXTERN u8 acpi_gbl_integer_bit_width;
 ACPI_EXTERN u8 acpi_gbl_integer_byte_width;
 ACPI_EXTERN u8 acpi_gbl_integer_nybble_width;
 
+/* Mutex for _OSI support */
+
+ACPI_EXTERN acpi_mutex acpi_gbl_osi_mutex;
+
 /* Reader/Writer lock is used for namespace walk and dynamic table unload */
 
 ACPI_EXTERN struct acpi_rw_lock acpi_gbl_namespace_rw_lock;
@@ -255,6 +260,7 @@ ACPI_EXTERN acpi_init_handler acpi_gbl_init_handler;
 ACPI_EXTERN acpi_tbl_handler acpi_gbl_table_handler;
 ACPI_EXTERN void *acpi_gbl_table_handler_context;
 ACPI_EXTERN struct acpi_walk_state *acpi_gbl_breakpoint_walk;
+ACPI_EXTERN acpi_interface_handler acpi_gbl_interface_handler;
 
 /* Owner ID support */
 
@@ -273,8 +279,8 @@ ACPI_EXTERN u8 acpi_gbl_debugger_configuration;
 ACPI_EXTERN u8 acpi_gbl_step_to_next_call;
 ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
 ACPI_EXTERN u8 acpi_gbl_events_initialized;
-ACPI_EXTERN u8 acpi_gbl_system_awake_and_running;
 ACPI_EXTERN u8 acpi_gbl_osi_data;
+ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
 
 #ifndef DEFINE_ACPI_GLOBALS
 
@@ -364,6 +370,7 @@ ACPI_EXTERN struct acpi_fixed_event_handler
 ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head;
 ACPI_EXTERN struct acpi_gpe_block_info
 *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS];
+ACPI_EXTERN u8 acpi_all_gpes_initialized;
 
 /*****************************************************************************
  *
index 120b3af..167470a 100644 (file)
@@ -121,6 +121,13 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
                                 struct acpi_gpe_block_info *gpe_block,
                                 void *context);
 
+/*
+ * hwpci - PCI configuration support
+ */
+acpi_status
+acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
+                     acpi_handle root_pci_device, acpi_handle pci_region);
+
 #ifdef ACPI_FUTURE_USAGE
 /*
  * hwtimer - ACPI Timer prototypes
index 7dad916..2ceb0c0 100644 (file)
@@ -413,6 +413,7 @@ struct acpi_handler_info {
        void *context;          /* Context to be passed to handler */
        struct acpi_namespace_node *method_node;        /* Method node for this GPE level (saved) */
        u8 orig_flags;          /* Original misc info about this GPE */
+       u8 orig_enabled;        /* Set if the GPE was originally enabled */
 };
 
 union acpi_gpe_dispatch_info {
@@ -457,6 +458,7 @@ struct acpi_gpe_block_info {
        u32 register_count;     /* Number of register pairs in block */
        u16 gpe_count;          /* Number of individual GPEs in block */
        u8 block_base_number;   /* Base GPE number for this block */
+       u8 initialized;         /* If set, the GPE block has been initialized */
 };
 
 /* Information about GPE interrupt handlers, one per each interrupt level used for GPEs */
@@ -473,7 +475,6 @@ struct acpi_gpe_walk_info {
        struct acpi_gpe_block_info *gpe_block;
        u16 count;
        acpi_owner_id owner_id;
-       u8 enable_this_gpe;
        u8 execute_by_owner_id;
 };
 
@@ -854,7 +855,7 @@ struct acpi_bit_register_info {
        ACPI_BITMASK_POWER_BUTTON_STATUS   | \
        ACPI_BITMASK_SLEEP_BUTTON_STATUS   | \
        ACPI_BITMASK_RT_CLOCK_STATUS       | \
-       ACPI_BITMASK_PCIEXP_WAKE_DISABLE   | \
+       ACPI_BITMASK_PCIEXP_WAKE_STATUS    | \
        ACPI_BITMASK_WAKE_STATUS)
 
 #define ACPI_BITMASK_TIMER_ENABLE               0x0001
@@ -909,15 +910,21 @@ struct acpi_bit_register_info {
 #define ACPI_OSI_WIN_VISTA              0x07
 #define ACPI_OSI_WINSRV_2008            0x08
 #define ACPI_OSI_WIN_VISTA_SP1          0x09
-#define ACPI_OSI_WIN_7                  0x0A
+#define ACPI_OSI_WIN_VISTA_SP2          0x0A
+#define ACPI_OSI_WIN_7                  0x0B
 
 #define ACPI_ALWAYS_ILLEGAL             0x00
 
 struct acpi_interface_info {
        char *name;
+       struct acpi_interface_info *next;
+       u8 flags;
        u8 value;
 };
 
+#define ACPI_OSI_INVALID                0x01
+#define ACPI_OSI_DYNAMIC                0x02
+
 struct acpi_port_info {
        char *name;
        u16 start;
@@ -997,7 +1004,7 @@ struct acpi_port_info {
 struct acpi_db_method_info {
        acpi_handle main_thread_gate;
        acpi_handle thread_complete_gate;
-       u32 *threads;
+       acpi_thread_id *threads;
        u32 num_threads;
        u32 num_created;
        u32 num_completed;
index 9894929..8d5c9e0 100644 (file)
  * the plist contains a set of parens to allow variable-length lists.
  * These macros are used for both the debug and non-debug versions of the code.
  */
-#define ACPI_ERROR_NAMESPACE(s, e)      acpi_ns_report_error (AE_INFO, s, e);
-#define ACPI_ERROR_METHOD(s, n, p, e)   acpi_ns_report_method_error (AE_INFO, s, n, p, e);
+#define ACPI_ERROR_NAMESPACE(s, e)      acpi_ut_namespace_error (AE_INFO, s, e);
+#define ACPI_ERROR_METHOD(s, n, p, e)   acpi_ut_method_error (AE_INFO, s, n, p, e);
 #define ACPI_WARN_PREDEFINED(plist)     acpi_ut_predefined_warning plist
 #define ACPI_INFO_PREDEFINED(plist)     acpi_ut_predefined_info plist
 
index 9f60ff0..d44d3bc 100644 (file)
@@ -339,18 +339,6 @@ acpi_object_type acpi_ns_get_type(struct acpi_namespace_node *node);
 u32 acpi_ns_local(acpi_object_type type);
 
 void
-acpi_ns_report_error(const char *module_name,
-                    u32 line_number,
-                    const char *internal_name, acpi_status lookup_status);
-
-void
-acpi_ns_report_method_error(const char *module_name,
-                           u32 line_number,
-                           const char *message,
-                           struct acpi_namespace_node *node,
-                           const char *path, acpi_status lookup_status);
-
-void
 acpi_ns_print_node_pathname(struct acpi_namespace_node *node, const char *msg);
 
 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info);
index 54857fa..bdbfaf2 100644 (file)
@@ -248,7 +248,7 @@ ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_NOTIFY_INFO};
        u32                             base_byte_offset;   /* Byte offset within containing object */\
        u32                             value;              /* Value to store into the Bank or Index register */\
        u8                              start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
-       u8                              access_bit_width;       /* Read/Write size in bits (8-64) */
+
 
 struct acpi_object_field_common {      /* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */
        ACPI_OBJECT_COMMON_HEADER ACPI_COMMON_FIELD_INFO union acpi_operand_object *region_obj; /* Parent Operation Region object (REGION/BANK fields only) */
index 35df755..72e4183 100644 (file)
@@ -312,8 +312,6 @@ void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list);
 /*
  * uteval - object evaluation
  */
-acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
-
 acpi_status
 acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node,
                        char *path,
@@ -395,6 +393,21 @@ acpi_status
 acpi_ut_get_object_size(union acpi_operand_object *obj, acpi_size * obj_length);
 
 /*
+ * utosi - Support for the _OSI predefined control method
+ */
+acpi_status acpi_ut_initialize_interfaces(void);
+
+void acpi_ut_interface_terminate(void);
+
+acpi_status acpi_ut_install_interface(acpi_string interface_name);
+
+acpi_status acpi_ut_remove_interface(acpi_string interface_name);
+
+struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name);
+
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state);
+
+/*
  * utstate - Generic state creation/cache routines
  */
 void
@@ -473,17 +486,6 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position);
 
 acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 * ret_integer);
 
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_warning(const char *module_name,
-                          u32 line_number,
-                          char *pathname,
-                          u8 node_flags, const char *format, ...);
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_info(const char *module_name,
-                       u32 line_number,
-                       char *pathname, u8 node_flags, const char *format, ...);
-
 /* Values for Base above (16=Hex, 10=Decimal) */
 
 #define ACPI_ANY_BASE        0
@@ -574,6 +576,32 @@ acpi_status
 acpi_ut_create_list(char *list_name,
                    u16 object_size, struct acpi_memory_list **return_cache);
 
-#endif
+#endif                         /* ACPI_DBG_TRACK_ALLOCATIONS */
+
+/*
+ * utxferror - various error/warning output functions
+ */
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_warning(const char *module_name,
+                          u32 line_number,
+                          char *pathname,
+                          u8 node_flags, const char *format, ...);
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_info(const char *module_name,
+                       u32 line_number,
+                       char *pathname, u8 node_flags, const char *format, ...);
+
+void
+acpi_ut_namespace_error(const char *module_name,
+                       u32 line_number,
+                       const char *internal_name, acpi_status lookup_status);
+
+void
+acpi_ut_method_error(const char *module_name,
+                    u32 line_number,
+                    const char *message,
+                    struct acpi_namespace_node *node,
+                    const char *path, acpi_status lookup_status);
 
 #endif                         /* _ACUTILS_H */
index 64750ee..d94dd89 100644 (file)
@@ -573,7 +573,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
 
                                acpi_os_release_mutex(method_desc->method.
                                                      mutex->mutex.os_mutex);
-                               method_desc->method.mutex->mutex.thread_id = NULL;
+                               method_desc->method.mutex->mutex.thread_id = 0;
                        }
                }
 
index d555b37..6b0b5d0 100644 (file)
@@ -300,10 +300,25 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
                         * we must enter this object into the namespace.  The created
                         * object is temporary and will be deleted upon completion of
                         * the execution of this method.
+                        *
+                        * Note 10/2010: Except for the Scope() op. This opcode does
+                        * not actually create a new object, it refers to an existing
+                        * object. However, for Scope(), we want to indeed open a
+                        * new scope.
                         */
-                       status = acpi_ds_load2_begin_op(walk_state, NULL);
+                       if (op->common.aml_opcode != AML_SCOPE_OP) {
+                               status =
+                                   acpi_ds_load2_begin_op(walk_state, NULL);
+                       } else {
+                               status =
+                                   acpi_ds_scope_stack_push(op->named.node,
+                                                            op->named.node->
+                                                            type, walk_state);
+                               if (ACPI_FAILURE(status)) {
+                                       return_ACPI_STATUS(status);
+                               }
+                       }
                }
-
                break;
 
        case AML_CLASS_EXECUTE:
index 3036188..c61c303 100644 (file)
@@ -95,47 +95,6 @@ acpi_status acpi_ev_initialize_events(void)
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ev_install_fadt_gpes
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Completes initialization of the FADT-defined GPE blocks
- *              (0 and 1). The HW must be fully initialized at this point,
- *              including global lock support.
- *
- ******************************************************************************/
-
-acpi_status acpi_ev_install_fadt_gpes(void)
-{
-       acpi_status status;
-
-       ACPI_FUNCTION_TRACE(ev_install_fadt_gpes);
-
-       /* Namespace must be locked */
-
-       status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
-       if (ACPI_FAILURE(status)) {
-               return (status);
-       }
-
-       /* FADT GPE Block 0 */
-
-       (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
-                                          acpi_gbl_gpe_fadt_blocks[0]);
-
-       /* FADT GPE Block 1 */
-
-       (void)acpi_ev_initialize_gpe_block(acpi_gbl_fadt_gpe_device,
-                                          acpi_gbl_gpe_fadt_blocks[1]);
-
-       (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
-       return_ACPI_STATUS(AE_OK);
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ev_install_xrupt_handlers
  *
  * PARAMETERS:  None
index 85445fb..020add3 100644 (file)
@@ -363,6 +363,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
        gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
        gpe_block->register_count = register_count;
        gpe_block->block_base_number = gpe_block_base_number;
+       gpe_block->initialized = FALSE;
 
        ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
                    sizeof(struct acpi_generic_address));
@@ -385,11 +386,12 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
                return_ACPI_STATUS(status);
        }
 
+       acpi_all_gpes_initialized = FALSE;
+
        /* Find all GPE methods (_Lxx or_Exx) for this block */
 
        walk_info.gpe_block = gpe_block;
        walk_info.gpe_device = gpe_device;
-       walk_info.enable_this_gpe = FALSE;
        walk_info.execute_by_owner_id = FALSE;
 
        status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
@@ -434,35 +436,34 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
  ******************************************************************************/
 
 acpi_status
-acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
-                            struct acpi_gpe_block_info *gpe_block)
+acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
+                            struct acpi_gpe_block_info *gpe_block,
+                            void *ignored)
 {
        acpi_status status;
        struct acpi_gpe_event_info *gpe_event_info;
        u32 gpe_enabled_count;
        u32 gpe_index;
-       u32 gpe_number;
        u32 i;
        u32 j;
 
        ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
 
-       /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
-
-       if (!gpe_block) {
+       /*
+        * Ignore a null GPE block (e.g., if no GPE block 1 exists) and
+        * GPE blocks that have been initialized already.
+        */
+       if (!gpe_block || gpe_block->initialized) {
                return_ACPI_STATUS(AE_OK);
        }
 
        /*
-        * Enable all GPEs that have a corresponding method.  Any other GPEs
-        * within this block must be enabled via the acpi_enable_gpe interface.
+        * Enable all GPEs that have a corresponding method and have the
+        * ACPI_GPE_CAN_WAKE flag unset.  Any other GPEs within this block must
+        * be enabled via the acpi_enable_gpe() interface.
         */
        gpe_enabled_count = 0;
 
-       if (gpe_device == acpi_gbl_fadt_gpe_device) {
-               gpe_device = NULL;
-       }
-
        for (i = 0; i < gpe_block->register_count; i++) {
                for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
 
@@ -470,27 +471,19 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
 
                        gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
                        gpe_event_info = &gpe_block->event_info[gpe_index];
-                       gpe_number = gpe_index + gpe_block->block_base_number;
 
                        /* Ignore GPEs that have no corresponding _Lxx/_Exx method */
 
-                       if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) {
+                       if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
+                           || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
                                continue;
                        }
 
-                       /*
-                        * If the GPE has already been enabled for runtime
-                        * signaling, make sure it remains enabled, but do not
-                        * increment its reference counter.
-                        */
-                       status = gpe_event_info->runtime_count ?
-                               acpi_ev_enable_gpe(gpe_event_info) :
-                               acpi_enable_gpe(gpe_device, gpe_number);
-
+                       status = acpi_raw_enable_gpe(gpe_event_info);
                        if (ACPI_FAILURE(status)) {
                                ACPI_EXCEPTION((AE_INFO, status,
-                                               "Could not enable GPE 0x%02X",
-                                               gpe_number));
+                                       "Could not enable GPE 0x%02X",
+                                       gpe_index + gpe_block->block_base_number));
                                continue;
                        }
 
@@ -504,5 +497,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device,
                                  gpe_enabled_count));
        }
 
+       gpe_block->initialized = TRUE;
+
        return_ACPI_STATUS(AE_OK);
 }
index 3084c5d..2c7def9 100644 (file)
@@ -210,8 +210,7 @@ acpi_status acpi_ev_gpe_initialize(void)
  *
  * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
  *              result of a Load() or load_table() operation. If new GPE
- *              methods have been installed, register the new methods and
- *              enable and runtime GPEs that are associated with them.
+ *              methods have been installed, register the new methods.
  *
  ******************************************************************************/
 
@@ -239,7 +238,6 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
        walk_info.owner_id = table_owner_id;
        walk_info.execute_by_owner_id = TRUE;
        walk_info.count = 0;
-       walk_info.enable_this_gpe = TRUE;
 
        /* Walk the interrupt level descriptor list */
 
@@ -301,8 +299,6 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
  *
  * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods
  *    with that owner.
- * If walk_info->enable_this_gpe is TRUE, the GPE that is referred to by a GPE
- *    method is immediately enabled (Used for Load/load_table operators)
  *
  ******************************************************************************/
 
@@ -315,8 +311,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
        struct acpi_gpe_walk_info *walk_info =
            ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
        struct acpi_gpe_event_info *gpe_event_info;
-       struct acpi_namespace_node *gpe_device;
-       acpi_status status;
        u32 gpe_number;
        char name[ACPI_NAME_SIZE + 1];
        u8 type;
@@ -421,29 +415,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
        gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD);
        gpe_event_info->dispatch.method_node = method_node;
 
-       /*
-        * Enable this GPE if requested. This only happens when during the
-        * execution of a Load or load_table operator. We have found a new
-        * GPE method and want to immediately enable the GPE if it is a
-        * runtime GPE.
-        */
-       if (walk_info->enable_this_gpe) {
-
-               walk_info->count++;
-               gpe_device = walk_info->gpe_device;
-
-               if (gpe_device == acpi_gbl_fadt_gpe_device) {
-                       gpe_device = NULL;
-               }
-
-               status = acpi_enable_gpe(gpe_device, gpe_number);
-               if (ACPI_FAILURE(status)) {
-                       ACPI_EXCEPTION((AE_INFO, status,
-                                       "Could not enable GPE 0x%02X",
-                                       gpe_number));
-               }
-       }
-
        ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
                          "Registered GPE method %s as GPE number 0x%.2X\n",
                          name, gpe_number));
index df0aea9..fcaed9f 100644 (file)
@@ -553,7 +553,7 @@ acpi_status acpi_ev_release_global_lock(void)
        acpi_gbl_global_lock_acquired = FALSE;
 
        /* Release the local GL mutex */
-       acpi_ev_global_lock_thread_id = NULL;
+       acpi_ev_global_lock_thread_id = 0;
        acpi_ev_global_lock_acquired = 0;
        acpi_os_release_mutex(acpi_gbl_global_lock_mutex->mutex.os_mutex);
        return_ACPI_STATUS(status);
index f40d271..0b47a6d 100644 (file)
@@ -289,8 +289,8 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
        }
 
        /*
-        * Get the PCI device and function numbers from the _ADR object contained
-        * in the parent's scope.
+        * Get the PCI device and function numbers from the _ADR object
+        * contained in the parent's scope.
         */
        status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
                                                 pci_device_node, &pci_value);
@@ -320,9 +320,15 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
                pci_id->bus = ACPI_LOWORD(pci_value);
        }
 
-       /* Complete this device's pci_id */
+       /* Complete/update the PCI ID for this device */
 
-       acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id);
+       status =
+           acpi_hw_derive_pci_id(pci_id, pci_root_node,
+                                 region_obj->region.node);
+       if (ACPI_FAILURE(status)) {
+               ACPI_FREE(pci_id);
+               return_ACPI_STATUS(status);
+       }
 
        *region_context = pci_id;
        return_ACPI_STATUS(AE_OK);
index 14e48ad..36af222 100644 (file)
@@ -726,15 +726,16 @@ acpi_install_gpe_handler(acpi_handle gpe_device,
                        (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
 
        /*
-        * If the GPE is associated with a method and it cannot wake up the
-        * system from sleep states, it was enabled automatically during
-        * initialization, so it has to be disabled now to avoid spurious
-        * execution of the handler.
+        * If the GPE is associated with a method, it might have been enabled
+        * automatically during initialization, in which case it has to be
+        * disabled now to avoid spurious execution of the handler.
         */
 
        if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
-           && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
+           && gpe_event_info->runtime_count) {
+               handler->orig_enabled = 1;
                (void)acpi_raw_disable_gpe(gpe_event_info);
+       }
 
        /* Install the handler */
 
@@ -837,13 +838,13 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
        gpe_event_info->flags |= handler->orig_flags;
 
        /*
-        * If the GPE was previously associated with a method and it cannot wake
-        * up the system from sleep states, it should be enabled at this point
-        * to restore the post-initialization configuration.
+        * If the GPE was previously associated with a method and it was
+        * enabled, it should be enabled at this point to restore the
+        * post-initialization configuration.
         */
 
        if ((handler->orig_flags & ACPI_GPE_DISPATCH_METHOD)
-           && !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE))
+           && handler->orig_enabled)
                (void)acpi_raw_enable_gpe(gpe_event_info);
 
        /* Now we can free the handler object */
index 3048255..a1dabe3 100644 (file)
@@ -379,21 +379,12 @@ acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
        /* Ensure that we have a valid GPE number */
 
        gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
-       if (!gpe_event_info) {
+       if (gpe_event_info) {
+               gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
+       } else {
                status = AE_BAD_PARAMETER;
-               goto unlock_and_exit;
-       }
-
-       if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
-               goto unlock_and_exit;
        }
 
-       gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
-       if (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD) {
-               (void)acpi_raw_disable_gpe(gpe_event_info);
-       }
-
-unlock_and_exit:
        acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
        return_ACPI_STATUS(status);
 }
@@ -651,7 +642,7 @@ acpi_install_gpe_block(acpi_handle gpe_device,
                       struct acpi_generic_address *gpe_block_address,
                       u32 register_count, u32 interrupt_number)
 {
-       acpi_status status;
+       acpi_status status = AE_OK;
        union acpi_operand_object *obj_desc;
        struct acpi_namespace_node *node;
        struct acpi_gpe_block_info *gpe_block;
@@ -715,10 +706,6 @@ acpi_install_gpe_block(acpi_handle gpe_device,
 
        obj_desc->device.gpe_block = gpe_block;
 
-       /* Enable the runtime GPEs in the new block */
-
-       status = acpi_ev_initialize_gpe_block(node, gpe_block);
-
       unlock_and_exit:
        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
        return_ACPI_STATUS(status);
@@ -924,3 +911,43 @@ acpi_status acpi_enable_all_runtime_gpes(void)
 
        return_ACPI_STATUS(status);
 }
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_update_gpes
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
+ *              are not pointed to by any device _PRW methods indicating that
+ *              these GPEs are generally intended for system or device wakeup
+ *              (such GPEs have to be enabled directly when the devices whose
+ *              _PRW methods point to them are set up for wakeup signaling).
+ *
+ ******************************************************************************/
+
+acpi_status acpi_update_gpes(void)
+{
+       acpi_status status;
+
+       ACPI_FUNCTION_TRACE(acpi_update_gpes);
+
+       status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       } else if (acpi_all_gpes_initialized) {
+               goto unlock;
+       }
+
+       status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
+       if (ACPI_SUCCESS(status)) {
+               acpi_all_gpes_initialized = TRUE;
+       }
+
+unlock:
+       (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
+
+       return_ACPI_STATUS(status);
+}
index 541cbc1..ce9314f 100644 (file)
@@ -64,6 +64,12 @@ ACPI_MODULE_NAME("evxfregn")
  *
  * DESCRIPTION: Install a handler for all op_regions of a given space_id.
  *
+ * NOTE: This function should only be called after acpi_enable_subsystem has
+ * been called. This is because any _REG methods associated with the Space ID
+ * are executed here, and these methods can only be safely executed after
+ * the default handlers have been installed and the hardware has been
+ * initialized (via acpi_enable_subsystem.)
+ *
  ******************************************************************************/
 acpi_status
 acpi_install_address_space_handler(acpi_handle device,
index 0472173..38293fd 100644 (file)
@@ -119,8 +119,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
        }
 
        /*
-        * Exit now for SMBus or IPMI address space, it has a non-linear address space
-        * and the request cannot be directly validated
+        * Exit now for SMBus or IPMI address space, it has a non-linear
+        * address space and the request cannot be directly validated
         */
        if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS ||
            rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) {
@@ -147,8 +147,7 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc,
         * (Region length is specified in bytes)
         */
        if (rgn_desc->region.length <
-           (obj_desc->common_field.base_byte_offset +
-            field_datum_byte_offset +
+           (obj_desc->common_field.base_byte_offset + field_datum_byte_offset +
             obj_desc->common_field.access_byte_width)) {
                if (acpi_gbl_enable_interpreter_slack) {
                        /*
@@ -680,6 +679,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
        u32 buffer_tail_bits;
        u32 datum_count;
        u32 field_datum_count;
+       u32 access_bit_width;
        u32 i;
 
        ACPI_FUNCTION_TRACE(ex_extract_from_field);
@@ -694,16 +694,36 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
 
                return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
        }
+
        ACPI_MEMSET(buffer, 0, buffer_length);
+       access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
+
+       /* Handle the simple case here */
+
+       if ((obj_desc->common_field.start_field_bit_offset == 0) &&
+           (obj_desc->common_field.bit_length == access_bit_width)) {
+               status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ);
+               return_ACPI_STATUS(status);
+       }
+
+/* TBD: Move to common setup code */
+
+       /* Field algorithm is limited to sizeof(u64), truncate if needed */
+
+       if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
+               obj_desc->common_field.access_byte_width = sizeof(u64);
+               access_bit_width = sizeof(u64) * 8;
+       }
 
        /* Compute the number of datums (access width data items) */
 
-       datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
-                                      obj_desc->common_field.access_bit_width);
+       datum_count =
+           ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
+                            access_bit_width);
+
        field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
                                             obj_desc->common_field.
                                             start_field_bit_offset,
-                                            obj_desc->common_field.
                                             access_bit_width);
 
        /* Priming read from the field */
@@ -738,12 +758,11 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
                 * This avoids the differences in behavior between different compilers
                 * concerning shift values larger than the target data width.
                 */
-               if ((obj_desc->common_field.access_bit_width -
-                    obj_desc->common_field.start_field_bit_offset) <
+               if (access_bit_width -
+                   obj_desc->common_field.start_field_bit_offset <
                    ACPI_INTEGER_BIT_SIZE) {
                        merged_datum |=
-                           raw_datum << (obj_desc->common_field.
-                                         access_bit_width -
+                           raw_datum << (access_bit_width -
                                          obj_desc->common_field.
                                          start_field_bit_offset);
                }
@@ -765,8 +784,7 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
 
        /* Mask off any extra bits in the last datum */
 
-       buffer_tail_bits = obj_desc->common_field.bit_length %
-           obj_desc->common_field.access_bit_width;
+       buffer_tail_bits = obj_desc->common_field.bit_length % access_bit_width;
        if (buffer_tail_bits) {
                merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
        }
@@ -798,6 +816,7 @@ acpi_status
 acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                          void *buffer, u32 buffer_length)
 {
+       void *new_buffer;
        acpi_status status;
        u64 mask;
        u64 width_mask;
@@ -808,9 +827,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
        u32 buffer_tail_bits;
        u32 datum_count;
        u32 field_datum_count;
-       u32 i;
+       u32 access_bit_width;
        u32 required_length;
-       void *new_buffer;
+       u32 i;
 
        ACPI_FUNCTION_TRACE(ex_insert_into_field);
 
@@ -844,17 +863,24 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                buffer_length = required_length;
        }
 
+/* TBD: Move to common setup code */
+
+       /* Algo is limited to sizeof(u64), so cut the access_byte_width */
+       if (obj_desc->common_field.access_byte_width > sizeof(u64)) {
+               obj_desc->common_field.access_byte_width = sizeof(u64);
+       }
+
+       access_bit_width = ACPI_MUL_8(obj_desc->common_field.access_byte_width);
+
        /*
         * Create the bitmasks used for bit insertion.
         * Note: This if/else is used to bypass compiler differences with the
         * shift operator
         */
-       if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
+       if (access_bit_width == ACPI_INTEGER_BIT_SIZE) {
                width_mask = ACPI_UINT64_MAX;
        } else {
-               width_mask =
-                   ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
-                                        access_bit_width);
+               width_mask = ACPI_MASK_BITS_ABOVE(access_bit_width);
        }
 
        mask = width_mask &
@@ -863,12 +889,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
        /* Compute the number of datums (access width data items) */
 
        datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
-                                      obj_desc->common_field.access_bit_width);
+                                      access_bit_width);
 
        field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
                                             obj_desc->common_field.
                                             start_field_bit_offset,
-                                            obj_desc->common_field.
                                             access_bit_width);
 
        /* Get initial Datum from the input buffer */
@@ -905,12 +930,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                 * This avoids the differences in behavior between different compilers
                 * concerning shift values larger than the target data width.
                 */
-               if ((obj_desc->common_field.access_bit_width -
+               if ((access_bit_width -
                     obj_desc->common_field.start_field_bit_offset) <
                    ACPI_INTEGER_BIT_SIZE) {
                        merged_datum =
-                           raw_datum >> (obj_desc->common_field.
-                                         access_bit_width -
+                           raw_datum >> (access_bit_width -
                                          obj_desc->common_field.
                                          start_field_bit_offset);
                } else {
@@ -929,6 +953,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
                ACPI_MEMCPY(&raw_datum, ((char *)buffer) + buffer_offset,
                            ACPI_MIN(obj_desc->common_field.access_byte_width,
                                     buffer_length - buffer_offset));
+
                merged_datum |=
                    raw_datum << obj_desc->common_field.start_field_bit_offset;
        }
@@ -937,7 +962,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
 
        buffer_tail_bits = (obj_desc->common_field.bit_length +
                            obj_desc->common_field.start_field_bit_offset) %
-           obj_desc->common_field.access_bit_width;
+           access_bit_width;
        if (buffer_tail_bits) {
                mask &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
        }
index f73be97..6af14e4 100644 (file)
@@ -336,7 +336,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
 
        /* Clear mutex info */
 
-       obj_desc->mutex.thread_id = NULL;
+       obj_desc->mutex.thread_id = 0;
        return_ACPI_STATUS(status);
 }
 
@@ -393,10 +393,10 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
        if ((owner_thread->thread_id != walk_state->thread->thread_id) &&
            (obj_desc != acpi_gbl_global_lock_mutex)) {
                ACPI_ERROR((AE_INFO,
-                           "Thread %p cannot release Mutex [%4.4s] acquired by thread %p",
-                           ACPI_CAST_PTR(void, walk_state->thread->thread_id),
+                           "Thread %u cannot release Mutex [%4.4s] acquired by thread %u",
+                           (u32)walk_state->thread->thread_id,
                            acpi_ut_get_node_name(obj_desc->mutex.node),
-                           ACPI_CAST_PTR(void, owner_thread->thread_id)));
+                           (u32)owner_thread->thread_id));
                return_ACPI_STATUS(AE_AML_NOT_OWNER);
        }
 
@@ -488,7 +488,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
                /* Mark mutex unowned */
 
                obj_desc->mutex.owner_thread = NULL;
-               obj_desc->mutex.thread_id = NULL;
+               obj_desc->mutex.thread_id = 0;
 
                /* Update Thread sync_level (Last mutex is the important one) */
 
index 98a331d..7aae29f 100644 (file)
@@ -355,12 +355,10 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc,
                return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
        }
 
-       /* Setup width (access granularity) fields */
+       /* Setup width (access granularity) fields (values are: 1, 2, 4, 8) */
 
        obj_desc->common_field.access_byte_width = (u8)
-           ACPI_DIV_8(access_bit_width);       /* 1,  2,  4,  8 */
-
-       obj_desc->common_field.access_bit_width = (u8) access_bit_width;
+           ACPI_DIV_8(access_bit_width);
 
        /*
         * base_byte_offset is the address of the start of the field within the
@@ -405,8 +403,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
 {
        union acpi_operand_object *obj_desc;
        union acpi_operand_object *second_desc = NULL;
-       u32 type;
        acpi_status status;
+       u32 access_byte_width;
+       u32 type;
 
        ACPI_FUNCTION_TRACE(ex_prep_field_value);
 
@@ -421,8 +420,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
                type = acpi_ns_get_type(info->region_node);
                if (type != ACPI_TYPE_REGION) {
                        ACPI_ERROR((AE_INFO,
-                                   "Needed Region, found type 0x%X (%s)",
-                                   type, acpi_ut_get_type_name(type)));
+                                   "Needed Region, found type 0x%X (%s)", type,
+                                   acpi_ut_get_type_name(type)));
 
                        return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
                }
@@ -438,7 +437,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
        /* Initialize areas of the object that are common to all fields */
 
        obj_desc->common_field.node = info->field_node;
-       status = acpi_ex_prep_common_field_object(obj_desc, info->field_flags,
+       status = acpi_ex_prep_common_field_object(obj_desc,
+                                                 info->field_flags,
                                                  info->attribute,
                                                  info->field_bit_position,
                                                  info->field_bit_length);
@@ -455,26 +455,25 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info)
                obj_desc->field.region_obj =
                    acpi_ns_get_attached_object(info->region_node);
 
-               /* An additional reference for the container */
+               /* Allow full data read from EC address space */
 
-               acpi_ut_add_reference(obj_desc->field.region_obj);
+               if ((obj_desc->field.region_obj->region.space_id ==
+                    ACPI_ADR_SPACE_EC)
+                   && (obj_desc->common_field.bit_length > 8)) {
+                       access_byte_width =
+                           ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.
+                                                       bit_length);
+
+                       /* Maximum byte width supported is 255 */
 
-               /* allow full data read from EC address space */
-               if (obj_desc->field.region_obj->region.space_id ==
-                       ACPI_ADR_SPACE_EC) {
-                       if (obj_desc->common_field.bit_length > 8) {
-                               unsigned width =
-                                       ACPI_ROUND_BITS_UP_TO_BYTES(
-                                       obj_desc->common_field.bit_length);
-                               // access_bit_width is u8, don't overflow it
-                               if (width > 8)
-                                       width = 8;
+                       if (access_byte_width < 256) {
                                obj_desc->common_field.access_byte_width =
-                                                       width;
-                               obj_desc->common_field.access_bit_width =
-                                                       8 * width;
+                                   (u8)access_byte_width;
                        }
                }
+               /* An additional reference for the container */
+
+               acpi_ut_add_reference(obj_desc->field.region_obj);
 
                ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
                                  "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n",
index 8819d2a..de17e10 100644 (file)
@@ -353,7 +353,6 @@ acpi_ex_pci_config_space_handler(u32 function,
        acpi_status status = AE_OK;
        struct acpi_pci_id *pci_id;
        u16 pci_register;
-       u32 value32;
 
        ACPI_FUNCTION_TRACE(ex_pci_config_space_handler);
 
@@ -381,8 +380,7 @@ acpi_ex_pci_config_space_handler(u32 function,
        case ACPI_READ:
 
                status = acpi_os_read_pci_configuration(pci_id, pci_register,
-                                                       &value32, bit_width);
-               *value = value32;
+                                                       value, bit_width);
                break;
 
        case ACPI_WRITE:
diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c
new file mode 100644 (file)
index 0000000..ad21c7d
--- /dev/null
@@ -0,0 +1,412 @@
+/*******************************************************************************
+ *
+ * Module Name: hwpci - Obtain PCI bus, device, and function numbers
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_NAMESPACE
+ACPI_MODULE_NAME("hwpci")
+
+/* PCI configuration space values */
+#define PCI_CFG_HEADER_TYPE_REG             0x0E
+#define PCI_CFG_PRIMARY_BUS_NUMBER_REG      0x18
+#define PCI_CFG_SECONDARY_BUS_NUMBER_REG    0x19
+/* PCI header values */
+#define PCI_HEADER_TYPE_MASK                0x7F
+#define PCI_TYPE_BRIDGE                     0x01
+#define PCI_TYPE_CARDBUS_BRIDGE             0x02
+typedef struct acpi_pci_device {
+       acpi_handle device;
+       struct acpi_pci_device *next;
+
+} acpi_pci_device;
+
+/* Local prototypes */
+
+static acpi_status
+acpi_hw_build_pci_list(acpi_handle root_pci_device,
+                      acpi_handle pci_region,
+                      struct acpi_pci_device **return_list_head);
+
+static acpi_status
+acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
+                        struct acpi_pci_device *list_head);
+
+static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head);
+
+static acpi_status
+acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
+                           acpi_handle pci_device,
+                           u16 *bus_number, u8 *is_bridge);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_derive_pci_id
+ *
+ * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
+ *                                    modified by this function.
+ *              root_pci_device     - A handle to a PCI device object. This
+ *                                    object must be a PCI Root Bridge having a
+ *                                    _HID value of either PNP0A03 or PNP0A08
+ *              pci_region          - A handle to a PCI configuration space
+ *                                    Operation Region being initialized
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This function derives a full PCI ID for a PCI device,
+ *              consisting of a Segment number, Bus number, Device number,
+ *              and function code.
+ *
+ *              The PCI hardware dynamically configures PCI bus numbers
+ *              depending on the bus topology discovered during system
+ *              initialization. This function is invoked during configuration
+ *              of a PCI_Config Operation Region in order to (possibly) update
+ *              the Bus/Device/Function numbers in the pci_id with the actual
+ *              values as determined by the hardware and operating system
+ *              configuration.
+ *
+ *              The pci_id parameter is initially populated during the Operation
+ *              Region initialization. This function is then called, and is
+ *              will make any necessary modifications to the Bus, Device, or
+ *              Function number PCI ID subfields as appropriate for the
+ *              current hardware and OS configuration.
+ *
+ * NOTE:        Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id
+ *              interface since this feature is OS-independent. This module
+ *              specifically avoids any use of recursion by building a local
+ *              temporary device list.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
+                     acpi_handle root_pci_device, acpi_handle pci_region)
+{
+       acpi_status status;
+       struct acpi_pci_device *list_head = NULL;
+
+       ACPI_FUNCTION_TRACE(hw_derive_pci_id);
+
+       if (!pci_id) {
+               return_ACPI_STATUS(AE_BAD_PARAMETER);
+       }
+
+       /* Build a list of PCI devices, from pci_region up to root_pci_device */
+
+       status =
+           acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head);
+       if (ACPI_SUCCESS(status)) {
+
+               /* Walk the list, updating the PCI device/function/bus numbers */
+
+               status = acpi_hw_process_pci_list(pci_id, list_head);
+       }
+
+       /* Always delete the list */
+
+       acpi_hw_delete_pci_list(list_head);
+       return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_build_pci_list
+ *
+ * PARAMETERS:  root_pci_device     - A handle to a PCI device object. This
+ *                                    object is guaranteed to be a PCI Root
+ *                                    Bridge having a _HID value of either
+ *                                    PNP0A03 or PNP0A08
+ *              pci_region          - A handle to the PCI configuration space
+ *                                    Operation Region
+ *              return_list_head    - Where the PCI device list is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Builds a list of devices from the input PCI region up to the
+ *              Root PCI device for this namespace subtree.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_hw_build_pci_list(acpi_handle root_pci_device,
+                      acpi_handle pci_region,
+                      struct acpi_pci_device **return_list_head)
+{
+       acpi_handle current_device;
+       acpi_handle parent_device;
+       acpi_status status;
+       struct acpi_pci_device *list_element;
+       struct acpi_pci_device *list_head = NULL;
+
+       /*
+        * Ascend namespace branch until the root_pci_device is reached, building
+        * a list of device nodes. Loop will exit when either the PCI device is
+        * found, or the root of the namespace is reached.
+        */
+       current_device = pci_region;
+       while (1) {
+               status = acpi_get_parent(current_device, &parent_device);
+               if (ACPI_FAILURE(status)) {
+                       return (status);
+               }
+
+               /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
+
+               if (parent_device == root_pci_device) {
+                       *return_list_head = list_head;
+                       return (AE_OK);
+               }
+
+               list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device));
+               if (!list_element) {
+                       return (AE_NO_MEMORY);
+               }
+
+               /* Put new element at the head of the list */
+
+               list_element->next = list_head;
+               list_element->device = parent_device;
+               list_head = list_element;
+
+               current_device = parent_device;
+       }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_process_pci_list
+ *
+ * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
+ *                                    modified by this function.
+ *              list_head           - Device list created by
+ *                                    acpi_hw_build_pci_list
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Walk downward through the PCI device list, getting the device
+ *              info for each, via the PCI configuration space and updating
+ *              the PCI ID as necessary. Deletes the list during traversal.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
+                        struct acpi_pci_device *list_head)
+{
+       acpi_status status = AE_OK;
+       struct acpi_pci_device *info;
+       u16 bus_number;
+       u8 is_bridge = TRUE;
+
+       ACPI_FUNCTION_NAME(hw_process_pci_list);
+
+       ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+                         "Input PciId:  Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
+                         pci_id->segment, pci_id->bus, pci_id->device,
+                         pci_id->function));
+
+       bus_number = pci_id->bus;
+
+       /*
+        * Descend down the namespace tree, collecting PCI device, function,
+        * and bus numbers. bus_number is only important for PCI bridges.
+        * Algorithm: As we descend the tree, use the last valid PCI device,
+        * function, and bus numbers that are discovered, and assign them
+        * to the PCI ID for the target device.
+        */
+       info = list_head;
+       while (info) {
+               status = acpi_hw_get_pci_device_info(pci_id, info->device,
+                                                    &bus_number, &is_bridge);
+               if (ACPI_FAILURE(status)) {
+                       return_ACPI_STATUS(status);
+               }
+
+               info = info->next;
+       }
+
+       ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+                         "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
+                         "Status %X BusNumber %X IsBridge %X\n",
+                         pci_id->segment, pci_id->bus, pci_id->device,
+                         pci_id->function, status, bus_number, is_bridge));
+
+       return_ACPI_STATUS(AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_delete_pci_list
+ *
+ * PARAMETERS:  list_head           - Device list created by
+ *                                    acpi_hw_build_pci_list
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Free the entire PCI list.
+ *
+ ******************************************************************************/
+
+static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head)
+{
+       struct acpi_pci_device *next;
+       struct acpi_pci_device *previous;
+
+       next = list_head;
+       while (next) {
+               previous = next;
+               next = previous->next;
+               ACPI_FREE(previous);
+       }
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_get_pci_device_info
+ *
+ * PARAMETERS:  pci_id              - Initial values for the PCI ID. May be
+ *                                    modified by this function.
+ *              pci_device          - Handle for the PCI device object
+ *              bus_number          - Where a PCI bridge bus number is returned
+ *              is_bridge           - Return value, indicates if this PCI
+ *                                    device is a PCI bridge
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Get the device info for a single PCI device object. Get the
+ *              _ADR (contains PCI device and function numbers), and for PCI
+ *              bridge devices, get the bus number from PCI configuration
+ *              space.
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
+                           acpi_handle pci_device,
+                           u16 *bus_number, u8 *is_bridge)
+{
+       acpi_status status;
+       acpi_object_type object_type;
+       u64 return_value;
+       u64 pci_value;
+
+       /* We only care about objects of type Device */
+
+       status = acpi_get_type(pci_device, &object_type);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       if (object_type != ACPI_TYPE_DEVICE) {
+               return (AE_OK);
+       }
+
+       /* We need an _ADR. Ignore device if not present */
+
+       status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
+                                                pci_device, &return_value);
+       if (ACPI_FAILURE(status)) {
+               return (AE_OK);
+       }
+
+       /*
+        * From _ADR, get the PCI Device and Function and
+        * update the PCI ID.
+        */
+       pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value));
+       pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value));
+
+       /*
+        * If the previous device was a bridge, use the previous
+        * device bus number
+        */
+       if (*is_bridge) {
+               pci_id->bus = *bus_number;
+       }
+
+       /*
+        * Get the bus numbers from PCI Config space:
+        *
+        * First, get the PCI header_type
+        */
+       *is_bridge = FALSE;
+       status = acpi_os_read_pci_configuration(pci_id,
+                                               PCI_CFG_HEADER_TYPE_REG,
+                                               &pci_value, 8);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
+
+       pci_value &= PCI_HEADER_TYPE_MASK;
+
+       if ((pci_value != PCI_TYPE_BRIDGE) &&
+           (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) {
+               return (AE_OK);
+       }
+
+       /* Bridge: Get the Primary bus_number */
+
+       status = acpi_os_read_pci_configuration(pci_id,
+                                               PCI_CFG_PRIMARY_BUS_NUMBER_REG,
+                                               &pci_value, 8);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       *is_bridge = TRUE;
+       pci_id->bus = (u16)pci_value;
+
+       /* Bridge: Get the Secondary bus_number */
+
+       status = acpi_os_read_pci_configuration(pci_id,
+                                               PCI_CFG_SECONDARY_BUS_NUMBER_REG,
+                                               &pci_value, 8);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       *bus_number = (u16)pci_value;
+       return (AE_OK);
+}
index 4009498..4ef9f43 100644 (file)
@@ -74,10 +74,18 @@ acpi_ns_repair_ALR(struct acpi_predefined_data *data,
                   union acpi_operand_object **return_object_ptr);
 
 static acpi_status
+acpi_ns_repair_CID(struct acpi_predefined_data *data,
+                  union acpi_operand_object **return_object_ptr);
+
+static acpi_status
 acpi_ns_repair_FDE(struct acpi_predefined_data *data,
                   union acpi_operand_object **return_object_ptr);
 
 static acpi_status
+acpi_ns_repair_HID(struct acpi_predefined_data *data,
+                  union acpi_operand_object **return_object_ptr);
+
+static acpi_status
 acpi_ns_repair_PSS(struct acpi_predefined_data *data,
                   union acpi_operand_object **return_object_ptr);
 
@@ -108,8 +116,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
  * As necessary:
  *
  * _ALR: Sort the list ascending by ambient_illuminance
+ * _CID: Strings: uppercase all, remove any leading asterisk
  * _FDE: Convert Buffer of BYTEs to a Buffer of DWORDs
  * _GTM: Convert Buffer of BYTEs to a Buffer of DWORDs
+ * _HID: Strings: uppercase all, remove any leading asterisk
  * _PSS: Sort the list descending by Power
  * _TSS: Sort the list descending by Power
  *
@@ -122,8 +132,10 @@ acpi_ns_sort_list(union acpi_operand_object **elements,
  */
 static const struct acpi_repair_info acpi_ns_repairable_names[] = {
        {"_ALR", acpi_ns_repair_ALR},
+       {"_CID", acpi_ns_repair_CID},
        {"_FDE", acpi_ns_repair_FDE},
        {"_GTM", acpi_ns_repair_FDE},   /* _GTM has same repair as _FDE */
+       {"_HID", acpi_ns_repair_HID},
        {"_PSS", acpi_ns_repair_PSS},
        {"_TSS", acpi_ns_repair_TSS},
        {{0, 0, 0, 0}, NULL}    /* Table terminator */
@@ -321,6 +333,157 @@ acpi_ns_repair_FDE(struct acpi_predefined_data *data,
 
 /******************************************************************************
  *
+ * FUNCTION:    acpi_ns_repair_CID
+ *
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              return_object_ptr   - Pointer to the object returned from the
+ *                                    evaluation of a method or object
+ *
+ * RETURN:      Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _CID object. If a string, ensure that all
+ *              letters are uppercase and that there is no leading asterisk.
+ *              If a Package, ensure same for all string elements.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_CID(struct acpi_predefined_data *data,
+                  union acpi_operand_object **return_object_ptr)
+{
+       acpi_status status;
+       union acpi_operand_object *return_object = *return_object_ptr;
+       union acpi_operand_object **element_ptr;
+       union acpi_operand_object *original_element;
+       u16 original_ref_count;
+       u32 i;
+
+       /* Check for _CID as a simple string */
+
+       if (return_object->common.type == ACPI_TYPE_STRING) {
+               status = acpi_ns_repair_HID(data, return_object_ptr);
+               return (status);
+       }
+
+       /* Exit if not a Package */
+
+       if (return_object->common.type != ACPI_TYPE_PACKAGE) {
+               return (AE_OK);
+       }
+
+       /* Examine each element of the _CID package */
+
+       element_ptr = return_object->package.elements;
+       for (i = 0; i < return_object->package.count; i++) {
+               original_element = *element_ptr;
+               original_ref_count = original_element->common.reference_count;
+
+               status = acpi_ns_repair_HID(data, element_ptr);
+               if (ACPI_FAILURE(status)) {
+                       return (status);
+               }
+
+               /* Take care with reference counts */
+
+               if (original_element != *element_ptr) {
+
+                       /* Element was replaced */
+
+                       (*element_ptr)->common.reference_count =
+                           original_ref_count;
+
+                       acpi_ut_remove_reference(original_element);
+               }
+
+               element_ptr++;
+       }
+
+       return (AE_OK);
+}
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_ns_repair_HID
+ *
+ * PARAMETERS:  Data                - Pointer to validation data structure
+ *              return_object_ptr   - Pointer to the object returned from the
+ *                                    evaluation of a method or object
+ *
+ * RETURN:      Status. AE_OK if object is OK or was repaired successfully
+ *
+ * DESCRIPTION: Repair for the _HID object. If a string, ensure that all
+ *              letters are uppercase and that there is no leading asterisk.
+ *
+ *****************************************************************************/
+
+static acpi_status
+acpi_ns_repair_HID(struct acpi_predefined_data *data,
+                  union acpi_operand_object **return_object_ptr)
+{
+       union acpi_operand_object *return_object = *return_object_ptr;
+       union acpi_operand_object *new_string;
+       char *source;
+       char *dest;
+
+       ACPI_FUNCTION_NAME(ns_repair_HID);
+
+       /* We only care about string _HID objects (not integers) */
+
+       if (return_object->common.type != ACPI_TYPE_STRING) {
+               return (AE_OK);
+       }
+
+       if (return_object->string.length == 0) {
+               ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags,
+                                     "Invalid zero-length _HID or _CID string"));
+
+               /* Return AE_OK anyway, let driver handle it */
+
+               data->flags |= ACPI_OBJECT_REPAIRED;
+               return (AE_OK);
+       }
+
+       /* It is simplest to always create a new string object */
+
+       new_string = acpi_ut_create_string_object(return_object->string.length);
+       if (!new_string) {
+               return (AE_NO_MEMORY);
+       }
+
+       /*
+        * Remove a leading asterisk if present. For some unknown reason, there
+        * are many machines in the field that contains IDs like this.
+        *
+        * Examples: "*PNP0C03", "*ACPI0003"
+        */
+       source = return_object->string.pointer;
+       if (*source == '*') {
+               source++;
+               new_string->string.length--;
+
+               ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
+                                 "%s: Removed invalid leading asterisk\n",
+                                 data->pathname));
+       }
+
+       /*
+        * Copy and uppercase the string. From the ACPI specification:
+        *
+        * A valid PNP ID must be of the form "AAA####" where A is an uppercase
+        * letter and # is a hex digit. A valid ACPI ID must be of the form
+        * "ACPI####" where # is a hex digit.
+        */
+       for (dest = new_string->string.pointer; *source; dest++, source++) {
+               *dest = (char)ACPI_TOUPPER(*source);
+       }
+
+       acpi_ut_remove_reference(return_object);
+       *return_object_ptr = new_string;
+       return (AE_OK);
+}
+
+/******************************************************************************
+ *
  * FUNCTION:    acpi_ns_repair_TSS
  *
  * PARAMETERS:  Data                - Pointer to validation data structure
index e1add34..a7d6ad9 100644 (file)
@@ -60,104 +60,6 @@ acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ns_report_error
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              internal_name       - Name or path of the namespace node
- *              lookup_status       - Exception code from NS lookup
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print warning message with full pathname
- *
- ******************************************************************************/
-
-void
-acpi_ns_report_error(const char *module_name,
-                    u32 line_number,
-                    const char *internal_name, acpi_status lookup_status)
-{
-       acpi_status status;
-       u32 bad_name;
-       char *name = NULL;
-
-       acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
-
-       if (lookup_status == AE_BAD_CHARACTER) {
-
-               /* There is a non-ascii character in the name */
-
-               ACPI_MOVE_32_TO_32(&bad_name,
-                                  ACPI_CAST_PTR(u32, internal_name));
-               acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
-       } else {
-               /* Convert path to external format */
-
-               status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
-                                                 internal_name, NULL, &name);
-
-               /* Print target name */
-
-               if (ACPI_SUCCESS(status)) {
-                       acpi_os_printf("[%s]", name);
-               } else {
-                       acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
-               }
-
-               if (name) {
-                       ACPI_FREE(name);
-               }
-       }
-
-       acpi_os_printf(" Namespace lookup failure, %s\n",
-                      acpi_format_exception(lookup_status));
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ns_report_method_error
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              Message             - Error message to use on failure
- *              prefix_node         - Prefix relative to the path
- *              Path                - Path to the node (optional)
- *              method_status       - Execution status
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print warning message with full pathname
- *
- ******************************************************************************/
-
-void
-acpi_ns_report_method_error(const char *module_name,
-                           u32 line_number,
-                           const char *message,
-                           struct acpi_namespace_node *prefix_node,
-                           const char *path, acpi_status method_status)
-{
-       acpi_status status;
-       struct acpi_namespace_node *node = prefix_node;
-
-       acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
-
-       if (path) {
-               status =
-                   acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
-                                    &node);
-               if (ACPI_FAILURE(status)) {
-                       acpi_os_printf("[Could not get node by pathname]");
-               }
-       }
-
-       acpi_ns_print_node_pathname(node, message);
-       acpi_os_printf(", %s\n", acpi_format_exception(method_status));
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ns_print_node_pathname
  *
  * PARAMETERS:  Node            - Object
index 1728cb9..d2ff432 100644 (file)
@@ -49,7 +49,7 @@
 ACPI_MODULE_NAME("tbfadt")
 
 /* Local prototypes */
-static inline void
+static ACPI_INLINE void
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
                             u8 space_id, u8 byte_width, u64 address);
 
@@ -181,7 +181,7 @@ static struct acpi_fadt_pm_info fadt_pm_info_table[] = {
  *
  ******************************************************************************/
 
-static inline void
+static ACPI_INLINE void
 acpi_tb_init_generic_address(struct acpi_generic_address *generic_address,
                             u8 space_id, u8 byte_width, u64 address)
 {
index 9835106..f21c486 100644 (file)
@@ -179,9 +179,8 @@ acpi_debug_print(u32 requested_debug_level,
        if (thread_id != acpi_gbl_prev_thread_id) {
                if (ACPI_LV_THREADS & acpi_dbg_level) {
                        acpi_os_printf
-                           ("\n**** Context Switch from TID %p to TID %p ****\n\n",
-                            ACPI_CAST_PTR(void, acpi_gbl_prev_thread_id),
-                            ACPI_CAST_PTR(void, thread_id));
+                           ("\n**** Context Switch from TID %u to TID %u ****\n\n",
+                            (u32)acpi_gbl_prev_thread_id, (u32)thread_id);
                }
 
                acpi_gbl_prev_thread_id = thread_id;
@@ -194,7 +193,7 @@ acpi_debug_print(u32 requested_debug_level,
        acpi_os_printf("%8s-%04ld ", module_name, line_number);
 
        if (ACPI_LV_THREADS & acpi_dbg_level) {
-               acpi_os_printf("[%p] ", ACPI_CAST_PTR(void, thread_id));
+               acpi_os_printf("[%u] ", (u32)thread_id);
        }
 
        acpi_os_printf("[%02ld] %-22.22s: ",
index 6dfdeb6..22f59ef 100644 (file)
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("uteval")
 
-/*
- * Strings supported by the _OSI predefined (internal) method.
- *
- * March 2009: Removed "Linux" as this host no longer wants to respond true
- * for this string. Basically, the only safe OS strings are windows-related
- * and in many or most cases represent the only test path within the
- * BIOS-provided ASL code.
- *
- * The second element of each entry is used to track the newest version of
- * Windows that the BIOS has requested.
- */
-static struct acpi_interface_info acpi_interfaces_supported[] = {
-       /* Operating System Vendor Strings */
-
-       {"Windows 2000", ACPI_OSI_WIN_2000},    /* Windows 2000 */
-       {"Windows 2001", ACPI_OSI_WIN_XP},      /* Windows XP */
-       {"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1},      /* Windows XP SP1 */
-       {"Windows 2001.1", ACPI_OSI_WINSRV_2003},       /* Windows Server 2003 */
-       {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2},      /* Windows XP SP2 */
-       {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1},       /* Windows Server 2003 SP1 - Added 03/2006 */
-       {"Windows 2006", ACPI_OSI_WIN_VISTA},   /* Windows Vista - Added 03/2006 */
-       {"Windows 2006.1", ACPI_OSI_WINSRV_2008},       /* Windows Server 2008 - Added 09/2009 */
-       {"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1},   /* Windows Vista SP1 - Added 09/2009 */
-       {"Windows 2009", ACPI_OSI_WIN_7},       /* Windows 7 and Server 2008 R2 - Added 09/2009 */
-
-       /* Feature Group Strings */
-
-       {"Extended Address Space Descriptor", 0}
-
-       /*
-        * All "optional" feature group strings (features that are implemented
-        * by the host) should be implemented in the host version of
-        * acpi_os_validate_interface and should not be added here.
-        */
-};
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_osi_implementation
- *
- * PARAMETERS:  walk_state          - Current walk state
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Implementation of the _OSI predefined control method
- *
- ******************************************************************************/
-
-acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
-{
-       acpi_status status;
-       union acpi_operand_object *string_desc;
-       union acpi_operand_object *return_desc;
-       u32 return_value;
-       u32 i;
-
-       ACPI_FUNCTION_TRACE(ut_osi_implementation);
-
-       /* Validate the string input argument */
-
-       string_desc = walk_state->arguments[0].object;
-       if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
-               return_ACPI_STATUS(AE_TYPE);
-       }
-
-       /* Create a return object */
-
-       return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
-       if (!return_desc) {
-               return_ACPI_STATUS(AE_NO_MEMORY);
-       }
-
-       /* Default return value is 0, NOT SUPPORTED */
-
-       return_value = 0;
-
-       /* Compare input string to static table of supported interfaces */
-
-       for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
-               if (!ACPI_STRCMP(string_desc->string.pointer,
-                                acpi_interfaces_supported[i].name)) {
-                       /*
-                        * The interface is supported.
-                        * Update the osi_data if necessary. We keep track of the latest
-                        * version of Windows that has been requested by the BIOS.
-                        */
-                       if (acpi_interfaces_supported[i].value >
-                           acpi_gbl_osi_data) {
-                               acpi_gbl_osi_data =
-                                   acpi_interfaces_supported[i].value;
-                       }
-
-                       return_value = ACPI_UINT32_MAX;
-                       goto exit;
-               }
-       }
-
-       /*
-        * Did not match the string in the static table, call the host OSL to
-        * check for a match with one of the optional strings (such as
-        * "Module Device", "3.0 Thermal Model", etc.)
-        */
-       status = acpi_os_validate_interface(string_desc->string.pointer);
-       if (ACPI_SUCCESS(status)) {
-
-               /* The interface is supported */
-
-               return_value = ACPI_UINT32_MAX;
-       }
-
-exit:
-       ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
-               "ACPI: BIOS _OSI(%s) is %ssupported\n",
-               string_desc->string.pointer, return_value == 0 ? "not " : ""));
-
-       /* Complete the return value */
-
-       return_desc->integer.value = return_value;
-       walk_state->return_desc = return_desc;
-       return_ACPI_STATUS (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_osi_invalidate
- *
- * PARAMETERS:  interface_string
- *
- * RETURN:      Status
- *
- * DESCRIPTION: invalidate string in pre-defiend _OSI string list
- *
- ******************************************************************************/
-
-acpi_status acpi_osi_invalidate(char *interface)
-{
-       int i;
-
-       for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) {
-               if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) {
-                       *acpi_interfaces_supported[i].name = '\0';
-                       return AE_OK;
-               }
-       }
-       return AE_NOT_FOUND;
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_evaluate_object
index 0558747..e87bc67 100644 (file)
@@ -154,14 +154,16 @@ ACPI_EXPORT_SYMBOL(acpi_format_exception)
  * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run
  *    during the initialization sequence.
  * 2) _TZ_ is defined to be a thermal zone in order to allow ASL code to
- *    perform a Notify() operation on it.
+ *    perform a Notify() operation on it. 09/2010: Changed to type Device.
+ *    This still allows notifies, but does not confuse host code that
+ *    searches for valid thermal_zone objects.
  */
 const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = {
        {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
        {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
        {"_SB_", ACPI_TYPE_DEVICE, NULL},
        {"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
-       {"_TZ_", ACPI_TYPE_THERMAL, NULL},
+       {"_TZ_", ACPI_TYPE_DEVICE, NULL},
        {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
        {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
        {"_GL_", ACPI_TYPE_MUTEX, (char *)1},
@@ -766,6 +768,7 @@ acpi_status acpi_ut_init_globals(void)
        acpi_gbl_gpe_fadt_blocks[0] = NULL;
        acpi_gbl_gpe_fadt_blocks[1] = NULL;
        acpi_current_gpe_count = 0;
+       acpi_all_gpes_initialized = FALSE;
 
        /* Global handlers */
 
@@ -774,6 +777,7 @@ acpi_status acpi_ut_init_globals(void)
        acpi_gbl_exception_handler = NULL;
        acpi_gbl_init_handler = NULL;
        acpi_gbl_table_handler = NULL;
+       acpi_gbl_interface_handler = NULL;
 
        /* Global Lock support */
 
@@ -800,6 +804,7 @@ acpi_status acpi_ut_init_globals(void)
        acpi_gbl_debugger_configuration = DEBUGGER_THREADING;
        acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
        acpi_gbl_osi_data = 0;
+       acpi_gbl_osi_mutex = NULL;
 
        /* Hardware oriented */
 
index 1397fad..d290632 100644 (file)
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utids")
 
-/* Local prototypes */
-static void acpi_ut_copy_id_string(char *destination, char *source);
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_copy_id_string
- *
- * PARAMETERS:  Destination         - Where to copy the string
- *              Source              - Source string
- *
- * RETURN:      None
- *
- * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods.
- *              Performs removal of a leading asterisk if present -- workaround
- *              for a known issue on a bunch of machines.
- *
- ******************************************************************************/
-
-static void acpi_ut_copy_id_string(char *destination, char *source)
-{
-
-       /*
-        * Workaround for ID strings that have a leading asterisk. This construct
-        * is not allowed by the ACPI specification  (ID strings must be
-        * alphanumeric), but enough existing machines have this embedded in their
-        * ID strings that the following code is useful.
-        */
-       if (*source == '*') {
-               source++;
-       }
-
-       /* Do the actual copy */
-
-       ACPI_STRCPY(destination, source);
-}
-
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_execute_HID
@@ -101,7 +65,6 @@ static void acpi_ut_copy_id_string(char *destination, char *source)
  *              NOTE: Internal function, no parameter validation
  *
  ******************************************************************************/
-
 acpi_status
 acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
                    struct acpica_device_id **return_id)
@@ -147,7 +110,7 @@ acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
        if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
                acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
        } else {
-               acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer);
+               ACPI_STRCPY(hid->string, obj_desc->string.pointer);
        }
 
        hid->length = length;
@@ -224,7 +187,7 @@ acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
        if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
                acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
        } else {
-               acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer);
+               ACPI_STRCPY(uid->string, obj_desc->string.pointer);
        }
 
        uid->length = length;
@@ -357,8 +320,8 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
 
                        /* Copy the String CID from the returned object */
 
-                       acpi_ut_copy_id_string(next_id_string,
-                                              cid_objects[i]->string.pointer);
+                       ACPI_STRCPY(next_id_string,
+                                   cid_objects[i]->string.pointer);
                        length = cid_objects[i]->string.length + 1;
                }
 
index a39c93d..c1b1c80 100644 (file)
@@ -117,6 +117,10 @@ void acpi_ut_subsystem_shutdown(void)
        /* Close the acpi_event Handling */
 
        acpi_ev_terminate();
+
+       /* Delete any dynamic _OSI interfaces */
+
+       acpi_ut_interface_terminate();
 #endif
 
        /* Close the Namespace */
index 35059a1..49cf7b7 100644 (file)
 ACPI_MODULE_NAME("utmath")
 
 /*
- * Support for double-precision integer divide.  This code is included here
- * in order to support kernel environments where the double-precision math
- * library is not available.
+ * Optional support for 64-bit double-precision integer divide. This code
+ * is configurable and is implemented in order to support 32-bit kernel
+ * environments where a 64-bit double-precision math library is not available.
+ *
+ * Support for a more normal 64-bit divide/modulo (with check for a divide-
+ * by-zero) appears after this optional section of code.
  */
 #ifndef ACPI_USE_NATIVE_DIVIDE
+/* Structures used only for 64-bit divide */
+typedef struct uint64_struct {
+       u32 lo;
+       u32 hi;
+
+} uint64_struct;
+
+typedef union uint64_overlay {
+       u64 full;
+       struct uint64_struct part;
+
+} uint64_overlay;
+
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_short_divide
@@ -69,6 +85,7 @@ ACPI_MODULE_NAME("utmath")
  *              32-bit remainder.
  *
  ******************************************************************************/
+
 acpi_status
 acpi_ut_short_divide(u64 dividend,
                     u32 divisor, u64 *out_quotient, u32 *out_remainder)
index e8d0724..c7d0e05 100644 (file)
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utmisc")
 
-/*
- * Common suffix for messages
- */
-#define ACPI_COMMON_MSG_SUFFIX \
-       acpi_os_printf(" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
 /*******************************************************************************
  *
  * FUNCTION:    acpi_ut_validate_exception
@@ -1044,160 +1039,3 @@ acpi_ut_walk_package_tree(union acpi_operand_object * source_object,
 
        return_ACPI_STATUS(AE_AML_INTERNAL);
 }
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_error, acpi_exception, acpi_warning, acpi_info
- *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              Format              - Printf format string + additional args
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print message with module/line/version info
- *
- ******************************************************************************/
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_error(const char *module_name, u32 line_number, const char *format, ...)
-{
-       va_list args;
-
-       acpi_os_printf("ACPI Error: ");
-
-       va_start(args, format);
-       acpi_os_vprintf(format, args);
-       ACPI_COMMON_MSG_SUFFIX;
-       va_end(args);
-}
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_exception(const char *module_name,
-              u32 line_number, acpi_status status, const char *format, ...)
-{
-       va_list args;
-
-       acpi_os_printf("ACPI Exception: %s, ", acpi_format_exception(status));
-
-       va_start(args, format);
-       acpi_os_vprintf(format, args);
-       ACPI_COMMON_MSG_SUFFIX;
-       va_end(args);
-}
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
-{
-       va_list args;
-
-       acpi_os_printf("ACPI Warning: ");
-
-       va_start(args, format);
-       acpi_os_vprintf(format, args);
-       ACPI_COMMON_MSG_SUFFIX;
-       va_end(args);
-}
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_info(const char *module_name, u32 line_number, const char *format, ...)
-{
-       va_list args;
-
-       acpi_os_printf("ACPI: ");
-
-       va_start(args, format);
-       acpi_os_vprintf(format, args);
-       acpi_os_printf("\n");
-       va_end(args);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_error)
-ACPI_EXPORT_SYMBOL(acpi_exception)
-ACPI_EXPORT_SYMBOL(acpi_warning)
-ACPI_EXPORT_SYMBOL(acpi_info)
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_predefined_warning
- *
- * PARAMETERS:  module_name     - Caller's module name (for error output)
- *              line_number     - Caller's line number (for error output)
- *              Pathname        - Full pathname to the node
- *              node_flags      - From Namespace node for the method/object
- *              Format          - Printf format string + additional args
- *
- * RETURN:      None
- *
- * DESCRIPTION: Warnings for the predefined validation module. Messages are
- *              only emitted the first time a problem with a particular
- *              method/object is detected. This prevents a flood of error
- *              messages for methods that are repeatedly evaluated.
- *
-******************************************************************************/
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_warning(const char *module_name,
-                          u32 line_number,
-                          char *pathname,
-                          u8 node_flags, const char *format, ...)
-{
-       va_list args;
-
-       /*
-        * Warning messages for this method/object will be disabled after the
-        * first time a validation fails or an object is successfully repaired.
-        */
-       if (node_flags & ANOBJ_EVALUATED) {
-               return;
-       }
-
-       acpi_os_printf("ACPI Warning for %s: ", pathname);
-
-       va_start(args, format);
-       acpi_os_vprintf(format, args);
-       ACPI_COMMON_MSG_SUFFIX;
-       va_end(args);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_predefined_info
- *
- * PARAMETERS:  module_name     - Caller's module name (for error output)
- *              line_number     - Caller's line number (for error output)
- *              Pathname        - Full pathname to the node
- *              node_flags      - From Namespace node for the method/object
- *              Format          - Printf format string + additional args
- *
- * RETURN:      None
- *
- * DESCRIPTION: Info messages for the predefined validation module. Messages
- *              are only emitted the first time a problem with a particular
- *              method/object is detected. This prevents a flood of
- *              messages for methods that are repeatedly evaluated.
- *
- ******************************************************************************/
-
-void ACPI_INTERNAL_VAR_XFACE
-acpi_ut_predefined_info(const char *module_name,
-                       u32 line_number,
-                       char *pathname, u8 node_flags, const char *format, ...)
-{
-       va_list args;
-
-       /*
-        * Warning messages for this method/object will be disabled after the
-        * first time a validation fails or an object is successfully repaired.
-        */
-       if (node_flags & ANOBJ_EVALUATED) {
-               return;
-       }
-
-       acpi_os_printf("ACPI Info for %s: ", pathname);
-
-       va_start(args, format);
-       acpi_os_vprintf(format, args);
-       ACPI_COMMON_MSG_SUFFIX;
-       va_end(args);
-}
index f5cca3a..d9efa49 100644 (file)
@@ -86,6 +86,12 @@ acpi_status acpi_ut_mutex_initialize(void)
        spin_lock_init(acpi_gbl_gpe_lock);
        spin_lock_init(acpi_gbl_hardware_lock);
 
+       /* Mutex for _OSI support */
+       status = acpi_os_create_mutex(&acpi_gbl_osi_mutex);
+       if (ACPI_FAILURE(status)) {
+               return_ACPI_STATUS(status);
+       }
+
        /* Create the reader/writer lock for namespace access */
 
        status = acpi_ut_create_rw_lock(&acpi_gbl_namespace_rw_lock);
@@ -117,6 +123,8 @@ void acpi_ut_mutex_terminate(void)
                acpi_ut_delete_mutex(i);
        }
 
+       acpi_os_delete_mutex(acpi_gbl_osi_mutex);
+
        /* Delete the spinlocks */
 
        acpi_os_delete_lock(acpi_gbl_gpe_lock);
@@ -220,18 +228,17 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
                        if (acpi_gbl_mutex_info[i].thread_id == this_thread_id) {
                                if (i == mutex_id) {
                                        ACPI_ERROR((AE_INFO,
-                                                   "Mutex [%s] already acquired by this thread [%p]",
+                                                   "Mutex [%s] already acquired by this thread [%u]",
                                                    acpi_ut_get_mutex_name
                                                    (mutex_id),
-                                                   ACPI_CAST_PTR(void,
-                                                                 this_thread_id)));
+                                                   (u32)this_thread_id));
 
                                        return (AE_ALREADY_ACQUIRED);
                                }
 
                                ACPI_ERROR((AE_INFO,
-                                           "Invalid acquire order: Thread %p owns [%s], wants [%s]",
-                                           ACPI_CAST_PTR(void, this_thread_id),
+                                           "Invalid acquire order: Thread %u owns [%s], wants [%s]",
+                                           (u32)this_thread_id,
                                            acpi_ut_get_mutex_name(i),
                                            acpi_ut_get_mutex_name(mutex_id)));
 
@@ -242,24 +249,24 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
 #endif
 
        ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-                         "Thread %p attempting to acquire Mutex [%s]\n",
-                         ACPI_CAST_PTR(void, this_thread_id),
+                         "Thread %u attempting to acquire Mutex [%s]\n",
+                         (u32)this_thread_id,
                          acpi_ut_get_mutex_name(mutex_id)));
 
        status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
                                       ACPI_WAIT_FOREVER);
        if (ACPI_SUCCESS(status)) {
                ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
-                                 "Thread %p acquired Mutex [%s]\n",
-                                 ACPI_CAST_PTR(void, this_thread_id),
+                                 "Thread %u acquired Mutex [%s]\n",
+                                 (u32)this_thread_id,
                                  acpi_ut_get_mutex_name(mutex_id)));
 
                acpi_gbl_mutex_info[mutex_id].use_count++;
                acpi_gbl_mutex_info[mutex_id].thread_id = this_thread_id;
        } else {
                ACPI_EXCEPTION((AE_INFO, status,
-                               "Thread %p could not acquire Mutex [0x%X]",
-                               ACPI_CAST_PTR(void, this_thread_id), mutex_id));
+                               "Thread %u could not acquire Mutex [0x%X]",
+                               (u32)this_thread_id, mutex_id));
        }
 
        return (status);
@@ -279,10 +286,14 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id)
 
 acpi_status acpi_ut_release_mutex(acpi_mutex_handle mutex_id)
 {
+       acpi_thread_id this_thread_id;
+
        ACPI_FUNCTION_NAME(ut_release_mutex);
 
-       ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %p releasing Mutex [%s]\n",
-                         ACPI_CAST_PTR(void, acpi_os_get_thread_id()),
+       this_thread_id = acpi_os_get_thread_id();
+
+       ACPI_DEBUG_PRINT((ACPI_DB_MUTEX, "Thread %u releasing Mutex [%s]\n",
+                         (u32)this_thread_id,
                          acpi_ut_get_mutex_name(mutex_id)));
 
        if (mutex_id > ACPI_MAX_MUTEX) {
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
new file mode 100644 (file)
index 0000000..18c59a8
--- /dev/null
@@ -0,0 +1,380 @@
+/******************************************************************************
+ *
+ * Module Name: utosi - Support for the _OSI predefined control method
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utosi")
+
+/*
+ * Strings supported by the _OSI predefined control method (which is
+ * implemented internally within this module.)
+ *
+ * March 2009: Removed "Linux" as this host no longer wants to respond true
+ * for this string. Basically, the only safe OS strings are windows-related
+ * and in many or most cases represent the only test path within the
+ * BIOS-provided ASL code.
+ *
+ * The last element of each entry is used to track the newest version of
+ * Windows that the BIOS has requested.
+ */
+static struct acpi_interface_info acpi_default_supported_interfaces[] = {
+       /* Operating System Vendor Strings */
+
+       {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000},   /* Windows 2000 */
+       {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP},     /* Windows XP */
+       {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1},     /* Windows XP SP1 */
+       {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003},      /* Windows Server 2003 */
+       {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2},     /* Windows XP SP2 */
+       {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1},      /* Windows Server 2003 SP1 - Added 03/2006 */
+       {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA},  /* Windows Vista - Added 03/2006 */
+       {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008},      /* Windows Server 2008 - Added 09/2009 */
+       {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1},  /* Windows Vista SP1 - Added 09/2009 */
+       {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2},  /* Windows Vista SP2 - Added 09/2010 */
+       {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7},      /* Windows 7 and Server 2008 R2 - Added 09/2009 */
+
+       /* Feature Group Strings */
+
+       {"Extended Address Space Descriptor", NULL, 0, 0}
+
+       /*
+        * All "optional" feature group strings (features that are implemented
+        * by the host) should be dynamically added by the host via
+        * acpi_install_interface and should not be manually added here.
+        *
+        * Examples of optional feature group strings:
+        *
+        * "Module Device"
+        * "Processor Device"
+        * "3.0 Thermal Model"
+        * "3.0 _SCP Extensions"
+        * "Processor Aggregator Device"
+        */
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_initialize_interfaces
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Initialize the global _OSI supported interfaces list
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_initialize_interfaces(void)
+{
+       u32 i;
+
+       (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+       acpi_gbl_supported_interfaces = acpi_default_supported_interfaces;
+
+       /* Link the static list of supported interfaces */
+
+       for (i = 0;
+            i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1);
+            i++) {
+               acpi_default_supported_interfaces[i].next =
+                   &acpi_default_supported_interfaces[(acpi_size) i + 1];
+       }
+
+       acpi_os_release_mutex(acpi_gbl_osi_mutex);
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_interface_terminate
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Delete all interfaces in the global list. Sets
+ *              acpi_gbl_supported_interfaces to NULL.
+ *
+ ******************************************************************************/
+
+void acpi_ut_interface_terminate(void)
+{
+       struct acpi_interface_info *next_interface;
+
+       (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+       next_interface = acpi_gbl_supported_interfaces;
+
+       while (next_interface) {
+               acpi_gbl_supported_interfaces = next_interface->next;
+
+               /* Only interfaces added at runtime can be freed */
+
+               if (next_interface->flags & ACPI_OSI_DYNAMIC) {
+                       ACPI_FREE(next_interface->name);
+                       ACPI_FREE(next_interface);
+               }
+
+               next_interface = acpi_gbl_supported_interfaces;
+       }
+
+       acpi_os_release_mutex(acpi_gbl_osi_mutex);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_install_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to install
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install the interface into the global interface list.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_install_interface(acpi_string interface_name)
+{
+       struct acpi_interface_info *interface_info;
+
+       /* Allocate info block and space for the name string */
+
+       interface_info =
+           ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info));
+       if (!interface_info) {
+               return (AE_NO_MEMORY);
+       }
+
+       interface_info->name =
+           ACPI_ALLOCATE_ZEROED(ACPI_STRLEN(interface_name) + 1);
+       if (!interface_info->name) {
+               ACPI_FREE(interface_info);
+               return (AE_NO_MEMORY);
+       }
+
+       /* Initialize new info and insert at the head of the global list */
+
+       ACPI_STRCPY(interface_info->name, interface_name);
+       interface_info->flags = ACPI_OSI_DYNAMIC;
+       interface_info->next = acpi_gbl_supported_interfaces;
+
+       acpi_gbl_supported_interfaces = interface_info;
+       return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_remove_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to remove
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove the interface from the global interface list.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_remove_interface(acpi_string interface_name)
+{
+       struct acpi_interface_info *previous_interface;
+       struct acpi_interface_info *next_interface;
+
+       previous_interface = next_interface = acpi_gbl_supported_interfaces;
+       while (next_interface) {
+               if (!ACPI_STRCMP(interface_name, next_interface->name)) {
+
+                       /* Found: name is in either the static list or was added at runtime */
+
+                       if (next_interface->flags & ACPI_OSI_DYNAMIC) {
+
+                               /* Interface was added dynamically, remove and free it */
+
+                               if (previous_interface == next_interface) {
+                                       acpi_gbl_supported_interfaces =
+                                           next_interface->next;
+                               } else {
+                                       previous_interface->next =
+                                           next_interface->next;
+                               }
+
+                               ACPI_FREE(next_interface->name);
+                               ACPI_FREE(next_interface);
+                       } else {
+                               /*
+                                * Interface is in static list. If marked invalid, then it
+                                * does not actually exist. Else, mark it invalid.
+                                */
+                               if (next_interface->flags & ACPI_OSI_INVALID) {
+                                       return (AE_NOT_EXIST);
+                               }
+
+                               next_interface->flags |= ACPI_OSI_INVALID;
+                       }
+
+                       return (AE_OK);
+               }
+
+               previous_interface = next_interface;
+               next_interface = next_interface->next;
+       }
+
+       /* Interface was not found */
+
+       return (AE_NOT_EXIST);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to find
+ *
+ * RETURN:      struct acpi_interface_info if found. NULL if not found.
+ *
+ * DESCRIPTION: Search for the specified interface name in the global list.
+ *              Caller MUST hold acpi_gbl_osi_mutex
+ *
+ ******************************************************************************/
+
+struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name)
+{
+       struct acpi_interface_info *next_interface;
+
+       next_interface = acpi_gbl_supported_interfaces;
+       while (next_interface) {
+               if (!ACPI_STRCMP(interface_name, next_interface->name)) {
+                       return (next_interface);
+               }
+
+               next_interface = next_interface->next;
+       }
+
+       return (NULL);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_osi_implementation
+ *
+ * PARAMETERS:  walk_state          - Current walk state
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Implementation of the _OSI predefined control method. When
+ *              an invocation of _OSI is encountered in the system AML,
+ *              control is transferred to this function.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ut_osi_implementation(struct acpi_walk_state * walk_state)
+{
+       union acpi_operand_object *string_desc;
+       union acpi_operand_object *return_desc;
+       struct acpi_interface_info *interface_info;
+       acpi_interface_handler interface_handler;
+       u32 return_value;
+
+       ACPI_FUNCTION_TRACE(ut_osi_implementation);
+
+       /* Validate the string input argument (from the AML caller) */
+
+       string_desc = walk_state->arguments[0].object;
+       if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
+               return_ACPI_STATUS(AE_TYPE);
+       }
+
+       /* Create a return object */
+
+       return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
+       if (!return_desc) {
+               return_ACPI_STATUS(AE_NO_MEMORY);
+       }
+
+       /* Default return value is 0, NOT SUPPORTED */
+
+       return_value = 0;
+       (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+       /* Lookup the interface in the global _OSI list */
+
+       interface_info = acpi_ut_get_interface(string_desc->string.pointer);
+       if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) {
+               /*
+                * The interface is supported.
+                * Update the osi_data if necessary. We keep track of the latest
+                * version of Windows that has been requested by the BIOS.
+                */
+               if (interface_info->value > acpi_gbl_osi_data) {
+                       acpi_gbl_osi_data = interface_info->value;
+               }
+
+               return_value = ACPI_UINT32_MAX;
+       }
+
+       acpi_os_release_mutex(acpi_gbl_osi_mutex);
+
+       /*
+        * Invoke an optional _OSI interface handler. The host OS may wish
+        * to do some interface-specific handling. For example, warn about
+        * certain interfaces or override the true/false support value.
+        */
+       interface_handler = acpi_gbl_interface_handler;
+       if (interface_handler) {
+               return_value =
+                   interface_handler(string_desc->string.pointer,
+                                     return_value);
+       }
+
+       ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
+                             "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
+                             string_desc->string.pointer,
+                             return_value == 0 ? "not " : ""));
+
+       /* Complete the return object */
+
+       return_desc->integer.value = return_value;
+       walk_state->return_desc = return_desc;
+       return_ACPI_STATUS(AE_OK);
+}
index 7f8cefc..1f484c9 100644 (file)
@@ -110,6 +110,15 @@ acpi_status __init acpi_initialize_subsystem(void)
                return_ACPI_STATUS(status);
        }
 
+       /* Initialize the global OSI interfaces list with the static names */
+
+       status = acpi_ut_initialize_interfaces();
+       if (ACPI_FAILURE(status)) {
+               ACPI_EXCEPTION((AE_INFO, status,
+                               "During OSI interfaces initialization"));
+               return_ACPI_STATUS(status);
+       }
+
        /* If configured, initialize the AML debugger */
 
        ACPI_DEBUGGER_EXEC(status = acpi_db_initialize());
@@ -290,19 +299,6 @@ acpi_status acpi_initialize_objects(u32 flags)
        }
 
        /*
-        * Complete the GPE initialization for the GPE blocks defined in the FADT
-        * (GPE block 0 and 1).
-        *
-        * NOTE: Currently, there seems to be no need to run the _REG methods
-        * before enabling the GPEs.
-        */
-       if (!(flags & ACPI_NO_EVENT_INIT)) {
-               status = acpi_ev_install_fadt_gpes();
-               if (ACPI_FAILURE(status))
-                       return (status);
-       }
-
-       /*
         * Empty the caches (delete the cached objects) on the assumption that
         * the table load filled them up more than they will be at runtime --
         * thus wasting non-paged memory.
@@ -506,6 +502,7 @@ acpi_install_initialization_handler(acpi_init_handler handler, u32 function)
 
 ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)
 #endif                         /*  ACPI_FUTURE_USAGE  */
+
 /*****************************************************************************
  *
  * FUNCTION:    acpi_purge_cached_objects
@@ -529,4 +526,117 @@ acpi_status acpi_purge_cached_objects(void)
 }
 
 ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)
-#endif
+
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_install_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to install
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install an _OSI interface to the global list
+ *
+ ****************************************************************************/
+acpi_status acpi_install_interface(acpi_string interface_name)
+{
+       acpi_status status;
+       struct acpi_interface_info *interface_info;
+
+       /* Parameter validation */
+
+       if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+       /* Check if the interface name is already in the global list */
+
+       interface_info = acpi_ut_get_interface(interface_name);
+       if (interface_info) {
+               /*
+                * The interface already exists in the list. This is OK if the
+                * interface has been marked invalid -- just clear the bit.
+                */
+               if (interface_info->flags & ACPI_OSI_INVALID) {
+                       interface_info->flags &= ~ACPI_OSI_INVALID;
+                       status = AE_OK;
+               } else {
+                       status = AE_ALREADY_EXISTS;
+               }
+       } else {
+               /* New interface name, install into the global list */
+
+               status = acpi_ut_install_interface(interface_name);
+       }
+
+       acpi_os_release_mutex(acpi_gbl_osi_mutex);
+       return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_install_interface)
+
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_remove_interface
+ *
+ * PARAMETERS:  interface_name      - The interface to remove
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Remove an _OSI interface from the global list
+ *
+ ****************************************************************************/
+acpi_status acpi_remove_interface(acpi_string interface_name)
+{
+       acpi_status status;
+
+       /* Parameter validation */
+
+       if (!interface_name || (ACPI_STRLEN(interface_name) == 0)) {
+               return (AE_BAD_PARAMETER);
+       }
+
+       (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+       status = acpi_ut_remove_interface(interface_name);
+
+       acpi_os_release_mutex(acpi_gbl_osi_mutex);
+       return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_remove_interface)
+
+/*****************************************************************************
+ *
+ * FUNCTION:    acpi_install_interface_handler
+ *
+ * PARAMETERS:  Handler             - The _OSI interface handler to install
+ *                                    NULL means "remove existing handler"
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Install a handler for the predefined _OSI ACPI method.
+ *              invoked during execution of the internal implementation of
+ *              _OSI. A NULL handler simply removes any existing handler.
+ *
+ ****************************************************************************/
+acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
+{
+       acpi_status status = AE_OK;
+
+       (void)acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
+
+       if (handler && acpi_gbl_interface_handler) {
+               status = AE_ALREADY_EXISTS;
+       } else {
+               acpi_gbl_interface_handler = handler;
+       }
+
+       acpi_os_release_mutex(acpi_gbl_osi_mutex);
+       return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
+#endif                         /* !ACPI_ASL_COMPILER */
diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c
new file mode 100644 (file)
index 0000000..6f12e31
--- /dev/null
@@ -0,0 +1,415 @@
+/*******************************************************************************
+ *
+ * Module Name: utxferror - Various error/warning output functions
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2010, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utxferror")
+
+/*
+ * This module is used for the in-kernel ACPICA as well as the ACPICA
+ * tools/applications.
+ *
+ * For the i_aSL compiler case, the output is redirected to stderr so that
+ * any of the various ACPI errors and warnings do not appear in the output
+ * files, for either the compiler or disassembler portions of the tool.
+ */
+#ifdef ACPI_ASL_COMPILER
+#include <stdio.h>
+extern FILE *acpi_gbl_output_file;
+
+#define ACPI_MSG_REDIRECT_BEGIN \
+       FILE                            *output_file = acpi_gbl_output_file; \
+       acpi_os_redirect_output (stderr);
+
+#define ACPI_MSG_REDIRECT_END \
+       acpi_os_redirect_output (output_file);
+
+#else
+/*
+ * non-i_aSL case - no redirection, nothing to do
+ */
+#define ACPI_MSG_REDIRECT_BEGIN
+#define ACPI_MSG_REDIRECT_END
+#endif
+/*
+ * Common message prefixes
+ */
+#define ACPI_MSG_ERROR          "ACPI Error: "
+#define ACPI_MSG_EXCEPTION      "ACPI Exception: "
+#define ACPI_MSG_WARNING        "ACPI Warning: "
+#define ACPI_MSG_INFO           "ACPI: "
+/*
+ * Common message suffix
+ */
+#define ACPI_MSG_SUFFIX \
+       acpi_os_printf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_error
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print "ACPI Error" message with module/line/version info
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_error(const char *module_name, u32 line_number, const char *format, ...)
+{
+       va_list arg_list;
+
+       ACPI_MSG_REDIRECT_BEGIN;
+       acpi_os_printf(ACPI_MSG_ERROR);
+
+       va_start(arg_list, format);
+       acpi_os_vprintf(format, arg_list);
+       ACPI_MSG_SUFFIX;
+       va_end(arg_list);
+
+       ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_error)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_exception
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Status              - Status to be formatted
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print "ACPI Exception" message with module/line/version info
+ *              and decoded acpi_status.
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_exception(const char *module_name,
+              u32 line_number, acpi_status status, const char *format, ...)
+{
+       va_list arg_list;
+
+       ACPI_MSG_REDIRECT_BEGIN;
+       acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ",
+                      acpi_format_exception(status));
+
+       va_start(arg_list, format);
+       acpi_os_vprintf(format, arg_list);
+       ACPI_MSG_SUFFIX;
+       va_end(arg_list);
+
+       ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_exception)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_warning
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print "ACPI Warning" message with module/line/version info
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_warning(const char *module_name, u32 line_number, const char *format, ...)
+{
+       va_list arg_list;
+
+       ACPI_MSG_REDIRECT_BEGIN;
+       acpi_os_printf(ACPI_MSG_WARNING);
+
+       va_start(arg_list, format);
+       acpi_os_vprintf(format, arg_list);
+       ACPI_MSG_SUFFIX;
+       va_end(arg_list);
+
+       ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_warning)
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_info
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Format              - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print generic "ACPI:" information message. There is no
+ *              module/line/version info in order to keep the message simple.
+ *
+ * TBD: module_name and line_number args are not needed, should be removed.
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_info(const char *module_name, u32 line_number, const char *format, ...)
+{
+       va_list arg_list;
+
+       ACPI_MSG_REDIRECT_BEGIN;
+       acpi_os_printf(ACPI_MSG_INFO);
+
+       va_start(arg_list, format);
+       acpi_os_vprintf(format, arg_list);
+       acpi_os_printf("\n");
+       va_end(arg_list);
+
+       ACPI_MSG_REDIRECT_END;
+}
+
+ACPI_EXPORT_SYMBOL(acpi_info)
+
+/*
+ * The remainder of this module contains internal error functions that may
+ * be configured out.
+ */
+#if !defined (ACPI_NO_ERROR_MESSAGES) && !defined (ACPI_BIN_APP)
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_predefined_warning
+ *
+ * PARAMETERS:  module_name     - Caller's module name (for error output)
+ *              line_number     - Caller's line number (for error output)
+ *              Pathname        - Full pathname to the node
+ *              node_flags      - From Namespace node for the method/object
+ *              Format          - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Warnings for the predefined validation module. Messages are
+ *              only emitted the first time a problem with a particular
+ *              method/object is detected. This prevents a flood of error
+ *              messages for methods that are repeatedly evaluated.
+ *
+ ******************************************************************************/
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_warning(const char *module_name,
+                          u32 line_number,
+                          char *pathname,
+                          u8 node_flags, const char *format, ...)
+{
+       va_list arg_list;
+
+       /*
+        * Warning messages for this method/object will be disabled after the
+        * first time a validation fails or an object is successfully repaired.
+        */
+       if (node_flags & ANOBJ_EVALUATED) {
+               return;
+       }
+
+       acpi_os_printf(ACPI_MSG_WARNING "For %s: ", pathname);
+
+       va_start(arg_list, format);
+       acpi_os_vprintf(format, arg_list);
+       ACPI_MSG_SUFFIX;
+       va_end(arg_list);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_predefined_info
+ *
+ * PARAMETERS:  module_name     - Caller's module name (for error output)
+ *              line_number     - Caller's line number (for error output)
+ *              Pathname        - Full pathname to the node
+ *              node_flags      - From Namespace node for the method/object
+ *              Format          - Printf format string + additional args
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Info messages for the predefined validation module. Messages
+ *              are only emitted the first time a problem with a particular
+ *              method/object is detected. This prevents a flood of
+ *              messages for methods that are repeatedly evaluated.
+ *
+ ******************************************************************************/
+
+void ACPI_INTERNAL_VAR_XFACE
+acpi_ut_predefined_info(const char *module_name,
+                       u32 line_number,
+                       char *pathname, u8 node_flags, const char *format, ...)
+{
+       va_list arg_list;
+
+       /*
+        * Warning messages for this method/object will be disabled after the
+        * first time a validation fails or an object is successfully repaired.
+        */
+       if (node_flags & ANOBJ_EVALUATED) {
+               return;
+       }
+
+       acpi_os_printf(ACPI_MSG_INFO "For %s: ", pathname);
+
+       va_start(arg_list, format);
+       acpi_os_vprintf(format, arg_list);
+       ACPI_MSG_SUFFIX;
+       va_end(arg_list);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_namespace_error
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              internal_name       - Name or path of the namespace node
+ *              lookup_status       - Exception code from NS lookup
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print error message with the full pathname for the NS node.
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_namespace_error(const char *module_name,
+                       u32 line_number,
+                       const char *internal_name, acpi_status lookup_status)
+{
+       acpi_status status;
+       u32 bad_name;
+       char *name = NULL;
+
+       ACPI_MSG_REDIRECT_BEGIN;
+       acpi_os_printf(ACPI_MSG_ERROR);
+
+       if (lookup_status == AE_BAD_CHARACTER) {
+
+               /* There is a non-ascii character in the name */
+
+               ACPI_MOVE_32_TO_32(&bad_name,
+                                  ACPI_CAST_PTR(u32, internal_name));
+               acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
+       } else {
+               /* Convert path to external format */
+
+               status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
+                                                 internal_name, NULL, &name);
+
+               /* Print target name */
+
+               if (ACPI_SUCCESS(status)) {
+                       acpi_os_printf("[%s]", name);
+               } else {
+                       acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
+               }
+
+               if (name) {
+                       ACPI_FREE(name);
+               }
+       }
+
+       acpi_os_printf(" Namespace lookup failure, %s",
+                      acpi_format_exception(lookup_status));
+
+       ACPI_MSG_SUFFIX;
+       ACPI_MSG_REDIRECT_END;
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_method_error
+ *
+ * PARAMETERS:  module_name         - Caller's module name (for error output)
+ *              line_number         - Caller's line number (for error output)
+ *              Message             - Error message to use on failure
+ *              prefix_node         - Prefix relative to the path
+ *              Path                - Path to the node (optional)
+ *              method_status       - Execution status
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Print error message with the full pathname for the method.
+ *
+ ******************************************************************************/
+
+void
+acpi_ut_method_error(const char *module_name,
+                    u32 line_number,
+                    const char *message,
+                    struct acpi_namespace_node *prefix_node,
+                    const char *path, acpi_status method_status)
+{
+       acpi_status status;
+       struct acpi_namespace_node *node = prefix_node;
+
+       ACPI_MSG_REDIRECT_BEGIN;
+       acpi_os_printf(ACPI_MSG_ERROR);
+
+       if (path) {
+               status =
+                   acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
+                                    &node);
+               if (ACPI_FAILURE(status)) {
+                       acpi_os_printf("[Could not get node by pathname]");
+               }
+       }
+
+       acpi_ns_print_node_pathname(node, message);
+       acpi_os_printf(", %s", acpi_format_exception(method_status));
+
+       ACPI_MSG_SUFFIX;
+       ACPI_MSG_REDIRECT_END;
+}
+
+#endif                         /* ACPI_NO_ERROR_MESSAGES */
index 9841720..95649d3 100644 (file)
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
-
-#ifdef CONFIG_ACPI_SYSFS_POWER
 #include <linux/power_supply.h>
-#endif
 
 #define PREFIX "ACPI: "
 
@@ -98,13 +95,12 @@ enum {
         * due to bad math.
         */
        ACPI_BATTERY_QUIRK_SIGNED16_CURRENT,
+       ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY,
 };
 
 struct acpi_battery {
        struct mutex lock;
-#ifdef CONFIG_ACPI_SYSFS_POWER
        struct power_supply bat;
-#endif
        struct acpi_device *device;
        unsigned long update_time;
        int rate_now;
@@ -141,7 +137,6 @@ inline int acpi_battery_present(struct acpi_battery *battery)
        return battery->device->status.battery_present;
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static int acpi_battery_technology(struct acpi_battery *battery)
 {
        if (!strcasecmp("NiCd", battery->type))
@@ -186,6 +181,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
                                     enum power_supply_property psp,
                                     union power_supply_propval *val)
 {
+       int ret = 0;
        struct acpi_battery *battery = to_acpi_battery(psy);
 
        if (acpi_battery_present(battery)) {
@@ -214,26 +210,44 @@ static int acpi_battery_get_property(struct power_supply *psy,
                val->intval = battery->cycle_count;
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
-               val->intval = battery->design_voltage * 1000;
+               if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
+                       ret = -ENODEV;
+               else
+                       val->intval = battery->design_voltage * 1000;
                break;
        case POWER_SUPPLY_PROP_VOLTAGE_NOW:
-               val->intval = battery->voltage_now * 1000;
+               if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN)
+                       ret = -ENODEV;
+               else
+                       val->intval = battery->voltage_now * 1000;
                break;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
        case POWER_SUPPLY_PROP_POWER_NOW:
-               val->intval = battery->rate_now * 1000;
+               if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN)
+                       ret = -ENODEV;
+               else
+                       val->intval = battery->rate_now * 1000;
                break;
        case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
        case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
-               val->intval = battery->design_capacity * 1000;
+               if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+                       ret = -ENODEV;
+               else
+                       val->intval = battery->design_capacity * 1000;
                break;
        case POWER_SUPPLY_PROP_CHARGE_FULL:
        case POWER_SUPPLY_PROP_ENERGY_FULL:
-               val->intval = battery->full_charge_capacity * 1000;
+               if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
+                       ret = -ENODEV;
+               else
+                       val->intval = battery->full_charge_capacity * 1000;
                break;
        case POWER_SUPPLY_PROP_CHARGE_NOW:
        case POWER_SUPPLY_PROP_ENERGY_NOW:
-               val->intval = battery->capacity_now * 1000;
+               if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN)
+                       ret = -ENODEV;
+               else
+                       val->intval = battery->capacity_now * 1000;
                break;
        case POWER_SUPPLY_PROP_MODEL_NAME:
                val->strval = battery->model_number;
@@ -245,9 +259,9 @@ static int acpi_battery_get_property(struct power_supply *psy,
                val->strval = battery->serial_number;
                break;
        default:
-               return -EINVAL;
+               ret = -EINVAL;
        }
-       return 0;
+       return ret;
 }
 
 static enum power_supply_property charge_battery_props[] = {
@@ -281,7 +295,6 @@ static enum power_supply_property energy_battery_props[] = {
        POWER_SUPPLY_PROP_MANUFACTURER,
        POWER_SUPPLY_PROP_SERIAL_NUMBER,
 };
-#endif
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 inline char *acpi_battery_units(struct acpi_battery *battery)
@@ -412,6 +425,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
                result = extract_package(battery, buffer.pointer,
                                info_offsets, ARRAY_SIZE(info_offsets));
        kfree(buffer.pointer);
+       if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
+               battery->full_charge_capacity = battery->design_capacity;
        return result;
 }
 
@@ -448,6 +463,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
            battery->rate_now != -1)
                battery->rate_now = abs((s16)battery->rate_now);
 
+       if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)
+           && battery->capacity_now >= 0 && battery->capacity_now <= 100)
+               battery->capacity_now = (battery->capacity_now *
+                               battery->full_charge_capacity) / 100;
        return result;
 }
 
@@ -492,7 +511,6 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery)
        return acpi_battery_set_alarm(battery);
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static ssize_t acpi_battery_alarm_show(struct device *dev,
                                        struct device_attribute *attr,
                                        char *buf)
@@ -552,7 +570,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery)
        power_supply_unregister(&battery->bat);
        battery->bat.dev = NULL;
 }
-#endif
 
 static void acpi_battery_quirks(struct acpi_battery *battery)
 {
@@ -561,6 +578,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery)
        }
 }
 
+/*
+ * According to the ACPI spec, some kinds of primary batteries can
+ * report percentage battery remaining capacity directly to OS.
+ * In this case, it reports the Last Full Charged Capacity == 100
+ * and BatteryPresentRate == 0xFFFFFFFF.
+ *
+ * Now we found some battery reports percentage remaining capacity
+ * even if it's rechargeable.
+ * https://bugzilla.kernel.org/show_bug.cgi?id=15979
+ *
+ * Handle this correctly so that they won't break userspace.
+ */
+static void acpi_battery_quirks2(struct acpi_battery *battery)
+{
+       if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags))
+               return ;
+
+        if (battery->full_charge_capacity == 100 &&
+            battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN &&
+            battery->capacity_now >=0 && battery->capacity_now <= 100) {
+               set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags);
+               battery->full_charge_capacity = battery->design_capacity;
+               battery->capacity_now = (battery->capacity_now *
+                               battery->full_charge_capacity) / 100;
+       }
+}
+
 static int acpi_battery_update(struct acpi_battery *battery)
 {
        int result, old_present = acpi_battery_present(battery);
@@ -568,9 +612,7 @@ static int acpi_battery_update(struct acpi_battery *battery)
        if (result)
                return result;
        if (!acpi_battery_present(battery)) {
-#ifdef CONFIG_ACPI_SYSFS_POWER
                sysfs_remove_battery(battery);
-#endif
                battery->update_time = 0;
                return 0;
        }
@@ -582,11 +624,11 @@ static int acpi_battery_update(struct acpi_battery *battery)
                acpi_battery_quirks(battery);
                acpi_battery_init_alarm(battery);
        }
-#ifdef CONFIG_ACPI_SYSFS_POWER
        if (!battery->bat.dev)
                sysfs_add_battery(battery);
-#endif
-       return acpi_battery_get_state(battery);
+       result = acpi_battery_get_state(battery);
+       acpi_battery_quirks2(battery);
+       return result;
 }
 
 /* --------------------------------------------------------------------------
@@ -867,26 +909,20 @@ static void acpi_battery_remove_fs(struct acpi_device *device)
 static void acpi_battery_notify(struct acpi_device *device, u32 event)
 {
        struct acpi_battery *battery = acpi_driver_data(device);
-#ifdef CONFIG_ACPI_SYSFS_POWER
        struct device *old;
-#endif
 
        if (!battery)
                return;
-#ifdef CONFIG_ACPI_SYSFS_POWER
        old = battery->bat.dev;
-#endif
        acpi_battery_update(battery);
        acpi_bus_generate_proc_event(device, event,
                                     acpi_battery_present(battery));
        acpi_bus_generate_netlink_event(device->pnp.device_class,
                                        dev_name(&device->dev), event,
                                        acpi_battery_present(battery));
-#ifdef CONFIG_ACPI_SYSFS_POWER
        /* acpi_battery_update could remove power_supply object */
        if (old && battery->bat.dev)
                power_supply_changed(&battery->bat);
-#endif
 }
 
 static int acpi_battery_add(struct acpi_device *device)
@@ -934,9 +970,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 #ifdef CONFIG_ACPI_PROCFS_POWER
        acpi_battery_remove_fs(device);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
        sysfs_remove_battery(battery);
-#endif
        mutex_destroy(&battery->lock);
        kfree(battery);
        return 0;
index 310e3b9..d68bd61 100644 (file)
@@ -935,6 +935,12 @@ static int __init acpi_bus_init(void)
                goto error1;
        }
 
+       /*
+        * _PDC control method may load dynamic SSDT tables,
+        * and we need to install the table handler before that.
+        */
+       acpi_sysfs_init();
+
        acpi_early_processor_set_pdc();
 
        /*
@@ -1026,7 +1032,6 @@ static int __init acpi_init(void)
        acpi_scan_init();
        acpi_ec_init();
        acpi_power_init();
-       acpi_sysfs_init();
        acpi_debugfs_init();
        acpi_sleep_proc_init();
        acpi_wakeup_device_init();
index 1575a9b..71ef9cd 100644 (file)
@@ -338,7 +338,8 @@ static int acpi_button_add(struct acpi_device *device)
 {
        struct acpi_button *button;
        struct input_dev *input;
-       char *hid, *name, *class;
+       const char *hid = acpi_device_hid(device);
+       char *name, *class;
        int error;
 
        button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL);
@@ -353,7 +354,6 @@ static int acpi_button_add(struct acpi_device *device)
                goto err_free_button;
        }
 
-       hid = acpi_device_hid(device);
        name = acpi_device_name(device);
        class = acpi_device_class(device);
 
index 3fe29e9..81514a4 100644 (file)
@@ -725,6 +725,7 @@ static void dock_notify(acpi_handle handle, u32 event, void *data)
                        complete_dock(ds);
                        dock_event(ds, event, DOCK_EVENT);
                        dock_lock(ds, 1);
+                       acpi_update_gpes();
                        break;
                }
                if (dock_present(ds) || dock_in_progress(ds))
@@ -929,7 +930,7 @@ static struct attribute_group dock_attribute_group = {
  * allocated and initialize a new dock station device.  Find all devices
  * that are on the dock station, and register for dock event notifications.
  */
-static int dock_add(acpi_handle handle)
+static int __init dock_add(acpi_handle handle)
 {
        int ret, id;
        struct dock_station ds, *dock_station;
@@ -1023,7 +1024,7 @@ static int dock_remove(struct dock_station *ds)
  *
  * This is called by acpi_walk_namespace to look for dock stations.
  */
-static acpi_status
+static __init acpi_status
 find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
        if (is_dock(handle))
@@ -1032,7 +1033,7 @@ find_dock(acpi_handle handle, u32 lvl, void *context, void **rv)
        return AE_OK;
 }
 
-static acpi_status
+static __init acpi_status
 find_bay(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
        /* If bay is a dock, it's already handled */
index f31291b..372ff80 100644 (file)
@@ -83,6 +83,11 @@ enum {
        EC_FLAGS_BLOCKED,               /* Transactions are blocked */
 };
 
+/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
+static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
+module_param(ec_delay, uint, 0644);
+MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes");
+
 /* If we find an EC via the ECDT, we need to keep a ptr to its context */
 /* External interfaces use first EC only, so remember */
 typedef int (*acpi_ec_query_func) (void *data);
@@ -210,7 +215,7 @@ static int ec_poll(struct acpi_ec *ec)
        int repeat = 2; /* number of command restarts */
        while (repeat--) {
                unsigned long delay = jiffies +
-                       msecs_to_jiffies(ACPI_EC_DELAY);
+                       msecs_to_jiffies(ec_delay);
                do {
                        /* don't sleep with disabled interrupts */
                        if (EC_FLAGS_MSI || irqs_disabled()) {
@@ -265,7 +270,7 @@ static int ec_check_ibf0(struct acpi_ec *ec)
 
 static int ec_wait_ibf0(struct acpi_ec *ec)
 {
-       unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
+       unsigned long delay = jiffies + msecs_to_jiffies(ec_delay);
        /* interrupt wait manually if GPE mode is not active */
        while (time_before(jiffies, delay))
                if (wait_event_timeout(ec->wait, ec_check_ibf0(ec),
index d94d295..6004908 100644 (file)
@@ -27,8 +27,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <asm/uaccess.h>
 #include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
@@ -119,122 +117,6 @@ static struct thermal_cooling_device_ops fan_cooling_ops = {
 };
 
 /* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
-
-static struct proc_dir_entry *acpi_fan_dir;
-
-static int acpi_fan_read_state(struct seq_file *seq, void *offset)
-{
-       struct acpi_device *device = seq->private;
-       int state = 0;
-
-
-       if (device) {
-               if (acpi_bus_get_power(device->handle, &state))
-                       seq_printf(seq, "status:                  ERROR\n");
-               else
-                       seq_printf(seq, "status:                  %s\n",
-                                  !state ? "on" : "off");
-       }
-       return 0;
-}
-
-static int acpi_fan_state_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_fan_read_state, PDE(inode)->data);
-}
-
-static ssize_t
-acpi_fan_write_state(struct file *file, const char __user * buffer,
-                    size_t count, loff_t * ppos)
-{
-       int result = 0;
-       struct seq_file *m = file->private_data;
-       struct acpi_device *device = m->private;
-       char state_string[3] = { '\0' };
-
-       if (count > sizeof(state_string) - 1)
-               return -EINVAL;
-
-       if (copy_from_user(state_string, buffer, count))
-               return -EFAULT;
-
-       state_string[count] = '\0';
-       if ((state_string[0] < '0') || (state_string[0] > '3'))
-               return -EINVAL;
-       if (state_string[1] == '\n')
-               state_string[1] = '\0';
-       if (state_string[1] != '\0')
-               return -EINVAL;
-
-       result = acpi_bus_set_power(device->handle,
-                                   simple_strtoul(state_string, NULL, 0));
-       if (result)
-               return result;
-
-       return count;
-}
-
-static const struct file_operations acpi_fan_state_ops = {
-       .open = acpi_fan_state_open_fs,
-       .read = seq_read,
-       .write = acpi_fan_write_state,
-       .llseek = seq_lseek,
-       .release = single_release,
-       .owner = THIS_MODULE,
-};
-
-static int acpi_fan_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry = NULL;
-
-
-       if (!device)
-               return -EINVAL;
-
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_fan_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-       }
-
-       /* 'status' [R/W] */
-       entry = proc_create_data(ACPI_FAN_FILE_STATE,
-                                S_IFREG | S_IRUGO | S_IWUSR,
-                                acpi_device_dir(device),
-                                &acpi_fan_state_ops,
-                                device);
-       if (!entry)
-               return -ENODEV;
-       return 0;
-}
-
-static int acpi_fan_remove_fs(struct acpi_device *device)
-{
-
-       if (acpi_device_dir(device)) {
-               remove_proc_entry(ACPI_FAN_FILE_STATE, acpi_device_dir(device));
-               remove_proc_entry(acpi_device_bid(device), acpi_fan_dir);
-               acpi_device_dir(device) = NULL;
-       }
-
-       return 0;
-}
-#else
-static int acpi_fan_add_fs(struct acpi_device *device)
-{
-       return 0;
-}
-
-static int acpi_fan_remove_fs(struct acpi_device *device)
-{
-       return 0;
-}
-#endif
-/* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
@@ -284,10 +166,6 @@ static int acpi_fan_add(struct acpi_device *device)
                dev_err(&device->dev, "Failed to create sysfs link "
                        "'device'\n");
 
-       result = acpi_fan_add_fs(device);
-       if (result)
-               goto end;
-
        printk(KERN_INFO PREFIX "%s [%s] (%s)\n",
               acpi_device_name(device), acpi_device_bid(device),
               !device->power.state ? "on" : "off");
@@ -303,7 +181,6 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
        if (!device || !cdev)
                return -EINVAL;
 
-       acpi_fan_remove_fs(device);
        sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
        sysfs_remove_link(&cdev->device.kobj, "device");
        thermal_cooling_device_unregister(cdev);
@@ -347,19 +224,9 @@ static int __init acpi_fan_init(void)
 {
        int result = 0;
 
-#ifdef CONFIG_ACPI_PROCFS
-       acpi_fan_dir = proc_mkdir(ACPI_FAN_CLASS, acpi_root_dir);
-       if (!acpi_fan_dir)
-               return -ENODEV;
-#endif
-
        result = acpi_bus_register_driver(&acpi_fan_driver);
-       if (result < 0) {
-#ifdef CONFIG_ACPI_PROCFS
-               remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
-#endif
+       if (result < 0)
                return -ENODEV;
-       }
 
        return 0;
 }
@@ -369,10 +236,6 @@ static void __exit acpi_fan_exit(void)
 
        acpi_bus_unregister_driver(&acpi_fan_driver);
 
-#ifdef CONFIG_ACPI_PROCFS
-       remove_proc_entry(ACPI_FAN_CLASS, acpi_root_dir);
-#endif
-
        return;
 }
 
index 65b25a3..966fedd 100644 (file)
@@ -95,8 +95,25 @@ struct acpi_res_list {
 static LIST_HEAD(resource_list_head);
 static DEFINE_SPINLOCK(acpi_res_lock);
 
+/*
+ * This list of permanent mappings is for memory that may be accessed from
+ * interrupt context, where we can't do the ioremap().
+ */
+struct acpi_ioremap {
+       struct list_head list;
+       void __iomem *virt;
+       acpi_physical_address phys;
+       acpi_size size;
+       struct kref ref;
+};
+
+static LIST_HEAD(acpi_ioremaps);
+static DEFINE_SPINLOCK(acpi_ioremap_lock);
+
 #define        OSI_STRING_LENGTH_MAX 64        /* arbitrary */
-static char osi_additional_string[OSI_STRING_LENGTH_MAX];
+static char osi_setup_string[OSI_STRING_LENGTH_MAX];
+
+static void __init acpi_osi_setup_late(void);
 
 /*
  * The story of _OSI(Linux)
@@ -138,6 +155,20 @@ static struct osi_linux {
        unsigned int    known:1;
 } osi_linux = { 0, 0, 0, 0};
 
+static u32 acpi_osi_handler(acpi_string interface, u32 supported)
+{
+       if (!strcmp("Linux", interface)) {
+
+               printk(KERN_NOTICE FW_BUG PREFIX
+                       "BIOS _OSI(Linux) query %s%s\n",
+                       osi_linux.enable ? "honored" : "ignored",
+                       osi_linux.cmdline ? " via cmdline" :
+                       osi_linux.dmi ? " via DMI" : "");
+       }
+
+       return supported;
+}
+
 static void __init acpi_request_region (struct acpi_generic_address *addr,
        unsigned int length, char *desc)
 {
@@ -185,36 +216,6 @@ static int __init acpi_reserve_resources(void)
 }
 device_initcall(acpi_reserve_resources);
 
-acpi_status __init acpi_os_initialize(void)
-{
-       return AE_OK;
-}
-
-acpi_status acpi_os_initialize1(void)
-{
-       kacpid_wq = create_workqueue("kacpid");
-       kacpi_notify_wq = create_workqueue("kacpi_notify");
-       kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
-       BUG_ON(!kacpid_wq);
-       BUG_ON(!kacpi_notify_wq);
-       BUG_ON(!kacpi_hotplug_wq);
-       return AE_OK;
-}
-
-acpi_status acpi_os_terminate(void)
-{
-       if (acpi_irq_handler) {
-               acpi_os_remove_interrupt_handler(acpi_irq_irq,
-                                                acpi_irq_handler);
-       }
-
-       destroy_workqueue(kacpid_wq);
-       destroy_workqueue(kacpi_notify_wq);
-       destroy_workqueue(kacpi_hotplug_wq);
-
-       return AE_OK;
-}
-
 void acpi_os_printf(const char *fmt, ...)
 {
        va_list args;
@@ -260,29 +261,135 @@ acpi_physical_address __init acpi_os_get_root_pointer(void)
        }
 }
 
+/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+static struct acpi_ioremap *
+acpi_map_lookup(acpi_physical_address phys, acpi_size size)
+{
+       struct acpi_ioremap *map;
+
+       list_for_each_entry_rcu(map, &acpi_ioremaps, list)
+               if (map->phys <= phys &&
+                   phys + size <= map->phys + map->size)
+                       return map;
+
+       return NULL;
+}
+
+/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+static void __iomem *
+acpi_map_vaddr_lookup(acpi_physical_address phys, unsigned int size)
+{
+       struct acpi_ioremap *map;
+
+       map = acpi_map_lookup(phys, size);
+       if (map)
+               return map->virt + (phys - map->phys);
+
+       return NULL;
+}
+
+/* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
+static struct acpi_ioremap *
+acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
+{
+       struct acpi_ioremap *map;
+
+       list_for_each_entry_rcu(map, &acpi_ioremaps, list)
+               if (map->virt <= virt &&
+                   virt + size <= map->virt + map->size)
+                       return map;
+
+       return NULL;
+}
+
 void __iomem *__init_refok
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
+       struct acpi_ioremap *map, *tmp_map;
+       unsigned long flags, pg_sz;
+       void __iomem *virt;
+       phys_addr_t pg_off;
+
        if (phys > ULONG_MAX) {
                printk(KERN_ERR PREFIX "Cannot map memory that high\n");
                return NULL;
        }
-       if (acpi_gbl_permanent_mmap)
-               /*
-               * ioremap checks to ensure this is in reserved space
-               */
-               return ioremap((unsigned long)phys, size);
-       else
+
+       if (!acpi_gbl_permanent_mmap)
                return __acpi_map_table((unsigned long)phys, size);
+
+       map = kzalloc(sizeof(*map), GFP_KERNEL);
+       if (!map)
+               return NULL;
+
+       pg_off = round_down(phys, PAGE_SIZE);
+       pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
+       virt = ioremap(pg_off, pg_sz);
+       if (!virt) {
+               kfree(map);
+               return NULL;
+       }
+
+       INIT_LIST_HEAD(&map->list);
+       map->virt = virt;
+       map->phys = pg_off;
+       map->size = pg_sz;
+       kref_init(&map->ref);
+
+       spin_lock_irqsave(&acpi_ioremap_lock, flags);
+       /* Check if page has already been mapped. */
+       tmp_map = acpi_map_lookup(phys, size);
+       if (tmp_map) {
+               kref_get(&tmp_map->ref);
+               spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+               iounmap(map->virt);
+               kfree(map);
+               return tmp_map->virt + (phys - tmp_map->phys);
+       }
+       list_add_tail_rcu(&map->list, &acpi_ioremaps);
+       spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+
+       return map->virt + (phys - map->phys);
 }
 EXPORT_SYMBOL_GPL(acpi_os_map_memory);
 
+static void acpi_kref_del_iomap(struct kref *ref)
+{
+       struct acpi_ioremap *map;
+
+       map = container_of(ref, struct acpi_ioremap, ref);
+       list_del_rcu(&map->list);
+}
+
 void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
-       if (acpi_gbl_permanent_mmap)
-               iounmap(virt);
-       else
+       struct acpi_ioremap *map;
+       unsigned long flags;
+       int del;
+
+       if (!acpi_gbl_permanent_mmap) {
                __acpi_unmap_table(virt, size);
+               return;
+       }
+
+       spin_lock_irqsave(&acpi_ioremap_lock, flags);
+       map = acpi_map_lookup_virt(virt, size);
+       if (!map) {
+               spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+               printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt);
+               dump_stack();
+               return;
+       }
+
+       del = kref_put(&map->ref, acpi_kref_del_iomap);
+       spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+
+       if (!del)
+               return;
+
+       synchronize_rcu();
+       iounmap(map->virt);
+       kfree(map);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
@@ -292,6 +399,44 @@ void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
                __acpi_unmap_table(virt, size);
 }
 
+int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+{
+       void __iomem *virt;
+
+       if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+               return 0;
+
+       if (!addr->address || !addr->bit_width)
+               return -EINVAL;
+
+       virt = acpi_os_map_memory(addr->address, addr->bit_width / 8);
+       if (!virt)
+               return -EIO;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_os_map_generic_address);
+
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+{
+       void __iomem *virt;
+       unsigned long flags;
+       acpi_size size = addr->bit_width / 8;
+
+       if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
+               return;
+
+       if (!addr->address || !addr->bit_width)
+               return;
+
+       spin_lock_irqsave(&acpi_ioremap_lock, flags);
+       virt = acpi_map_vaddr_lookup(addr->address, size);
+       spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+
+       acpi_os_unmap_memory(virt, size);
+}
+EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address);
+
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
 acpi_os_get_physical_address(void *virt, acpi_physical_address * phys)
@@ -495,8 +640,15 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
 {
        u32 dummy;
        void __iomem *virt_addr;
-
-       virt_addr = ioremap(phys_addr, width);
+       int size = width / 8, unmap = 0;
+
+       rcu_read_lock();
+       virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+       rcu_read_unlock();
+       if (!virt_addr) {
+               virt_addr = ioremap(phys_addr, size);
+               unmap = 1;
+       }
        if (!value)
                value = &dummy;
 
@@ -514,7 +666,8 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width)
                BUG();
        }
 
-       iounmap(virt_addr);
+       if (unmap)
+               iounmap(virt_addr);
 
        return AE_OK;
 }
@@ -523,8 +676,15 @@ acpi_status
 acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
 {
        void __iomem *virt_addr;
-
-       virt_addr = ioremap(phys_addr, width);
+       int size = width / 8, unmap = 0;
+
+       rcu_read_lock();
+       virt_addr = acpi_map_vaddr_lookup(phys_addr, size);
+       rcu_read_unlock();
+       if (!virt_addr) {
+               virt_addr = ioremap(phys_addr, size);
+               unmap = 1;
+       }
 
        switch (width) {
        case 8:
@@ -540,16 +700,18 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width)
                BUG();
        }
 
-       iounmap(virt_addr);
+       if (unmap)
+               iounmap(virt_addr);
 
        return AE_OK;
 }
 
 acpi_status
 acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
-                              u32 *value, u32 width)
+                              u64 *value, u32 width)
 {
        int result, size;
+       u32 value32;
 
        if (!value)
                return AE_BAD_PARAMETER;
@@ -570,7 +732,8 @@ acpi_os_read_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
 
        result = raw_pci_read(pci_id->segment, pci_id->bus,
                                PCI_DEVFN(pci_id->device, pci_id->function),
-                               reg, size, value);
+                               reg, size, &value32);
+       *value = value32;
 
        return (result ? AE_ERROR : AE_OK);
 }
@@ -602,74 +765,6 @@ acpi_os_write_pci_configuration(struct acpi_pci_id * pci_id, u32 reg,
        return (result ? AE_ERROR : AE_OK);
 }
 
-/* TODO: Change code to take advantage of driver model more */
-static void acpi_os_derive_pci_id_2(acpi_handle rhandle,       /* upper bound  */
-                                   acpi_handle chandle,        /* current node */
-                                   struct acpi_pci_id **id,
-                                   int *is_bridge, u8 * bus_number)
-{
-       acpi_handle handle;
-       struct acpi_pci_id *pci_id = *id;
-       acpi_status status;
-       unsigned long long temp;
-       acpi_object_type type;
-
-       acpi_get_parent(chandle, &handle);
-       if (handle != rhandle) {
-               acpi_os_derive_pci_id_2(rhandle, handle, &pci_id, is_bridge,
-                                       bus_number);
-
-               status = acpi_get_type(handle, &type);
-               if ((ACPI_FAILURE(status)) || (type != ACPI_TYPE_DEVICE))
-                       return;
-
-               status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
-                                         &temp);
-               if (ACPI_SUCCESS(status)) {
-                       u32 val;
-                       pci_id->device = ACPI_HIWORD(ACPI_LODWORD(temp));
-                       pci_id->function = ACPI_LOWORD(ACPI_LODWORD(temp));
-
-                       if (*is_bridge)
-                               pci_id->bus = *bus_number;
-
-                       /* any nicer way to get bus number of bridge ? */
-                       status =
-                           acpi_os_read_pci_configuration(pci_id, 0x0e, &val,
-                                                          8);
-                       if (ACPI_SUCCESS(status)
-                           && ((val & 0x7f) == 1 || (val & 0x7f) == 2)) {
-                               status =
-                                   acpi_os_read_pci_configuration(pci_id, 0x18,
-                                                                  &val, 8);
-                               if (!ACPI_SUCCESS(status)) {
-                                       /* Certainly broken...  FIX ME */
-                                       return;
-                               }
-                               *is_bridge = 1;
-                               pci_id->bus = val;
-                               status =
-                                   acpi_os_read_pci_configuration(pci_id, 0x19,
-                                                                  &val, 8);
-                               if (ACPI_SUCCESS(status)) {
-                                       *bus_number = val;
-                               }
-                       } else
-                               *is_bridge = 0;
-               }
-       }
-}
-
-void acpi_os_derive_pci_id(acpi_handle rhandle,        /* upper bound  */
-                          acpi_handle chandle, /* current node */
-                          struct acpi_pci_id **id)
-{
-       int is_bridge = 1;
-       u8 bus_number = (*id)->bus;
-
-       acpi_os_derive_pci_id_2(rhandle, chandle, id, &is_bridge, &bus_number);
-}
-
 static void acpi_os_execute_deferred(struct work_struct *work)
 {
        struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work);
@@ -780,16 +875,6 @@ void acpi_os_wait_events_complete(void *context)
 EXPORT_SYMBOL(acpi_os_wait_events_complete);
 
 /*
- * Allocate the memory for a spinlock and initialize it.
- */
-acpi_status acpi_os_create_lock(acpi_spinlock * handle)
-{
-       spin_lock_init(*handle);
-
-       return AE_OK;
-}
-
-/*
  * Deallocate the memory for a spinlock.
  */
 void acpi_os_delete_lock(acpi_spinlock handle)
@@ -977,6 +1062,12 @@ static void __init set_osi_linux(unsigned int enable)
                printk(KERN_NOTICE PREFIX "%sed _OSI(Linux)\n",
                        enable ? "Add": "Delet");
        }
+
+       if (osi_linux.enable)
+               acpi_osi_setup("Linux");
+       else
+               acpi_osi_setup("!Linux");
+
        return;
 }
 
@@ -1011,21 +1102,33 @@ void __init acpi_dmi_osi_linux(int enable, const struct dmi_system_id *d)
  * string starting with '!' disables that string
  * otherwise string is added to list, augmenting built-in strings
  */
-int __init acpi_osi_setup(char *str)
+static void __init acpi_osi_setup_late(void)
 {
-       if (str == NULL || *str == '\0') {
-               printk(KERN_INFO PREFIX "_OSI method disabled\n");
-               acpi_gbl_create_osi_method = FALSE;
-       } else if (!strcmp("!Linux", str)) {
+       char *str = osi_setup_string;
+
+       if (*str == '\0')
+               return;
+
+       if (!strcmp("!Linux", str)) {
                acpi_cmdline_osi_linux(0);      /* !enable */
        } else if (*str == '!') {
-               if (acpi_osi_invalidate(++str) == AE_OK)
+               if (acpi_remove_interface(++str) == AE_OK)
                        printk(KERN_INFO PREFIX "Deleted _OSI(%s)\n", str);
        } else if (!strcmp("Linux", str)) {
                acpi_cmdline_osi_linux(1);      /* enable */
-       } else if (*osi_additional_string == '\0') {
-               strncpy(osi_additional_string, str, OSI_STRING_LENGTH_MAX);
-               printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+       } else {
+               if (acpi_install_interface(str) == AE_OK)
+                       printk(KERN_INFO PREFIX "Added _OSI(%s)\n", str);
+       }
+}
+
+int __init acpi_osi_setup(char *str)
+{
+       if (str == NULL || *str == '\0') {
+               printk(KERN_INFO PREFIX "_OSI method disabled\n");
+               acpi_gbl_create_osi_method = FALSE;
+       } else {
+               strncpy(osi_setup_string, str, OSI_STRING_LENGTH_MAX);
        }
 
        return 1;
@@ -1152,21 +1255,6 @@ int acpi_check_region(resource_size_t start, resource_size_t n,
 }
 EXPORT_SYMBOL(acpi_check_region);
 
-int acpi_check_mem_region(resource_size_t start, resource_size_t n,
-                     const char *name)
-{
-       struct resource res = {
-               .start = start,
-               .end   = start + n - 1,
-               .name  = name,
-               .flags = IORESOURCE_MEM,
-       };
-
-       return acpi_check_resource_conflict(&res);
-
-}
-EXPORT_SYMBOL(acpi_check_mem_region);
-
 /*
  * Let drivers know whether the resource checks are effective
  */
@@ -1282,38 +1370,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
        return (AE_OK);
 }
 
-/******************************************************************************
- *
- * FUNCTION:    acpi_os_validate_interface
- *
- * PARAMETERS:  interface           - Requested interface to be validated
- *
- * RETURN:      AE_OK if interface is supported, AE_SUPPORT otherwise
- *
- * DESCRIPTION: Match an interface string to the interfaces supported by the
- *              host. Strings originate from an AML call to the _OSI method.
- *
- *****************************************************************************/
-
-acpi_status
-acpi_os_validate_interface (char *interface)
-{
-       if (!strncmp(osi_additional_string, interface, OSI_STRING_LENGTH_MAX))
-               return AE_OK;
-       if (!strcmp("Linux", interface)) {
-
-               printk(KERN_NOTICE PREFIX
-                       "BIOS _OSI(Linux) query %s%s\n",
-                       osi_linux.enable ? "honored" : "ignored",
-                       osi_linux.cmdline ? " via cmdline" :
-                       osi_linux.dmi ? " via DMI" : "");
-
-               if (osi_linux.enable)
-                       return AE_OK;
-       }
-       return AE_SUPPORT;
-}
-
 static inline int acpi_res_list_add(struct acpi_res_list *res)
 {
        struct acpi_res_list *res_list_elem;
@@ -1462,5 +1518,46 @@ acpi_os_validate_address (
        }
        return AE_OK;
 }
-
 #endif
+
+acpi_status __init acpi_os_initialize(void)
+{
+       acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
+       acpi_os_map_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
+       acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe0_block);
+       acpi_os_map_generic_address(&acpi_gbl_FADT.xgpe1_block);
+
+       return AE_OK;
+}
+
+acpi_status acpi_os_initialize1(void)
+{
+       kacpid_wq = create_workqueue("kacpid");
+       kacpi_notify_wq = create_workqueue("kacpi_notify");
+       kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
+       BUG_ON(!kacpid_wq);
+       BUG_ON(!kacpi_notify_wq);
+       BUG_ON(!kacpi_hotplug_wq);
+       acpi_install_interface_handler(acpi_osi_handler);
+       acpi_osi_setup_late();
+       return AE_OK;
+}
+
+acpi_status acpi_os_terminate(void)
+{
+       if (acpi_irq_handler) {
+               acpi_os_remove_interrupt_handler(acpi_irq_irq,
+                                                acpi_irq_handler);
+       }
+
+       acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe1_block);
+       acpi_os_unmap_generic_address(&acpi_gbl_FADT.xgpe0_block);
+       acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1b_event_block);
+       acpi_os_unmap_generic_address(&acpi_gbl_FADT.xpm1a_event_block);
+
+       destroy_workqueue(kacpid_wq);
+       destroy_workqueue(kacpi_notify_wq);
+       destroy_workqueue(kacpi_hotplug_wq);
+
+       return AE_OK;
+}
index e4804fb..f907cfb 100644 (file)
@@ -32,7 +32,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
index 8d47a58..9ff80a7 100644 (file)
@@ -34,7 +34,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pci.h>
index 3ba8d1f..96668ad 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/types.h>
-#include <linux/proc_fs.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
 #include <linux/pm_runtime.h>
index 844c155..67dedee 100644 (file)
@@ -80,18 +80,13 @@ static struct acpi_driver acpi_power_driver = {
                },
 };
 
-struct acpi_power_reference {
-       struct list_head node;
-       struct acpi_device *device;
-};
-
 struct acpi_power_resource {
        struct acpi_device * device;
        acpi_bus_id name;
        u32 system_level;
        u32 order;
+       unsigned int ref_count;
        struct mutex resource_lock;
-       struct list_head reference;
 };
 
 static struct list_head acpi_power_resource_list;
@@ -184,101 +179,89 @@ static int acpi_power_get_list_state(struct acpi_handle_list *list, int *state)
        return result;
 }
 
-static int acpi_power_on(acpi_handle handle, struct acpi_device *dev)
+static int __acpi_power_on(struct acpi_power_resource *resource)
 {
-       int result = 0;
-       int found = 0;
        acpi_status status = AE_OK;
-       struct acpi_power_resource *resource = NULL;
-       struct list_head *node, *next;
-       struct acpi_power_reference *ref;
 
+       status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
+       if (ACPI_FAILURE(status))
+               return -ENODEV;
+
+       /* Update the power resource's _device_ power state */
+       resource->device->power.state = ACPI_STATE_D0;
+
+       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
+                         resource->name));
+
+       return 0;
+}
+
+static int acpi_power_on(acpi_handle handle)
+{
+       int result = 0;
+       struct acpi_power_resource *resource = NULL;
 
        result = acpi_power_get_context(handle, &resource);
        if (result)
                return result;
 
        mutex_lock(&resource->resource_lock);
-       list_for_each_safe(node, next, &resource->reference) {
-               ref = container_of(node, struct acpi_power_reference, node);
-               if (dev->handle == ref->device->handle) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] already referenced by resource [%s]\n",
-                                 dev->pnp.bus_id, resource->name));
-                       found = 1;
-                       break;
-               }
-       }
 
-       if (!found) {
-               ref = kmalloc(sizeof (struct acpi_power_reference),
-                   irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
-               if (!ref) {
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "kmalloc() failed\n"));
-                       mutex_unlock(&resource->resource_lock);
-                       return -ENOMEM;
-               }
-               list_add_tail(&ref->node, &resource->reference);
-               ref->device = dev;
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] added to resource [%s] references\n",
-                         dev->pnp.bus_id, resource->name));
+       if (resource->ref_count++) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Power resource [%s] already on",
+                                 resource->name));
+       } else {
+               result = __acpi_power_on(resource);
        }
-       mutex_unlock(&resource->resource_lock);
 
-       status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-
-       /* Update the power resource's _device_ power state */
-       resource->device->power.state = ACPI_STATE_D0;
+       mutex_unlock(&resource->resource_lock);
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned on\n",
-                         resource->name));
        return 0;
 }
 
-static int acpi_power_off_device(acpi_handle handle, struct acpi_device *dev)
+static int acpi_power_off_device(acpi_handle handle)
 {
        int result = 0;
        acpi_status status = AE_OK;
        struct acpi_power_resource *resource = NULL;
-       struct list_head *node, *next;
-       struct acpi_power_reference *ref;
 
        result = acpi_power_get_context(handle, &resource);
        if (result)
                return result;
 
        mutex_lock(&resource->resource_lock);
-       list_for_each_safe(node, next, &resource->reference) {
-               ref = container_of(node, struct acpi_power_reference, node);
-               if (dev->handle == ref->device->handle) {
-                       list_del(&ref->node);
-                       kfree(ref);
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device [%s] removed from resource [%s] references\n",
-                           dev->pnp.bus_id, resource->name));
-                       break;
-               }
+
+       if (!resource->ref_count) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Power resource [%s] already off",
+                                 resource->name));
+               goto unlock;
        }
 
-       if (!list_empty(&resource->reference)) {
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Cannot turn resource [%s] off - resource is in use\n",
-                   resource->name));
-               mutex_unlock(&resource->resource_lock);
-               return 0;
+       if (--resource->ref_count) {
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Power resource [%s] still in use\n",
+                                 resource->name));
+               goto unlock;
        }
-       mutex_unlock(&resource->resource_lock);
 
        status = acpi_evaluate_object(resource->device->handle, "_OFF", NULL, NULL);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
+       if (ACPI_FAILURE(status)) {
+               result = -ENODEV;
+       } else {
+               /* Update the power resource's _device_ power state */
+               resource->device->power.state = ACPI_STATE_D3;
 
-       /* Update the power resource's _device_ power state */
-       resource->device->power.state = ACPI_STATE_D3;
+               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+                                 "Power resource [%s] turned off\n",
+                                 resource->name));
+       }
 
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Resource [%s] turned off\n",
-                         resource->name));
+ unlock:
+       mutex_unlock(&resource->resource_lock);
 
-       return 0;
+       return result;
 }
 
 /**
@@ -364,7 +347,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
 
        /* Open power resource */
        for (i = 0; i < dev->wakeup.resources.count; i++) {
-               int ret = acpi_power_on(dev->wakeup.resources.handles[i], dev);
+               int ret = acpi_power_on(dev->wakeup.resources.handles[i]);
                if (ret) {
                        printk(KERN_ERR PREFIX "Transition power state\n");
                        dev->wakeup.flags.valid = 0;
@@ -420,7 +403,7 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
        /* Close power resource */
        for (i = 0; i < dev->wakeup.resources.count; i++) {
                int ret = acpi_power_off_device(
-                               dev->wakeup.resources.handles[i], dev);
+                               dev->wakeup.resources.handles[i]);
                if (ret) {
                        printk(KERN_ERR PREFIX "Transition power state\n");
                        dev->wakeup.flags.valid = 0;
@@ -500,7 +483,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
         * (e.g. so the device doesn't lose power while transitioning).
         */
        for (i = 0; i < tl->count; i++) {
-               result = acpi_power_on(tl->handles[i], device);
+               result = acpi_power_on(tl->handles[i]);
                if (result)
                        goto end;
        }
@@ -513,7 +496,7 @@ int acpi_power_transition(struct acpi_device *device, int state)
         * Then we dereference all power resources used in the current list.
         */
        for (i = 0; i < cl->count; i++) {
-               result = acpi_power_off_device(cl->handles[i], device);
+               result = acpi_power_off_device(cl->handles[i]);
                if (result)
                        goto end;
        }
@@ -551,7 +534,6 @@ static int acpi_power_add(struct acpi_device *device)
 
        resource->device = device;
        mutex_init(&resource->resource_lock);
-       INIT_LIST_HEAD(&resource->reference);
        strcpy(resource->name, device->pnp.bus_id);
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
@@ -594,22 +576,14 @@ static int acpi_power_add(struct acpi_device *device)
 
 static int acpi_power_remove(struct acpi_device *device, int type)
 {
-       struct acpi_power_resource *resource = NULL;
-       struct list_head *node, *next;
+       struct acpi_power_resource *resource;
 
-
-       if (!device || !acpi_driver_data(device))
+       if (!device)
                return -EINVAL;
 
        resource = acpi_driver_data(device);
-
-       mutex_lock(&resource->resource_lock);
-       list_for_each_safe(node, next, &resource->reference) {
-               struct acpi_power_reference *ref = container_of(node, struct acpi_power_reference, node);
-               list_del(&ref->node);
-               kfree(ref);
-       }
-       mutex_unlock(&resource->resource_lock);
+       if (!resource)
+               return -EINVAL;
 
        kfree(resource);
 
@@ -619,29 +593,28 @@ static int acpi_power_remove(struct acpi_device *device, int type)
 static int acpi_power_resume(struct acpi_device *device)
 {
        int result = 0, state;
-       struct acpi_power_resource *resource = NULL;
-       struct acpi_power_reference *ref;
+       struct acpi_power_resource *resource;
 
-       if (!device || !acpi_driver_data(device))
+       if (!device)
                return -EINVAL;
 
        resource = acpi_driver_data(device);
+       if (!resource)
+               return -EINVAL;
+
+       mutex_lock(&resource->resource_lock);
 
        result = acpi_power_get_state(device->handle, &state);
        if (result)
-               return result;
+               goto unlock;
 
-       mutex_lock(&resource->resource_lock);
-       if (state == ACPI_POWER_RESOURCE_STATE_OFF &&
-           !list_empty(&resource->reference)) {
-               ref = container_of(resource->reference.next, struct acpi_power_reference, node);
-               mutex_unlock(&resource->resource_lock);
-               result = acpi_power_on(device->handle, ref->device);
-               return result;
-       }
+       if (state == ACPI_POWER_RESOURCE_STATE_OFF && resource->ref_count)
+               result = __acpi_power_on(resource);
 
+ unlock:
        mutex_unlock(&resource->resource_lock);
-       return 0;
+
+       return result;
 }
 
 int __init acpi_power_init(void)
index 347eb21..85e4804 100644 (file)
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/cpu.h>
+#ifdef CONFIG_ACPI_PROCFS
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#endif
 #include <linux/dmi.h>
 #include <linux/moduleparam.h>
 #include <linux/cpuidle.h>
@@ -244,6 +246,7 @@ static int acpi_processor_errata(struct acpi_processor *pr)
        return result;
 }
 
+#ifdef CONFIG_ACPI_PROCFS
 static struct proc_dir_entry *acpi_processor_dir = NULL;
 
 static int __cpuinit acpi_processor_add_fs(struct acpi_device *device)
@@ -280,7 +283,16 @@ static int acpi_processor_remove_fs(struct acpi_device *device)
 
        return 0;
 }
-
+#else
+static inline int acpi_processor_add_fs(struct acpi_device *device)
+{
+       return 0;
+}
+static inline int acpi_processor_remove_fs(struct acpi_device *device)
+{
+       return 0;
+}
+#endif
 /* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
@@ -842,9 +854,11 @@ static int __init acpi_processor_init(void)
 
        memset(&errata, 0, sizeof(errata));
 
+#ifdef CONFIG_ACPI_PROCFS
        acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir);
        if (!acpi_processor_dir)
                return -ENOMEM;
+#endif
 
        if (!cpuidle_register_driver(&acpi_idle_driver)) {
                printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n",
@@ -871,7 +885,9 @@ static int __init acpi_processor_init(void)
 out_cpuidle:
        cpuidle_unregister_driver(&acpi_idle_driver);
 
+#ifdef CONFIG_ACPI_PROCFS
        remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+#endif
 
        return result;
 }
@@ -891,7 +907,9 @@ static void __exit acpi_processor_exit(void)
 
        cpuidle_unregister_driver(&acpi_idle_driver);
 
+#ifdef CONFIG_ACPI_PROCFS
        remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir);
+#endif
 
        return;
 }
@@ -899,6 +917,4 @@ static void __exit acpi_processor_exit(void)
 module_init(acpi_processor_init);
 module_exit(acpi_processor_exit);
 
-EXPORT_SYMBOL(acpi_processor_set_thermal_limit);
-
 MODULE_ALIAS("processor");
index f4428e8..dcb38f8 100644 (file)
@@ -64,7 +64,6 @@
 #define ACPI_PROCESSOR_CLASS            "processor"
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_idle");
-#define ACPI_PROCESSOR_FILE_POWER      "power"
 #define PM_TIMER_TICK_NS               (1000000000ULL/PM_TIMER_FREQUENCY)
 #define C2_OVERHEAD                    1       /* 1us */
 #define C3_OVERHEAD                    1       /* 1us */
@@ -1013,7 +1012,6 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
                strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
                state->exit_latency = cx->latency;
                state->target_residency = cx->latency * latency_factor;
-               state->power_usage = cx->power;
 
                state->flags = 0;
                switch (cx->type) {
index 953b25f..fde49b9 100644 (file)
 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_thermal");
 
-/* --------------------------------------------------------------------------
-                                 Limit Interface
-   -------------------------------------------------------------------------- */
-static int acpi_processor_apply_limit(struct acpi_processor *pr)
-{
-       int result = 0;
-       u16 px = 0;
-       u16 tx = 0;
-
-
-       if (!pr)
-               return -EINVAL;
-
-       if (!pr->flags.limit)
-               return -ENODEV;
-
-       if (pr->flags.throttling) {
-               if (pr->limit.user.tx > tx)
-                       tx = pr->limit.user.tx;
-               if (pr->limit.thermal.tx > tx)
-                       tx = pr->limit.thermal.tx;
-
-               result = acpi_processor_set_throttling(pr, tx, false);
-               if (result)
-                       goto end;
-       }
-
-       pr->limit.state.px = px;
-       pr->limit.state.tx = tx;
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                         "Processor [%d] limit set to (P%d:T%d)\n", pr->id,
-                         pr->limit.state.px, pr->limit.state.tx));
-
-      end:
-       if (result)
-               printk(KERN_ERR PREFIX "Unable to set limit\n");
-
-       return result;
-}
-
 #ifdef CONFIG_CPU_FREQ
 
 /* If a passive cooling situation is detected, primarily CPUfreq is used, as it
@@ -107,36 +66,6 @@ static int cpu_has_cpufreq(unsigned int cpu)
        return 1;
 }
 
-static int acpi_thermal_cpufreq_increase(unsigned int cpu)
-{
-       if (!cpu_has_cpufreq(cpu))
-               return -ENODEV;
-
-       if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) <
-               CPUFREQ_THERMAL_MAX_STEP) {
-               per_cpu(cpufreq_thermal_reduction_pctg, cpu)++;
-               cpufreq_update_policy(cpu);
-               return 0;
-       }
-
-       return -ERANGE;
-}
-
-static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
-{
-       if (!cpu_has_cpufreq(cpu))
-               return -ENODEV;
-
-       if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) >
-               (CPUFREQ_THERMAL_MIN_STEP + 1))
-               per_cpu(cpufreq_thermal_reduction_pctg, cpu)--;
-       else
-               per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0;
-       cpufreq_update_policy(cpu);
-       /* We reached max freq again and can leave passive mode */
-       return !per_cpu(cpufreq_thermal_reduction_pctg, cpu);
-}
-
 static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb,
                                         unsigned long event, void *data)
 {
@@ -238,113 +167,6 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu)
 
 #endif
 
-int acpi_processor_set_thermal_limit(acpi_handle handle, int type)
-{
-       int result = 0;
-       struct acpi_processor *pr = NULL;
-       struct acpi_device *device = NULL;
-       int tx = 0, max_tx_px = 0;
-
-
-       if ((type < ACPI_PROCESSOR_LIMIT_NONE)
-           || (type > ACPI_PROCESSOR_LIMIT_DECREMENT))
-               return -EINVAL;
-
-       result = acpi_bus_get_device(handle, &device);
-       if (result)
-               return result;
-
-       pr = acpi_driver_data(device);
-       if (!pr)
-               return -ENODEV;
-
-       /* Thermal limits are always relative to the current Px/Tx state. */
-       if (pr->flags.throttling)
-               pr->limit.thermal.tx = pr->throttling.state;
-
-       /*
-        * Our default policy is to only use throttling at the lowest
-        * performance state.
-        */
-
-       tx = pr->limit.thermal.tx;
-
-       switch (type) {
-
-       case ACPI_PROCESSOR_LIMIT_NONE:
-               do {
-                       result = acpi_thermal_cpufreq_decrease(pr->id);
-               } while (!result);
-               tx = 0;
-               break;
-
-       case ACPI_PROCESSOR_LIMIT_INCREMENT:
-               /* if going up: P-states first, T-states later */
-
-               result = acpi_thermal_cpufreq_increase(pr->id);
-               if (!result)
-                       goto end;
-               else if (result == -ERANGE)
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "At maximum performance state\n"));
-
-               if (pr->flags.throttling) {
-                       if (tx == (pr->throttling.state_count - 1))
-                               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                                 "At maximum throttling state\n"));
-                       else
-                               tx++;
-               }
-               break;
-
-       case ACPI_PROCESSOR_LIMIT_DECREMENT:
-               /* if going down: T-states first, P-states later */
-
-               if (pr->flags.throttling) {
-                       if (tx == 0) {
-                               max_tx_px = 1;
-                               ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                                 "At minimum throttling state\n"));
-                       } else {
-                               tx--;
-                               goto end;
-                       }
-               }
-
-               result = acpi_thermal_cpufreq_decrease(pr->id);
-               if (result) {
-                       /*
-                        * We only could get -ERANGE, 1 or 0.
-                        * In the first two cases we reached max freq again.
-                        */
-                       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                                         "At minimum performance state\n"));
-                       max_tx_px = 1;
-               } else
-                       max_tx_px = 0;
-
-               break;
-       }
-
-      end:
-       if (pr->flags.throttling) {
-               pr->limit.thermal.px = 0;
-               pr->limit.thermal.tx = tx;
-
-               result = acpi_processor_apply_limit(pr);
-               if (result)
-                       printk(KERN_ERR PREFIX "Unable to set thermal limit\n");
-
-               ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Thermal limit now (P%d:T%d)\n",
-                                 pr->limit.thermal.px, pr->limit.thermal.tx));
-       } else
-               result = 0;
-       if (max_tx_px)
-               return 1;
-       else
-               return result;
-}
-
 int acpi_processor_get_limit_info(struct acpi_processor *pr)
 {
 
index 7308638..ff36327 100644 (file)
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/cpufreq.h>
+#ifdef CONFIG_ACPI_PROCFS
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#endif
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -1214,6 +1216,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr)
        return result;
 }
 
+#ifdef CONFIG_ACPI_PROCFS
 /* proc interface */
 static int acpi_processor_throttling_seq_show(struct seq_file *seq,
                                              void *offset)
@@ -1322,3 +1325,4 @@ const struct file_operations acpi_processor_throttling_fops = {
        .llseek = seq_lseek,
        .release = single_release,
 };
+#endif
index 4ff76e8..e5dbedb 100644 (file)
 #include <linux/timer.h>
 #include <linux/jiffies.h>
 #include <linux/delay.h>
-
-#ifdef CONFIG_ACPI_SYSFS_POWER
 #include <linux/power_supply.h>
-#endif
 
 #include "sbshc.h"
 
@@ -85,9 +82,7 @@ static const struct acpi_device_id sbs_device_ids[] = {
 MODULE_DEVICE_TABLE(acpi, sbs_device_ids);
 
 struct acpi_battery {
-#ifdef CONFIG_ACPI_SYSFS_POWER
        struct power_supply bat;
-#endif
        struct acpi_sbs *sbs;
 #ifdef CONFIG_ACPI_PROCFS_POWER
        struct proc_dir_entry *proc_entry;
@@ -120,9 +115,7 @@ struct acpi_battery {
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 struct acpi_sbs {
-#ifdef CONFIG_ACPI_SYSFS_POWER
        struct power_supply charger;
-#endif
        struct acpi_device *device;
        struct acpi_smb_hc *hc;
        struct mutex lock;
@@ -166,7 +159,6 @@ static inline int acpi_battery_scale(struct acpi_battery *battery)
            acpi_battery_ipscale(battery);
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static int sbs_get_ac_property(struct power_supply *psy,
                               enum power_supply_property psp,
                               union power_supply_propval *val)
@@ -313,7 +305,6 @@ static enum power_supply_property sbs_energy_battery_props[] = {
        POWER_SUPPLY_PROP_MANUFACTURER,
 };
 
-#endif
 
 /* --------------------------------------------------------------------------
                             Smart Battery System Management
@@ -449,7 +440,6 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs)
        return result;
 }
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
 static ssize_t acpi_battery_alarm_show(struct device *dev,
                                        struct device_attribute *attr,
                                        char *buf)
@@ -479,7 +469,6 @@ static struct device_attribute alarm_attr = {
        .show = acpi_battery_alarm_show,
        .store = acpi_battery_alarm_store,
 };
-#endif
 
 /* --------------------------------------------------------------------------
                               FS Interface (/proc/acpi)
@@ -798,7 +787,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
                        &acpi_battery_state_fops, &acpi_battery_alarm_fops,
                        battery);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
        battery->bat.name = battery->name;
        battery->bat.type = POWER_SUPPLY_TYPE_BATTERY;
        if (!acpi_battery_mode(battery)) {
@@ -819,7 +807,6 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
                goto end;
        battery->have_sysfs_alarm = 1;
       end:
-#endif
        printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n",
               ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
               battery->name, battery->present ? "present" : "absent");
@@ -828,17 +815,13 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id)
 
 static void acpi_battery_remove(struct acpi_sbs *sbs, int id)
 {
-#if defined(CONFIG_ACPI_SYSFS_POWER) || defined(CONFIG_ACPI_PROCFS_POWER)
        struct acpi_battery *battery = &sbs->battery[id];
-#endif
 
-#ifdef CONFIG_ACPI_SYSFS_POWER
        if (battery->bat.dev) {
                if (battery->have_sysfs_alarm)
                        device_remove_file(battery->bat.dev, &alarm_attr);
                power_supply_unregister(&battery->bat);
        }
-#endif
 #ifdef CONFIG_ACPI_PROCFS_POWER
        if (battery->proc_entry)
                acpi_sbs_remove_fs(&battery->proc_entry, acpi_battery_dir);
@@ -859,14 +842,12 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
        if (result)
                goto end;
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
        sbs->charger.name = "sbs-charger";
        sbs->charger.type = POWER_SUPPLY_TYPE_MAINS;
        sbs->charger.properties = sbs_ac_props;
        sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props);
        sbs->charger.get_property = sbs_get_ac_property;
        power_supply_register(&sbs->device->dev, &sbs->charger);
-#endif
        printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n",
               ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device),
               ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line");
@@ -876,10 +857,8 @@ static int acpi_charger_add(struct acpi_sbs *sbs)
 
 static void acpi_charger_remove(struct acpi_sbs *sbs)
 {
-#ifdef CONFIG_ACPI_SYSFS_POWER
        if (sbs->charger.dev)
                power_supply_unregister(&sbs->charger);
-#endif
 #ifdef CONFIG_ACPI_PROCFS_POWER
        if (sbs->charger_entry)
                acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir);
@@ -900,9 +879,7 @@ static void acpi_sbs_callback(void *context)
                                              ACPI_SBS_NOTIFY_STATUS,
                                              sbs->charger_present);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
                kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE);
-#endif
        }
        if (sbs->manager_present) {
                for (id = 0; id < MAX_SBS_BAT; ++id) {
@@ -919,9 +896,7 @@ static void acpi_sbs_callback(void *context)
                                                      ACPI_SBS_NOTIFY_STATUS,
                                                      bat->present);
 #endif
-#ifdef CONFIG_ACPI_SYSFS_POWER
                        kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE);
-#endif
                }
        }
 }
index b23825e..2b6c21d 100644 (file)
@@ -26,6 +26,8 @@ extern struct acpi_device *acpi_root;
 
 #define ACPI_IS_ROOT_DEVICE(device)    (!(device)->parent)
 
+static const char *dummy_hid = "device";
+
 static LIST_HEAD(acpi_device_list);
 static LIST_HEAD(acpi_bus_id_list);
 DEFINE_MUTEX(acpi_device_lock);
@@ -49,6 +51,9 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
        int count;
        struct acpi_hardware_id *id;
 
+       if (list_empty(&acpi_dev->pnp.ids))
+               return 0;
+
        len = snprintf(modalias, size, "acpi:");
        size -= len;
 
@@ -202,13 +207,15 @@ static int acpi_device_setup_files(struct acpi_device *dev)
                        goto end;
        }
 
-       result = device_create_file(&dev->dev, &dev_attr_hid);
-       if (result)
-               goto end;
+       if (!list_empty(&dev->pnp.ids)) {
+               result = device_create_file(&dev->dev, &dev_attr_hid);
+               if (result)
+                       goto end;
 
-       result = device_create_file(&dev->dev, &dev_attr_modalias);
-       if (result)
-               goto end;
+               result = device_create_file(&dev->dev, &dev_attr_modalias);
+               if (result)
+                       goto end;
+       }
 
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
@@ -316,6 +323,9 @@ static int acpi_device_uevent(struct device *dev, struct kobj_uevent_env *env)
        struct acpi_device *acpi_dev = to_acpi_device(dev);
        int len;
 
+       if (list_empty(&acpi_dev->pnp.ids))
+               return 0;
+
        if (add_uevent_var(env, "MODALIAS="))
                return -ENOMEM;
        len = create_modalias(acpi_dev, &env->buf[env->buflen - 1],
@@ -1010,10 +1020,13 @@ static int acpi_dock_match(struct acpi_device *device)
        return acpi_get_handle(device->handle, "_DCK", &tmp);
 }
 
-char *acpi_device_hid(struct acpi_device *device)
+const char *acpi_device_hid(struct acpi_device *device)
 {
        struct acpi_hardware_id *hid;
 
+       if (list_empty(&device->pnp.ids))
+               return dummy_hid;
+
        hid = list_first_entry(&device->pnp.ids, struct acpi_hardware_id, list);
        return hid->id;
 }
@@ -1142,16 +1155,6 @@ static void acpi_device_set_id(struct acpi_device *device)
                acpi_add_id(device, ACPI_BUTTON_HID_SLEEPF);
                break;
        }
-
-       /*
-        * We build acpi_devices for some objects that don't have _HID or _CID,
-        * e.g., PCI bridges and slots.  Drivers can't bind to these objects,
-        * but we do use them indirectly by traversing the acpi_device tree.
-        * This generic ID isn't useful for driver binding, but it provides
-        * the useful property that "every acpi_device has an ID."
-        */
-       if (list_empty(&device->pnp.ids))
-               acpi_add_id(device, "device");
 }
 
 static int acpi_device_set_context(struct acpi_device *device)
@@ -1431,6 +1434,7 @@ EXPORT_SYMBOL(acpi_bus_add);
 int acpi_bus_start(struct acpi_device *device)
 {
        struct acpi_bus_ops ops;
+       int result;
 
        if (!device)
                return -EINVAL;
@@ -1438,7 +1442,11 @@ int acpi_bus_start(struct acpi_device *device)
        memset(&ops, 0, sizeof(ops));
        ops.acpi_op_start = 1;
 
-       return acpi_bus_scan(device->handle, &ops, NULL);
+       result = acpi_bus_scan(device->handle, &ops, NULL);
+
+       acpi_update_gpes();
+
+       return result;
 }
 EXPORT_SYMBOL(acpi_bus_start);
 
@@ -1552,6 +1560,8 @@ int __init acpi_scan_init(void)
 
        if (result)
                acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+       else
+               acpi_update_gpes();
 
        return result;
 }
index 4754ff6..721d93b 100644 (file)
@@ -25,7 +25,9 @@
 #include "internal.h"
 #include "sleep.h"
 
-u8 sleep_states[ACPI_S_STATE_COUNT];
+static u8 sleep_states[ACPI_S_STATE_COUNT];
+
+static u32 acpi_target_sleep_state = ACPI_STATE_S0;
 
 static void acpi_sleep_tts_switch(u32 acpi_state)
 {
@@ -79,8 +81,6 @@ static int acpi_sleep_prepare(u32 acpi_state)
 }
 
 #ifdef CONFIG_ACPI_SLEEP
-static u32 acpi_target_sleep_state = ACPI_STATE_S0;
-
 /*
  * The ACPI specification wants us to save NVS memory regions during hibernation
  * and to restore them during the subsequent resume.  Windows does that also for
@@ -419,6 +419,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
                DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"),
                },
        },
+       {
+       .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VPCEB1Z1E",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"),
+               },
+       },
        {},
 };
 #endif /* CONFIG_SUSPEND */
@@ -562,7 +570,7 @@ int acpi_suspend(u32 acpi_state)
        return -EINVAL;
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_OPS
 /**
  *     acpi_pm_device_sleep_state - return preferred power state of ACPI device
  *             in the system sleep state given by %acpi_target_sleep_state
@@ -624,7 +632,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
         * can wake the system.  _S0W may be valid, too.
         */
        if (acpi_target_sleep_state == ACPI_STATE_S0 ||
-           (device_may_wakeup(dev) && adev->wakeup.state.enabled &&
+           (device_may_wakeup(dev) &&
             adev->wakeup.sleep_state <= acpi_target_sleep_state)) {
                acpi_status status;
 
@@ -632,7 +640,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
                status = acpi_evaluate_integer(handle, acpi_method, NULL,
                                                &d_max);
                if (ACPI_FAILURE(status)) {
-                       d_max = d_min;
+                       if (acpi_target_sleep_state != ACPI_STATE_S0 ||
+                           status != AE_NOT_FOUND)
+                               d_max = d_min;
                } else if (d_max < d_min) {
                        /* Warn the user of the broken DSDT */
                        printk(KERN_WARNING "ACPI: Wrong value from %s\n",
@@ -646,7 +656,9 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
                *d_min_p = d_min;
        return d_max;
 }
+#endif /* CONFIG_PM_OPS */
 
+#ifdef CONFIG_PM_SLEEP
 /**
  *     acpi_pm_device_sleep_wake - enable or disable the system wake-up
  *                                  capability of given device
@@ -677,7 +689,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 
        return error;
 }
-#endif
+#endif  /* CONFIG_PM_SLEEP */
 
 static void acpi_power_off_prepare(void)
 {
@@ -702,7 +714,7 @@ static void acpi_power_off(void)
  * paths through the BIOS, so disable _GTS and _BFS by default,
  * but do speak up and offer the option to enable them.
  */
-void __init acpi_gts_bfs_check(void)
+static void __init acpi_gts_bfs_check(void)
 {
        acpi_handle dummy;
 
index d882180..74d59c8 100644 (file)
@@ -1,5 +1,4 @@
 
-extern u8 sleep_states[];
 extern int acpi_suspend(u32 state);
 
 extern void acpi_enable_wakeup_devices(u8 sleep_state);
index 2f8f171..5a27b0a 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-
-#ifdef CONFIG_ACPI_PROCFS
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#endif
-
 #include <linux/jiffies.h>
 #include <linux/kmod.h>
 #include <linux/reboot.h>
@@ -195,61 +189,6 @@ struct acpi_thermal {
        struct mutex lock;
 };
 
-#ifdef CONFIG_ACPI_PROCFS
-static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file);
-static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_cooling_mode(struct file *,
-                                              const char __user *, size_t,
-                                              loff_t *);
-static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_thermal_write_polling(struct file *, const char __user *,
-                                         size_t, loff_t *);
-
-static const struct file_operations acpi_thermal_state_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_thermal_state_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static const struct file_operations acpi_thermal_temp_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_thermal_temp_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static const struct file_operations acpi_thermal_trip_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_thermal_trip_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static const struct file_operations acpi_thermal_cooling_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_thermal_cooling_open_fs,
-       .read = seq_read,
-       .write = acpi_thermal_write_cooling_mode,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static const struct file_operations acpi_thermal_polling_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_thermal_polling_open_fs,
-       .read = seq_read,
-       .write = acpi_thermal_write_polling,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-#endif /* CONFIG_ACPI_PROCFS*/
-
 /* --------------------------------------------------------------------------
                              Thermal Zone Management
    -------------------------------------------------------------------------- */
@@ -958,358 +897,6 @@ static void acpi_thermal_unregister_thermal_zone(struct acpi_thermal *tz)
 
 
 /* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
-static struct proc_dir_entry *acpi_thermal_dir;
-
-static int acpi_thermal_state_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_thermal *tz = seq->private;
-
-
-       if (!tz)
-               goto end;
-
-       seq_puts(seq, "state:                   ");
-
-       if (!tz->state.critical && !tz->state.hot && !tz->state.passive
-           && !tz->state.active)
-               seq_puts(seq, "ok\n");
-       else {
-               if (tz->state.critical)
-                       seq_puts(seq, "critical ");
-               if (tz->state.hot)
-                       seq_puts(seq, "hot ");
-               if (tz->state.passive)
-                       seq_puts(seq, "passive ");
-               if (tz->state.active)
-                       seq_printf(seq, "active[%d]", tz->state.active_index);
-               seq_puts(seq, "\n");
-       }
-
-      end:
-       return 0;
-}
-
-static int acpi_thermal_state_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_thermal_state_seq_show, PDE(inode)->data);
-}
-
-static int acpi_thermal_temp_seq_show(struct seq_file *seq, void *offset)
-{
-       int result = 0;
-       struct acpi_thermal *tz = seq->private;
-
-
-       if (!tz)
-               goto end;
-
-       result = acpi_thermal_get_temperature(tz);
-       if (result)
-               goto end;
-
-       seq_printf(seq, "temperature:             %ld C\n",
-                  KELVIN_TO_CELSIUS(tz->temperature));
-
-      end:
-       return 0;
-}
-
-static int acpi_thermal_temp_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_thermal_temp_seq_show, PDE(inode)->data);
-}
-
-static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_thermal *tz = seq->private;
-       struct acpi_device *device;
-       acpi_status status;
-
-       int i = 0;
-       int j = 0;
-
-
-       if (!tz)
-               goto end;
-
-       if (tz->trips.critical.flags.valid)
-               seq_printf(seq, "critical (S5):           %ld C%s",
-                          KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
-                          nocrt ? " <disabled>\n" : "\n");
-
-       if (tz->trips.hot.flags.valid)
-               seq_printf(seq, "hot (S4):                %ld C%s",
-                          KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
-                          nocrt ? " <disabled>\n" : "\n");
-
-       if (tz->trips.passive.flags.valid) {
-               seq_printf(seq,
-                          "passive:                 %ld C: tc1=%lu tc2=%lu tsp=%lu devices=",
-                          KELVIN_TO_CELSIUS(tz->trips.passive.temperature),
-                          tz->trips.passive.tc1, tz->trips.passive.tc2,
-                          tz->trips.passive.tsp);
-               for (j = 0; j < tz->trips.passive.devices.count; j++) {
-                       status = acpi_bus_get_device(tz->trips.passive.devices.
-                                                    handles[j], &device);
-                       seq_printf(seq, "%4.4s ", status ? "" :
-                                  acpi_device_bid(device));
-               }
-               seq_puts(seq, "\n");
-       } else {
-               seq_printf(seq, "passive (forced):");
-               if (tz->thermal_zone->forced_passive)
-                       seq_printf(seq, "        %i C\n",
-                                  tz->thermal_zone->forced_passive / 1000);
-               else
-                       seq_printf(seq, "<not set>\n");
-       }
-
-       for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
-               if (!(tz->trips.active[i].flags.valid))
-                       break;
-               seq_printf(seq, "active[%d]:               %ld C: devices=",
-                          i,
-                          KELVIN_TO_CELSIUS(tz->trips.active[i].temperature));
-               for (j = 0; j < tz->trips.active[i].devices.count; j++){
-                       status = acpi_bus_get_device(tz->trips.active[i].
-                                                    devices.handles[j],
-                                                    &device);
-                       seq_printf(seq, "%4.4s ", status ? "" :
-                                  acpi_device_bid(device));
-               }
-               seq_puts(seq, "\n");
-       }
-
-      end:
-       return 0;
-}
-
-static int acpi_thermal_trip_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_thermal_trip_seq_show, PDE(inode)->data);
-}
-
-static int acpi_thermal_cooling_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_thermal *tz = seq->private;
-
-
-       if (!tz)
-               goto end;
-
-       if (!tz->flags.cooling_mode)
-               seq_puts(seq, "<setting not supported>\n");
-       else
-               seq_puts(seq, "0 - Active; 1 - Passive\n");
-
-      end:
-       return 0;
-}
-
-static int acpi_thermal_cooling_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_thermal_cooling_seq_show,
-                          PDE(inode)->data);
-}
-
-static ssize_t
-acpi_thermal_write_cooling_mode(struct file *file,
-                               const char __user * buffer,
-                               size_t count, loff_t * ppos)
-{
-       struct seq_file *m = file->private_data;
-       struct acpi_thermal *tz = m->private;
-       int result = 0;
-       char mode_string[12] = { '\0' };
-
-
-       if (!tz || (count > sizeof(mode_string) - 1))
-               return -EINVAL;
-
-       if (!tz->flags.cooling_mode)
-               return -ENODEV;
-
-       if (copy_from_user(mode_string, buffer, count))
-               return -EFAULT;
-
-       mode_string[count] = '\0';
-
-       result = acpi_thermal_set_cooling_mode(tz,
-                                              simple_strtoul(mode_string, NULL,
-                                                             0));
-       if (result)
-               return result;
-
-       acpi_thermal_check(tz);
-
-       return count;
-}
-
-static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_thermal *tz = seq->private;
-
-
-       if (!tz)
-               goto end;
-
-       if (!tz->thermal_zone->polling_delay) {
-               seq_puts(seq, "<polling disabled>\n");
-               goto end;
-       }
-
-       seq_printf(seq, "polling frequency:       %d seconds\n",
-                  (tz->thermal_zone->polling_delay / 1000));
-
-      end:
-       return 0;
-}
-
-static int acpi_thermal_polling_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_thermal_polling_seq_show,
-                          PDE(inode)->data);
-}
-
-static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
-{
-       if (!tz)
-               return -EINVAL;
-
-       /* Convert value to deci-seconds */
-       tz->polling_frequency = seconds * 10;
-
-       tz->thermal_zone->polling_delay = seconds * 1000;
-
-       if (tz->tz_enabled)
-               thermal_zone_device_update(tz->thermal_zone);
-
-       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-                         "Polling frequency set to %lu seconds\n",
-                         tz->polling_frequency/10));
-
-       return 0;
-}
-
-static ssize_t
-acpi_thermal_write_polling(struct file *file,
-                          const char __user * buffer,
-                          size_t count, loff_t * ppos)
-{
-       struct seq_file *m = file->private_data;
-       struct acpi_thermal *tz = m->private;
-       int result = 0;
-       char polling_string[12] = { '\0' };
-       int seconds = 0;
-
-
-       if (!tz || (count > sizeof(polling_string) - 1))
-               return -EINVAL;
-
-       if (copy_from_user(polling_string, buffer, count))
-               return -EFAULT;
-
-       polling_string[count] = '\0';
-
-       seconds = simple_strtoul(polling_string, NULL, 0);
-
-       result = acpi_thermal_set_polling(tz, seconds);
-       if (result)
-               return result;
-
-       acpi_thermal_check(tz);
-
-       return count;
-}
-
-static int acpi_thermal_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry = NULL;
-
-
-       if (!acpi_device_dir(device)) {
-               acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
-                                                    acpi_thermal_dir);
-               if (!acpi_device_dir(device))
-                       return -ENODEV;
-       }
-
-       /* 'state' [R] */
-       entry = proc_create_data(ACPI_THERMAL_FILE_STATE,
-                                S_IRUGO, acpi_device_dir(device),
-                                &acpi_thermal_state_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -ENODEV;
-
-       /* 'temperature' [R] */
-       entry = proc_create_data(ACPI_THERMAL_FILE_TEMPERATURE,
-                                S_IRUGO, acpi_device_dir(device),
-                                &acpi_thermal_temp_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -ENODEV;
-
-       /* 'trip_points' [R] */
-       entry = proc_create_data(ACPI_THERMAL_FILE_TRIP_POINTS,
-                                S_IRUGO,
-                                acpi_device_dir(device),
-                                &acpi_thermal_trip_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -ENODEV;
-
-       /* 'cooling_mode' [R/W] */
-       entry = proc_create_data(ACPI_THERMAL_FILE_COOLING_MODE,
-                                S_IFREG | S_IRUGO | S_IWUSR,
-                                acpi_device_dir(device),
-                                &acpi_thermal_cooling_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -ENODEV;
-
-       /* 'polling_frequency' [R/W] */
-       entry = proc_create_data(ACPI_THERMAL_FILE_POLLING_FREQ,
-                                S_IFREG | S_IRUGO | S_IWUSR,
-                                acpi_device_dir(device),
-                                &acpi_thermal_polling_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               return -ENODEV;
-       return 0;
-}
-
-static int acpi_thermal_remove_fs(struct acpi_device *device)
-{
-
-       if (acpi_device_dir(device)) {
-               remove_proc_entry(ACPI_THERMAL_FILE_POLLING_FREQ,
-                                 acpi_device_dir(device));
-               remove_proc_entry(ACPI_THERMAL_FILE_COOLING_MODE,
-                                 acpi_device_dir(device));
-               remove_proc_entry(ACPI_THERMAL_FILE_TRIP_POINTS,
-                                 acpi_device_dir(device));
-               remove_proc_entry(ACPI_THERMAL_FILE_TEMPERATURE,
-                                 acpi_device_dir(device));
-               remove_proc_entry(ACPI_THERMAL_FILE_STATE,
-                                 acpi_device_dir(device));
-               remove_proc_entry(acpi_device_bid(device), acpi_thermal_dir);
-               acpi_device_dir(device) = NULL;
-       }
-
-       return 0;
-}
-#else
-static inline int acpi_thermal_add_fs(struct acpi_device *device) { return 0; }
-static inline int acpi_thermal_remove_fs(struct acpi_device *device)
-{
-       return 0;
-}
-#endif /* CONFIG_ACPI_PROCFS */
-/* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
@@ -1428,17 +1015,11 @@ static int acpi_thermal_add(struct acpi_device *device)
        if (result)
                goto free_memory;
 
-       result = acpi_thermal_add_fs(device);
-       if (result)
-               goto unregister_thermal_zone;
-
        printk(KERN_INFO PREFIX "%s [%s] (%ld C)\n",
               acpi_device_name(device), acpi_device_bid(device),
               KELVIN_TO_CELSIUS(tz->temperature));
        goto end;
 
-unregister_thermal_zone:
-       thermal_zone_device_unregister(tz->thermal_zone);
 free_memory:
        kfree(tz);
 end:
@@ -1454,7 +1035,6 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
 
        tz = acpi_driver_data(device);
 
-       acpi_thermal_remove_fs(device);
        acpi_thermal_unregister_thermal_zone(tz);
        mutex_destroy(&tz->lock);
        kfree(tz);
@@ -1580,19 +1160,9 @@ static int __init acpi_thermal_init(void)
                return -ENODEV;
        }
 
-#ifdef CONFIG_ACPI_PROCFS
-       acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
-       if (!acpi_thermal_dir)
-               return -ENODEV;
-#endif
-
        result = acpi_bus_register_driver(&acpi_thermal_driver);
-       if (result < 0) {
-#ifdef CONFIG_ACPI_PROCFS
-               remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
-#endif
+       if (result < 0)
                return -ENODEV;
-       }
 
        return 0;
 }
@@ -1602,10 +1172,6 @@ static void __exit acpi_thermal_exit(void)
 
        acpi_bus_unregister_driver(&acpi_thermal_driver);
 
-#ifdef CONFIG_ACPI_PROCFS
-       remove_proc_entry(ACPI_THERMAL_CLASS, acpi_root_dir);
-#endif
-
        return;
 }
 
index 67dec0c..5cd0228 100644 (file)
@@ -30,8 +30,6 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/mutex.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/input.h>
 #include <linux/backlight.h>
 #include <linux/thermal.h>
@@ -152,9 +150,6 @@ struct acpi_video_bus {
        struct acpi_video_bus_flags flags;
        struct list_head video_device_list;
        struct mutex device_list_lock;  /* protects video_device_list */
-#ifdef CONFIG_ACPI_PROCFS
-       struct proc_dir_entry *dir;
-#endif
        struct input_dev *input;
        char phys[32];  /* for input device */
        struct notifier_block pm_nb;
@@ -210,108 +205,6 @@ struct acpi_video_device {
        struct output_device *output_dev;
 };
 
-#ifdef CONFIG_ACPI_PROCFS
-/* bus */
-static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file);
-static const struct file_operations acpi_video_bus_info_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_bus_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file);
-static const struct file_operations acpi_video_bus_ROM_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_bus_ROM_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int acpi_video_bus_POST_info_open_fs(struct inode *inode,
-                                           struct file *file);
-static const struct file_operations acpi_video_bus_POST_info_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_bus_POST_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_video_bus_write_POST(struct file *file,
-       const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_bus_POST_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_bus_POST_open_fs,
-       .read = seq_read,
-       .write = acpi_video_bus_write_POST,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file);
-static ssize_t acpi_video_bus_write_DOS(struct file *file,
-       const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_bus_DOS_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_bus_DOS_open_fs,
-       .read = seq_read,
-       .write = acpi_video_bus_write_DOS,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-/* device */
-static int acpi_video_device_info_open_fs(struct inode *inode,
-                                         struct file *file);
-static const struct file_operations acpi_video_device_info_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_device_info_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int acpi_video_device_state_open_fs(struct inode *inode,
-                                          struct file *file);
-static ssize_t acpi_video_device_write_state(struct file *file,
-       const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_device_state_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_device_state_open_fs,
-       .read = seq_read,
-       .write = acpi_video_device_write_state,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int acpi_video_device_brightness_open_fs(struct inode *inode,
-                                               struct file *file);
-static ssize_t acpi_video_device_write_brightness(struct file *file,
-       const char __user *buffer, size_t count, loff_t *data);
-static const struct file_operations acpi_video_device_brightness_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_device_brightness_open_fs,
-       .read = seq_read,
-       .write = acpi_video_device_write_brightness,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int acpi_video_device_EDID_open_fs(struct inode *inode,
-                                         struct file *file);
-static const struct file_operations acpi_video_device_EDID_fops = {
-       .owner = THIS_MODULE,
-       .open = acpi_video_device_EDID_open_fs,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-#endif /* CONFIG_ACPI_PROCFS */
-
 static const char device_decode[][30] = {
        "motherboard VGA device",
        "PCI VGA device",
@@ -1111,646 +1004,6 @@ static int acpi_video_bus_check(struct acpi_video_bus *video)
 }
 
 /* --------------------------------------------------------------------------
-                              FS Interface (/proc)
-   -------------------------------------------------------------------------- */
-#ifdef CONFIG_ACPI_PROCFS
-
-static struct proc_dir_entry *acpi_video_dir;
-
-/* video devices */
-
-static int acpi_video_device_info_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_device *dev = seq->private;
-
-
-       if (!dev)
-               goto end;
-
-       seq_printf(seq, "device_id:    0x%04x\n", (u32) dev->device_id);
-       seq_printf(seq, "type:         ");
-       if (dev->flags.crt)
-               seq_printf(seq, "CRT\n");
-       else if (dev->flags.lcd)
-               seq_printf(seq, "LCD\n");
-       else if (dev->flags.tvout)
-               seq_printf(seq, "TVOUT\n");
-       else if (dev->flags.dvi)
-               seq_printf(seq, "DVI\n");
-       else
-               seq_printf(seq, "UNKNOWN\n");
-
-       seq_printf(seq, "known by bios: %s\n", dev->flags.bios ? "yes" : "no");
-
-      end:
-       return 0;
-}
-
-static int
-acpi_video_device_info_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_device_info_seq_show,
-                          PDE(inode)->data);
-}
-
-static int
-acpi_video_device_query(struct acpi_video_device *device,
-                       unsigned long long *state)
-{
-       int status;
-
-       status = acpi_evaluate_integer(device->dev->handle, "_DGS",
-                                      NULL, state);
-
-       return status;
-}
-
-static int acpi_video_device_state_seq_show(struct seq_file *seq, void *offset)
-{
-       int status;
-       struct acpi_video_device *dev = seq->private;
-       unsigned long long state;
-
-
-       if (!dev)
-               goto end;
-
-       status = acpi_video_device_get_state(dev, &state);
-       seq_printf(seq, "state:     ");
-       if (ACPI_SUCCESS(status))
-               seq_printf(seq, "0x%02llx\n", state);
-       else
-               seq_printf(seq, "<not supported>\n");
-
-       status = acpi_video_device_query(dev, &state);
-       seq_printf(seq, "query:     ");
-       if (ACPI_SUCCESS(status))
-               seq_printf(seq, "0x%02llx\n", state);
-       else
-               seq_printf(seq, "<not supported>\n");
-
-      end:
-       return 0;
-}
-
-static int
-acpi_video_device_state_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_device_state_seq_show,
-                          PDE(inode)->data);
-}
-
-static ssize_t
-acpi_video_device_write_state(struct file *file,
-                             const char __user * buffer,
-                             size_t count, loff_t * data)
-{
-       int status;
-       struct seq_file *m = file->private_data;
-       struct acpi_video_device *dev = m->private;
-       char str[12] = { 0 };
-       u32 state = 0;
-
-
-       if (!dev || count >= sizeof(str))
-               return -EINVAL;
-
-       if (copy_from_user(str, buffer, count))
-               return -EFAULT;
-
-       str[count] = 0;
-       state = simple_strtoul(str, NULL, 0);
-       state &= ((1ul << 31) | (1ul << 30) | (1ul << 0));
-
-       status = acpi_video_device_set_state(dev, state);
-
-       if (status)
-               return -EFAULT;
-
-       return count;
-}
-
-static int
-acpi_video_device_brightness_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_device *dev = seq->private;
-       int i;
-
-
-       if (!dev || !dev->brightness) {
-               seq_printf(seq, "<not supported>\n");
-               return 0;
-       }
-
-       seq_printf(seq, "levels: ");
-       for (i = 2; i < dev->brightness->count; i++)
-               seq_printf(seq, " %d", dev->brightness->levels[i]);
-       seq_printf(seq, "\ncurrent: %d\n", dev->brightness->curr);
-
-       return 0;
-}
-
-static int
-acpi_video_device_brightness_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_device_brightness_seq_show,
-                          PDE(inode)->data);
-}
-
-static ssize_t
-acpi_video_device_write_brightness(struct file *file,
-                                  const char __user * buffer,
-                                  size_t count, loff_t * data)
-{
-       struct seq_file *m = file->private_data;
-       struct acpi_video_device *dev = m->private;
-       char str[5] = { 0 };
-       unsigned int level = 0;
-       int i;
-
-
-       if (!dev || !dev->brightness || count >= sizeof(str))
-               return -EINVAL;
-
-       if (copy_from_user(str, buffer, count))
-               return -EFAULT;
-
-       str[count] = 0;
-       level = simple_strtoul(str, NULL, 0);
-
-       if (level > 100)
-               return -EFAULT;
-
-       /* validate through the list of available levels */
-       for (i = 2; i < dev->brightness->count; i++)
-               if (level == dev->brightness->levels[i]) {
-                       if (!acpi_video_device_lcd_set_level(dev, level))
-                               return count;
-                       break;
-               }
-
-       return -EINVAL;
-}
-
-static int acpi_video_device_EDID_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_device *dev = seq->private;
-       int status;
-       int i;
-       union acpi_object *edid = NULL;
-
-
-       if (!dev)
-               goto out;
-
-       status = acpi_video_device_EDID(dev, &edid, 128);
-       if (ACPI_FAILURE(status)) {
-               status = acpi_video_device_EDID(dev, &edid, 256);
-       }
-
-       if (ACPI_FAILURE(status)) {
-               goto out;
-       }
-
-       if (edid && edid->type == ACPI_TYPE_BUFFER) {
-               for (i = 0; i < edid->buffer.length; i++)
-                       seq_putc(seq, edid->buffer.pointer[i]);
-       }
-
-      out:
-       if (!edid)
-               seq_printf(seq, "<not supported>\n");
-       else
-               kfree(edid);
-
-       return 0;
-}
-
-static int
-acpi_video_device_EDID_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_device_EDID_seq_show,
-                          PDE(inode)->data);
-}
-
-static int acpi_video_device_add_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *entry, *device_dir;
-       struct acpi_video_device *vid_dev;
-
-       vid_dev = acpi_driver_data(device);
-       if (!vid_dev)
-               return -ENODEV;
-
-       device_dir = proc_mkdir(acpi_device_bid(device),
-                               vid_dev->video->dir);
-       if (!device_dir)
-               return -ENOMEM;
-
-       /* 'info' [R] */
-       entry = proc_create_data("info", S_IRUGO, device_dir,
-                       &acpi_video_device_info_fops, acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_dir;
-
-       /* 'state' [R/W] */
-       entry = proc_create_data("state", S_IFREG | S_IRUGO | S_IWUSR,
-                                device_dir,
-                                &acpi_video_device_state_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_info;
-
-       /* 'brightness' [R/W] */
-       entry = proc_create_data("brightness", S_IFREG | S_IRUGO | S_IWUSR,
-                                device_dir,
-                                &acpi_video_device_brightness_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_state;
-
-       /* 'EDID' [R] */
-       entry = proc_create_data("EDID", S_IRUGO, device_dir,
-                                &acpi_video_device_EDID_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_brightness;
-
-       acpi_device_dir(device) = device_dir;
-
-       return 0;
-
- err_remove_brightness:
-       remove_proc_entry("brightness", device_dir);
- err_remove_state:
-       remove_proc_entry("state", device_dir);
- err_remove_info:
-       remove_proc_entry("info", device_dir);
- err_remove_dir:
-       remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
-       return -ENOMEM;
-}
-
-static int acpi_video_device_remove_fs(struct acpi_device *device)
-{
-       struct acpi_video_device *vid_dev;
-       struct proc_dir_entry *device_dir;
-
-       vid_dev = acpi_driver_data(device);
-       if (!vid_dev || !vid_dev->video || !vid_dev->video->dir)
-               return -ENODEV;
-
-       device_dir = acpi_device_dir(device);
-       if (device_dir) {
-               remove_proc_entry("info", device_dir);
-               remove_proc_entry("state", device_dir);
-               remove_proc_entry("brightness", device_dir);
-               remove_proc_entry("EDID", device_dir);
-               remove_proc_entry(acpi_device_bid(device), vid_dev->video->dir);
-               acpi_device_dir(device) = NULL;
-       }
-
-       return 0;
-}
-
-/* video bus */
-static int acpi_video_bus_info_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_bus *video = seq->private;
-
-
-       if (!video)
-               goto end;
-
-       seq_printf(seq, "Switching heads:              %s\n",
-                  video->flags.multihead ? "yes" : "no");
-       seq_printf(seq, "Video ROM:                    %s\n",
-                  video->flags.rom ? "yes" : "no");
-       seq_printf(seq, "Device to be POSTed on boot:  %s\n",
-                  video->flags.post ? "yes" : "no");
-
-      end:
-       return 0;
-}
-
-static int acpi_video_bus_info_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_bus_info_seq_show,
-                          PDE(inode)->data);
-}
-
-static int acpi_video_bus_ROM_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_bus *video = seq->private;
-
-
-       if (!video)
-               goto end;
-
-       printk(KERN_INFO PREFIX "Please implement %s\n", __func__);
-       seq_printf(seq, "<TODO>\n");
-
-      end:
-       return 0;
-}
-
-static int acpi_video_bus_ROM_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_bus_ROM_seq_show, PDE(inode)->data);
-}
-
-static int
-acpi_video_bus_POST_options(struct acpi_video_bus *video,
-                           unsigned long long *options)
-{
-       int status;
-
-       status = acpi_evaluate_integer(video->device->handle, "_VPO",
-                                      NULL, options);
-       *options &= 3;
-
-       return status;
-}
-
-static int acpi_video_bus_POST_info_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_bus *video = seq->private;
-       unsigned long long options;
-       int status;
-
-
-       if (!video)
-               goto end;
-
-       status = acpi_video_bus_POST_options(video, &options);
-       if (ACPI_SUCCESS(status)) {
-               if (!(options & 1)) {
-                       printk(KERN_WARNING PREFIX
-                              "The motherboard VGA device is not listed as a possible POST device.\n");
-                       printk(KERN_WARNING PREFIX
-                              "This indicates a BIOS bug. Please contact the manufacturer.\n");
-               }
-               printk(KERN_WARNING "%llx\n", options);
-               seq_printf(seq, "can POST: <integrated video>");
-               if (options & 2)
-                       seq_printf(seq, " <PCI video>");
-               if (options & 4)
-                       seq_printf(seq, " <AGP video>");
-               seq_putc(seq, '\n');
-       } else
-               seq_printf(seq, "<not supported>\n");
-      end:
-       return 0;
-}
-
-static int
-acpi_video_bus_POST_info_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_bus_POST_info_seq_show,
-                          PDE(inode)->data);
-}
-
-static int
-acpi_video_bus_get_POST(struct acpi_video_bus *video, unsigned long long *id)
-{
-       int status;
-
-       status = acpi_evaluate_integer(video->device->handle, "_GPD", NULL, id);
-
-       return status;
-}
-
-static int acpi_video_bus_POST_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_bus *video = seq->private;
-       int status;
-       unsigned long long id;
-
-
-       if (!video)
-               goto end;
-
-       status = acpi_video_bus_get_POST(video, &id);
-       if (!ACPI_SUCCESS(status)) {
-               seq_printf(seq, "<not supported>\n");
-               goto end;
-       }
-       seq_printf(seq, "device POSTed is <%s>\n", device_decode[id & 3]);
-
-      end:
-       return 0;
-}
-
-static int acpi_video_bus_DOS_seq_show(struct seq_file *seq, void *offset)
-{
-       struct acpi_video_bus *video = seq->private;
-
-
-       seq_printf(seq, "DOS setting: <%d>\n", video->dos_setting);
-
-       return 0;
-}
-
-static int acpi_video_bus_POST_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_bus_POST_seq_show,
-                          PDE(inode)->data);
-}
-
-static int acpi_video_bus_DOS_open_fs(struct inode *inode, struct file *file)
-{
-       return single_open(file, acpi_video_bus_DOS_seq_show, PDE(inode)->data);
-}
-
-static int
-acpi_video_bus_set_POST(struct acpi_video_bus *video, unsigned long option)
-{
-       int status;
-       unsigned long long tmp;
-       union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-       struct acpi_object_list args = { 1, &arg0 };
-
-
-       arg0.integer.value = option;
-
-       status = acpi_evaluate_integer(video->device->handle, "_SPD",
-                                      &args, &tmp);
-       if (ACPI_SUCCESS(status))
-               status = tmp ? (-EINVAL) : (AE_OK);
-
-       return status;
-}
-
-static ssize_t
-acpi_video_bus_write_POST(struct file *file,
-                         const char __user * buffer,
-                         size_t count, loff_t * data)
-{
-       int status;
-       struct seq_file *m = file->private_data;
-       struct acpi_video_bus *video = m->private;
-       char str[12] = { 0 };
-       unsigned long long opt, options;
-
-
-       if (!video || count >= sizeof(str))
-               return -EINVAL;
-
-       status = acpi_video_bus_POST_options(video, &options);
-       if (!ACPI_SUCCESS(status))
-               return -EINVAL;
-
-       if (copy_from_user(str, buffer, count))
-               return -EFAULT;
-
-       str[count] = 0;
-       opt = strtoul(str, NULL, 0);
-       if (opt > 3)
-               return -EFAULT;
-
-       /* just in case an OEM 'forgot' the motherboard... */
-       options |= 1;
-
-       if (options & (1ul << opt)) {
-               status = acpi_video_bus_set_POST(video, opt);
-               if (!ACPI_SUCCESS(status))
-                       return -EFAULT;
-
-       }
-
-       return count;
-}
-
-static ssize_t
-acpi_video_bus_write_DOS(struct file *file,
-                        const char __user * buffer,
-                        size_t count, loff_t * data)
-{
-       int status;
-       struct seq_file *m = file->private_data;
-       struct acpi_video_bus *video = m->private;
-       char str[12] = { 0 };
-       unsigned long opt;
-
-
-       if (!video || count >= sizeof(str))
-               return -EINVAL;
-
-       if (copy_from_user(str, buffer, count))
-               return -EFAULT;
-
-       str[count] = 0;
-       opt = strtoul(str, NULL, 0);
-       if (opt > 7)
-               return -EFAULT;
-
-       status = acpi_video_bus_DOS(video, opt & 0x3, (opt & 0x4) >> 2);
-
-       if (!ACPI_SUCCESS(status))
-               return -EFAULT;
-
-       return count;
-}
-
-static int acpi_video_bus_add_fs(struct acpi_device *device)
-{
-       struct acpi_video_bus *video = acpi_driver_data(device);
-       struct proc_dir_entry *device_dir;
-       struct proc_dir_entry *entry;
-
-       device_dir = proc_mkdir(acpi_device_bid(device), acpi_video_dir);
-       if (!device_dir)
-               return -ENOMEM;
-
-       /* 'info' [R] */
-       entry = proc_create_data("info", S_IRUGO, device_dir,
-                                &acpi_video_bus_info_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_dir;
-
-       /* 'ROM' [R] */
-       entry = proc_create_data("ROM", S_IRUGO, device_dir,
-                                &acpi_video_bus_ROM_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_info;
-
-       /* 'POST_info' [R] */
-       entry = proc_create_data("POST_info", S_IRUGO, device_dir,
-                                &acpi_video_bus_POST_info_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_rom;
-
-       /* 'POST' [R/W] */
-       entry = proc_create_data("POST", S_IFREG | S_IRUGO | S_IWUSR,
-                                device_dir,
-                                &acpi_video_bus_POST_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_post_info;
-
-       /* 'DOS' [R/W] */
-       entry = proc_create_data("DOS", S_IFREG | S_IRUGO | S_IWUSR,
-                                device_dir,
-                                &acpi_video_bus_DOS_fops,
-                                acpi_driver_data(device));
-       if (!entry)
-               goto err_remove_post;
-
-       video->dir = acpi_device_dir(device) = device_dir;
-       return 0;
-
- err_remove_post:
-       remove_proc_entry("POST", device_dir);
- err_remove_post_info:
-       remove_proc_entry("POST_info", device_dir);
- err_remove_rom:
-       remove_proc_entry("ROM", device_dir);
- err_remove_info:
-       remove_proc_entry("info", device_dir);
- err_remove_dir:
-       remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
-       return -ENOMEM;
-}
-
-static int acpi_video_bus_remove_fs(struct acpi_device *device)
-{
-       struct proc_dir_entry *device_dir = acpi_device_dir(device);
-
-       if (device_dir) {
-               remove_proc_entry("info", device_dir);
-               remove_proc_entry("ROM", device_dir);
-               remove_proc_entry("POST_info", device_dir);
-               remove_proc_entry("POST", device_dir);
-               remove_proc_entry("DOS", device_dir);
-               remove_proc_entry(acpi_device_bid(device), acpi_video_dir);
-               acpi_device_dir(device) = NULL;
-       }
-
-       return 0;
-}
-#else
-static inline int acpi_video_device_add_fs(struct acpi_device *device)
-{
-       return 0;
-}
-static inline int acpi_video_device_remove_fs(struct acpi_device *device)
-{
-       return 0;
-}
-static inline int acpi_video_bus_add_fs(struct acpi_device *device)
-{
-       return 0;
-}
-static inline int acpi_video_bus_remove_fs(struct acpi_device *device)
-{
-       return 0;
-}
-#endif /* CONFIG_ACPI_PROCFS */
-
-/* --------------------------------------------------------------------------
                                  Driver Interface
    -------------------------------------------------------------------------- */
 
@@ -1877,8 +1130,6 @@ acpi_video_bus_get_one_device(struct acpi_device *device,
                list_add_tail(&data->entry, &video->video_device_list);
                mutex_unlock(&video->device_list_lock);
 
-               acpi_video_device_add_fs(device);
-
                return 0;
        }
 
@@ -2181,8 +1432,6 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device)
        if (!device || !device->video)
                return -ENOENT;
 
-       acpi_video_device_remove_fs(device->dev);
-
        status = acpi_remove_notify_handler(device->dev->handle,
                                            ACPI_DEVICE_NOTIFY,
                                            acpi_video_device_notify);
@@ -2466,10 +1715,6 @@ static int acpi_video_bus_add(struct acpi_device *device)
        if (error)
                goto err_free_video;
 
-       error = acpi_video_bus_add_fs(device);
-       if (error)
-               goto err_free_video;
-
        mutex_init(&video->device_list_lock);
        INIT_LIST_HEAD(&video->video_device_list);
 
@@ -2522,7 +1767,6 @@ static int acpi_video_bus_add(struct acpi_device *device)
        acpi_video_bus_stop_devices(video);
        acpi_video_bus_put_devices(video);
        kfree(video->attached_array);
-       acpi_video_bus_remove_fs(device);
  err_free_video:
        kfree(video);
        device->driver_data = NULL;
@@ -2544,7 +1788,6 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type)
 
        acpi_video_bus_stop_devices(video);
        acpi_video_bus_put_devices(video);
-       acpi_video_bus_remove_fs(device);
 
        input_unregister_device(video->input);
        kfree(video->attached_array);
@@ -2584,17 +1827,9 @@ int acpi_video_register(void)
                return 0;
        }
 
-#ifdef CONFIG_ACPI_PROCFS
-       acpi_video_dir = proc_mkdir(ACPI_VIDEO_CLASS, acpi_root_dir);
-       if (!acpi_video_dir)
-               return -ENODEV;
-#endif
-
        result = acpi_bus_register_driver(&acpi_video_bus);
-       if (result < 0) {
-               remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
+       if (result < 0)
                return -ENODEV;
-       }
 
        /*
         * When the acpi_video_bus is loaded successfully, increase
@@ -2617,10 +1852,6 @@ void acpi_video_unregister(void)
        }
        acpi_bus_unregister_driver(&acpi_video_bus);
 
-#ifdef CONFIG_ACPI_PROCFS
-       remove_proc_entry(ACPI_VIDEO_CLASS, acpi_root_dir);
-#endif
-
        register_count = 0;
 
        return;
index ee53558..ce012a9 100644 (file)
@@ -160,6 +160,18 @@ static ssize_t node_read_numastat(struct sys_device * dev,
 }
 static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL);
 
+static ssize_t node_read_vmstat(struct sys_device *dev,
+                               struct sysdev_attribute *attr, char *buf)
+{
+       int nid = dev->id;
+       return sprintf(buf,
+               "nr_written %lu\n"
+               "nr_dirtied %lu\n",
+               node_page_state(nid, NR_WRITTEN),
+               node_page_state(nid, NR_DIRTIED));
+}
+static SYSDEV_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
+
 static ssize_t node_read_distance(struct sys_device * dev,
                        struct sysdev_attribute *attr, char * buf)
 {
@@ -243,6 +255,7 @@ int register_node(struct node *node, int num, struct node *parent)
                sysdev_create_file(&node->sysdev, &attr_meminfo);
                sysdev_create_file(&node->sysdev, &attr_numastat);
                sysdev_create_file(&node->sysdev, &attr_distance);
+               sysdev_create_file(&node->sysdev, &attr_vmstat);
 
                scan_unevictable_register_node(node);
 
@@ -267,6 +280,7 @@ void unregister_node(struct node *node)
        sysdev_remove_file(&node->sysdev, &attr_meminfo);
        sysdev_remove_file(&node->sysdev, &attr_numastat);
        sysdev_remove_file(&node->sysdev, &attr_distance);
+       sysdev_remove_file(&node->sysdev, &attr_vmstat);
 
        scan_unevictable_unregister_node(node);
        hugetlb_unregister_node(node);          /* no-op, if memoryless node */
index 1dd8676..126ca49 100644 (file)
@@ -503,7 +503,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
         * the resume will actually succeed.
         */
        if (dev->power.no_callbacks && !parent && dev->parent) {
-               spin_lock(&dev->parent->power.lock);
+               spin_lock_nested(&dev->parent->power.lock, SINGLE_DEPTH_NESTING);
                if (dev->parent->power.disable_depth > 0
                    || dev->parent->power.ignore_children
                    || dev->parent->power.runtime_status == RPM_ACTIVE) {
index 6c48b35..450c958 100644 (file)
@@ -101,8 +101,8 @@ static int transfer_none(struct loop_device *lo, int cmd,
        else
                memcpy(raw_buf, loop_buf, size);
 
-       kunmap_atomic(raw_buf, KM_USER0);
        kunmap_atomic(loop_buf, KM_USER1);
+       kunmap_atomic(raw_buf, KM_USER0);
        cond_resched();
        return 0;
 }
@@ -130,8 +130,8 @@ static int transfer_xor(struct loop_device *lo, int cmd,
        for (i = 0; i < size; i++)
                *out++ = *in++ ^ key[(i & 511) % keysize];
 
-       kunmap_atomic(raw_buf, KM_USER0);
        kunmap_atomic(loop_buf, KM_USER1);
+       kunmap_atomic(raw_buf, KM_USER0);
        cond_resched();
        return 0;
 }
index a4eee32..55b8667 100644 (file)
 #include <linux/bitops.h>
 #include <linux/compat.h>
 #include <linux/clocksource.h>
+#include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/io.h>
 
 #include <asm/current.h>
-#include <asm/uaccess.h>
 #include <asm/system.h>
-#include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/div64.h>
 
@@ -81,13 +81,13 @@ static cycle_t read_hpet(struct clocksource *cs)
 }
 
 static struct clocksource clocksource_hpet = {
-        .name           = "hpet",
-        .rating         = 250,
-        .read           = read_hpet,
-        .mask           = CLOCKSOURCE_MASK(64),
-       .mult           = 0, /* to be calculated */
-        .shift          = 10,
-        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .name           = "hpet",
+       .rating         = 250,
+       .read           = read_hpet,
+       .mask           = CLOCKSOURCE_MASK(64),
+       .mult           = 0,            /* to be calculated */
+       .shift          = 10,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 static struct clocksource *hpet_clocksource;
 #endif
@@ -465,6 +465,21 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
        if (irq) {
                unsigned long irq_flags;
 
+               if (devp->hd_flags & HPET_SHARED_IRQ) {
+                       /*
+                        * To prevent the interrupt handler from seeing an
+                        * unwanted interrupt status bit, program the timer
+                        * so that it will not fire in the near future ...
+                        */
+                       writel(readl(&timer->hpet_config) & ~Tn_TYPE_CNF_MASK,
+                              &timer->hpet_config);
+                       write_counter(read_counter(&hpet->hpet_mc),
+                                     &timer->hpet_compare);
+                       /* ... and clear any left-over status. */
+                       isr = 1 << (devp - devp->hd_hpets->hp_dev);
+                       writel(isr, &hpet->hpet_isr);
+               }
+
                sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
                irq_flags = devp->hd_flags & HPET_SHARED_IRQ
                                                ? IRQF_SHARED : IRQF_DISABLED;
@@ -581,11 +596,10 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg,
                break;
        case HPET_INFO:
                {
+                       memset(info, 0, sizeof(*info));
                        if (devp->hd_ireqfreq)
                                info->hi_ireqfreq =
                                        hpet_time_div(hpetp, devp->hd_ireqfreq);
-                       else
-                               info->hi_ireqfreq = 0;
                        info->hi_flags =
                            readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
                        info->hi_hpet = hpetp->hp_which;
@@ -811,7 +825,7 @@ int hpet_alloc(struct hpet_data *hdp)
        struct hpets *hpetp;
        size_t siz;
        struct hpet __iomem *hpet;
-       static struct hpets *last = NULL;
+       static struct hpets *last;
        unsigned long period;
        unsigned long long temp;
        u32 remainder;
@@ -1000,6 +1014,8 @@ static int hpet_acpi_add(struct acpi_device *device)
                return -ENODEV;
 
        if (!data.hd_address || !data.hd_nirqs) {
+               if (data.hd_address)
+                       iounmap(data.hd_address);
                printk("%s: no address or irqs in _CRS\n", __func__);
                return -ENODEV;
        }
index c4efb55..7a84a05 100644 (file)
@@ -61,7 +61,8 @@ console_initcall(hvc_tile_console_init);
 
 static int __init hvc_tile_init(void)
 {
-       hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
-       return 0;
+       struct hvc_struct *s;
+       s = hvc_alloc(0, 0, &hvc_tile_get_put_ops, 128);
+       return IS_ERR(s) ? PTR_ERR(s) : 0;
 }
 device_initcall(hvc_tile_init);
index e537610..b293d57 100644 (file)
@@ -1665,6 +1665,17 @@ static int check_hotmod_int_op(const char *curr, const char *option,
        return 0;
 }
 
+static struct smi_info *smi_info_alloc(void)
+{
+       struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL);
+
+       if (info) {
+               spin_lock_init(&info->si_lock);
+               spin_lock_init(&info->msg_lock);
+       }
+       return info;
+}
+
 static int hotmod_handler(const char *val, struct kernel_param *kp)
 {
        char *str = kstrdup(val, GFP_KERNEL);
@@ -1779,7 +1790,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp)
                }
 
                if (op == HM_ADD) {
-                       info = kzalloc(sizeof(*info), GFP_KERNEL);
+                       info = smi_info_alloc();
                        if (!info) {
                                rv = -ENOMEM;
                                goto out;
@@ -1844,7 +1855,7 @@ static __devinit void hardcode_find_bmc(void)
                if (!ports[i] && !addrs[i])
                        continue;
 
-               info = kzalloc(sizeof(*info), GFP_KERNEL);
+               info = smi_info_alloc();
                if (!info)
                        return;
 
@@ -2027,7 +2038,7 @@ static __devinit int try_init_spmi(struct SPMITable *spmi)
                return -ENODEV;
        }
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       info = smi_info_alloc();
        if (!info) {
                printk(KERN_ERR PFX "Could not allocate SI data (3)\n");
                return -ENOMEM;
@@ -2137,7 +2148,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev,
        if (!acpi_dev)
                return -ENODEV;
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       info = smi_info_alloc();
        if (!info)
                return -ENOMEM;
 
@@ -2318,7 +2329,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
 {
        struct smi_info *info;
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       info = smi_info_alloc();
        if (!info) {
                printk(KERN_ERR PFX "Could not allocate SI data\n");
                return;
@@ -2425,7 +2436,7 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev,
        int class_type = pdev->class & PCI_ERMC_CLASSCODE_TYPE_MASK;
        struct smi_info *info;
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       info = smi_info_alloc();
        if (!info)
                return -ENOMEM;
 
@@ -2566,7 +2577,7 @@ static int __devinit ipmi_of_probe(struct platform_device *dev,
                return -EINVAL;
        }
 
-       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       info = smi_info_alloc();
 
        if (!info) {
                dev_err(&dev->dev,
@@ -3013,7 +3024,7 @@ static __devinit void default_find_bmc(void)
                if (check_legacy_ioport(ipmi_defaults[i].port))
                        continue;
 #endif
-               info = kzalloc(sizeof(*info), GFP_KERNEL);
+               info = smi_info_alloc();
                if (!info)
                        return;
 
@@ -3138,9 +3149,6 @@ static int try_smi_init(struct smi_info *new_smi)
                goto out_err;
        }
 
-       spin_lock_init(&(new_smi->si_lock));
-       spin_lock_init(&(new_smi->msg_lock));
-
        /* Do low-level detection first. */
        if (new_smi->handlers->detect(new_smi->si_sm)) {
                if (new_smi->addr_source)
index 199dcb9..c63a438 100644 (file)
@@ -918,8 +918,8 @@ static int cpufreq_add_dev_interface(unsigned int cpu,
 
        spin_lock_irqsave(&cpufreq_driver_lock, flags);
        for_each_cpu(j, policy->cpus) {
-       if (!cpu_online(j))
-               continue;
+               if (!cpu_online(j))
+                       continue;
                per_cpu(cpufreq_cpu_data, j) = policy;
                per_cpu(cpufreq_policy_cpu, j) = policy->cpu;
        }
index 7b50936..c631f27 100644 (file)
@@ -30,6 +30,8 @@
 
 #define DEF_FREQUENCY_DOWN_DIFFERENTIAL                (10)
 #define DEF_FREQUENCY_UP_THRESHOLD             (80)
+#define DEF_SAMPLING_DOWN_FACTOR               (1)
+#define MAX_SAMPLING_DOWN_FACTOR               (100000)
 #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL      (3)
 #define MICRO_FREQUENCY_UP_THRESHOLD           (95)
 #define MICRO_FREQUENCY_MIN_SAMPLE_RATE                (10000)
@@ -82,6 +84,7 @@ struct cpu_dbs_info_s {
        unsigned int freq_lo;
        unsigned int freq_lo_jiffies;
        unsigned int freq_hi_jiffies;
+       unsigned int rate_mult;
        int cpu;
        unsigned int sample_type:1;
        /*
@@ -108,10 +111,12 @@ static struct dbs_tuners {
        unsigned int up_threshold;
        unsigned int down_differential;
        unsigned int ignore_nice;
+       unsigned int sampling_down_factor;
        unsigned int powersave_bias;
        unsigned int io_is_busy;
 } dbs_tuners_ins = {
        .up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
+       .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR,
        .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL,
        .ignore_nice = 0,
        .powersave_bias = 0,
@@ -259,6 +264,7 @@ static ssize_t show_##file_name                                             \
 show_one(sampling_rate, sampling_rate);
 show_one(io_is_busy, io_is_busy);
 show_one(up_threshold, up_threshold);
+show_one(sampling_down_factor, sampling_down_factor);
 show_one(ignore_nice_load, ignore_nice);
 show_one(powersave_bias, powersave_bias);
 
@@ -340,6 +346,29 @@ static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
        return count;
 }
 
+static ssize_t store_sampling_down_factor(struct kobject *a,
+                       struct attribute *b, const char *buf, size_t count)
+{
+       unsigned int input, j;
+       int ret;
+       ret = sscanf(buf, "%u", &input);
+
+       if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
+               return -EINVAL;
+       mutex_lock(&dbs_mutex);
+       dbs_tuners_ins.sampling_down_factor = input;
+
+       /* Reset down sampling multiplier in case it was active */
+       for_each_online_cpu(j) {
+               struct cpu_dbs_info_s *dbs_info;
+               dbs_info = &per_cpu(od_cpu_dbs_info, j);
+               dbs_info->rate_mult = 1;
+       }
+       mutex_unlock(&dbs_mutex);
+
+       return count;
+}
+
 static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
                                      const char *buf, size_t count)
 {
@@ -401,6 +430,7 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b,
 define_one_global_rw(sampling_rate);
 define_one_global_rw(io_is_busy);
 define_one_global_rw(up_threshold);
+define_one_global_rw(sampling_down_factor);
 define_one_global_rw(ignore_nice_load);
 define_one_global_rw(powersave_bias);
 
@@ -409,6 +439,7 @@ static struct attribute *dbs_attributes[] = {
        &sampling_rate_min.attr,
        &sampling_rate.attr,
        &up_threshold.attr,
+       &sampling_down_factor.attr,
        &ignore_nice_load.attr,
        &powersave_bias.attr,
        &io_is_busy.attr,
@@ -562,6 +593,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
 
        /* Check for frequency increase */
        if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) {
+               /* If switching to max speed, apply sampling_down_factor */
+               if (policy->cur < policy->max)
+                       this_dbs_info->rate_mult =
+                               dbs_tuners_ins.sampling_down_factor;
                dbs_freq_increase(policy, policy->max);
                return;
        }
@@ -584,6 +619,9 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
                                (dbs_tuners_ins.up_threshold -
                                 dbs_tuners_ins.down_differential);
 
+               /* No longer fully busy, reset rate_mult */
+               this_dbs_info->rate_mult = 1;
+
                if (freq_next < policy->min)
                        freq_next = policy->min;
 
@@ -607,7 +645,8 @@ static void do_dbs_timer(struct work_struct *work)
        int sample_type = dbs_info->sample_type;
 
        /* We want all CPUs to do sampling nearly on same jiffy */
-       int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
+       int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
+               * dbs_info->rate_mult);
 
        if (num_online_cpus() > 1)
                delay -= jiffies % delay;
@@ -711,6 +750,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
                        }
                }
                this_dbs_info->cpu = cpu;
+               this_dbs_info->rate_mult = 1;
                ondemand_powersave_bias_init_cpu(cpu);
                /*
                 * Start the timerschedule work, when this governor
index 0eac3da..a84250a 100644 (file)
@@ -1467,7 +1467,7 @@ static int ablkcipher_add(unsigned int *drestp, struct scatterlist *dst,
                return -EINVAL;
 
        while (size) {
-               copy = min(drest, min(size, dst->length));
+               copy = min3(drest, size, dst->length);
 
                size -= copy;
                drest -= copy;
@@ -1729,7 +1729,7 @@ static int ablkcipher_get(void *saddr, unsigned int *srestp, unsigned int offset
                return -EINVAL;
 
        while (size) {
-               copy = min(srest, min(dst->length, size));
+               copy = min3(srest, dst->length, size);
 
                daddr = kmap_atomic(sg_page(dst), KM_IRQ0);
                memcpy(daddr + dst->offset + offset, saddr, copy);
index ce71466..d7ca43a 100644 (file)
 
 #if PAGE_SHIFT < 20
 #define PAGES_TO_MiB( pages )  ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
+#define MiB_TO_PAGES(mb)       ((mb) >> (20 - PAGE_SHIFT))
 #else                          /* PAGE_SHIFT > 20 */
 #define PAGES_TO_MiB( pages )  ( ( pages ) << ( PAGE_SHIFT - 20 ) )
+#define MiB_TO_PAGES(mb)       ((mb) >> (PAGE_SHIFT - 20))
 #endif
 
 #define edac_printk(level, prefix, fmt, arg...) \
@@ -328,7 +330,7 @@ struct csrow_info {
 
 struct mcidev_sysfs_group {
        const char *name;                               /* group name */
-       struct mcidev_sysfs_attribute *mcidev_attr;     /* group attributes */
+       const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
 };
 
 struct mcidev_sysfs_group_kobj {
@@ -336,7 +338,7 @@ struct mcidev_sysfs_group_kobj {
 
        struct kobject kobj;            /* kobj for the group */
 
-       struct mcidev_sysfs_group *grp; /* group description table */
+       const struct mcidev_sysfs_group *grp;   /* group description table */
        struct mem_ctl_info *mci;       /* the parent */
 };
 
@@ -347,7 +349,7 @@ struct mcidev_sysfs_group_kobj {
 struct mcidev_sysfs_attribute {
        /* It should use either attr or grp */
        struct attribute attr;
-       struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
+       const struct mcidev_sysfs_group *grp;   /* Points to a group of attributes */
 
        /* Ops for show/store values at the attribute - not used on group */
         ssize_t (*show)(struct mem_ctl_info *,char *);
@@ -440,7 +442,7 @@ struct mem_ctl_info {
         * If attributes are desired, then set to array of attributes
         * If no attributes are desired, leave NULL
         */
-       struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
+       const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
 
        /* work struct for this MC */
        struct delayed_work work;
@@ -810,6 +812,7 @@ extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
 extern int edac_mc_add_mc(struct mem_ctl_info *mci);
 extern void edac_mc_free(struct mem_ctl_info *mci);
 extern struct mem_ctl_info *edac_mc_find(int idx);
+extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);
 extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev);
 extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
                                      unsigned long page);
index 6b21e25..ba6586a 100644 (file)
@@ -207,6 +207,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
        }
 
        mci->op_state = OP_ALLOC;
+       INIT_LIST_HEAD(&mci->grp_kobj_list);
 
        /*
         * Initialize the 'root' kobj for the edac_mc controller
@@ -234,18 +235,24 @@ EXPORT_SYMBOL_GPL(edac_mc_alloc);
  */
 void edac_mc_free(struct mem_ctl_info *mci)
 {
+       debugf1("%s()\n", __func__);
+
        edac_mc_unregister_sysfs_main_kobj(mci);
+
+       /* free the mci instance memory here */
+       kfree(mci);
 }
 EXPORT_SYMBOL_GPL(edac_mc_free);
 
 
-/*
+/**
  * find_mci_by_dev
  *
  *     scan list of controllers looking for the one that manages
  *     the 'dev' device
+ * @dev: pointer to a struct device related with the MCI
  */
-static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
+struct mem_ctl_info *find_mci_by_dev(struct device *dev)
 {
        struct mem_ctl_info *mci;
        struct list_head *item;
@@ -261,6 +268,7 @@ static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
 
        return NULL;
 }
+EXPORT_SYMBOL_GPL(find_mci_by_dev);
 
 /*
  * handler for EDAC to check if NMI type handler has asserted interrupt
index a413586..dce61f7 100644 (file)
@@ -631,9 +631,6 @@ static void edac_mci_control_release(struct kobject *kobj)
 
        /* decrement the module ref count */
        module_put(mci->owner);
-
-       /* free the mci instance memory here */
-       kfree(mci);
 }
 
 static struct kobj_type ktype_mci = {
@@ -713,6 +710,8 @@ fail_out:
  */
 void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
 {
+       debugf1("%s()\n", __func__);
+
        /* delete the kobj from the mc_kset */
        kobject_put(&mci->edac_mci_kobj);
 }
@@ -760,8 +759,6 @@ static void edac_inst_grp_release(struct kobject *kobj)
 
        grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
        mci = grp->mci;
-
-       kobject_put(&mci->edac_mci_kobj);
 }
 
 /* Intermediate show/store table */
@@ -784,7 +781,7 @@ static struct kobj_type ktype_inst_grp = {
  * object tree.
  */
 static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
-                               struct mcidev_sysfs_attribute *sysfs_attrib,
+                               const struct mcidev_sysfs_attribute *sysfs_attrib,
                                struct kobject *kobj)
 {
        int err;
@@ -792,6 +789,7 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
        debugf1("%s()\n", __func__);
 
        while (sysfs_attrib) {
+               debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
                if (sysfs_attrib->grp) {
                        struct mcidev_sysfs_group_kobj *grp_kobj;
 
@@ -799,10 +797,9 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
                        if (!grp_kobj)
                                return -ENOMEM;
 
-                       list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
-
                        grp_kobj->grp = sysfs_attrib->grp;
                        grp_kobj->mci = mci;
+                       list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
 
                        debugf0("%s() grp %s, mci %p\n", __func__,
                                sysfs_attrib->grp->name, mci);
@@ -811,26 +808,28 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
                                                &ktype_inst_grp,
                                                &mci->edac_mci_kobj,
                                                sysfs_attrib->grp->name);
-                       if (err)
+                       if (err < 0) {
+                               printk(KERN_ERR "kobject_init_and_add failed: %d\n", err);
                                return err;
-
+                       }
                        err = edac_create_mci_instance_attributes(mci,
                                        grp_kobj->grp->mcidev_attr,
                                        &grp_kobj->kobj);
 
-                       if (err)
+                       if (err < 0)
                                return err;
                } else if (sysfs_attrib->attr.name) {
                        debugf0("%s() file %s\n", __func__,
                                sysfs_attrib->attr.name);
 
                        err = sysfs_create_file(kobj, &sysfs_attrib->attr);
+                       if (err < 0) {
+                               printk(KERN_ERR "sysfs_create_file failed: %d\n", err);
+                               return err;
+                       }
                } else
                        break;
 
-               if (err) {
-                       return err;
-               }
                sysfs_attrib++;
        }
 
@@ -843,7 +842,7 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
  *     directory of this mci instance.
  */
 static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
-                               struct mcidev_sysfs_attribute *sysfs_attrib,
+                               const struct mcidev_sysfs_attribute *sysfs_attrib,
                                struct kobject *kobj, int count)
 {
        struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
@@ -855,13 +854,24 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
         * Remove first all the atributes
         */
        while (sysfs_attrib) {
+               debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
                if (sysfs_attrib->grp) {
-                       list_for_each_entry(grp_kobj, &mci->grp_kobj_list,
-                                           list)
-                               if (grp_kobj->grp == sysfs_attrib->grp)
+                       debugf1("%s() seeking for group %s\n",
+                               __func__, sysfs_attrib->grp->name);
+                       list_for_each_entry(grp_kobj,
+                                           &mci->grp_kobj_list, list) {
+                               debugf1("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
+                               if (grp_kobj->grp == sysfs_attrib->grp) {
                                        edac_remove_mci_instance_attributes(mci,
                                                    grp_kobj->grp->mcidev_attr,
                                                    &grp_kobj->kobj, count + 1);
+                                       debugf0("%s() group %s\n", __func__,
+                                               sysfs_attrib->grp->name);
+                                       kobject_put(&grp_kobj->kobj);
+                               }
+                       }
+                       debugf1("%s() end of seeking for group %s\n",
+                               __func__, sysfs_attrib->grp->name);
                } else if (sysfs_attrib->attr.name) {
                        debugf0("%s() file %s\n", __func__,
                                sysfs_attrib->attr.name);
@@ -871,15 +881,14 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
                sysfs_attrib++;
        }
 
-       /*
-        * Now that all attributes got removed, it is save to remove all groups
-        */
-       if (!count)
-               list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list,
-                                        list) {
-                       debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name);
-                       kobject_put(&grp_kobj->kobj);
-               }
+       /* Remove the group objects */
+       if (count)
+               return;
+       list_for_each_entry_safe(grp_kobj, tmp,
+                                &mci->grp_kobj_list, list) {
+               list_del(&grp_kobj->list);
+               kfree(grp_kobj);
+       }
 }
 
 
@@ -971,6 +980,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
        debugf0("%s()\n", __func__);
 
        /* remove all csrow kobjects */
+       debugf0("%s()  unregister this mci kobj\n", __func__);
        for (i = 0; i < mci->nr_csrows; i++) {
                if (mci->csrows[i].nr_pages > 0) {
                        debugf0("%s()  unreg csrow-%d\n", __func__, i);
@@ -978,20 +988,20 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
                }
        }
 
-       debugf0("%s()  remove_link\n", __func__);
+       /* remove this mci instance's attribtes */
+       if (mci->mc_driver_sysfs_attributes) {
+               debugf0("%s()  unregister mci private attributes\n", __func__);
+               edac_remove_mci_instance_attributes(mci,
+                                               mci->mc_driver_sysfs_attributes,
+                                               &mci->edac_mci_kobj, 0);
+       }
 
        /* remove the symlink */
+       debugf0("%s()  remove_link\n", __func__);
        sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
 
-       debugf0("%s()  remove_mci_instance\n", __func__);
-
-       /* remove this mci instance's attribtes */
-       edac_remove_mci_instance_attributes(mci,
-                                           mci->mc_driver_sysfs_attributes,
-                                           &mci->edac_mci_kobj, 0);
-       debugf0("%s()  unregister this mci kobj\n", __func__);
-
        /* unregister this instance's kobject */
+       debugf0("%s()  remove_mci_instance\n", __func__);
        kobject_put(&mci->edac_mci_kobj);
 }
 
index 0fd5b85..362861c 100644 (file)
 
 #include "edac_core.h"
 
+/* Static vars */
+static LIST_HEAD(i7core_edac_list);
+static DEFINE_MUTEX(i7core_edac_lock);
+static int probed;
+
+static int use_pci_fixup;
+module_param(use_pci_fixup, int, 0444);
+MODULE_PARM_DESC(use_pci_fixup, "Enable PCI fixup to seek for hidden devices");
 /*
  * This is used for Nehalem-EP and Nehalem-EX devices, where the non-core
  * registers start at bus 255, and are not reported by BIOS.
@@ -212,8 +220,8 @@ struct pci_id_descr {
 };
 
 struct pci_id_table {
-       struct pci_id_descr     *descr;
-       int                     n_devs;
+       const struct pci_id_descr       *descr;
+       int                             n_devs;
 };
 
 struct i7core_dev {
@@ -235,8 +243,6 @@ struct i7core_pvt {
        struct i7core_inject    inject;
        struct i7core_channel   channel[NUM_CHANS];
 
-       int             channels; /* Number of active channels */
-
        int             ce_count_available;
        int             csrow_map[NUM_CHANS][MAX_DIMMS];
 
@@ -261,22 +267,22 @@ struct i7core_pvt {
 
        /* Count indicator to show errors not got */
        unsigned                mce_overrun;
-};
 
-/* Static vars */
-static LIST_HEAD(i7core_edac_list);
-static DEFINE_MUTEX(i7core_edac_lock);
+       /* Struct to control EDAC polling */
+       struct edac_pci_ctl_info *i7core_pci;
+};
 
 #define PCI_DESCR(device, function, device_id) \
        .dev = (device),                        \
        .func = (function),                     \
        .dev_id = (device_id)
 
-struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
+static const struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
                /* Memory controller */
        { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR)     },
        { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD)  },
-                       /* Exists only for RDIMM */
+
+               /* Exists only for RDIMM */
        { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS), .optional = 1  },
        { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
 
@@ -297,19 +303,9 @@ struct pci_id_descr pci_dev_descr_i7core_nehalem[] = {
        { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
        { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
        { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC)   },
-
-               /* Generic Non-core registers */
-       /*
-        * This is the PCI device on i7core and on Xeon 35xx (8086:2c41)
-        * On Xeon 55xx, however, it has a different id (8086:2c40). So,
-        * the probing code needs to test for the other address in case of
-        * failure of this one
-        */
-       { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE)  },
-
 };
 
-struct pci_id_descr pci_dev_descr_lynnfield[] = {
+static const struct pci_id_descr pci_dev_descr_lynnfield[] = {
        { PCI_DESCR( 3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR)         },
        { PCI_DESCR( 3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD)      },
        { PCI_DESCR( 3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST)     },
@@ -323,15 +319,9 @@ struct pci_id_descr pci_dev_descr_lynnfield[] = {
        { PCI_DESCR( 5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) },
        { PCI_DESCR( 5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) },
        { PCI_DESCR( 5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC)   },
-
-       /*
-        * This is the PCI device has an alternate address on some
-        * processors like Core i7 860
-        */
-       { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE)     },
 };
 
-struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
+static const struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
                /* Memory controller */
        { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2)     },
        { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2)  },
@@ -356,17 +346,14 @@ struct pci_id_descr pci_dev_descr_i7core_westmere[] = {
        { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) },
        { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) },
        { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2)   },
-
-               /* Generic Non-core registers */
-       { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2)  },
-
 };
 
-#define PCI_ID_TABLE_ENTRY(A) { A, ARRAY_SIZE(A) }
-struct pci_id_table pci_dev_table[] = {
+#define PCI_ID_TABLE_ENTRY(A) { .descr=A, .n_devs = ARRAY_SIZE(A) }
+static const struct pci_id_table pci_dev_table[] = {
        PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_nehalem),
        PCI_ID_TABLE_ENTRY(pci_dev_descr_lynnfield),
        PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_westmere),
+       {0,}                    /* 0 terminated list. */
 };
 
 /*
@@ -378,8 +365,6 @@ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
        {0,}                    /* 0 terminated list. */
 };
 
-static struct edac_pci_ctl_info *i7core_pci;
-
 /****************************************************************************
                        Anciliary status routines
  ****************************************************************************/
@@ -442,6 +427,36 @@ static struct i7core_dev *get_i7core_dev(u8 socket)
        return NULL;
 }
 
+static struct i7core_dev *alloc_i7core_dev(u8 socket,
+                                          const struct pci_id_table *table)
+{
+       struct i7core_dev *i7core_dev;
+
+       i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
+       if (!i7core_dev)
+               return NULL;
+
+       i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * table->n_devs,
+                                  GFP_KERNEL);
+       if (!i7core_dev->pdev) {
+               kfree(i7core_dev);
+               return NULL;
+       }
+
+       i7core_dev->socket = socket;
+       i7core_dev->n_devs = table->n_devs;
+       list_add_tail(&i7core_dev->list, &i7core_edac_list);
+
+       return i7core_dev;
+}
+
+static void free_i7core_dev(struct i7core_dev *i7core_dev)
+{
+       list_del(&i7core_dev->list);
+       kfree(i7core_dev->pdev);
+       kfree(i7core_dev);
+}
+
 /****************************************************************************
                        Memory check routines
  ****************************************************************************/
@@ -484,7 +499,7 @@ static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
  * to add a fake description for csrows.
  * So, this driver is attributing one DIMM memory for one csrow.
  */
-static int i7core_get_active_channels(u8 socket, unsigned *channels,
+static int i7core_get_active_channels(const u8 socket, unsigned *channels,
                                      unsigned *csrows)
 {
        struct pci_dev *pdev = NULL;
@@ -545,12 +560,13 @@ static int i7core_get_active_channels(u8 socket, unsigned *channels,
        return 0;
 }
 
-static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
+static int get_dimm_config(const struct mem_ctl_info *mci)
 {
        struct i7core_pvt *pvt = mci->pvt_info;
        struct csrow_info *csr;
        struct pci_dev *pdev;
        int i, j;
+       int csrow = 0;
        unsigned long last_page = 0;
        enum edac_type mode;
        enum mem_type mtype;
@@ -664,13 +680,9 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
                                RANKOFFSET(dimm_dod[j]),
                                banks, ranks, rows, cols);
 
-#if PAGE_SHIFT > 20
-                       npages = size >> (PAGE_SHIFT - 20);
-#else
-                       npages = size << (20 - PAGE_SHIFT);
-#endif
+                       npages = MiB_TO_PAGES(size);
 
-                       csr = &mci->csrows[*csrow];
+                       csr = &mci->csrows[csrow];
                        csr->first_page = last_page + 1;
                        last_page += npages;
                        csr->last_page = last_page;
@@ -678,13 +690,13 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
 
                        csr->page_mask = 0;
                        csr->grain = 8;
-                       csr->csrow_idx = *csrow;
+                       csr->csrow_idx = csrow;
                        csr->nr_channels = 1;
 
                        csr->channels[0].chan_idx = i;
                        csr->channels[0].ce_count = 0;
 
-                       pvt->csrow_map[i][j] = *csrow;
+                       pvt->csrow_map[i][j] = csrow;
 
                        switch (banks) {
                        case 4:
@@ -703,7 +715,7 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
                        csr->edac_mode = mode;
                        csr->mtype = mtype;
 
-                       (*csrow)++;
+                       csrow++;
                }
 
                pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
@@ -736,7 +748,7 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow)
    we're disabling error injection on all write calls to the sysfs nodes that
    controls the error code injection.
  */
-static int disable_inject(struct mem_ctl_info *mci)
+static int disable_inject(const struct mem_ctl_info *mci)
 {
        struct i7core_pvt *pvt = mci->pvt_info;
 
@@ -921,7 +933,7 @@ DECLARE_ADDR_MATCH(bank, 32);
 DECLARE_ADDR_MATCH(page, 0x10000);
 DECLARE_ADDR_MATCH(col, 0x4000);
 
-static int write_and_test(struct pci_dev *dev, int where, u32 val)
+static int write_and_test(struct pci_dev *dev, const int where, const u32 val)
 {
        u32 read;
        int count;
@@ -1120,35 +1132,34 @@ DECLARE_COUNTER(2);
  * Sysfs struct
  */
 
-
-static struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
+static const struct mcidev_sysfs_attribute i7core_addrmatch_attrs[] = {
        ATTR_ADDR_MATCH(channel),
        ATTR_ADDR_MATCH(dimm),
        ATTR_ADDR_MATCH(rank),
        ATTR_ADDR_MATCH(bank),
        ATTR_ADDR_MATCH(page),
        ATTR_ADDR_MATCH(col),
-       { .attr = { .name = NULL } }
+       { } /* End of list */
 };
 
-static struct mcidev_sysfs_group i7core_inject_addrmatch = {
+static const struct mcidev_sysfs_group i7core_inject_addrmatch = {
        .name  = "inject_addrmatch",
        .mcidev_attr = i7core_addrmatch_attrs,
 };
 
-static struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
+static const struct mcidev_sysfs_attribute i7core_udimm_counters_attrs[] = {
        ATTR_COUNTER(0),
        ATTR_COUNTER(1),
        ATTR_COUNTER(2),
        { .attr = { .name = NULL } }
 };
 
-static struct mcidev_sysfs_group i7core_udimm_counters = {
+static const struct mcidev_sysfs_group i7core_udimm_counters = {
        .name  = "all_channel_counts",
        .mcidev_attr = i7core_udimm_counters_attrs,
 };
 
-static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
+static const struct mcidev_sysfs_attribute i7core_sysfs_rdimm_attrs[] = {
        {
                .attr = {
                        .name = "inject_section",
@@ -1180,8 +1191,44 @@ static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
                .show  = i7core_inject_enable_show,
                .store = i7core_inject_enable_store,
        },
-       { .attr = { .name = NULL } },   /* Reserved for udimm counters */
-       { .attr = { .name = NULL } }
+       { }     /* End of list */
+};
+
+static const struct mcidev_sysfs_attribute i7core_sysfs_udimm_attrs[] = {
+       {
+               .attr = {
+                       .name = "inject_section",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_section_show,
+               .store = i7core_inject_section_store,
+       }, {
+               .attr = {
+                       .name = "inject_type",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_type_show,
+               .store = i7core_inject_type_store,
+       }, {
+               .attr = {
+                       .name = "inject_eccmask",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_eccmask_show,
+               .store = i7core_inject_eccmask_store,
+       }, {
+               .grp = &i7core_inject_addrmatch,
+       }, {
+               .attr = {
+                       .name = "inject_enable",
+                       .mode = (S_IRUGO | S_IWUSR)
+               },
+               .show  = i7core_inject_enable_show,
+               .store = i7core_inject_enable_store,
+       }, {
+               .grp = &i7core_udimm_counters,
+       },
+       { }     /* End of list */
 };
 
 /****************************************************************************
@@ -1189,7 +1236,7 @@ static struct mcidev_sysfs_attribute i7core_sysfs_attrs[] = {
  ****************************************************************************/
 
 /*
- *     i7core_put_devices      'put' all the devices that we have
+ *     i7core_put_all_devices  'put' all the devices that we have
  *                             reserved via 'get'
  */
 static void i7core_put_devices(struct i7core_dev *i7core_dev)
@@ -1206,23 +1253,23 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev)
                        PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
                pci_dev_put(pdev);
        }
-       kfree(i7core_dev->pdev);
-       list_del(&i7core_dev->list);
-       kfree(i7core_dev);
 }
 
 static void i7core_put_all_devices(void)
 {
        struct i7core_dev *i7core_dev, *tmp;
 
-       list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list)
+       list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
                i7core_put_devices(i7core_dev);
+               free_i7core_dev(i7core_dev);
+       }
 }
 
-static void __init i7core_xeon_pci_fixup(struct pci_id_table *table)
+static void __init i7core_xeon_pci_fixup(const struct pci_id_table *table)
 {
        struct pci_dev *pdev = NULL;
        int i;
+
        /*
         * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core pci buses
         * aren't announced by acpi. So, we need to use a legacy scan probing
@@ -1257,16 +1304,18 @@ static unsigned i7core_pci_lastbus(void)
 }
 
 /*
- *     i7core_get_devices      Find and perform 'get' operation on the MCH's
+ *     i7core_get_all_devices  Find and perform 'get' operation on the MCH's
  *                     device/functions we want to reference for this driver
  *
  *                     Need to 'get' device 16 func 1 and func 2
  */
-int i7core_get_onedevice(struct pci_dev **prev, int devno,
-                        struct pci_id_descr *dev_descr, unsigned n_devs,
-                        unsigned last_bus)
+static int i7core_get_onedevice(struct pci_dev **prev,
+                               const struct pci_id_table *table,
+                               const unsigned devno,
+                               const unsigned last_bus)
 {
        struct i7core_dev *i7core_dev;
+       const struct pci_id_descr *dev_descr = &table->descr[devno];
 
        struct pci_dev *pdev = NULL;
        u8 bus = 0;
@@ -1275,20 +1324,6 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
        pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                              dev_descr->dev_id, *prev);
 
-       /*
-        * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs
-        * is at addr 8086:2c40, instead of 8086:2c41. So, we need
-        * to probe for the alternate address in case of failure
-        */
-       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev)
-               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                     PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev);
-
-       if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev)
-               pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                     PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT,
-                                     *prev);
-
        if (!pdev) {
                if (*prev) {
                        *prev = pdev;
@@ -1315,18 +1350,11 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
 
        i7core_dev = get_i7core_dev(socket);
        if (!i7core_dev) {
-               i7core_dev = kzalloc(sizeof(*i7core_dev), GFP_KERNEL);
-               if (!i7core_dev)
-                       return -ENOMEM;
-               i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * n_devs,
-                                          GFP_KERNEL);
-               if (!i7core_dev->pdev) {
-                       kfree(i7core_dev);
+               i7core_dev = alloc_i7core_dev(socket, table);
+               if (!i7core_dev) {
+                       pci_dev_put(pdev);
                        return -ENOMEM;
                }
-               i7core_dev->socket = socket;
-               i7core_dev->n_devs = n_devs;
-               list_add_tail(&i7core_dev->list, &i7core_edac_list);
        }
 
        if (i7core_dev->pdev[devno]) {
@@ -1368,27 +1396,31 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno,
                dev_descr->func,
                PCI_VENDOR_ID_INTEL, dev_descr->dev_id);
 
+       /*
+        * As stated on drivers/pci/search.c, the reference count for
+        * @from is always decremented if it is not %NULL. So, as we need
+        * to get all devices up to null, we need to do a get for the device
+        */
+       pci_dev_get(pdev);
+
        *prev = pdev;
 
        return 0;
 }
 
-static int i7core_get_devices(struct pci_id_table *table)
+static int i7core_get_all_devices(void)
 {
        int i, rc, last_bus;
        struct pci_dev *pdev = NULL;
-       struct pci_id_descr *dev_descr;
+       const struct pci_id_table *table = pci_dev_table;
 
        last_bus = i7core_pci_lastbus();
 
        while (table && table->descr) {
-               dev_descr = table->descr;
                for (i = 0; i < table->n_devs; i++) {
                        pdev = NULL;
                        do {
-                               rc = i7core_get_onedevice(&pdev, i,
-                                                         &dev_descr[i],
-                                                         table->n_devs,
+                               rc = i7core_get_onedevice(&pdev, table, i,
                                                          last_bus);
                                if (rc < 0) {
                                        if (i == 0) {
@@ -1404,7 +1436,6 @@ static int i7core_get_devices(struct pci_id_table *table)
        }
 
        return 0;
-       return 0;
 }
 
 static int mci_bind_devs(struct mem_ctl_info *mci,
@@ -1414,10 +1445,6 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
        struct pci_dev *pdev;
        int i, func, slot;
 
-       /* Associates i7core_dev and mci for future usage */
-       pvt->i7core_dev = i7core_dev;
-       i7core_dev->mci = mci;
-
        pvt->is_registered = 0;
        for (i = 0; i < i7core_dev->n_devs; i++) {
                pdev = i7core_dev->pdev[i];
@@ -1448,15 +1475,6 @@ static int mci_bind_devs(struct mem_ctl_info *mci,
                        pvt->is_registered = 1;
        }
 
-       /*
-        * Add extra nodes to count errors on udimm
-        * For registered memory, this is not needed, since the counters
-        * are already displayed at the standard locations
-        */
-       if (!pvt->is_registered)
-               i7core_sysfs_attrs[ARRAY_SIZE(i7core_sysfs_attrs)-2].grp =
-                       &i7core_udimm_counters;
-
        return 0;
 
 error:
@@ -1470,7 +1488,9 @@ error:
                        Error check routines
  ****************************************************************************/
 static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci,
-                                        int chan, int dimm, int add)
+                                     const int chan,
+                                     const int dimm,
+                                     const int add)
 {
        char *msg;
        struct i7core_pvt *pvt = mci->pvt_info;
@@ -1487,7 +1507,10 @@ static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci,
 }
 
 static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci,
-                       int chan, int new0, int new1, int new2)
+                                        const int chan,
+                                        const int new0,
+                                        const int new1,
+                                        const int new2)
 {
        struct i7core_pvt *pvt = mci->pvt_info;
        int add0 = 0, add1 = 0, add2 = 0;
@@ -1641,7 +1664,7 @@ static void i7core_udimm_check_mc_ecc_err(struct mem_ctl_info *mci)
  * fields
  */
 static void i7core_mce_output_error(struct mem_ctl_info *mci,
-                                   struct mce *m)
+                                   const struct mce *m)
 {
        struct i7core_pvt *pvt = mci->pvt_info;
        char *type, *optype, *err, *msg;
@@ -1845,28 +1868,85 @@ static int i7core_mce_check_error(void *priv, struct mce *mce)
        return 1;
 }
 
-static int i7core_register_mci(struct i7core_dev *i7core_dev,
-                              int num_channels, int num_csrows)
+static void i7core_pci_ctl_create(struct i7core_pvt *pvt)
+{
+       pvt->i7core_pci = edac_pci_create_generic_ctl(
+                                               &pvt->i7core_dev->pdev[0]->dev,
+                                               EDAC_MOD_STR);
+       if (unlikely(!pvt->i7core_pci))
+               pr_warn("Unable to setup PCI error report via EDAC\n");
+}
+
+static void i7core_pci_ctl_release(struct i7core_pvt *pvt)
+{
+       if (likely(pvt->i7core_pci))
+               edac_pci_release_generic_ctl(pvt->i7core_pci);
+       else
+               i7core_printk(KERN_ERR,
+                               "Couldn't find mem_ctl_info for socket %d\n",
+                               pvt->i7core_dev->socket);
+       pvt->i7core_pci = NULL;
+}
+
+static void i7core_unregister_mci(struct i7core_dev *i7core_dev)
+{
+       struct mem_ctl_info *mci = i7core_dev->mci;
+       struct i7core_pvt *pvt;
+
+       if (unlikely(!mci || !mci->pvt_info)) {
+               debugf0("MC: " __FILE__ ": %s(): dev = %p\n",
+                       __func__, &i7core_dev->pdev[0]->dev);
+
+               i7core_printk(KERN_ERR, "Couldn't find mci handler\n");
+               return;
+       }
+
+       pvt = mci->pvt_info;
+
+       debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+               __func__, mci, &i7core_dev->pdev[0]->dev);
+
+       /* Disable MCE NMI handler */
+       edac_mce_unregister(&pvt->edac_mce);
+
+       /* Disable EDAC polling */
+       i7core_pci_ctl_release(pvt);
+
+       /* Remove MC sysfs nodes */
+       edac_mc_del_mc(mci->dev);
+
+       debugf1("%s: free mci struct\n", mci->ctl_name);
+       kfree(mci->ctl_name);
+       edac_mc_free(mci);
+       i7core_dev->mci = NULL;
+}
+
+static int i7core_register_mci(struct i7core_dev *i7core_dev)
 {
        struct mem_ctl_info *mci;
        struct i7core_pvt *pvt;
-       int csrow = 0;
-       int rc;
+       int rc, channels, csrows;
+
+       /* Check the number of active and not disabled channels */
+       rc = i7core_get_active_channels(i7core_dev->socket, &channels, &csrows);
+       if (unlikely(rc < 0))
+               return rc;
 
        /* allocate a new MC control structure */
-       mci = edac_mc_alloc(sizeof(*pvt), num_csrows, num_channels,
-                           i7core_dev->socket);
+       mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, i7core_dev->socket);
        if (unlikely(!mci))
                return -ENOMEM;
 
-       debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci);
-
-       /* record ptr to the generic device */
-       mci->dev = &i7core_dev->pdev[0]->dev;
+       debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n",
+               __func__, mci, &i7core_dev->pdev[0]->dev);
 
        pvt = mci->pvt_info;
        memset(pvt, 0, sizeof(*pvt));
 
+       /* Associates i7core_dev and mci for future usage */
+       pvt->i7core_dev = i7core_dev;
+       i7core_dev->mci = mci;
+
        /*
         * FIXME: how to handle RDDR3 at MCI level? It is possible to have
         * Mixed RDDR3/UDDR3 with Nehalem, provided that they are on different
@@ -1881,17 +1961,23 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev,
                                  i7core_dev->socket);
        mci->dev_name = pci_name(i7core_dev->pdev[0]);
        mci->ctl_page_to_phys = NULL;
-       mci->mc_driver_sysfs_attributes = i7core_sysfs_attrs;
-       /* Set the function pointer to an actual operation function */
-       mci->edac_check = i7core_check_error;
 
        /* Store pci devices at mci for faster access */
        rc = mci_bind_devs(mci, i7core_dev);
        if (unlikely(rc < 0))
-               goto fail;
+               goto fail0;
+
+       if (pvt->is_registered)
+               mci->mc_driver_sysfs_attributes = i7core_sysfs_rdimm_attrs;
+       else
+               mci->mc_driver_sysfs_attributes = i7core_sysfs_udimm_attrs;
 
        /* Get dimm basic config */
-       get_dimm_config(mci, &csrow);
+       get_dimm_config(mci);
+       /* record ptr to the generic device */
+       mci->dev = &i7core_dev->pdev[0]->dev;
+       /* Set the function pointer to an actual operation function */
+       mci->edac_check = i7core_check_error;
 
        /* add this new MC control structure to EDAC's list of MCs */
        if (unlikely(edac_mc_add_mc(mci))) {
@@ -1902,19 +1988,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev,
                 */
 
                rc = -EINVAL;
-               goto fail;
-       }
-
-       /* allocating generic PCI control info */
-       i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
-                                                EDAC_MOD_STR);
-       if (unlikely(!i7core_pci)) {
-               printk(KERN_WARNING
-                       "%s(): Unable to create PCI control\n",
-                       __func__);
-               printk(KERN_WARNING
-                       "%s(): PCI error report via EDAC not setup\n",
-                       __func__);
+               goto fail0;
        }
 
        /* Default error mask is any memory */
@@ -1925,19 +1999,28 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev,
        pvt->inject.page = -1;
        pvt->inject.col = -1;
 
+       /* allocating generic PCI control info */
+       i7core_pci_ctl_create(pvt);
+
        /* Registers on edac_mce in order to receive memory errors */
        pvt->edac_mce.priv = mci;
        pvt->edac_mce.check_error = i7core_mce_check_error;
-
        rc = edac_mce_register(&pvt->edac_mce);
        if (unlikely(rc < 0)) {
                debugf0("MC: " __FILE__
                        ": %s(): failed edac_mce_register()\n", __func__);
+               goto fail1;
        }
 
-fail:
-       if (rc < 0)
-               edac_mc_free(mci);
+       return 0;
+
+fail1:
+       i7core_pci_ctl_release(pvt);
+       edac_mc_del_mc(mci->dev);
+fail0:
+       kfree(mci->ctl_name);
+       edac_mc_free(mci);
+       i7core_dev->mci = NULL;
        return rc;
 }
 
@@ -1949,8 +2032,6 @@ fail:
  *             < 0 for error code
  */
 
-static int probed = 0;
-
 static int __devinit i7core_probe(struct pci_dev *pdev,
                                  const struct pci_device_id *id)
 {
@@ -1965,25 +2046,16 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
         */
        if (unlikely(probed >= 1)) {
                mutex_unlock(&i7core_edac_lock);
-               return -EINVAL;
+               return -ENODEV;
        }
        probed++;
 
-       rc = i7core_get_devices(pci_dev_table);
+       rc = i7core_get_all_devices();
        if (unlikely(rc < 0))
                goto fail0;
 
        list_for_each_entry(i7core_dev, &i7core_edac_list, list) {
-               int channels;
-               int csrows;
-
-               /* Check the number of active and not disabled channels */
-               rc = i7core_get_active_channels(i7core_dev->socket,
-                                               &channels, &csrows);
-               if (unlikely(rc < 0))
-                       goto fail1;
-
-               rc = i7core_register_mci(i7core_dev, channels, csrows);
+               rc = i7core_register_mci(i7core_dev);
                if (unlikely(rc < 0))
                        goto fail1;
        }
@@ -1994,6 +2066,9 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
        return 0;
 
 fail1:
+       list_for_each_entry(i7core_dev, &i7core_edac_list, list)
+               i7core_unregister_mci(i7core_dev);
+
        i7core_put_all_devices();
 fail0:
        mutex_unlock(&i7core_edac_lock);
@@ -2006,14 +2081,10 @@ fail0:
  */
 static void __devexit i7core_remove(struct pci_dev *pdev)
 {
-       struct mem_ctl_info *mci;
-       struct i7core_dev *i7core_dev, *tmp;
+       struct i7core_dev *i7core_dev;
 
        debugf0(__FILE__ ": %s()\n", __func__);
 
-       if (i7core_pci)
-               edac_pci_release_generic_ctl(i7core_pci);
-
        /*
         * we have a trouble here: pdev value for removal will be wrong, since
         * it will point to the X58 register used to detect that the machine
@@ -2023,22 +2094,18 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
         */
 
        mutex_lock(&i7core_edac_lock);
-       list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
-               mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
-               if (mci) {
-                       struct i7core_pvt *pvt = mci->pvt_info;
-
-                       i7core_dev = pvt->i7core_dev;
-                       edac_mce_unregister(&pvt->edac_mce);
-                       kfree(mci->ctl_name);
-                       edac_mc_free(mci);
-                       i7core_put_devices(i7core_dev);
-               } else {
-                       i7core_printk(KERN_ERR,
-                                     "Couldn't find mci for socket %d\n",
-                                     i7core_dev->socket);
-               }
+
+       if (unlikely(!probed)) {
+               mutex_unlock(&i7core_edac_lock);
+               return;
        }
+
+       list_for_each_entry(i7core_dev, &i7core_edac_list, list)
+               i7core_unregister_mci(i7core_dev);
+
+       /* Release PCI resources */
+       i7core_put_all_devices();
+
        probed--;
 
        mutex_unlock(&i7core_edac_lock);
@@ -2070,7 +2137,8 @@ static int __init i7core_init(void)
        /* Ensure that the OPSTATE is set correctly for POLL or NMI */
        opstate_init();
 
-       i7core_xeon_pci_fixup(pci_dev_table);
+       if (use_pci_fixup)
+               i7core_xeon_pci_fixup(pci_dev_table);
 
        pci_rc = pci_register_driver(&i7core_driver);
 
index a2b12aa..5018666 100644 (file)
@@ -345,7 +345,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
 
        do {
                level = __ffs(pending);
-               handle_nested_irq(level + chip->irq_base);
+               generic_handle_irq(level + chip->irq_base);
 
                pending &= ~(1 << level);
        } while (pending);
@@ -360,7 +360,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
        struct pca953x_platform_data *pdata = client->dev.platform_data;
        int ret;
 
-       if (pdata->irq_base && (id->driver_data & PCA953X_INT)) {
+       if (pdata->irq_base != -1
+                       && (id->driver_data & PCA953X_INT)) {
                int lvl;
 
                ret = pca953x_read_reg(chip, PCA953X_INPUT,
@@ -383,7 +384,6 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
                        set_irq_chip_data(irq, chip);
                        set_irq_chip_and_handler(irq, &pca953x_irq_chip,
                                                 handle_edge_irq);
-                       set_irq_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
                        set_irq_flags(irq, IRQF_VALID);
 #else
@@ -394,6 +394,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
                ret = request_threaded_irq(client->irq,
                                           NULL,
                                           pca953x_irq_handler,
+                                          IRQF_TRIGGER_RISING |
                                           IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                           dev_name(&client->dev), chip);
                if (ret) {
@@ -408,13 +409,13 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
        return 0;
 
 out_failed:
-       chip->irq_base = 0;
+       chip->irq_base = -1;
        return ret;
 }
 
 static void pca953x_irq_teardown(struct pca953x_chip *chip)
 {
-       if (chip->irq_base)
+       if (chip->irq_base != -1)
                free_irq(chip->client->irq, chip);
 }
 #else /* CONFIG_GPIO_PCA953X_IRQ */
@@ -424,7 +425,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
        struct i2c_client *client = chip->client;
        struct pca953x_platform_data *pdata = client->dev.platform_data;
 
-       if (pdata->irq_base && (id->driver_data & PCA953X_INT))
+       if (pdata->irq_base != -1 && (id->driver_data & PCA953X_INT))
                dev_warn(&client->dev, "interrupt support not compiled in\n");
 
        return 0;
index 90b1d67..eb6c473 100644 (file)
@@ -155,11 +155,11 @@ fast_shmem_read(struct page **pages,
        char __iomem *vaddr;
        int unwritten;
 
-       vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
+       vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
        if (vaddr == NULL)
                return -ENOMEM;
        unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length);
-       kunmap_atomic(vaddr, KM_USER0);
+       kunmap_atomic(vaddr);
 
        if (unwritten)
                return -EFAULT;
@@ -509,10 +509,10 @@ fast_user_write(struct io_mapping *mapping,
        char *vaddr_atomic;
        unsigned long unwritten;
 
-       vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base, KM_USER0);
+       vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
        unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
                                                      user_data, length);
-       io_mapping_unmap_atomic(vaddr_atomic, KM_USER0);
+       io_mapping_unmap_atomic(vaddr_atomic);
        if (unwritten)
                return -EFAULT;
        return 0;
@@ -551,11 +551,11 @@ fast_shmem_write(struct page **pages,
        char __iomem *vaddr;
        unsigned long unwritten;
 
-       vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
+       vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]);
        if (vaddr == NULL)
                return -ENOMEM;
        unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length);
-       kunmap_atomic(vaddr, KM_USER0);
+       kunmap_atomic(vaddr);
 
        if (unwritten)
                return -EFAULT;
@@ -3346,8 +3346,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                reloc_offset = obj_priv->gtt_offset + reloc->offset;
                reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
                                                      (reloc_offset &
-                                                      ~(PAGE_SIZE - 1)),
-                                                     KM_USER0);
+                                                      ~(PAGE_SIZE - 1)));
                reloc_entry = (uint32_t __iomem *)(reloc_page +
                                                   (reloc_offset & (PAGE_SIZE - 1)));
                reloc_val = target_obj_priv->gtt_offset + reloc->delta;
@@ -3358,7 +3357,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
                          readl(reloc_entry), reloc_val);
 #endif
                writel(reloc_val, reloc_entry);
-               io_mapping_unmap_atomic(reloc_page, KM_USER0);
+               io_mapping_unmap_atomic(reloc_page);
 
                /* The updated presumed offset for this entry will be
                 * copied back out to the user.
@@ -4772,11 +4771,11 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
        page_count = obj->size / PAGE_SIZE;
 
        for (i = 0; i < page_count; i++) {
-               char *dst = kmap_atomic(obj_priv->pages[i], KM_USER0);
+               char *dst = kmap_atomic(obj_priv->pages[i]);
                char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
 
                memcpy(dst, src, PAGE_SIZE);
-               kunmap_atomic(dst, KM_USER0);
+               kunmap_atomic(dst);
        }
        drm_clflush_pages(obj_priv->pages, page_count);
        drm_agp_chipset_flush(dev);
@@ -4833,11 +4832,11 @@ i915_gem_attach_phys_object(struct drm_device *dev,
        page_count = obj->size / PAGE_SIZE;
 
        for (i = 0; i < page_count; i++) {
-               char *src = kmap_atomic(obj_priv->pages[i], KM_USER0);
+               char *src = kmap_atomic(obj_priv->pages[i]);
                char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
 
                memcpy(dst, src, PAGE_SIZE);
-               kunmap_atomic(src, KM_USER0);
+               kunmap_atomic(src);
        }
 
        i915_gem_object_put_pages(obj);
index 744225e..b80010f 100644 (file)
@@ -456,10 +456,9 @@ i915_error_object_create(struct drm_device *dev,
 
                local_irq_save(flags);
                s = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
-                                            reloc_offset,
-                                            KM_IRQ0);
+                                            reloc_offset);
                memcpy_fromio(d, s, PAGE_SIZE);
-               io_mapping_unmap_atomic(s, KM_IRQ0);
+               io_mapping_unmap_atomic(s);
                local_irq_restore(flags);
 
                dst->pages[page] = d;
index 1d306a4..3264bbd 100644 (file)
@@ -187,8 +187,7 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
 
        if (OVERLAY_NONPHYSICAL(overlay->dev)) {
                regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
-                                               overlay->reg_bo->gtt_offset,
-                                               KM_USER0);
+                                               overlay->reg_bo->gtt_offset);
 
                if (!regs) {
                        DRM_ERROR("failed to map overlay regs in GTT\n");
@@ -203,7 +202,7 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
 static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
 {
        if (OVERLAY_NONPHYSICAL(overlay->dev))
-               io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0);
+               io_mapping_unmap_atomic(overlay->virt_addr);
 
        overlay->virt_addr = NULL;
 
index 974b0f8..8fa3396 100644 (file)
@@ -2167,11 +2167,11 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb,
 
        if (off < pci_resource_len(dev->pdev, 1)) {
                uint8_t __iomem *p =
-                       io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
+                       io_mapping_map_atomic_wc(fb, off & PAGE_MASK);
 
                val = ioread32(p + (off & ~PAGE_MASK));
 
-               io_mapping_unmap_atomic(p, KM_USER0);
+               io_mapping_unmap_atomic(p);
        }
 
        return val;
@@ -2183,12 +2183,12 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb,
 {
        if (off < pci_resource_len(dev->pdev, 1)) {
                uint8_t __iomem *p =
-                       io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);
+                       io_mapping_map_atomic_wc(fb, off & PAGE_MASK);
 
                iowrite32(val, p + (off & ~PAGE_MASK));
                wmb();
 
-               io_mapping_unmap_atomic(p, KM_USER0);
+               io_mapping_unmap_atomic(p);
        }
 }
 
index 3451a82..e8a73e6 100644 (file)
@@ -170,7 +170,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
        src = (void *)((unsigned long)src + (page << PAGE_SHIFT));
 
 #ifdef CONFIG_X86
-       dst = kmap_atomic_prot(d, KM_USER0, prot);
+       dst = kmap_atomic_prot(d, prot);
 #else
        if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
                dst = vmap(&d, 1, 0, prot);
@@ -183,7 +183,7 @@ static int ttm_copy_io_ttm_page(struct ttm_tt *ttm, void *src,
        memcpy_fromio(dst, src, PAGE_SIZE);
 
 #ifdef CONFIG_X86
-       kunmap_atomic(dst, KM_USER0);
+       kunmap_atomic(dst);
 #else
        if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
                vunmap(dst);
@@ -206,7 +206,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
 
        dst = (void *)((unsigned long)dst + (page << PAGE_SHIFT));
 #ifdef CONFIG_X86
-       src = kmap_atomic_prot(s, KM_USER0, prot);
+       src = kmap_atomic_prot(s, prot);
 #else
        if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
                src = vmap(&s, 1, 0, prot);
@@ -219,7 +219,7 @@ static int ttm_copy_ttm_io_page(struct ttm_tt *ttm, void *dst,
        memcpy_toio(dst, src, PAGE_SIZE);
 
 #ifdef CONFIG_X86
-       kunmap_atomic(src, KM_USER0);
+       kunmap_atomic(src);
 #else
        if (pgprot_val(prot) != pgprot_val(PAGE_KERNEL))
                vunmap(src);
index e382da3..c357c83 100644 (file)
@@ -399,6 +399,15 @@ config SENSORS_GL520SM
          This driver can also be built as a module.  If so, the module
          will be called gl520sm.
 
+config SENSORS_GPIO_FAN
+       tristate "GPIO fan"
+       depends on GENERIC_GPIO
+       help
+         If you say yes here you get support for fans connected to GPIO lines.
+
+         This driver can also be built as a module.  If so, the module
+         will be called gpio-fan.
+
 config SENSORS_CORETEMP
        tristate "Intel Core/Core2/Atom temperature sensor"
        depends on X86 && PCI && EXPERIMENTAL
@@ -654,6 +663,17 @@ config SENSORS_LTC4245
          This driver can also be built as a module. If so, the module will
          be called ltc4245.
 
+config SENSORS_LTC4261
+       tristate "Linear Technology LTC4261"
+       depends on I2C && EXPERIMENTAL
+       default n
+       help
+         If you say yes here you get support for Linear Technology LTC4261
+         Negative Voltage Hot Swap Controller I2C interface.
+
+         This driver can also be built as a module. If so, the module will
+         be called ltc4261.
+
 config SENSORS_LM95241
        tristate "National Semiconductor LM95241 sensor chip"
        depends on I2C
index ec9cb73..d30f0f6 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_SENSORS_FSCHMD)  += fschmd.o
 obj-$(CONFIG_SENSORS_G760A)    += g760a.o
 obj-$(CONFIG_SENSORS_GL518SM)  += gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)  += gl520sm.o
+obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
 obj-$(CONFIG_SENSORS_ULTRA45)  += ultra45_env.o
 obj-$(CONFIG_SENSORS_I5K_AMB)  += i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)   += ibmaem.o
@@ -79,6 +80,7 @@ obj-$(CONFIG_SENSORS_LM93)    += lm93.o
 obj-$(CONFIG_SENSORS_LM95241)  += lm95241.o
 obj-$(CONFIG_SENSORS_LTC4215)  += ltc4215.o
 obj-$(CONFIG_SENSORS_LTC4245)  += ltc4245.o
+obj-$(CONFIG_SENSORS_LTC4261)  += ltc4261.o
 obj-$(CONFIG_SENSORS_MAX1111)  += max1111.o
 obj-$(CONFIG_SENSORS_MAX1619)  += max1619.o
 obj-$(CONFIG_SENSORS_MAX6650)  += max6650.o
index a23b17a..42de98d 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -280,11 +279,9 @@ static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
        case 0x1a:
                dev_warn(dev, "TjMax is assumed as 100 C!\n");
                return 100000;
-               break;
        case 0x17:
        case 0x1c:              /* Atom CPUs */
                return adjust_tjmax(c, id, dev);
-               break;
        default:
                dev_warn(dev, "CPU (model=0x%x) is not supported yet,"
                        " using default TjMax of 100C.\n", c->x86_model);
@@ -292,6 +289,15 @@ static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
        }
 }
 
+static void __devinit get_ucode_rev_on_cpu(void *edx)
+{
+       u32 eax;
+
+       wrmsr(MSR_IA32_UCODE_REV, 0, 0);
+       sync_core();
+       rdmsr(MSR_IA32_UCODE_REV, eax, *(u32 *)edx);
+}
+
 static int __devinit coretemp_probe(struct platform_device *pdev)
 {
        struct coretemp_data *data;
@@ -327,8 +333,15 @@ static int __devinit coretemp_probe(struct platform_device *pdev)
 
        if ((c->x86_model == 0xe) && (c->x86_mask < 0xc)) {
                /* check for microcode update */
-               rdmsr_on_cpu(data->id, MSR_IA32_UCODE_REV, &eax, &edx);
-               if (edx < 0x39) {
+               err = smp_call_function_single(data->id, get_ucode_rev_on_cpu,
+                                              &edx, 1);
+               if (err) {
+                       dev_err(&pdev->dev,
+                               "Cannot determine microcode revision of "
+                               "CPU#%u (%d)!\n", data->id, err);
+                       err = -ENODEV;
+                       goto exit_free;
+               } else if (edx < 0x39) {
                        err = -ENODEV;
                        dev_err(&pdev->dev,
                                "Errata AE18 not fixed, update BIOS or "
@@ -490,7 +503,7 @@ exit:
        return err;
 }
 
-static void coretemp_device_remove(unsigned int cpu)
+static void __cpuinit coretemp_device_remove(unsigned int cpu)
 {
        struct pdev_entry *p;
        unsigned int i;
@@ -569,9 +582,8 @@ exit:
 static void __exit coretemp_exit(void)
 {
        struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
        unregister_hotcpu_notifier(&coretemp_cpu_notifier);
-#endif
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
                platform_device_unregister(p->pdev);
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
new file mode 100644 (file)
index 0000000..aa701a1
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * gpio-fan.c - Hwmon driver for fans connected to GPIO lines.
+ *
+ * Copyright (C) 2010 LaCie
+ *
+ * Author: Simon Guinot <sguinot@lacie.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/hwmon.h>
+#include <linux/gpio.h>
+#include <linux/gpio-fan.h>
+
+struct gpio_fan_data {
+       struct platform_device  *pdev;
+       struct device           *hwmon_dev;
+       struct mutex            lock; /* lock GPIOs operations. */
+       int                     num_ctrl;
+       unsigned                *ctrl;
+       int                     num_speed;
+       struct gpio_fan_speed   *speed;
+       int                     speed_index;
+#ifdef CONFIG_PM
+       int                     resume_speed;
+#endif
+       bool                    pwm_enable;
+       struct gpio_fan_alarm   *alarm;
+       struct work_struct      alarm_work;
+};
+
+/*
+ * Alarm GPIO.
+ */
+
+static void fan_alarm_notify(struct work_struct *ws)
+{
+       struct gpio_fan_data *fan_data =
+               container_of(ws, struct gpio_fan_data, alarm_work);
+
+       sysfs_notify(&fan_data->pdev->dev.kobj, NULL, "fan1_alarm");
+       kobject_uevent(&fan_data->pdev->dev.kobj, KOBJ_CHANGE);
+}
+
+static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id)
+{
+       struct gpio_fan_data *fan_data = dev_id;
+
+       schedule_work(&fan_data->alarm_work);
+
+       return IRQ_NONE;
+}
+
+static ssize_t show_fan_alarm(struct device *dev,
+                             struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       struct gpio_fan_alarm *alarm = fan_data->alarm;
+       int value = gpio_get_value(alarm->gpio);
+
+       if (alarm->active_low)
+               value = !value;
+
+       return sprintf(buf, "%d\n", value);
+}
+
+static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL);
+
+static int fan_alarm_init(struct gpio_fan_data *fan_data,
+                         struct gpio_fan_alarm *alarm)
+{
+       int err;
+       int alarm_irq;
+       struct platform_device *pdev = fan_data->pdev;
+
+       fan_data->alarm = alarm;
+
+       err = gpio_request(alarm->gpio, "GPIO fan alarm");
+       if (err)
+               return err;
+
+       err = gpio_direction_input(alarm->gpio);
+       if (err)
+               goto err_free_gpio;
+
+       err = device_create_file(&pdev->dev, &dev_attr_fan1_alarm);
+       if (err)
+               goto err_free_gpio;
+
+       /*
+        * If the alarm GPIO don't support interrupts, just leave
+        * without initializing the fail notification support.
+        */
+       alarm_irq = gpio_to_irq(alarm->gpio);
+       if (alarm_irq < 0)
+               return 0;
+
+       INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
+       set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
+       err = request_irq(alarm_irq, fan_alarm_irq_handler, IRQF_SHARED,
+                         "GPIO fan alarm", fan_data);
+       if (err)
+               goto err_free_sysfs;
+
+       return 0;
+
+err_free_sysfs:
+       device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
+err_free_gpio:
+       gpio_free(alarm->gpio);
+
+       return err;
+}
+
+static void fan_alarm_free(struct gpio_fan_data *fan_data)
+{
+       struct platform_device *pdev = fan_data->pdev;
+       int alarm_irq = gpio_to_irq(fan_data->alarm->gpio);
+
+       if (alarm_irq >= 0)
+               free_irq(alarm_irq, fan_data);
+       device_remove_file(&pdev->dev, &dev_attr_fan1_alarm);
+       gpio_free(fan_data->alarm->gpio);
+}
+
+/*
+ * Control GPIOs.
+ */
+
+/* Must be called with fan_data->lock held, except during initialization. */
+static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
+{
+       int i;
+
+       for (i = 0; i < fan_data->num_ctrl; i++)
+               gpio_set_value(fan_data->ctrl[i], (ctrl_val >> i) & 1);
+}
+
+static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
+{
+       int i;
+       int ctrl_val = 0;
+
+       for (i = 0; i < fan_data->num_ctrl; i++) {
+               int value;
+
+               value = gpio_get_value(fan_data->ctrl[i]);
+               ctrl_val |= (value << i);
+       }
+       return ctrl_val;
+}
+
+/* Must be called with fan_data->lock held, except during initialization. */
+static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)
+{
+       if (fan_data->speed_index == speed_index)
+               return;
+
+       __set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);
+       fan_data->speed_index = speed_index;
+}
+
+static int get_fan_speed_index(struct gpio_fan_data *fan_data)
+{
+       int ctrl_val = __get_fan_ctrl(fan_data);
+       int i;
+
+       for (i = 0; i < fan_data->num_speed; i++)
+               if (fan_data->speed[i].ctrl_val == ctrl_val)
+                       return i;
+
+       dev_warn(&fan_data->pdev->dev,
+                "missing speed array entry for GPIO value 0x%x\n", ctrl_val);
+
+       return -EINVAL;
+}
+
+static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm)
+{
+       struct gpio_fan_speed *speed = fan_data->speed;
+       int i;
+
+       for (i = 0; i < fan_data->num_speed; i++)
+               if (speed[i].rpm >= rpm)
+                       return i;
+
+       return fan_data->num_speed - 1;
+}
+
+static ssize_t show_pwm(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       u8 pwm = fan_data->speed_index * 255 / (fan_data->num_speed - 1);
+
+       return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       unsigned long pwm;
+       int speed_index;
+       int ret = count;
+
+       if (strict_strtoul(buf, 10, &pwm) || pwm > 255)
+               return -EINVAL;
+
+       mutex_lock(&fan_data->lock);
+
+       if (!fan_data->pwm_enable) {
+               ret = -EPERM;
+               goto exit_unlock;
+       }
+
+       speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255);
+       set_fan_speed(fan_data, speed_index);
+
+exit_unlock:
+       mutex_unlock(&fan_data->lock);
+
+       return ret;
+}
+
+static ssize_t show_pwm_enable(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", fan_data->pwm_enable);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr,
+                             const char *buf, size_t count)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) || val > 1)
+               return -EINVAL;
+
+       if (fan_data->pwm_enable == val)
+               return count;
+
+       mutex_lock(&fan_data->lock);
+
+       fan_data->pwm_enable = val;
+
+       /* Disable manual control mode: set fan at full speed. */
+       if (val == 0)
+               set_fan_speed(fan_data, fan_data->num_speed - 1);
+
+       mutex_unlock(&fan_data->lock);
+
+       return count;
+}
+
+static ssize_t show_pwm_mode(struct device *dev,
+                            struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "0\n");
+}
+
+static ssize_t show_rpm_min(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", fan_data->speed[0].rpm);
+}
+
+static ssize_t show_rpm_max(struct device *dev,
+                           struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n",
+                      fan_data->speed[fan_data->num_speed - 1].rpm);
+}
+
+static ssize_t show_rpm(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%d\n", fan_data->speed[fan_data->speed_index].rpm);
+}
+
+static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
+       unsigned long rpm;
+       int ret = count;
+
+       if (strict_strtoul(buf, 10, &rpm))
+               return -EINVAL;
+
+       mutex_lock(&fan_data->lock);
+
+       if (!fan_data->pwm_enable) {
+               ret = -EPERM;
+               goto exit_unlock;
+       }
+
+       set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));
+
+exit_unlock:
+       mutex_unlock(&fan_data->lock);
+
+       return ret;
+}
+
+static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
+static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+                  show_pwm_enable, set_pwm_enable);
+static DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL);
+static DEVICE_ATTR(fan1_min, S_IRUGO, show_rpm_min, NULL);
+static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL);
+static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL);
+static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm);
+
+static struct attribute *gpio_fan_ctrl_attributes[] = {
+       &dev_attr_pwm1.attr,
+       &dev_attr_pwm1_enable.attr,
+       &dev_attr_pwm1_mode.attr,
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan1_target.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan1_max.attr,
+       NULL
+};
+
+static const struct attribute_group gpio_fan_ctrl_group = {
+       .attrs = gpio_fan_ctrl_attributes,
+};
+
+static int fan_ctrl_init(struct gpio_fan_data *fan_data,
+                        struct gpio_fan_platform_data *pdata)
+{
+       struct platform_device *pdev = fan_data->pdev;
+       int num_ctrl = pdata->num_ctrl;
+       unsigned *ctrl = pdata->ctrl;
+       int i, err;
+
+       for (i = 0; i < num_ctrl; i++) {
+               err = gpio_request(ctrl[i], "GPIO fan control");
+               if (err)
+                       goto err_free_gpio;
+
+               err = gpio_direction_output(ctrl[i], gpio_get_value(ctrl[i]));
+               if (err) {
+                       gpio_free(ctrl[i]);
+                       goto err_free_gpio;
+               }
+       }
+
+       err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
+       if (err)
+               goto err_free_gpio;
+
+       fan_data->num_ctrl = num_ctrl;
+       fan_data->ctrl = ctrl;
+       fan_data->num_speed = pdata->num_speed;
+       fan_data->speed = pdata->speed;
+       fan_data->pwm_enable = true; /* Enable manual fan speed control. */
+       fan_data->speed_index = get_fan_speed_index(fan_data);
+       if (fan_data->speed_index < 0) {
+               err = -ENODEV;
+               goto err_free_gpio;
+       }
+
+       return 0;
+
+err_free_gpio:
+       for (i = i - 1; i >= 0; i--)
+               gpio_free(ctrl[i]);
+
+       return err;
+}
+
+static void fan_ctrl_free(struct gpio_fan_data *fan_data)
+{
+       struct platform_device *pdev = fan_data->pdev;
+       int i;
+
+       sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_ctrl_group);
+       for (i = 0; i < fan_data->num_ctrl; i++)
+               gpio_free(fan_data->ctrl[i]);
+}
+
+/*
+ * Platform driver.
+ */
+
+static ssize_t show_name(struct device *dev,
+                        struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "gpio-fan\n");
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static int __devinit gpio_fan_probe(struct platform_device *pdev)
+{
+       int err;
+       struct gpio_fan_data *fan_data;
+       struct gpio_fan_platform_data *pdata = pdev->dev.platform_data;
+
+       if (!pdata)
+               return -EINVAL;
+
+       fan_data = kzalloc(sizeof(struct gpio_fan_data), GFP_KERNEL);
+       if (!fan_data)
+               return -ENOMEM;
+
+       fan_data->pdev = pdev;
+       platform_set_drvdata(pdev, fan_data);
+       mutex_init(&fan_data->lock);
+
+       /* Configure alarm GPIO if available. */
+       if (pdata->alarm) {
+               err = fan_alarm_init(fan_data, pdata->alarm);
+               if (err)
+                       goto err_free_data;
+       }
+
+       /* Configure control GPIOs if available. */
+       if (pdata->ctrl && pdata->num_ctrl > 0) {
+               if (!pdata->speed || pdata->num_speed <= 1) {
+                       err = -EINVAL;
+                       goto err_free_alarm;
+               }
+               err = fan_ctrl_init(fan_data, pdata);
+               if (err)
+                       goto err_free_alarm;
+       }
+
+       err = device_create_file(&pdev->dev, &dev_attr_name);
+       if (err)
+               goto err_free_ctrl;
+
+       /* Make this driver part of hwmon class. */
+       fan_data->hwmon_dev = hwmon_device_register(&pdev->dev);
+       if (IS_ERR(fan_data->hwmon_dev)) {
+               err = PTR_ERR(fan_data->hwmon_dev);
+               goto err_remove_name;
+       }
+
+       dev_info(&pdev->dev, "GPIO fan initialized\n");
+
+       return 0;
+
+err_remove_name:
+       device_remove_file(&pdev->dev, &dev_attr_name);
+err_free_ctrl:
+       if (fan_data->ctrl)
+               fan_ctrl_free(fan_data);
+err_free_alarm:
+       if (fan_data->alarm)
+               fan_alarm_free(fan_data);
+err_free_data:
+       platform_set_drvdata(pdev, NULL);
+       kfree(fan_data);
+
+       return err;
+}
+
+static int __devexit gpio_fan_remove(struct platform_device *pdev)
+{
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       hwmon_device_unregister(fan_data->hwmon_dev);
+       device_remove_file(&pdev->dev, &dev_attr_name);
+       if (fan_data->alarm)
+               fan_alarm_free(fan_data);
+       if (fan_data->ctrl)
+               fan_ctrl_free(fan_data);
+       kfree(fan_data);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int gpio_fan_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       if (fan_data->ctrl) {
+               fan_data->resume_speed = fan_data->speed_index;
+               set_fan_speed(fan_data, 0);
+       }
+
+       return 0;
+}
+
+static int gpio_fan_resume(struct platform_device *pdev)
+{
+       struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);
+
+       if (fan_data->ctrl)
+               set_fan_speed(fan_data, fan_data->resume_speed);
+
+       return 0;
+}
+#else
+#define gpio_fan_suspend NULL
+#define gpio_fan_resume NULL
+#endif
+
+static struct platform_driver gpio_fan_driver = {
+       .probe          = gpio_fan_probe,
+       .remove         = __devexit_p(gpio_fan_remove),
+       .suspend        = gpio_fan_suspend,
+       .resume         = gpio_fan_resume,
+       .driver = {
+               .name   = "gpio-fan",
+       },
+};
+
+static int __init gpio_fan_init(void)
+{
+       return platform_driver_register(&gpio_fan_driver);
+}
+
+static void __exit gpio_fan_exit(void)
+{
+       platform_driver_unregister(&gpio_fan_driver);
+}
+
+module_init(gpio_fan_init);
+module_exit(gpio_fan_exit);
+
+MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
+MODULE_DESCRIPTION("GPIO FAN driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:gpio-fan");
index 36e9575..a56a784 100644 (file)
@@ -146,7 +146,7 @@ int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
 
 static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
 {
-       lis3_dev.ac = *((struct axis_conversion *)dmi->driver_data);
+       lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
        printk(KERN_INFO DRIVER_NAME ": hardware type %s found.\n", dmi->ident);
 
        return 1;
@@ -154,16 +154,19 @@ static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
 
 /* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
  * If the value is negative, the opposite of the hw value is used. */
-static struct axis_conversion lis3lv02d_axis_normal = {1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_y_inverted = {1, -2, 3};
-static struct axis_conversion lis3lv02d_axis_x_inverted = {-1, 2, 3};
-static struct axis_conversion lis3lv02d_axis_z_inverted = {1, 2, -3};
-static struct axis_conversion lis3lv02d_axis_xy_swap = {2, 1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_left = {-2, 1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_left_usd = {-2, 1, -3};
-static struct axis_conversion lis3lv02d_axis_xy_swap_inverted = {-2, -1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_rotated_right = {2, -1, 3};
-static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
+#define DEFINE_CONV(name, x, y, z)                           \
+       static union axis_conversion lis3lv02d_axis_##name = \
+               { .as_array = { x, y, z } }
+DEFINE_CONV(normal, 1, 2, 3);
+DEFINE_CONV(y_inverted, 1, -2, 3);
+DEFINE_CONV(x_inverted, -1, 2, 3);
+DEFINE_CONV(z_inverted, 1, 2, -3);
+DEFINE_CONV(xy_swap, 2, 1, 3);
+DEFINE_CONV(xy_rotated_left, -2, 1, 3);
+DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
+DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
+DEFINE_CONV(xy_rotated_right, 2, -1, 3);
+DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
 
 #define AXIS_DMI_MATCH(_ident, _name, _axis) {         \
        .ident = _ident,                                \
@@ -222,7 +225,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
        AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
        AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
        AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
-       AXIS_DMI_MATCH("Mini5102", "HP Mini 5102", xy_rotated_left_usd),
+       AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
        { NULL, }
 /* Laptop models without axis info (yet):
  * "NC6910" "HP Compaq 6910"
@@ -299,7 +302,10 @@ static int lis3lv02d_add(struct acpi_device *device)
        lis3lv02d_enum_resources(device);
 
        /* If possible use a "standard" axes order */
-       if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+       if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
+               printk(KERN_INFO DRIVER_NAME ": Using custom axes %d,%d,%d\n",
+                      lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
+       } else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
                printk(KERN_INFO DRIVER_NAME ": laptop model unknown, "
                                 "using default axes configuration\n");
                lis3_dev.ac = lis3lv02d_axis_normal;
index fc591ae..0cee73a 100644 (file)
 #include <linux/delay.h>
 #include <linux/wait.h>
 #include <linux/poll.h>
+#include <linux/slab.h>
 #include <linux/freezer.h>
 #include <linux/uaccess.h>
 #include <linux/miscdevice.h>
+#include <linux/pm_runtime.h>
 #include <asm/atomic.h>
 #include "lis3lv02d.h"
 
 #define MDPS_POLL_INTERVAL 50
 #define MDPS_POLL_MIN     0
 #define MDPS_POLL_MAX     2000
+
+#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
+
+#define SELFTEST_OK           0
+#define SELFTEST_FAIL         -1
+#define SELFTEST_IRQ          -2
+
+#define IRQ_LINE0             0
+#define IRQ_LINE1             1
+
 /*
  * The sensor can also generate interrupts (DRDY) but it's pretty pointless
  * because they are generated even if the data do not change. So it's better
 #define LIS3_SENSITIVITY_12B           ((LIS3_ACCURACY * 1000) / 1024)
 #define LIS3_SENSITIVITY_8B            (18 * LIS3_ACCURACY)
 
-#define LIS3_DEFAULT_FUZZ              3
-#define LIS3_DEFAULT_FLAT              3
+#define LIS3_DEFAULT_FUZZ_12B          3
+#define LIS3_DEFAULT_FLAT_12B          3
+#define LIS3_DEFAULT_FUZZ_8B           1
+#define LIS3_DEFAULT_FLAT_8B           1
 
 struct lis3lv02d lis3_dev = {
        .misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
@@ -75,6 +89,30 @@ struct lis3lv02d lis3_dev = {
 
 EXPORT_SYMBOL_GPL(lis3_dev);
 
+/* just like param_set_int() but does sanity-check so that it won't point
+ * over the axis array size
+ */
+static int param_set_axis(const char *val, const struct kernel_param *kp)
+{
+       int ret = param_set_int(val, kp);
+       if (!ret) {
+               int val = *(int *)kp->arg;
+               if (val < 0)
+                       val = -val;
+               if (!val || val > 3)
+                       return -EINVAL;
+       }
+       return ret;
+}
+
+static struct kernel_param_ops param_ops_axis = {
+       .set = param_set_axis,
+       .get = param_get_int,
+};
+
+module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
+MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
+
 static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
 {
        s8 lo;
@@ -123,9 +161,24 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
        int position[3];
        int i;
 
-       position[0] = lis3->read_data(lis3, OUTX);
-       position[1] = lis3->read_data(lis3, OUTY);
-       position[2] = lis3->read_data(lis3, OUTZ);
+       if (lis3->blkread) {
+               if (lis3_dev.whoami == WAI_12B) {
+                       u16 data[3];
+                       lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
+                       for (i = 0; i < 3; i++)
+                               position[i] = (s16)le16_to_cpu(data[i]);
+               } else {
+                       u8 data[5];
+                       /* Data: x, dummy, y, dummy, z */
+                       lis3->blkread(lis3, OUTX, 5, data);
+                       for (i = 0; i < 3; i++)
+                               position[i] = (s8)data[i * 2];
+               }
+       } else {
+               position[0] = lis3->read_data(lis3, OUTX);
+               position[1] = lis3->read_data(lis3, OUTY);
+               position[2] = lis3->read_data(lis3, OUTZ);
+       }
 
        for (i = 0; i < 3; i++)
                position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
@@ -138,6 +191,7 @@ static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
 /* conversion btw sampling rate and the register values */
 static int lis3_12_rates[4] = {40, 160, 640, 2560};
 static int lis3_8_rates[2] = {100, 400};
+static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
 
 /* ODR is Output Data Rate */
 static int lis3lv02d_get_odr(void)
@@ -156,6 +210,9 @@ static int lis3lv02d_set_odr(int rate)
        u8 ctrl;
        int i, len, shift;
 
+       if (!rate)
+               return -EINVAL;
+
        lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
        ctrl &= ~lis3_dev.odr_mask;
        len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
@@ -172,19 +229,42 @@ static int lis3lv02d_set_odr(int rate)
 
 static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
 {
-       u8 reg;
+       u8 ctlreg, reg;
        s16 x, y, z;
        u8 selftest;
        int ret;
+       u8 ctrl_reg_data;
+       unsigned char irq_cfg;
 
        mutex_lock(&lis3->mutex);
-       if (lis3_dev.whoami == WAI_12B)
-               selftest = CTRL1_ST;
-       else
-               selftest = CTRL1_STP;
 
-       lis3->read(lis3, CTRL_REG1, &reg);
-       lis3->write(lis3, CTRL_REG1, (reg | selftest));
+       irq_cfg = lis3->irq_cfg;
+       if (lis3_dev.whoami == WAI_8B) {
+               lis3->data_ready_count[IRQ_LINE0] = 0;
+               lis3->data_ready_count[IRQ_LINE1] = 0;
+
+               /* Change interrupt cfg to data ready for selftest */
+               atomic_inc(&lis3_dev.wake_thread);
+               lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
+               lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
+               lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
+                               ~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
+                               (LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
+       }
+
+       if (lis3_dev.whoami == WAI_3DC) {
+               ctlreg = CTRL_REG4;
+               selftest = CTRL4_ST0;
+       } else {
+               ctlreg = CTRL_REG1;
+               if (lis3_dev.whoami == WAI_12B)
+                       selftest = CTRL1_ST;
+               else
+                       selftest = CTRL1_STP;
+       }
+
+       lis3->read(lis3, ctlreg, &reg);
+       lis3->write(lis3, ctlreg, (reg | selftest));
        msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
        /* Read directly to avoid axis remap */
@@ -193,7 +273,7 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
        z = lis3->read_data(lis3, OUTZ);
 
        /* back to normal settings */
-       lis3->write(lis3, CTRL_REG1, reg);
+       lis3->write(lis3, ctlreg, reg);
        msleep(lis3->pwron_delay / lis3lv02d_get_odr());
 
        results[0] = x - lis3->read_data(lis3, OUTX);
@@ -201,13 +281,33 @@ static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
        results[2] = z - lis3->read_data(lis3, OUTZ);
 
        ret = 0;
+
+       if (lis3_dev.whoami == WAI_8B) {
+               /* Restore original interrupt configuration */
+               atomic_dec(&lis3_dev.wake_thread);
+               lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
+               lis3->irq_cfg = irq_cfg;
+
+               if ((irq_cfg & LIS3_IRQ1_MASK) &&
+                       lis3->data_ready_count[IRQ_LINE0] < 2) {
+                       ret = SELFTEST_IRQ;
+                       goto fail;
+               }
+
+               if ((irq_cfg & LIS3_IRQ2_MASK) &&
+                       lis3->data_ready_count[IRQ_LINE1] < 2) {
+                       ret = SELFTEST_IRQ;
+                       goto fail;
+               }
+       }
+
        if (lis3->pdata) {
                int i;
                for (i = 0; i < 3; i++) {
                        /* Check against selftest acceptance limits */
                        if ((results[i] < lis3->pdata->st_min_limits[i]) ||
                            (results[i] > lis3->pdata->st_max_limits[i])) {
-                               ret = -EIO;
+                               ret = SELFTEST_FAIL;
                                goto fail;
                        }
                }
@@ -219,10 +319,46 @@ fail:
        return ret;
 }
 
+/*
+ * Order of registers in the list affects to order of the restore process.
+ * Perhaps it is a good idea to set interrupt enable register as a last one
+ * after all other configurations
+ */
+static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
+                              FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
+                              CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
+                              CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
+                              CTRL_REG1, CTRL_REG2, CTRL_REG3};
+
+static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
+                              FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
+                              DD_THSE_L, DD_THSE_H,
+                              CTRL_REG1, CTRL_REG3, CTRL_REG2};
+
+static inline void lis3_context_save(struct lis3lv02d *lis3)
+{
+       int i;
+       for (i = 0; i < lis3->regs_size; i++)
+               lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
+       lis3->regs_stored = true;
+}
+
+static inline void lis3_context_restore(struct lis3lv02d *lis3)
+{
+       int i;
+       if (lis3->regs_stored)
+               for (i = 0; i < lis3->regs_size; i++)
+                       lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
+}
+
 void lis3lv02d_poweroff(struct lis3lv02d *lis3)
 {
+       if (lis3->reg_ctrl)
+               lis3_context_save(lis3);
        /* disable X,Y,Z axis and power down */
        lis3->write(lis3, CTRL_REG1, 0x00);
+       if (lis3->reg_ctrl)
+               lis3->reg_ctrl(lis3, LIS3_REG_OFF);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
 
@@ -232,19 +368,24 @@ void lis3lv02d_poweron(struct lis3lv02d *lis3)
 
        lis3->init(lis3);
 
-       /* LIS3 power on delay is quite long */
-       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
        /*
         * Common configuration
         * BDU: (12 bits sensors only) LSB and MSB values are not updated until
         *      both have been read. So the value read will always be correct.
+        * Set BOOT bit to refresh factory tuning values.
         */
-       if (lis3->whoami ==  WAI_12B) {
-               lis3->read(lis3, CTRL_REG2, &reg);
-               reg |= CTRL2_BDU;
-               lis3->write(lis3, CTRL_REG2, reg);
-       }
+       lis3->read(lis3, CTRL_REG2, &reg);
+       if (lis3->whoami ==  WAI_12B)
+               reg |= CTRL2_BDU | CTRL2_BOOT;
+       else
+               reg |= CTRL2_BOOT_8B;
+       lis3->write(lis3, CTRL_REG2, reg);
+
+       /* LIS3 power on delay is quite long */
+       msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+       if (lis3->reg_ctrl)
+               lis3_context_restore(lis3);
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
 
@@ -262,6 +403,27 @@ static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
        mutex_unlock(&lis3_dev.mutex);
 }
 
+static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
+{
+       if (lis3_dev.pm_dev)
+               pm_runtime_get_sync(lis3_dev.pm_dev);
+
+       if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
+               atomic_set(&lis3_dev.wake_thread, 1);
+       /*
+        * Update coordinates for the case where poll interval is 0 and
+        * the chip in running purely under interrupt control
+        */
+       lis3lv02d_joystick_poll(pidev);
+}
+
+static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
+{
+       atomic_set(&lis3_dev.wake_thread, 0);
+       if (lis3_dev.pm_dev)
+               pm_runtime_put(lis3_dev.pm_dev);
+}
+
 static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
 {
        if (!test_bit(0, &lis3_dev.misc_opened))
@@ -277,8 +439,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
        wake_up_interruptible(&lis3_dev.misc_wait);
        kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
 out:
-       if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev &&
-           lis3_dev.idev->input->users)
+       if (atomic_read(&lis3_dev.wake_thread))
                return IRQ_WAKE_THREAD;
        return IRQ_HANDLED;
 }
@@ -309,44 +470,41 @@ static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
        mutex_unlock(&lis3->mutex);
 }
 
-static void lis302dl_interrupt_handle_ff_wu(struct lis3lv02d *lis3)
+static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
 {
-       u8 wu1_src;
-       u8 wu2_src;
-
-       lis3->read(lis3, FF_WU_SRC_1, &wu1_src);
-       lis3->read(lis3, FF_WU_SRC_2, &wu2_src);
+       int dummy;
 
-       wu1_src = wu1_src & FF_WU_SRC_IA ? wu1_src : 0;
-       wu2_src = wu2_src & FF_WU_SRC_IA ? wu2_src : 0;
-
-       /* joystick poll is internally protected by the lis3->mutex. */
-       if (wu1_src || wu2_src)
-               lis3lv02d_joystick_poll(lis3_dev.idev);
+       /* Dummy read to ack interrupt */
+       lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
+       lis3->data_ready_count[index]++;
 }
 
 static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
 {
-
        struct lis3lv02d *lis3 = data;
+       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
 
-       if ((lis3->pdata->irq_cfg & LIS3_IRQ1_MASK) == LIS3_IRQ1_CLICK)
+       if (irq_cfg == LIS3_IRQ1_CLICK)
                lis302dl_interrupt_handle_click(lis3);
+       else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
+               lis302dl_data_ready(lis3, IRQ_LINE0);
        else
-               lis302dl_interrupt_handle_ff_wu(lis3);
+               lis3lv02d_joystick_poll(lis3->idev);
 
        return IRQ_HANDLED;
 }
 
 static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
 {
-
        struct lis3lv02d *lis3 = data;
+       u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
 
-       if ((lis3->pdata->irq_cfg & LIS3_IRQ2_MASK) == LIS3_IRQ2_CLICK)
+       if (irq_cfg == LIS3_IRQ2_CLICK)
                lis302dl_interrupt_handle_click(lis3);
+       else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
+               lis302dl_data_ready(lis3, IRQ_LINE1);
        else
-               lis302dl_interrupt_handle_ff_wu(lis3);
+               lis3lv02d_joystick_poll(lis3->idev);
 
        return IRQ_HANDLED;
 }
@@ -356,6 +514,9 @@ static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
        if (test_and_set_bit(0, &lis3_dev.misc_opened))
                return -EBUSY; /* already open */
 
+       if (lis3_dev.pm_dev)
+               pm_runtime_get_sync(lis3_dev.pm_dev);
+
        atomic_set(&lis3_dev.count, 0);
        return 0;
 }
@@ -364,6 +525,8 @@ static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
 {
        fasync_helper(-1, file, 0, &lis3_dev.async_queue);
        clear_bit(0, &lis3_dev.misc_opened); /* release the device */
+       if (lis3_dev.pm_dev)
+               pm_runtime_put(lis3_dev.pm_dev);
        return 0;
 }
 
@@ -460,6 +623,8 @@ int lis3lv02d_joystick_enable(void)
                return -ENOMEM;
 
        lis3_dev.idev->poll = lis3lv02d_joystick_poll;
+       lis3_dev.idev->open = lis3lv02d_joystick_open;
+       lis3_dev.idev->close = lis3lv02d_joystick_close;
        lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
        lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
        lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
@@ -473,8 +638,16 @@ int lis3lv02d_joystick_enable(void)
 
        set_bit(EV_ABS, input_dev->evbit);
        max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
-       fuzz = (LIS3_DEFAULT_FUZZ * lis3_dev.scale) / LIS3_ACCURACY;
-       flat = (LIS3_DEFAULT_FLAT * lis3_dev.scale) / LIS3_ACCURACY;
+       if (lis3_dev.whoami == WAI_12B) {
+               fuzz = LIS3_DEFAULT_FUZZ_12B;
+               flat = LIS3_DEFAULT_FLAT_12B;
+       } else {
+               fuzz = LIS3_DEFAULT_FUZZ_8B;
+               flat = LIS3_DEFAULT_FLAT_8B;
+       }
+       fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
+       flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+
        input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
        input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
        input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
@@ -512,14 +685,47 @@ void lis3lv02d_joystick_disable(void)
 EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
 
 /* Sysfs stuff */
+static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
+{
+       /*
+        * SYSFS functions are fast visitors so put-call
+        * immediately after the get-call. However, keep
+        * chip running for a while and schedule delayed
+        * suspend. This way periodic sysfs calls doesn't
+        * suffer from relatively long power up time.
+        */
+
+       if (lis3->pm_dev) {
+               pm_runtime_get_sync(lis3->pm_dev);
+               pm_runtime_put_noidle(lis3->pm_dev);
+               pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
+       }
+}
+
 static ssize_t lis3lv02d_selftest_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
-       int result;
        s16 values[3];
 
-       result = lis3lv02d_selftest(&lis3_dev, values);
-       return sprintf(buf, "%s %d %d %d\n", result == 0 ? "OK" : "FAIL",
+       static const char ok[] = "OK";
+       static const char fail[] = "FAIL";
+       static const char irq[] = "FAIL_IRQ";
+       const char *res;
+
+       lis3lv02d_sysfs_poweron(&lis3_dev);
+       switch (lis3lv02d_selftest(&lis3_dev, values)) {
+       case SELFTEST_FAIL:
+               res = fail;
+               break;
+       case SELFTEST_IRQ:
+               res = irq;
+               break;
+       case SELFTEST_OK:
+       default:
+               res = ok;
+               break;
+       }
+       return sprintf(buf, "%s %d %d %d\n", res,
                values[0], values[1], values[2]);
 }
 
@@ -528,6 +734,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
 {
        int x, y, z;
 
+       lis3lv02d_sysfs_poweron(&lis3_dev);
        mutex_lock(&lis3_dev.mutex);
        lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
        mutex_unlock(&lis3_dev.mutex);
@@ -537,6 +744,7 @@ static ssize_t lis3lv02d_position_show(struct device *dev,
 static ssize_t lis3lv02d_rate_show(struct device *dev,
                        struct device_attribute *attr, char *buf)
 {
+       lis3lv02d_sysfs_poweron(&lis3_dev);
        return sprintf(buf, "%d\n", lis3lv02d_get_odr());
 }
 
@@ -549,6 +757,7 @@ static ssize_t lis3lv02d_rate_set(struct device *dev,
        if (strict_strtoul(buf, 0, &rate))
                return -EINVAL;
 
+       lis3lv02d_sysfs_poweron(&lis3_dev);
        if (lis3lv02d_set_odr(rate))
                return -EINVAL;
 
@@ -585,6 +794,18 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
 {
        sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
        platform_device_unregister(lis3->pdev);
+       if (lis3->pm_dev) {
+               /* Barrier after the sysfs remove */
+               pm_runtime_barrier(lis3->pm_dev);
+
+               /* SYSFS may have left chip running. Turn off if necessary */
+               if (!pm_runtime_suspended(lis3->pm_dev))
+                       lis3lv02d_poweroff(&lis3_dev);
+
+               pm_runtime_disable(lis3->pm_dev);
+               pm_runtime_set_suspended(lis3->pm_dev);
+       }
+       kfree(lis3->reg_cache);
        return 0;
 }
 EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
@@ -616,16 +837,16 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
        if (p->wakeup_flags) {
                dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
                dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
-               /* default to 2.5ms for now */
-               dev->write(dev, FF_WU_DURATION_1, 1);
+               /* pdata value + 1 to keep this backward compatible*/
+               dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
                ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
        }
 
        if (p->wakeup_flags2) {
                dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
                dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
-               /* default to 2.5ms for now */
-               dev->write(dev, FF_WU_DURATION_2, 1);
+               /* pdata value + 1 to keep this backward compatible*/
+               dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
                ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
        }
        /* Configure hipass filters */
@@ -635,8 +856,8 @@ static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
                err = request_threaded_irq(p->irq2,
                                        NULL,
                                        lis302dl_interrupt_thread2_8b,
-                                       IRQF_TRIGGER_RISING |
-                                       IRQF_ONESHOT,
+                                       IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+                                       (p->irq_flags2 & IRQF_TRIGGER_MASK),
                                        DRIVER_NAME, &lis3_dev);
                if (err < 0)
                        printk(KERN_ERR DRIVER_NAME
@@ -652,6 +873,7 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
 {
        int err;
        irq_handler_t thread_fn;
+       int irq_flags = 0;
 
        dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
 
@@ -664,6 +886,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                dev->odrs = lis3_12_rates;
                dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
                dev->scale = LIS3_SENSITIVITY_12B;
+               dev->regs = lis3_wai12_regs;
+               dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
                break;
        case WAI_8B:
                printk(KERN_INFO DRIVER_NAME ": 8 bits sensor found\n");
@@ -673,6 +897,17 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                dev->odrs = lis3_8_rates;
                dev->odr_mask = CTRL1_DR;
                dev->scale = LIS3_SENSITIVITY_8B;
+               dev->regs = lis3_wai8_regs;
+               dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+               break;
+       case WAI_3DC:
+               printk(KERN_INFO DRIVER_NAME ": 8 bits 3DC sensor found\n");
+               dev->read_data = lis3lv02d_read_8;
+               dev->mdps_max_val = 128;
+               dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+               dev->odrs = lis3_3dc_rates;
+               dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+               dev->scale = LIS3_SENSITIVITY_8B;
                break;
        default:
                printk(KERN_ERR DRIVER_NAME
@@ -680,11 +915,25 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                return -EINVAL;
        }
 
+       dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+                                    sizeof(lis3_wai12_regs)), GFP_KERNEL);
+
+       if (dev->reg_cache == NULL) {
+               printk(KERN_ERR DRIVER_NAME "out of memory\n");
+               return -ENOMEM;
+       }
+
        mutex_init(&dev->mutex);
+       atomic_set(&dev->wake_thread, 0);
 
        lis3lv02d_add_fs(dev);
        lis3lv02d_poweron(dev);
 
+       if (dev->pm_dev) {
+               pm_runtime_set_active(dev->pm_dev);
+               pm_runtime_enable(dev->pm_dev);
+       }
+
        if (lis3lv02d_joystick_enable())
                printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
 
@@ -696,8 +945,14 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
                if (dev->whoami == WAI_8B)
                        lis3lv02d_8b_configure(dev, p);
 
+               irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
+
+               dev->irq_cfg = p->irq_cfg;
                if (p->irq_cfg)
                        dev->write(dev, CTRL_REG3, p->irq_cfg);
+
+               if (p->default_rate)
+                       lis3lv02d_set_odr(p->default_rate);
        }
 
        /* bail if we did not get an IRQ from the bus layer */
@@ -725,7 +980,8 @@ int lis3lv02d_init_device(struct lis3lv02d *dev)
 
        err = request_threaded_irq(dev->irq, lis302dl_interrupt,
                                thread_fn,
-                               IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                               IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+                               irq_flags,
                                DRIVER_NAME, &lis3_dev);
 
        if (err < 0) {
index 8540913..a193958 100644 (file)
@@ -20,6 +20,7 @@
  */
 #include <linux/platform_device.h>
 #include <linux/input-polldev.h>
+#include <linux/regulator/consumer.h>
 
 /*
  * This driver tries to support the "digital" accelerometer chips from
@@ -45,6 +46,7 @@ enum lis3_reg {
        CTRL_REG1       = 0x20,
        CTRL_REG2       = 0x21,
        CTRL_REG3       = 0x22,
+       CTRL_REG4       = 0x23,
        HP_FILTER_RESET = 0x23,
        STATUS_REG      = 0x27,
        OUTX_L          = 0x28,
@@ -93,6 +95,7 @@ enum lis3lv02d_reg {
 };
 
 enum lis3_who_am_i {
+       WAI_3DC         = 0x33, /* 8 bits: LIS3DC, HP3DC */
        WAI_12B         = 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
        WAI_8B          = 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
        WAI_6B          = 0x52, /* 6 bits: LIS331DLF - not supported */
@@ -118,6 +121,13 @@ enum lis3lv02d_ctrl1_8b {
        CTRL1_DR        = 0x80,
 };
 
+enum lis3lv02d_ctrl1_3dc {
+       CTRL1_ODR0      = 0x10,
+       CTRL1_ODR1      = 0x20,
+       CTRL1_ODR2      = 0x40,
+       CTRL1_ODR3      = 0x80,
+};
+
 enum lis3lv02d_ctrl2 {
        CTRL2_DAS       = 0x01,
        CTRL2_SIM       = 0x02,
@@ -129,9 +139,18 @@ enum lis3lv02d_ctrl2 {
        CTRL2_FS        = 0x80, /* Full Scale selection */
 };
 
+enum lis3lv02d_ctrl4_3dc {
+       CTRL4_SIM       = 0x01,
+       CTRL4_ST0       = 0x02,
+       CTRL4_ST1       = 0x04,
+       CTRL4_FS0       = 0x10,
+       CTRL4_FS1       = 0x20,
+};
+
 enum lis302d_ctrl2 {
        HP_FF_WU2       = 0x08,
        HP_FF_WU1       = 0x04,
+       CTRL2_BOOT_8B   = 0x40,
 };
 
 enum lis3lv02d_ctrl3 {
@@ -206,19 +225,33 @@ enum lis3lv02d_click_src_8b {
        CLICK_IA        = 0x40,
 };
 
-struct axis_conversion {
-       s8      x;
-       s8      y;
-       s8      z;
+enum lis3lv02d_reg_state {
+       LIS3_REG_OFF    = 0x00,
+       LIS3_REG_ON     = 0x01,
+};
+
+union axis_conversion {
+       struct {
+               int x, y, z;
+       };
+       int as_array[3];
+
 };
 
 struct lis3lv02d {
        void                    *bus_priv; /* used by the bus layer only */
+       struct device           *pm_dev; /* for pm_runtime purposes */
        int (*init) (struct lis3lv02d *lis3);
        int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
        int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
+       int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
+       int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
 
        int                     *odrs;     /* Supported output data rates */
+       u8                      *regs;     /* Regs to store / restore */
+       int                     regs_size;
+       u8                      *reg_cache;
+       bool                    regs_stored;
        u8                      odr_mask;  /* ODR bit mask */
        u8                      whoami;    /* indicates measurement precision */
        s16 (*read_data) (struct lis3lv02d *lis3, int reg);
@@ -231,14 +264,18 @@ struct lis3lv02d {
 
        struct input_polled_dev *idev;     /* input device */
        struct platform_device  *pdev;     /* platform device */
+       struct regulator_bulk_data regulators[2];
        atomic_t                count;     /* interrupt count after last read */
-       struct axis_conversion  ac;        /* hw -> logical axis */
+       union axis_conversion   ac;        /* hw -> logical axis */
        int                     mapped_btns[3];
 
        u32                     irq;       /* IRQ number */
        struct fasync_struct    *async_queue; /* queue for the misc device */
        wait_queue_head_t       misc_wait; /* Wait queue for the misc device */
        unsigned long           misc_opened; /* bit0: whether the device is open */
+       int                     data_ready_count[2];
+       atomic_t                wake_thread;
+       unsigned char           irq_cfg;
 
        struct lis3lv02d_platform_data *pdata;  /* for passing board config */
        struct mutex            mutex;     /* Serialize poll and selftest */
index 8e5933b..9f4bae0 100644 (file)
 #include <linux/init.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
 #include "lis3lv02d.h"
 
 #define DRV_NAME       "lis3lv02d_i2c"
 
+static const char reg_vdd[]    = "Vdd";
+static const char reg_vdd_io[] = "Vdd_IO";
+
+static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
+{
+       int ret;
+       if (state == LIS3_REG_OFF) {
+               ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
+                                       lis3->regulators);
+       } else {
+               ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
+                                       lis3->regulators);
+               /* Chip needs time to wakeup. Not mentioned in datasheet */
+               usleep_range(10000, 20000);
+       }
+       return ret;
+}
+
 static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
 {
        struct i2c_client *c = lis3->bus_priv;
@@ -46,24 +66,38 @@ static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
        return 0;
 }
 
+static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
+                               u8 *v)
+{
+       struct i2c_client *c = lis3->bus_priv;
+       reg |= (1 << 7); /* 7th bit enables address auto incrementation */
+       return i2c_smbus_read_i2c_block_data(c, reg, len, v);
+}
+
 static int lis3_i2c_init(struct lis3lv02d *lis3)
 {
        u8 reg;
        int ret;
 
+       if (lis3->reg_ctrl)
+               lis3_reg_ctrl(lis3, LIS3_REG_ON);
+
+       lis3->read(lis3, WHO_AM_I, &reg);
+       if (reg != lis3->whoami)
+               printk(KERN_ERR "lis3: power on failure\n");
+
        /* power up the device */
        ret = lis3->read(lis3, CTRL_REG1, &reg);
        if (ret < 0)
                return ret;
 
-       reg |= CTRL1_PD0;
+       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
        return lis3->write(lis3, CTRL_REG1, reg);
 }
 
 /* Default axis mapping but it can be overwritten by platform data */
-static struct axis_conversion lis3lv02d_axis_map = { LIS3_DEV_X,
-                                                    LIS3_DEV_Y,
-                                                    LIS3_DEV_Z };
+static union axis_conversion lis3lv02d_axis_map =
+       { .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
 
 static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
                                        const struct i2c_device_id *id)
@@ -72,6 +106,15 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
        struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
 
        if (pdata) {
+               /* Regulator control is optional */
+               if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
+                       lis3_dev.reg_ctrl = lis3_reg_ctrl;
+
+               if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
+                       (i2c_check_functionality(client->adapter,
+                                               I2C_FUNC_SMBUS_I2C_BLOCK)))
+                       lis3_dev.blkread  = lis3_i2c_blockread;
+
                if (pdata->axis_x)
                        lis3lv02d_axis_map.x = pdata->axis_x;
 
@@ -88,6 +131,16 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
                        goto fail;
        }
 
+       if (lis3_dev.reg_ctrl) {
+               lis3_dev.regulators[0].supply = reg_vdd;
+               lis3_dev.regulators[1].supply = reg_vdd_io;
+               ret = regulator_bulk_get(&client->dev,
+                                       ARRAY_SIZE(lis3_dev.regulators),
+                                       lis3_dev.regulators);
+               if (ret < 0)
+                       goto fail;
+       }
+
        lis3_dev.pdata    = pdata;
        lis3_dev.bus_priv = client;
        lis3_dev.init     = lis3_i2c_init;
@@ -95,10 +148,24 @@ static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
        lis3_dev.write    = lis3_i2c_write;
        lis3_dev.irq      = client->irq;
        lis3_dev.ac       = lis3lv02d_axis_map;
+       lis3_dev.pm_dev   = &client->dev;
 
        i2c_set_clientdata(client, &lis3_dev);
+
+       /* Provide power over the init call */
+       if (lis3_dev.reg_ctrl)
+               lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+
        ret = lis3lv02d_init_device(&lis3_dev);
+
+       if (lis3_dev.reg_ctrl)
+               lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+
+       if (ret == 0)
+               return 0;
 fail:
+       if (pdata && pdata->release_resources)
+               pdata->release_resources();
        return ret;
 }
 
@@ -111,14 +178,18 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
                pdata->release_resources();
 
        lis3lv02d_joystick_disable();
-       lis3lv02d_poweroff(lis3);
+       lis3lv02d_remove_fs(&lis3_dev);
 
-       return lis3lv02d_remove_fs(&lis3_dev);
+       if (lis3_dev.reg_ctrl)
+               regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+                               lis3_dev.regulators);
+       return 0;
 }
 
 #ifdef CONFIG_PM
-static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+static int lis3lv02d_i2c_suspend(struct device *dev)
 {
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
        if (!lis3->pdata || !lis3->pdata->wakeup_flags)
@@ -126,18 +197,21 @@ static int lis3lv02d_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
        return 0;
 }
 
-static int lis3lv02d_i2c_resume(struct i2c_client *client)
+static int lis3lv02d_i2c_resume(struct device *dev)
 {
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
        struct lis3lv02d *lis3 = i2c_get_clientdata(client);
 
-       if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+       /*
+        * pm_runtime documentation says that devices should always
+        * be powered on at resume. Pm_runtime turns them off after system
+        * wide resume is complete.
+        */
+       if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
+               pm_runtime_suspended(dev))
                lis3lv02d_poweron(lis3);
-       return 0;
-}
 
-static void lis3lv02d_i2c_shutdown(struct i2c_client *client)
-{
-       lis3lv02d_i2c_suspend(client, PMSG_SUSPEND);
+       return 0;
 }
 #else
 #define lis3lv02d_i2c_suspend  NULL
@@ -145,6 +219,24 @@ static void lis3lv02d_i2c_shutdown(struct i2c_client *client)
 #define lis3lv02d_i2c_shutdown NULL
 #endif
 
+static int lis3_i2c_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       lis3lv02d_poweroff(lis3);
+       return 0;
+}
+
+static int lis3_i2c_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+       lis3lv02d_poweron(lis3);
+       return 0;
+}
+
 static const struct i2c_device_id lis3lv02d_id[] = {
        {"lis3lv02d", 0 },
        {}
@@ -152,14 +244,20 @@ static const struct i2c_device_id lis3lv02d_id[] = {
 
 MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
 
+static const struct dev_pm_ops lis3_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
+                               lis3lv02d_i2c_resume)
+       SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
+                          lis3_i2c_runtime_resume,
+                          NULL)
+};
+
 static struct i2c_driver lis3lv02d_i2c_driver = {
        .driver  = {
                .name   = DRV_NAME,
                .owner  = THIS_MODULE,
+               .pm     = &lis3_pm_ops,
        },
-       .suspend = lis3lv02d_i2c_suspend,
-       .shutdown = lis3lv02d_i2c_shutdown,
-       .resume = lis3lv02d_i2c_resume,
        .probe  = lis3lv02d_i2c_probe,
        .remove = __devexit_p(lis3lv02d_i2c_remove),
        .id_table = lis3lv02d_id,
index b9be5e3..2549de1 100644 (file)
@@ -50,11 +50,12 @@ static int lis3_spi_init(struct lis3lv02d *lis3)
        if (ret < 0)
                return ret;
 
-       reg |= CTRL1_PD0;
+       reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
        return lis3->write(lis3, CTRL_REG1, reg);
 }
 
-static struct axis_conversion lis3lv02d_axis_normal = { 1, 2, 3 };
+static union axis_conversion lis3lv02d_axis_normal =
+       { .as_array = { 1, 2, 3 } };
 
 static int __devinit lis302dl_spi_probe(struct spi_device *spi)
 {
diff --git a/drivers/hwmon/ltc4261.c b/drivers/hwmon/ltc4261.c
new file mode 100644 (file)
index 0000000..2676261
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Driver for Linear Technology LTC4261 I2C Negative Voltage Hot Swap Controller
+ *
+ * Copyright (C) 2010 Ericsson AB.
+ *
+ * Derived from:
+ *
+ *  Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller
+ *  Copyright (C) 2008 Ira W. Snyder <iws@ovro.caltech.edu>
+ *
+ * Datasheet: http://cds.linear.com/docs/Datasheet/42612fb.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/* chip registers */
+#define LTC4261_STATUS 0x00    /* readonly */
+#define LTC4261_FAULT  0x01
+#define LTC4261_ALERT  0x02
+#define LTC4261_CONTROL        0x03
+#define LTC4261_SENSE_H        0x04
+#define LTC4261_SENSE_L        0x05
+#define LTC4261_ADIN2_H        0x06
+#define LTC4261_ADIN2_L        0x07
+#define LTC4261_ADIN_H 0x08
+#define LTC4261_ADIN_L 0x09
+
+/*
+ * Fault register bits
+ */
+#define FAULT_OV       (1<<0)
+#define FAULT_UV       (1<<1)
+#define FAULT_OC       (1<<2)
+
+struct ltc4261_data {
+       struct device *hwmon_dev;
+
+       struct mutex update_lock;
+       bool valid;
+       unsigned long last_updated;     /* in jiffies */
+
+       /* Registers */
+       u8 regs[10];
+};
+
+static struct ltc4261_data *ltc4261_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ltc4261_data *data = i2c_get_clientdata(client);
+       struct ltc4261_data *ret = data;
+
+       mutex_lock(&data->update_lock);
+
+       if (time_after(jiffies, data->last_updated + HZ / 4) || !data->valid) {
+               int i;
+
+               /* Read registers -- 0x00 to 0x09 */
+               for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
+                       int val;
+
+                       val = i2c_smbus_read_byte_data(client, i);
+                       if (unlikely(val < 0)) {
+                               dev_dbg(dev,
+                                       "Failed to read ADC value: error %d",
+                                       val);
+                               ret = ERR_PTR(val);
+                               goto abort;
+                       }
+                       data->regs[i] = val;
+               }
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+abort:
+       mutex_unlock(&data->update_lock);
+       return ret;
+}
+
+/* Return the voltage from the given register in mV or mA */
+static int ltc4261_get_value(struct ltc4261_data *data, u8 reg)
+{
+       u32 val;
+
+       val = (data->regs[reg] << 2) + (data->regs[reg + 1] >> 6);
+
+       switch (reg) {
+       case LTC4261_ADIN_H:
+       case LTC4261_ADIN2_H:
+               /* 2.5mV resolution. Convert to mV. */
+               val = val * 25 / 10;
+               break;
+       case LTC4261_SENSE_H:
+               /*
+                * 62.5uV resolution. Convert to current as measured with
+                * an 1 mOhm sense resistor, in mA. If a different sense
+                * resistor is installed, calculate the actual current by
+                * dividing the reported current by the sense resistor value
+                * in mOhm.
+                */
+               val = val * 625 / 10;
+               break;
+       default:
+               /* If we get here, the developer messed up */
+               WARN_ON_ONCE(1);
+               val = 0;
+               break;
+       }
+
+       return val;
+}
+
+static ssize_t ltc4261_show_value(struct device *dev,
+                                 struct device_attribute *da, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct ltc4261_data *data = ltc4261_update_device(dev);
+       int value;
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       value = ltc4261_get_value(data, attr->index);
+       return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+static ssize_t ltc4261_show_bool(struct device *dev,
+                                struct device_attribute *da, char *buf)
+{
+       struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+       struct i2c_client *client = to_i2c_client(dev);
+       struct ltc4261_data *data = ltc4261_update_device(dev);
+       u8 fault;
+
+       if (IS_ERR(data))
+               return PTR_ERR(data);
+
+       fault = data->regs[LTC4261_FAULT] & attr->index;
+       if (fault)              /* Clear reported faults in chip register */
+               i2c_smbus_write_byte_data(client, LTC4261_FAULT, ~fault);
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0);
+}
+
+/*
+ * These macros are used below in constructing device attribute objects
+ * for use with sysfs_create_group() to make a sysfs device file
+ * for each register.
+ */
+
+#define LTC4261_VALUE(name, ltc4261_cmd_idx) \
+       static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+       ltc4261_show_value, NULL, ltc4261_cmd_idx)
+
+#define LTC4261_BOOL(name, mask) \
+       static SENSOR_DEVICE_ATTR(name, S_IRUGO, \
+       ltc4261_show_bool, NULL, (mask))
+
+/*
+ * Input voltages.
+ */
+LTC4261_VALUE(in1_input, LTC4261_ADIN_H);
+LTC4261_VALUE(in2_input, LTC4261_ADIN2_H);
+
+/*
+ * Voltage alarms. The chip has only one set of voltage alarm status bits,
+ * triggered by input voltage alarms. In many designs, those alarms are
+ * associated with the ADIN2 sensor, due to the proximity of the ADIN2 pin
+ * to the OV pin. ADIN2 is, however, not available on all chip variants.
+ * To ensure that the alarm condition is reported to the user, report it
+ * with both voltage sensors.
+ */
+LTC4261_BOOL(in1_min_alarm, FAULT_UV);
+LTC4261_BOOL(in1_max_alarm, FAULT_OV);
+LTC4261_BOOL(in2_min_alarm, FAULT_UV);
+LTC4261_BOOL(in2_max_alarm, FAULT_OV);
+
+/* Currents (via sense resistor) */
+LTC4261_VALUE(curr1_input, LTC4261_SENSE_H);
+
+/* Overcurrent alarm */
+LTC4261_BOOL(curr1_max_alarm, FAULT_OC);
+
+static struct attribute *ltc4261_attributes[] = {
+       &sensor_dev_attr_in1_input.dev_attr.attr,
+       &sensor_dev_attr_in1_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_in1_max_alarm.dev_attr.attr,
+       &sensor_dev_attr_in2_input.dev_attr.attr,
+       &sensor_dev_attr_in2_min_alarm.dev_attr.attr,
+       &sensor_dev_attr_in2_max_alarm.dev_attr.attr,
+
+       &sensor_dev_attr_curr1_input.dev_attr.attr,
+       &sensor_dev_attr_curr1_max_alarm.dev_attr.attr,
+
+       NULL,
+};
+
+static const struct attribute_group ltc4261_group = {
+       .attrs = ltc4261_attributes,
+};
+
+static int ltc4261_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct i2c_adapter *adapter = client->adapter;
+       struct ltc4261_data *data;
+       int ret;
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -ENODEV;
+
+       if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) {
+               dev_err(&client->dev, "Failed to read register %d:%02x:%02x\n",
+                       adapter->id, client->addr, LTC4261_STATUS);
+               return -ENODEV;
+       }
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               ret = -ENOMEM;
+               goto out_kzalloc;
+       }
+
+       i2c_set_clientdata(client, data);
+       mutex_init(&data->update_lock);
+
+       /* Clear faults */
+       i2c_smbus_write_byte_data(client, LTC4261_FAULT, 0x00);
+
+       /* Register sysfs hooks */
+       ret = sysfs_create_group(&client->dev.kobj, &ltc4261_group);
+       if (ret)
+               goto out_sysfs_create_group;
+
+       data->hwmon_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               ret = PTR_ERR(data->hwmon_dev);
+               goto out_hwmon_device_register;
+       }
+
+       return 0;
+
+out_hwmon_device_register:
+       sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
+out_sysfs_create_group:
+       kfree(data);
+out_kzalloc:
+       return ret;
+}
+
+static int ltc4261_remove(struct i2c_client *client)
+{
+       struct ltc4261_data *data = i2c_get_clientdata(client);
+
+       hwmon_device_unregister(data->hwmon_dev);
+       sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
+
+       kfree(data);
+
+       return 0;
+}
+
+static const struct i2c_device_id ltc4261_id[] = {
+       {"ltc4261", 0},
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ltc4261_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc4261_driver = {
+       .driver = {
+                  .name = "ltc4261",
+                  },
+       .probe = ltc4261_probe,
+       .remove = ltc4261_remove,
+       .id_table = ltc4261_id,
+};
+
+static int __init ltc4261_init(void)
+{
+       return i2c_add_driver(&ltc4261_driver);
+}
+
+static void __exit ltc4261_exit(void)
+{
+       i2c_del_driver(&ltc4261_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION("LTC4261 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ltc4261_init);
+module_exit(ltc4261_exit);
index f119039..0798210 100644 (file)
@@ -21,7 +21,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
@@ -35,6 +34,7 @@
 #include <linux/cpu.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include <asm/smp.h>
 
 #define DRVNAME        "pkgtemp"
 
@@ -339,8 +339,7 @@ exit:
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void pkgtemp_device_remove(unsigned int cpu)
+static void __cpuinit pkgtemp_device_remove(unsigned int cpu)
 {
        struct pdev_entry *p;
        unsigned int i;
@@ -387,12 +386,10 @@ static int __cpuinit pkgtemp_cpu_callback(struct notifier_block *nfb,
 static struct notifier_block pkgtemp_cpu_notifier __refdata = {
        .notifier_call = pkgtemp_cpu_callback,
 };
-#endif                         /* !CONFIG_HOTPLUG_CPU */
 
 static int __init pkgtemp_init(void)
 {
        int i, err = -ENODEV;
-       struct pdev_entry *p, *n;
 
        /* quick check if we run Intel */
        if (cpu_data(0).x86_vendor != X86_VENDOR_INTEL)
@@ -402,31 +399,23 @@ static int __init pkgtemp_init(void)
        if (err)
                goto exit;
 
-       for_each_online_cpu(i) {
-               err = pkgtemp_device_add(i);
-               if (err)
-                       goto exit_devices_unreg;
-       }
+       for_each_online_cpu(i)
+               pkgtemp_device_add(i);
+
+#ifndef CONFIG_HOTPLUG_CPU
        if (list_empty(&pdev_list)) {
                err = -ENODEV;
                goto exit_driver_unreg;
        }
+#endif
 
-#ifdef CONFIG_HOTPLUG_CPU
        register_hotcpu_notifier(&pkgtemp_cpu_notifier);
-#endif
        return 0;
 
-exit_devices_unreg:
-       mutex_lock(&pdev_list_mutex);
-       list_for_each_entry_safe(p, n, &pdev_list, list) {
-               platform_device_unregister(p->pdev);
-               list_del(&p->list);
-               kfree(p);
-       }
-       mutex_unlock(&pdev_list_mutex);
+#ifndef CONFIG_HOTPLUG_CPU
 exit_driver_unreg:
        platform_driver_unregister(&pkgtemp_driver);
+#endif
 exit:
        return err;
 }
@@ -434,9 +423,8 @@ exit:
 static void __exit pkgtemp_exit(void)
 {
        struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
        unregister_hotcpu_notifier(&pkgtemp_cpu_notifier);
-#endif
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
                platform_device_unregister(p->pdev);
index ffb793a..ec7fad7 100644 (file)
  */
 
 #include <linux/module.h>
-#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/jiffies.h>
 #include <linux/hwmon.h>
 #include <linux/sysfs.h>
 #include <linux/hwmon-sysfs.h>
@@ -237,8 +235,7 @@ exit:
        return err;
 }
 
-#ifdef CONFIG_HOTPLUG_CPU
-static void via_cputemp_device_remove(unsigned int cpu)
+static void __cpuinit via_cputemp_device_remove(unsigned int cpu)
 {
        struct pdev_entry *p, *n;
        mutex_lock(&pdev_list_mutex);
@@ -272,7 +269,6 @@ static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb,
 static struct notifier_block via_cputemp_cpu_notifier __refdata = {
        .notifier_call = via_cputemp_cpu_callback,
 };
-#endif                         /* !CONFIG_HOTPLUG_CPU */
 
 static int __init via_cputemp_init(void)
 {
@@ -313,9 +309,7 @@ static int __init via_cputemp_init(void)
                goto exit_driver_unreg;
        }
 
-#ifdef CONFIG_HOTPLUG_CPU
        register_hotcpu_notifier(&via_cputemp_cpu_notifier);
-#endif
        return 0;
 
 exit_devices_unreg:
@@ -335,9 +329,8 @@ exit:
 static void __exit via_cputemp_exit(void)
 {
        struct pdev_entry *p, *n;
-#ifdef CONFIG_HOTPLUG_CPU
+
        unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
-#endif
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
                platform_device_unregister(p->pdev);
index cb3ccf3..41665d2 100644 (file)
@@ -74,7 +74,7 @@ static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1;
 static unsigned int mwait_substates;
 
 /* Reliable LAPIC Timer States, bit 1 for C1 etc.  */
-static unsigned int lapic_timer_reliable_states;
+static unsigned int lapic_timer_reliable_states = (1 << 1);     /* Default to only C1 */
 
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state);
@@ -94,7 +94,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .driver_data = (void *) 0x00,
                .flags = CPUIDLE_FLAG_TIME_VALID,
                .exit_latency = 3,
-               .power_usage = 1000,
                .target_residency = 6,
                .enter = &intel_idle },
        { /* MWAIT C2 */
@@ -103,7 +102,6 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .driver_data = (void *) 0x10,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 20,
-               .power_usage = 500,
                .target_residency = 80,
                .enter = &intel_idle },
        { /* MWAIT C3 */
@@ -112,11 +110,46 @@ static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .driver_data = (void *) 0x20,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 200,
-               .power_usage = 350,
                .target_residency = 800,
                .enter = &intel_idle },
 };
 
+static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
+       { /* MWAIT C0 */ },
+       { /* MWAIT C1 */
+               .name = "SNB-C1",
+               .desc = "MWAIT 0x00",
+               .driver_data = (void *) 0x00,
+               .flags = CPUIDLE_FLAG_TIME_VALID,
+               .exit_latency = 1,
+               .target_residency = 4,
+               .enter = &intel_idle },
+       { /* MWAIT C2 */
+               .name = "SNB-C3",
+               .desc = "MWAIT 0x10",
+               .driver_data = (void *) 0x10,
+               .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 80,
+               .target_residency = 160,
+               .enter = &intel_idle },
+       { /* MWAIT C3 */
+               .name = "SNB-C6",
+               .desc = "MWAIT 0x20",
+               .driver_data = (void *) 0x20,
+               .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 104,
+               .target_residency = 208,
+               .enter = &intel_idle },
+       { /* MWAIT C4 */
+               .name = "SNB-C7",
+               .desc = "MWAIT 0x30",
+               .driver_data = (void *) 0x30,
+               .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
+               .exit_latency = 109,
+               .target_residency = 300,
+               .enter = &intel_idle },
+};
+
 static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
        { /* MWAIT C0 */ },
        { /* MWAIT C1 */
@@ -125,7 +158,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .driver_data = (void *) 0x00,
                .flags = CPUIDLE_FLAG_TIME_VALID,
                .exit_latency = 1,
-               .power_usage = 1000,
                .target_residency = 4,
                .enter = &intel_idle },
        { /* MWAIT C2 */
@@ -134,7 +166,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .driver_data = (void *) 0x10,
                .flags = CPUIDLE_FLAG_TIME_VALID,
                .exit_latency = 20,
-               .power_usage = 500,
                .target_residency = 80,
                .enter = &intel_idle },
        { /* MWAIT C3 */ },
@@ -144,7 +175,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .driver_data = (void *) 0x30,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 100,
-               .power_usage = 250,
                .target_residency = 400,
                .enter = &intel_idle },
        { /* MWAIT C5 */ },
@@ -154,7 +184,6 @@ static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
                .driver_data = (void *) 0x52,
                .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
                .exit_latency = 140,
-               .power_usage = 150,
                .target_residency = 560,
                .enter = &intel_idle },
 };
@@ -179,13 +208,10 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
        local_irq_disable();
 
        /*
-        * If the state flag indicates that the TLB will be flushed or if this
-        * is the deepest c-state supported, do a voluntary leave mm to avoid
-        * costly and mostly unnecessary wakeups for flushing the user TLB's
-        * associated with the active mm.
+        * leave_mm() to avoid costly and often unnecessary wakeups
+        * for flushing the user TLB's associated with the active mm.
         */
-       if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED ||
-           (&dev->states[dev->state_count - 1] == state))
+       if (state->flags & CPUIDLE_FLAG_TLB_FLUSHED)
                leave_mm(cpu);
 
        if (!(lapic_timer_reliable_states & (1 << (cstate))))
@@ -269,9 +295,14 @@ static int intel_idle_probe(void)
 
        case 0x1C:      /* 28 - Atom Processor */
        case 0x26:      /* 38 - Lincroft Atom Processor */
-               lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
+               lapic_timer_reliable_states = (1 << 1); /* C1 */
                cpuidle_state_table = atom_cstates;
                break;
+
+       case 0x2A:      /* SNB */
+       case 0x2D:      /* SNB Xeon */
+               cpuidle_state_table = snb_cstates;
+               break;
 #ifdef FUTURE_USE
        case 0x17:      /* 23 - Core 2 Duo */
                lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */
index ae7c288..91916a8 100644 (file)
@@ -59,8 +59,8 @@ __ib_get_agent_port(struct ib_device *device, int port_num)
        struct ib_agent_port_private *entry;
 
        list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-               if (entry->agent[0]->device == device &&
-                   entry->agent[0]->port_num == port_num)
+               if (entry->agent[1]->device == device &&
+                   entry->agent[1]->port_num == port_num)
                        return entry;
        }
        return NULL;
@@ -155,14 +155,16 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
                goto error1;
        }
 
-       /* Obtain send only MAD agent for SMI QP */
-       port_priv->agent[0] = ib_register_mad_agent(device, port_num,
-                                                   IB_QPT_SMI, NULL, 0,
-                                                   &agent_send_handler,
-                                                   NULL, NULL);
-       if (IS_ERR(port_priv->agent[0])) {
-               ret = PTR_ERR(port_priv->agent[0]);
-               goto error2;
+       if (rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND) {
+               /* Obtain send only MAD agent for SMI QP */
+               port_priv->agent[0] = ib_register_mad_agent(device, port_num,
+                                                           IB_QPT_SMI, NULL, 0,
+                                                           &agent_send_handler,
+                                                           NULL, NULL);
+               if (IS_ERR(port_priv->agent[0])) {
+                       ret = PTR_ERR(port_priv->agent[0]);
+                       goto error2;
+               }
        }
 
        /* Obtain send only MAD agent for GSI QP */
@@ -182,7 +184,8 @@ int ib_agent_port_open(struct ib_device *device, int port_num)
        return 0;
 
 error3:
-       ib_unregister_mad_agent(port_priv->agent[0]);
+       if (port_priv->agent[0])
+               ib_unregister_mad_agent(port_priv->agent[0]);
 error2:
        kfree(port_priv);
 error1:
@@ -205,7 +208,9 @@ int ib_agent_port_close(struct ib_device *device, int port_num)
        spin_unlock_irqrestore(&ib_agent_port_list_lock, flags);
 
        ib_unregister_mad_agent(port_priv->agent[1]);
-       ib_unregister_mad_agent(port_priv->agent[0]);
+       if (port_priv->agent[0])
+               ib_unregister_mad_agent(port_priv->agent[0]);
+
        kfree(port_priv);
        return 0;
 }
index b930b81..6884da2 100644 (file)
@@ -59,6 +59,7 @@ MODULE_LICENSE("Dual BSD/GPL");
 #define CMA_CM_RESPONSE_TIMEOUT 20
 #define CMA_MAX_CM_RETRIES 15
 #define CMA_CM_MRA_SETTING (IB_CM_MRA_FLAG_DELAY | 24)
+#define CMA_IBOE_PACKET_LIFETIME 18
 
 static void cma_add_one(struct ib_device *device);
 static void cma_remove_one(struct ib_device *device);
@@ -157,6 +158,7 @@ struct cma_multicast {
        struct list_head        list;
        void                    *context;
        struct sockaddr_storage addr;
+       struct kref             mcref;
 };
 
 struct cma_work {
@@ -173,6 +175,12 @@ struct cma_ndev_work {
        struct rdma_cm_event    event;
 };
 
+struct iboe_mcast_work {
+       struct work_struct       work;
+       struct rdma_id_private  *id;
+       struct cma_multicast    *mc;
+};
+
 union cma_ip_addr {
        struct in6_addr ip6;
        struct {
@@ -281,6 +289,8 @@ static void cma_attach_to_dev(struct rdma_id_private *id_priv,
        atomic_inc(&cma_dev->refcount);
        id_priv->cma_dev = cma_dev;
        id_priv->id.device = cma_dev->device;
+       id_priv->id.route.addr.dev_addr.transport =
+               rdma_node_get_transport(cma_dev->device->node_type);
        list_add_tail(&id_priv->list, &cma_dev->id_list);
 }
 
@@ -290,6 +300,14 @@ static inline void cma_deref_dev(struct cma_device *cma_dev)
                complete(&cma_dev->comp);
 }
 
+static inline void release_mc(struct kref *kref)
+{
+       struct cma_multicast *mc = container_of(kref, struct cma_multicast, mcref);
+
+       kfree(mc->multicast.ib);
+       kfree(mc);
+}
+
 static void cma_detach_from_dev(struct rdma_id_private *id_priv)
 {
        list_del(&id_priv->list);
@@ -323,22 +341,63 @@ static int cma_set_qkey(struct rdma_id_private *id_priv)
        return ret;
 }
 
+static int find_gid_port(struct ib_device *device, union ib_gid *gid, u8 port_num)
+{
+       int i;
+       int err;
+       struct ib_port_attr props;
+       union ib_gid tmp;
+
+       err = ib_query_port(device, port_num, &props);
+       if (err)
+               return 1;
+
+       for (i = 0; i < props.gid_tbl_len; ++i) {
+               err = ib_query_gid(device, port_num, i, &tmp);
+               if (err)
+                       return 1;
+               if (!memcmp(&tmp, gid, sizeof tmp))
+                       return 0;
+       }
+
+       return -EAGAIN;
+}
+
 static int cma_acquire_dev(struct rdma_id_private *id_priv)
 {
        struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
        struct cma_device *cma_dev;
-       union ib_gid gid;
+       union ib_gid gid, iboe_gid;
        int ret = -ENODEV;
+       u8 port;
+       enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
+               IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
 
-       rdma_addr_get_sgid(dev_addr, &gid);
+       iboe_addr_get_sgid(dev_addr, &iboe_gid);
+       memcpy(&gid, dev_addr->src_dev_addr +
+              rdma_addr_gid_offset(dev_addr), sizeof gid);
        list_for_each_entry(cma_dev, &dev_list, list) {
-               ret = ib_find_cached_gid(cma_dev->device, &gid,
-                                        &id_priv->id.port_num, NULL);
-               if (!ret) {
-                       cma_attach_to_dev(id_priv, cma_dev);
-                       break;
+               for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) {
+                       if (rdma_port_get_link_layer(cma_dev->device, port) == dev_ll) {
+                               if (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB &&
+                                   rdma_port_get_link_layer(cma_dev->device, port) == IB_LINK_LAYER_ETHERNET)
+                                       ret = find_gid_port(cma_dev->device, &iboe_gid, port);
+                               else
+                                       ret = find_gid_port(cma_dev->device, &gid, port);
+
+                               if (!ret) {
+                                       id_priv->id.port_num = port;
+                                       goto out;
+                               } else if (ret == 1)
+                                       break;
+                       }
                }
        }
+
+out:
+       if (!ret)
+               cma_attach_to_dev(id_priv, cma_dev);
+
        return ret;
 }
 
@@ -556,10 +615,16 @@ static int cma_ib_init_qp_attr(struct rdma_id_private *id_priv,
 {
        struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
        int ret;
+       u16 pkey;
+
+       if (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num) ==
+           IB_LINK_LAYER_INFINIBAND)
+               pkey = ib_addr_get_pkey(dev_addr);
+       else
+               pkey = 0xffff;
 
        ret = ib_find_cached_pkey(id_priv->id.device, id_priv->id.port_num,
-                                 ib_addr_get_pkey(dev_addr),
-                                 &qp_attr->pkey_index);
+                                 pkey, &qp_attr->pkey_index);
        if (ret)
                return ret;
 
@@ -737,8 +802,8 @@ static inline int cma_user_data_offset(enum rdma_port_space ps)
 
 static void cma_cancel_route(struct rdma_id_private *id_priv)
 {
-       switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
-       case RDMA_TRANSPORT_IB:
+       switch (rdma_port_get_link_layer(id_priv->id.device, id_priv->id.port_num)) {
+       case IB_LINK_LAYER_INFINIBAND:
                if (id_priv->query)
                        ib_sa_cancel_query(id_priv->query_id, id_priv->query);
                break;
@@ -816,8 +881,17 @@ static void cma_leave_mc_groups(struct rdma_id_private *id_priv)
                mc = container_of(id_priv->mc_list.next,
                                  struct cma_multicast, list);
                list_del(&mc->list);
-               ib_sa_free_multicast(mc->multicast.ib);
-               kfree(mc);
+               switch (rdma_port_get_link_layer(id_priv->cma_dev->device, id_priv->id.port_num)) {
+               case IB_LINK_LAYER_INFINIBAND:
+                       ib_sa_free_multicast(mc->multicast.ib);
+                       kfree(mc);
+                       break;
+               case IB_LINK_LAYER_ETHERNET:
+                       kref_put(&mc->mcref, release_mc);
+                       break;
+               default:
+                       break;
+               }
        }
 }
 
@@ -833,7 +907,7 @@ void rdma_destroy_id(struct rdma_cm_id *id)
        mutex_lock(&lock);
        if (id_priv->cma_dev) {
                mutex_unlock(&lock);
-               switch (rdma_node_get_transport(id->device->node_type)) {
+               switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
                case RDMA_TRANSPORT_IB:
                        if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
                                ib_destroy_cm_id(id_priv->cm_id.ib);
@@ -1708,6 +1782,81 @@ static int cma_resolve_iw_route(struct rdma_id_private *id_priv, int timeout_ms)
        return 0;
 }
 
+static int cma_resolve_iboe_route(struct rdma_id_private *id_priv)
+{
+       struct rdma_route *route = &id_priv->id.route;
+       struct rdma_addr *addr = &route->addr;
+       struct cma_work *work;
+       int ret;
+       struct sockaddr_in *src_addr = (struct sockaddr_in *)&route->addr.src_addr;
+       struct sockaddr_in *dst_addr = (struct sockaddr_in *)&route->addr.dst_addr;
+       struct net_device *ndev = NULL;
+       u16 vid;
+
+       if (src_addr->sin_family != dst_addr->sin_family)
+               return -EINVAL;
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return -ENOMEM;
+
+       work->id = id_priv;
+       INIT_WORK(&work->work, cma_work_handler);
+
+       route->path_rec = kzalloc(sizeof *route->path_rec, GFP_KERNEL);
+       if (!route->path_rec) {
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       route->num_paths = 1;
+
+       if (addr->dev_addr.bound_dev_if)
+               ndev = dev_get_by_index(&init_net, addr->dev_addr.bound_dev_if);
+       if (!ndev) {
+               ret = -ENODEV;
+               goto err2;
+       }
+
+       vid = rdma_vlan_dev_vlan_id(ndev);
+
+       iboe_mac_vlan_to_ll(&route->path_rec->sgid, addr->dev_addr.src_dev_addr, vid);
+       iboe_mac_vlan_to_ll(&route->path_rec->dgid, addr->dev_addr.dst_dev_addr, vid);
+
+       route->path_rec->hop_limit = 1;
+       route->path_rec->reversible = 1;
+       route->path_rec->pkey = cpu_to_be16(0xffff);
+       route->path_rec->mtu_selector = IB_SA_EQ;
+       route->path_rec->sl = id_priv->tos >> 5;
+
+       route->path_rec->mtu = iboe_get_mtu(ndev->mtu);
+       route->path_rec->rate_selector = IB_SA_EQ;
+       route->path_rec->rate = iboe_get_rate(ndev);
+       dev_put(ndev);
+       route->path_rec->packet_life_time_selector = IB_SA_EQ;
+       route->path_rec->packet_life_time = CMA_IBOE_PACKET_LIFETIME;
+       if (!route->path_rec->mtu) {
+               ret = -EINVAL;
+               goto err2;
+       }
+
+       work->old_state = CMA_ROUTE_QUERY;
+       work->new_state = CMA_ROUTE_RESOLVED;
+       work->event.event = RDMA_CM_EVENT_ROUTE_RESOLVED;
+       work->event.status = 0;
+
+       queue_work(cma_wq, &work->work);
+
+       return 0;
+
+err2:
+       kfree(route->path_rec);
+       route->path_rec = NULL;
+err1:
+       kfree(work);
+       return ret;
+}
+
 int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
 {
        struct rdma_id_private *id_priv;
@@ -1720,7 +1869,16 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
        atomic_inc(&id_priv->refcount);
        switch (rdma_node_get_transport(id->device->node_type)) {
        case RDMA_TRANSPORT_IB:
-               ret = cma_resolve_ib_route(id_priv, timeout_ms);
+               switch (rdma_port_get_link_layer(id->device, id->port_num)) {
+               case IB_LINK_LAYER_INFINIBAND:
+                       ret = cma_resolve_ib_route(id_priv, timeout_ms);
+                       break;
+               case IB_LINK_LAYER_ETHERNET:
+                       ret = cma_resolve_iboe_route(id_priv);
+                       break;
+               default:
+                       ret = -ENOSYS;
+               }
                break;
        case RDMA_TRANSPORT_IWARP:
                ret = cma_resolve_iw_route(id_priv, timeout_ms);
@@ -1773,7 +1931,7 @@ port_found:
                goto out;
 
        id_priv->id.route.addr.dev_addr.dev_type =
-               (rdma_node_get_transport(cma_dev->device->node_type) == RDMA_TRANSPORT_IB) ?
+               (rdma_port_get_link_layer(cma_dev->device, p) == IB_LINK_LAYER_INFINIBAND) ?
                ARPHRD_INFINIBAND : ARPHRD_ETHER;
 
        rdma_addr_set_sgid(&id_priv->id.route.addr.dev_addr, &gid);
@@ -2758,6 +2916,102 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
        return 0;
 }
 
+static void iboe_mcast_work_handler(struct work_struct *work)
+{
+       struct iboe_mcast_work *mw = container_of(work, struct iboe_mcast_work, work);
+       struct cma_multicast *mc = mw->mc;
+       struct ib_sa_multicast *m = mc->multicast.ib;
+
+       mc->multicast.ib->context = mc;
+       cma_ib_mc_handler(0, m);
+       kref_put(&mc->mcref, release_mc);
+       kfree(mw);
+}
+
+static void cma_iboe_set_mgid(struct sockaddr *addr, union ib_gid *mgid)
+{
+       struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+
+       if (cma_any_addr(addr)) {
+               memset(mgid, 0, sizeof *mgid);
+       } else if (addr->sa_family == AF_INET6) {
+               memcpy(mgid, &sin6->sin6_addr, sizeof *mgid);
+       } else {
+               mgid->raw[0] = 0xff;
+               mgid->raw[1] = 0x0e;
+               mgid->raw[2] = 0;
+               mgid->raw[3] = 0;
+               mgid->raw[4] = 0;
+               mgid->raw[5] = 0;
+               mgid->raw[6] = 0;
+               mgid->raw[7] = 0;
+               mgid->raw[8] = 0;
+               mgid->raw[9] = 0;
+               mgid->raw[10] = 0xff;
+               mgid->raw[11] = 0xff;
+               *(__be32 *)(&mgid->raw[12]) = sin->sin_addr.s_addr;
+       }
+}
+
+static int cma_iboe_join_multicast(struct rdma_id_private *id_priv,
+                                  struct cma_multicast *mc)
+{
+       struct iboe_mcast_work *work;
+       struct rdma_dev_addr *dev_addr = &id_priv->id.route.addr.dev_addr;
+       int err;
+       struct sockaddr *addr = (struct sockaddr *)&mc->addr;
+       struct net_device *ndev = NULL;
+
+       if (cma_zero_addr((struct sockaddr *)&mc->addr))
+               return -EINVAL;
+
+       work = kzalloc(sizeof *work, GFP_KERNEL);
+       if (!work)
+               return -ENOMEM;
+
+       mc->multicast.ib = kzalloc(sizeof(struct ib_sa_multicast), GFP_KERNEL);
+       if (!mc->multicast.ib) {
+               err = -ENOMEM;
+               goto out1;
+       }
+
+       cma_iboe_set_mgid(addr, &mc->multicast.ib->rec.mgid);
+
+       mc->multicast.ib->rec.pkey = cpu_to_be16(0xffff);
+       if (id_priv->id.ps == RDMA_PS_UDP)
+               mc->multicast.ib->rec.qkey = cpu_to_be32(RDMA_UDP_QKEY);
+
+       if (dev_addr->bound_dev_if)
+               ndev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+       if (!ndev) {
+               err = -ENODEV;
+               goto out2;
+       }
+       mc->multicast.ib->rec.rate = iboe_get_rate(ndev);
+       mc->multicast.ib->rec.hop_limit = 1;
+       mc->multicast.ib->rec.mtu = iboe_get_mtu(ndev->mtu);
+       dev_put(ndev);
+       if (!mc->multicast.ib->rec.mtu) {
+               err = -EINVAL;
+               goto out2;
+       }
+       iboe_addr_get_sgid(dev_addr, &mc->multicast.ib->rec.port_gid);
+       work->id = id_priv;
+       work->mc = mc;
+       INIT_WORK(&work->work, iboe_mcast_work_handler);
+       kref_get(&mc->mcref);
+       queue_work(cma_wq, &work->work);
+
+       return 0;
+
+out2:
+       kfree(mc->multicast.ib);
+out1:
+       kfree(work);
+       return err;
+}
+
 int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
                        void *context)
 {
@@ -2784,7 +3038,17 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
 
        switch (rdma_node_get_transport(id->device->node_type)) {
        case RDMA_TRANSPORT_IB:
-               ret = cma_join_ib_multicast(id_priv, mc);
+               switch (rdma_port_get_link_layer(id->device, id->port_num)) {
+               case IB_LINK_LAYER_INFINIBAND:
+                       ret = cma_join_ib_multicast(id_priv, mc);
+                       break;
+               case IB_LINK_LAYER_ETHERNET:
+                       kref_init(&mc->mcref);
+                       ret = cma_iboe_join_multicast(id_priv, mc);
+                       break;
+               default:
+                       ret = -EINVAL;
+               }
                break;
        default:
                ret = -ENOSYS;
@@ -2817,8 +3081,19 @@ void rdma_leave_multicast(struct rdma_cm_id *id, struct sockaddr *addr)
                                ib_detach_mcast(id->qp,
                                                &mc->multicast.ib->rec.mgid,
                                                mc->multicast.ib->rec.mlid);
-                       ib_sa_free_multicast(mc->multicast.ib);
-                       kfree(mc);
+                       if (rdma_node_get_transport(id_priv->cma_dev->device->node_type) == RDMA_TRANSPORT_IB) {
+                               switch (rdma_port_get_link_layer(id->device, id->port_num)) {
+                               case IB_LINK_LAYER_INFINIBAND:
+                                       ib_sa_free_multicast(mc->multicast.ib);
+                                       kfree(mc);
+                                       break;
+                               case IB_LINK_LAYER_ETHERNET:
+                                       kref_put(&mc->mcref, release_mc);
+                                       break;
+                               default:
+                                       break;
+                               }
+                       }
                        return;
                }
        }
index bfead5b..2a1e9ae 100644 (file)
@@ -506,6 +506,8 @@ int iw_cm_accept(struct iw_cm_id *cm_id,
        qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
        if (!qp) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+               wake_up_all(&cm_id_priv->connect_wait);
                return -EINVAL;
        }
        cm_id->device->iwcm->add_ref(qp);
@@ -565,6 +567,8 @@ int iw_cm_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *iw_param)
        qp = cm_id->device->iwcm->get_qp(cm_id->device, iw_param->qpn);
        if (!qp) {
                spin_unlock_irqrestore(&cm_id_priv->lock, flags);
+               clear_bit(IWCM_F_CONNECT_WAIT, &cm_id_priv->flags);
+               wake_up_all(&cm_id_priv->connect_wait);
                return -EINVAL;
        }
        cm_id->device->iwcm->add_ref(qp);
index ef1304f..822cfdc 100644 (file)
@@ -2598,6 +2598,9 @@ static void cleanup_recv_queue(struct ib_mad_qp_info *qp_info)
        struct ib_mad_private *recv;
        struct ib_mad_list_head *mad_list;
 
+       if (!qp_info->qp)
+               return;
+
        while (!list_empty(&qp_info->recv_queue.list)) {
 
                mad_list = list_entry(qp_info->recv_queue.list.next,
@@ -2639,6 +2642,9 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
 
        for (i = 0; i < IB_MAD_QPS_CORE; i++) {
                qp = port_priv->qp_info[i].qp;
+               if (!qp)
+                       continue;
+
                /*
                 * PKey index for QP1 is irrelevant but
                 * one is needed for the Reset to Init transition
@@ -2680,6 +2686,9 @@ static int ib_mad_port_start(struct ib_mad_port_private *port_priv)
        }
 
        for (i = 0; i < IB_MAD_QPS_CORE; i++) {
+               if (!port_priv->qp_info[i].qp)
+                       continue;
+
                ret = ib_mad_post_receive_mads(&port_priv->qp_info[i], NULL);
                if (ret) {
                        printk(KERN_ERR PFX "Couldn't post receive WRs\n");
@@ -2758,6 +2767,9 @@ error:
 
 static void destroy_mad_qp(struct ib_mad_qp_info *qp_info)
 {
+       if (!qp_info->qp)
+               return;
+
        ib_destroy_qp(qp_info->qp);
        kfree(qp_info->snoop_table);
 }
@@ -2773,6 +2785,7 @@ static int ib_mad_port_open(struct ib_device *device,
        struct ib_mad_port_private *port_priv;
        unsigned long flags;
        char name[sizeof "ib_mad123"];
+       int has_smi;
 
        /* Create new device info */
        port_priv = kzalloc(sizeof *port_priv, GFP_KERNEL);
@@ -2788,7 +2801,11 @@ static int ib_mad_port_open(struct ib_device *device,
        init_mad_qp(port_priv, &port_priv->qp_info[0]);
        init_mad_qp(port_priv, &port_priv->qp_info[1]);
 
-       cq_size = (mad_sendq_size + mad_recvq_size) * 2;
+       cq_size = mad_sendq_size + mad_recvq_size;
+       has_smi = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_INFINIBAND;
+       if (has_smi)
+               cq_size *= 2;
+
        port_priv->cq = ib_create_cq(port_priv->device,
                                     ib_mad_thread_completion_handler,
                                     NULL, port_priv, cq_size, 0);
@@ -2812,9 +2829,11 @@ static int ib_mad_port_open(struct ib_device *device,
                goto error5;
        }
 
-       ret = create_mad_qp(&port_priv->qp_info[0], IB_QPT_SMI);
-       if (ret)
-               goto error6;
+       if (has_smi) {
+               ret = create_mad_qp(&port_priv->qp_info[0], IB_QPT_SMI);
+               if (ret)
+                       goto error6;
+       }
        ret = create_mad_qp(&port_priv->qp_info[1], IB_QPT_GSI);
        if (ret)
                goto error7;
index a519801..68b4162 100644 (file)
@@ -774,6 +774,10 @@ static void mcast_event_handler(struct ib_event_handler *handler,
        int index;
 
        dev = container_of(handler, struct mcast_device, event_handler);
+       if (rdma_port_get_link_layer(dev->device, event->element.port_num) !=
+           IB_LINK_LAYER_INFINIBAND)
+               return;
+
        index = event->element.port_num - dev->start_port;
 
        switch (event->event) {
@@ -796,6 +800,7 @@ static void mcast_add_one(struct ib_device *device)
        struct mcast_device *dev;
        struct mcast_port *port;
        int i;
+       int count = 0;
 
        if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
                return;
@@ -813,6 +818,9 @@ static void mcast_add_one(struct ib_device *device)
        }
 
        for (i = 0; i <= dev->end_port - dev->start_port; i++) {
+               if (rdma_port_get_link_layer(device, dev->start_port + i) !=
+                   IB_LINK_LAYER_INFINIBAND)
+                       continue;
                port = &dev->port[i];
                port->dev = dev;
                port->port_num = dev->start_port + i;
@@ -820,6 +828,12 @@ static void mcast_add_one(struct ib_device *device)
                port->table = RB_ROOT;
                init_completion(&port->comp);
                atomic_set(&port->refcount, 1);
+               ++count;
+       }
+
+       if (!count) {
+               kfree(dev);
+               return;
        }
 
        dev->device = device;
@@ -843,9 +857,12 @@ static void mcast_remove_one(struct ib_device *device)
        flush_workqueue(mcast_wq);
 
        for (i = 0; i <= dev->end_port - dev->start_port; i++) {
-               port = &dev->port[i];
-               deref_port(port);
-               wait_for_completion(&port->comp);
+               if (rdma_port_get_link_layer(device, dev->start_port + i) ==
+                   IB_LINK_LAYER_INFINIBAND) {
+                       port = &dev->port[i];
+                       deref_port(port);
+                       wait_for_completion(&port->comp);
+               }
        }
 
        kfree(dev);
index 7e1ffd8..91a6603 100644 (file)
@@ -416,6 +416,9 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
                struct ib_sa_port *port =
                        &sa_dev->port[event->element.port_num - sa_dev->start_port];
 
+               if (rdma_port_get_link_layer(handler->device, port->port_num) != IB_LINK_LAYER_INFINIBAND)
+                       return;
+
                spin_lock_irqsave(&port->ah_lock, flags);
                if (port->sm_ah)
                        kref_put(&port->sm_ah->ref, free_sm_ah);
@@ -493,6 +496,7 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
 {
        int ret;
        u16 gid_index;
+       int force_grh;
 
        memset(ah_attr, 0, sizeof *ah_attr);
        ah_attr->dlid = be16_to_cpu(rec->dlid);
@@ -502,7 +506,9 @@ int ib_init_ah_from_path(struct ib_device *device, u8 port_num,
        ah_attr->port_num = port_num;
        ah_attr->static_rate = rec->rate;
 
-       if (rec->hop_limit > 1) {
+       force_grh = rdma_port_get_link_layer(device, port_num) == IB_LINK_LAYER_ETHERNET;
+
+       if (rec->hop_limit > 1 || force_grh) {
                ah_attr->ah_flags = IB_AH_GRH;
                ah_attr->grh.dgid = rec->dgid;
 
@@ -1007,7 +1013,7 @@ static void ib_sa_add_one(struct ib_device *device)
                e = device->phys_port_cnt;
        }
 
-       sa_dev = kmalloc(sizeof *sa_dev +
+       sa_dev = kzalloc(sizeof *sa_dev +
                         (e - s + 1) * sizeof (struct ib_sa_port),
                         GFP_KERNEL);
        if (!sa_dev)
@@ -1017,9 +1023,12 @@ static void ib_sa_add_one(struct ib_device *device)
        sa_dev->end_port   = e;
 
        for (i = 0; i <= e - s; ++i) {
+               spin_lock_init(&sa_dev->port[i].ah_lock);
+               if (rdma_port_get_link_layer(device, i + 1) != IB_LINK_LAYER_INFINIBAND)
+                       continue;
+
                sa_dev->port[i].sm_ah    = NULL;
                sa_dev->port[i].port_num = i + s;
-               spin_lock_init(&sa_dev->port[i].ah_lock);
 
                sa_dev->port[i].agent =
                        ib_register_mad_agent(device, i + s, IB_QPT_GSI,
@@ -1045,13 +1054,15 @@ static void ib_sa_add_one(struct ib_device *device)
                goto err;
 
        for (i = 0; i <= e - s; ++i)
-               update_sm_ah(&sa_dev->port[i].update_task);
+               if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND)
+                       update_sm_ah(&sa_dev->port[i].update_task);
 
        return;
 
 err:
        while (--i >= 0)
-               ib_unregister_mad_agent(sa_dev->port[i].agent);
+               if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND)
+                       ib_unregister_mad_agent(sa_dev->port[i].agent);
 
        kfree(sa_dev);
 
@@ -1071,9 +1082,12 @@ static void ib_sa_remove_one(struct ib_device *device)
        flush_scheduled_work();
 
        for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
-               ib_unregister_mad_agent(sa_dev->port[i].agent);
-               if (sa_dev->port[i].sm_ah)
-                       kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+               if (rdma_port_get_link_layer(device, i + 1) == IB_LINK_LAYER_INFINIBAND) {
+                       ib_unregister_mad_agent(sa_dev->port[i].agent);
+                       if (sa_dev->port[i].sm_ah)
+                               kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+               }
+
        }
 
        kfree(sa_dev);
index 3627300..9ab5df7 100644 (file)
@@ -222,6 +222,19 @@ static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused,
        }
 }
 
+static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,
+                              char *buf)
+{
+       switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) {
+       case IB_LINK_LAYER_INFINIBAND:
+               return sprintf(buf, "%s\n", "InfiniBand");
+       case IB_LINK_LAYER_ETHERNET:
+               return sprintf(buf, "%s\n", "Ethernet");
+       default:
+               return sprintf(buf, "%s\n", "Unknown");
+       }
+}
+
 static PORT_ATTR_RO(state);
 static PORT_ATTR_RO(lid);
 static PORT_ATTR_RO(lid_mask_count);
@@ -230,6 +243,7 @@ static PORT_ATTR_RO(sm_sl);
 static PORT_ATTR_RO(cap_mask);
 static PORT_ATTR_RO(rate);
 static PORT_ATTR_RO(phys_state);
+static PORT_ATTR_RO(link_layer);
 
 static struct attribute *port_default_attrs[] = {
        &port_attr_state.attr,
@@ -240,6 +254,7 @@ static struct attribute *port_default_attrs[] = {
        &port_attr_cap_mask.attr,
        &port_attr_rate.attr,
        &port_attr_phys_state.attr,
+       &port_attr_link_layer.attr,
        NULL
 };
 
index ac7edc2..ca12acf 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/in6.h>
 #include <linux/miscdevice.h>
 #include <linux/slab.h>
+#include <linux/sysctl.h>
 
 #include <rdma/rdma_user_cm.h>
 #include <rdma/ib_marshall.h>
@@ -50,8 +51,24 @@ MODULE_AUTHOR("Sean Hefty");
 MODULE_DESCRIPTION("RDMA Userspace Connection Manager Access");
 MODULE_LICENSE("Dual BSD/GPL");
 
-enum {
-       UCMA_MAX_BACKLOG        = 128
+static unsigned int max_backlog = 1024;
+
+static struct ctl_table_header *ucma_ctl_table_hdr;
+static ctl_table ucma_ctl_table[] = {
+       {
+               .procname       = "max_backlog",
+               .data           = &max_backlog,
+               .maxlen         = sizeof max_backlog,
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
+       { }
+};
+
+static struct ctl_path ucma_ctl_path[] = {
+       { .procname = "net" },
+       { .procname = "rdma_ucm" },
+       { }
 };
 
 struct ucma_file {
@@ -583,6 +600,42 @@ static void ucma_copy_ib_route(struct rdma_ucm_query_route_resp *resp,
        }
 }
 
+static void ucma_copy_iboe_route(struct rdma_ucm_query_route_resp *resp,
+                                struct rdma_route *route)
+{
+       struct rdma_dev_addr *dev_addr;
+       struct net_device *dev;
+       u16 vid = 0;
+
+       resp->num_paths = route->num_paths;
+       switch (route->num_paths) {
+       case 0:
+               dev_addr = &route->addr.dev_addr;
+               dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+                       if (dev) {
+                               vid = rdma_vlan_dev_vlan_id(dev);
+                               dev_put(dev);
+                       }
+
+               iboe_mac_vlan_to_ll((union ib_gid *) &resp->ib_route[0].dgid,
+                                   dev_addr->dst_dev_addr, vid);
+               iboe_addr_get_sgid(dev_addr,
+                                  (union ib_gid *) &resp->ib_route[0].sgid);
+               resp->ib_route[0].pkey = cpu_to_be16(0xffff);
+               break;
+       case 2:
+               ib_copy_path_rec_to_user(&resp->ib_route[1],
+                                        &route->path_rec[1]);
+               /* fall through */
+       case 1:
+               ib_copy_path_rec_to_user(&resp->ib_route[0],
+                                        &route->path_rec[0]);
+               break;
+       default:
+               break;
+       }
+}
+
 static ssize_t ucma_query_route(struct ucma_file *file,
                                const char __user *inbuf,
                                int in_len, int out_len)
@@ -617,12 +670,17 @@ static ssize_t ucma_query_route(struct ucma_file *file,
 
        resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
        resp.port_num = ctx->cm_id->port_num;
-       switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
-       case RDMA_TRANSPORT_IB:
-               ucma_copy_ib_route(&resp, &ctx->cm_id->route);
-               break;
-       default:
-               break;
+       if (rdma_node_get_transport(ctx->cm_id->device->node_type) == RDMA_TRANSPORT_IB) {
+               switch (rdma_port_get_link_layer(ctx->cm_id->device, ctx->cm_id->port_num)) {
+               case IB_LINK_LAYER_INFINIBAND:
+                       ucma_copy_ib_route(&resp, &ctx->cm_id->route);
+                       break;
+               case IB_LINK_LAYER_ETHERNET:
+                       ucma_copy_iboe_route(&resp, &ctx->cm_id->route);
+                       break;
+               default:
+                       break;
+               }
        }
 
 out:
@@ -686,8 +744,8 @@ static ssize_t ucma_listen(struct ucma_file *file, const char __user *inbuf,
        if (IS_ERR(ctx))
                return PTR_ERR(ctx);
 
-       ctx->backlog = cmd.backlog > 0 && cmd.backlog < UCMA_MAX_BACKLOG ?
-                      cmd.backlog : UCMA_MAX_BACKLOG;
+       ctx->backlog = cmd.backlog > 0 && cmd.backlog < max_backlog ?
+                      cmd.backlog : max_backlog;
        ret = rdma_listen(ctx->cm_id, ctx->backlog);
        ucma_put_ctx(ctx);
        return ret;
@@ -1279,16 +1337,26 @@ static int __init ucma_init(void)
        ret = device_create_file(ucma_misc.this_device, &dev_attr_abi_version);
        if (ret) {
                printk(KERN_ERR "rdma_ucm: couldn't create abi_version attr\n");
-               goto err;
+               goto err1;
+       }
+
+       ucma_ctl_table_hdr = register_sysctl_paths(ucma_ctl_path, ucma_ctl_table);
+       if (!ucma_ctl_table_hdr) {
+               printk(KERN_ERR "rdma_ucm: couldn't register sysctl paths\n");
+               ret = -ENOMEM;
+               goto err2;
        }
        return 0;
-err:
+err2:
+       device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
+err1:
        misc_deregister(&ucma_misc);
        return ret;
 }
 
 static void __exit ucma_cleanup(void)
 {
+       unregister_sysctl_table(ucma_ctl_table_hdr);
        device_remove_file(ucma_misc.this_device, &dev_attr_abi_version);
        misc_deregister(&ucma_misc);
        idr_destroy(&ctx_idr);
index 650b501..bb7e192 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/if_ether.h>
 
 #include <rdma/ib_pack.h>
 
@@ -80,6 +81,40 @@ static const struct ib_field lrh_table[]  = {
          .size_bits    = 16 }
 };
 
+static const struct ib_field eth_table[]  = {
+       { STRUCT_FIELD(eth, dmac_h),
+         .offset_words = 0,
+         .offset_bits  = 0,
+         .size_bits    = 32 },
+       { STRUCT_FIELD(eth, dmac_l),
+         .offset_words = 1,
+         .offset_bits  = 0,
+         .size_bits    = 16 },
+       { STRUCT_FIELD(eth, smac_h),
+         .offset_words = 1,
+         .offset_bits  = 16,
+         .size_bits    = 16 },
+       { STRUCT_FIELD(eth, smac_l),
+         .offset_words = 2,
+         .offset_bits  = 0,
+         .size_bits    = 32 },
+       { STRUCT_FIELD(eth, type),
+         .offset_words = 3,
+         .offset_bits  = 0,
+         .size_bits    = 16 }
+};
+
+static const struct ib_field vlan_table[]  = {
+       { STRUCT_FIELD(vlan, tag),
+         .offset_words = 0,
+         .offset_bits  = 0,
+         .size_bits    = 16 },
+       { STRUCT_FIELD(vlan, type),
+         .offset_words = 0,
+         .offset_bits  = 16,
+         .size_bits    = 16 }
+};
+
 static const struct ib_field grh_table[]  = {
        { STRUCT_FIELD(grh, ip_version),
          .offset_words = 0,
@@ -180,38 +215,43 @@ static const struct ib_field deth_table[] = {
 /**
  * ib_ud_header_init - Initialize UD header structure
  * @payload_bytes:Length of packet payload
+ * @lrh_present: specify if LRH is present
+ * @eth_present: specify if Eth header is present
+ * @vlan_present: packet is tagged vlan
  * @grh_present:GRH flag (if non-zero, GRH will be included)
- * @immediate_present: specify if immediate data should be used
+ * @immediate_present: specify if immediate data is present
  * @header:Structure to initialize
- *
- * ib_ud_header_init() initializes the lrh.link_version, lrh.link_next_header,
- * lrh.packet_length, grh.ip_version, grh.payload_length,
- * grh.next_header, bth.opcode, bth.pad_count and
- * bth.transport_header_version fields of a &struct ib_ud_header given
- * the payload length and whether a GRH will be included.
  */
 void ib_ud_header_init(int                         payload_bytes,
+                      int                  lrh_present,
+                      int                  eth_present,
+                      int                  vlan_present,
                       int                  grh_present,
                       int                  immediate_present,
                       struct ib_ud_header *header)
 {
-       u16 packet_length;
-
        memset(header, 0, sizeof *header);
 
-       header->lrh.link_version     = 0;
-       header->lrh.link_next_header =
-               grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
-       packet_length                = (IB_LRH_BYTES     +
-                                       IB_BTH_BYTES     +
-                                       IB_DETH_BYTES    +
-                                       payload_bytes    +
-                                       4                + /* ICRC     */
-                                       3) / 4;            /* round up */
-
-       header->grh_present          = grh_present;
+       if (lrh_present) {
+               u16 packet_length;
+
+               header->lrh.link_version     = 0;
+               header->lrh.link_next_header =
+                       grh_present ? IB_LNH_IBA_GLOBAL : IB_LNH_IBA_LOCAL;
+               packet_length = (IB_LRH_BYTES   +
+                                IB_BTH_BYTES   +
+                                IB_DETH_BYTES  +
+                                (grh_present ? IB_GRH_BYTES : 0) +
+                                payload_bytes  +
+                                4              + /* ICRC     */
+                                3) / 4;          /* round up */
+               header->lrh.packet_length = cpu_to_be16(packet_length);
+       }
+
+       if (vlan_present)
+               header->eth.type = cpu_to_be16(ETH_P_8021Q);
+
        if (grh_present) {
-               packet_length              += IB_GRH_BYTES / 4;
                header->grh.ip_version      = 6;
                header->grh.payload_length  =
                        cpu_to_be16((IB_BTH_BYTES     +
@@ -222,19 +262,52 @@ void ib_ud_header_init(int                    payload_bytes,
                header->grh.next_header     = 0x1b;
        }
 
-       header->lrh.packet_length = cpu_to_be16(packet_length);
-
-       header->immediate_present            = immediate_present;
        if (immediate_present)
                header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE;
        else
                header->bth.opcode           = IB_OPCODE_UD_SEND_ONLY;
        header->bth.pad_count                = (4 - payload_bytes) & 3;
        header->bth.transport_header_version = 0;
+
+       header->lrh_present = lrh_present;
+       header->eth_present = eth_present;
+       header->vlan_present = vlan_present;
+       header->grh_present = grh_present;
+       header->immediate_present = immediate_present;
 }
 EXPORT_SYMBOL(ib_ud_header_init);
 
 /**
+ * ib_lrh_header_pack - Pack LRH header struct into wire format
+ * @lrh:unpacked LRH header struct
+ * @buf:Buffer to pack into
+ *
+ * ib_lrh_header_pack() packs the LRH header structure @lrh into
+ * wire format in the buffer @buf.
+ */
+int ib_lrh_header_pack(struct ib_unpacked_lrh *lrh, void *buf)
+{
+       ib_pack(lrh_table, ARRAY_SIZE(lrh_table), lrh, buf);
+       return 0;
+}
+EXPORT_SYMBOL(ib_lrh_header_pack);
+
+/**
+ * ib_lrh_header_unpack - Unpack LRH structure from wire format
+ * @lrh:unpacked LRH header struct
+ * @buf:Buffer to pack into
+ *
+ * ib_lrh_header_unpack() unpacks the LRH header structure from
+ * wire format (in buf) into @lrh.
+ */
+int ib_lrh_header_unpack(void *buf, struct ib_unpacked_lrh *lrh)
+{
+       ib_unpack(lrh_table, ARRAY_SIZE(lrh_table), buf, lrh);
+       return 0;
+}
+EXPORT_SYMBOL(ib_lrh_header_unpack);
+
+/**
  * ib_ud_header_pack - Pack UD header struct into wire format
  * @header:UD header struct
  * @buf:Buffer to pack into
@@ -247,10 +320,21 @@ int ib_ud_header_pack(struct ib_ud_header *header,
 {
        int len = 0;
 
-       ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
-               &header->lrh, buf);
-       len += IB_LRH_BYTES;
-
+       if (header->lrh_present) {
+               ib_pack(lrh_table, ARRAY_SIZE(lrh_table),
+                       &header->lrh, buf + len);
+               len += IB_LRH_BYTES;
+       }
+       if (header->eth_present) {
+               ib_pack(eth_table, ARRAY_SIZE(eth_table),
+                       &header->eth, buf + len);
+               len += IB_ETH_BYTES;
+       }
+       if (header->vlan_present) {
+               ib_pack(vlan_table, ARRAY_SIZE(vlan_table),
+                       &header->vlan, buf + len);
+               len += IB_VLAN_BYTES;
+       }
        if (header->grh_present) {
                ib_pack(grh_table, ARRAY_SIZE(grh_table),
                        &header->grh, buf + len);
index 5fa8569..cd1996d 100644 (file)
@@ -1022,7 +1022,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
 
        port->ib_dev   = device;
        port->port_num = port_num;
-       init_MUTEX(&port->sm_sem);
+       sema_init(&port->sm_sem, 1);
        mutex_init(&port->file_mutex);
        INIT_LIST_HEAD(&port->file_list);
 
index 6fcfbeb..b342248 100644 (file)
@@ -460,6 +460,8 @@ ssize_t ib_uverbs_query_port(struct ib_uverbs_file *file,
        resp.active_width    = attr.active_width;
        resp.active_speed    = attr.active_speed;
        resp.phys_state      = attr.phys_state;
+       resp.link_layer      = rdma_port_get_link_layer(file->device->ib_dev,
+                                                       cmd.port_num);
 
        if (copy_to_user((void __user *) (unsigned long) cmd.response,
                         &resp, sizeof resp))
index e0fa222..af7a8b0 100644 (file)
@@ -94,6 +94,22 @@ rdma_node_get_transport(enum rdma_node_type node_type)
 }
 EXPORT_SYMBOL(rdma_node_get_transport);
 
+enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device, u8 port_num)
+{
+       if (device->get_link_layer)
+               return device->get_link_layer(device, port_num);
+
+       switch (rdma_node_get_transport(device->node_type)) {
+       case RDMA_TRANSPORT_IB:
+               return IB_LINK_LAYER_INFINIBAND;
+       case RDMA_TRANSPORT_IWARP:
+               return IB_LINK_LAYER_ETHERNET;
+       default:
+               return IB_LINK_LAYER_UNSPECIFIED;
+       }
+}
+EXPORT_SYMBOL(rdma_port_get_link_layer);
+
 /* Protection domains */
 
 struct ib_pd *ib_alloc_pd(struct ib_device *device)
index 06964c4..950dfab 100644 (file)
@@ -1,6 +1,4 @@
-ifdef CONFIG_INFINIBAND_AMSO1100_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_INFINIBAND_AMSO1100_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_INFINIBAND_AMSO1100) += iw_c2.o
 
index 3b50954..0ebe4e8 100644 (file)
@@ -62,8 +62,8 @@ void c2_rnic_interrupt(struct c2_dev *c2dev)
 static void handle_mq(struct c2_dev *c2dev, u32 mq_index)
 {
        if (c2dev->qptr_array[mq_index] == NULL) {
-               pr_debug(KERN_INFO "handle_mq: stray activity for mq_index=%d\n",
-                       mq_index);
+               pr_debug("handle_mq: stray activity for mq_index=%d\n",
+                        mq_index);
                return;
        }
 
index 7e7b5a6..621619c 100644 (file)
@@ -1,10 +1,8 @@
-EXTRA_CFLAGS += -Idrivers/net/cxgb3
+ccflags-y := -Idrivers/net/cxgb3
 
 obj-$(CONFIG_INFINIBAND_CXGB3) += iw_cxgb3.o
 
 iw_cxgb3-y :=  iwch_cm.o iwch_ev.o iwch_cq.o iwch_qp.o iwch_mem.o \
               iwch_provider.o iwch.o cxio_hal.o cxio_resource.o
 
-ifdef CONFIG_INFINIBAND_CXGB3_DEBUG
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_INFINIBAND_CXGB3_DEBUG) += -DDEBUG
index 005b7b5..09dda0b 100644 (file)
@@ -160,6 +160,7 @@ int cxio_create_cq(struct cxio_rdev *rdev_p, struct t3_cq *cq, int kernel)
        struct rdma_cq_setup setup;
        int size = (1UL << (cq->size_log2)) * sizeof(struct t3_cqe);
 
+       size += 1; /* one extra page for storing cq-in-err state */
        cq->cqid = cxio_hal_get_cqid(rdev_p->rscp);
        if (!cq->cqid)
                return -ENOMEM;
index e5ddb63..4bb997a 100644 (file)
@@ -728,6 +728,22 @@ struct t3_cq {
 #define CQ_VLD_ENTRY(ptr,size_log2,cqe) (Q_GENBIT(ptr,size_log2) == \
                                         CQE_GENBIT(*cqe))
 
+struct t3_cq_status_page {
+       u32 cq_err;
+};
+
+static inline int cxio_cq_in_error(struct t3_cq *cq)
+{
+       return ((struct t3_cq_status_page *)
+               &cq->queue[1 << cq->size_log2])->cq_err;
+}
+
+static inline void cxio_set_cq_in_error(struct t3_cq *cq)
+{
+       ((struct t3_cq_status_page *)
+        &cq->queue[1 << cq->size_log2])->cq_err = 1;
+}
+
 static inline void cxio_set_wq_in_error(struct t3_wq *wq)
 {
        wq->queue->wq_in_err.err |= 1;
index 13c8887..d02dcc6 100644 (file)
@@ -1093,8 +1093,8 @@ static int tx_ack(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
        PDBG("%s ep %p credits %u\n", __func__, ep, credits);
 
        if (credits == 0) {
-               PDBG(KERN_ERR "%s 0 credit ack  ep %p state %u\n",
-                       __func__, ep, state_read(&ep->com));
+               PDBG("%s 0 credit ack  ep %p state %u\n",
+                    __func__, ep, state_read(&ep->com));
                return CPL_RET_BUF_DONE;
        }
 
index 6afc89e..71e0d84 100644 (file)
@@ -76,6 +76,14 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
        atomic_inc(&qhp->refcnt);
        spin_unlock(&rnicp->lock);
 
+       if (qhp->attr.state == IWCH_QP_STATE_RTS) {
+               attrs.next_state = IWCH_QP_STATE_TERMINATE;
+               iwch_modify_qp(qhp->rhp, qhp, IWCH_QP_ATTR_NEXT_STATE,
+                              &attrs, 1);
+               if (send_term)
+                       iwch_post_terminate(qhp, rsp_msg);
+       }
+
        event.event = ib_event;
        event.device = chp->ibcq.device;
        if (ib_event == IB_EVENT_CQ_ERR)
@@ -86,13 +94,7 @@ static void post_qp_event(struct iwch_dev *rnicp, struct iwch_cq *chp,
        if (qhp->ibqp.event_handler)
                (*qhp->ibqp.event_handler)(&event, qhp->ibqp.qp_context);
 
-       if (qhp->attr.state == IWCH_QP_STATE_RTS) {
-               attrs.next_state = IWCH_QP_STATE_TERMINATE;
-               iwch_modify_qp(qhp->rhp, qhp, IWCH_QP_ATTR_NEXT_STATE,
-                              &attrs, 1);
-               if (send_term)
-                       iwch_post_terminate(qhp, rsp_msg);
-       }
+       (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
 
        if (atomic_dec_and_test(&qhp->refcnt))
                wake_up(&qhp->wait);
@@ -179,7 +181,6 @@ void iwch_ev_dispatch(struct cxio_rdev *rdev_p, struct sk_buff *skb)
        case TPT_ERR_BOUND:
        case TPT_ERR_INVALIDATE_SHARED_MR:
        case TPT_ERR_INVALIDATE_MR_WITH_MW_BOUND:
-               (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
                post_qp_event(rnicp, chp, rsp_msg, IB_EVENT_QP_ACCESS_ERR, 1);
                break;
 
index fca0b4b..2e27413 100644 (file)
@@ -154,6 +154,8 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
        struct iwch_create_cq_resp uresp;
        struct iwch_create_cq_req ureq;
        struct iwch_ucontext *ucontext = NULL;
+       static int warned;
+       size_t resplen;
 
        PDBG("%s ib_dev %p entries %d\n", __func__, ibdev, entries);
        rhp = to_iwch_dev(ibdev);
@@ -217,15 +219,26 @@ static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, int ve
                uresp.key = ucontext->key;
                ucontext->key += PAGE_SIZE;
                spin_unlock(&ucontext->mmap_lock);
-               if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) {
+               mm->key = uresp.key;
+               mm->addr = virt_to_phys(chp->cq.queue);
+               if (udata->outlen < sizeof uresp) {
+                       if (!warned++)
+                               printk(KERN_WARNING MOD "Warning - "
+                                      "downlevel libcxgb3 (non-fatal).\n");
+                       mm->len = PAGE_ALIGN((1UL << uresp.size_log2) *
+                                            sizeof(struct t3_cqe));
+                       resplen = sizeof(struct iwch_create_cq_resp_v0);
+               } else {
+                       mm->len = PAGE_ALIGN(((1UL << uresp.size_log2) + 1) *
+                                            sizeof(struct t3_cqe));
+                       uresp.memsize = mm->len;
+                       resplen = sizeof uresp;
+               }
+               if (ib_copy_to_udata(udata, &uresp, resplen)) {
                        kfree(mm);
                        iwch_destroy_cq(&chp->ibcq);
                        return ERR_PTR(-EFAULT);
                }
-               mm->key = uresp.key;
-               mm->addr = virt_to_phys(chp->cq.queue);
-               mm->len = PAGE_ALIGN((1UL << uresp.size_log2) *
-                                            sizeof (struct t3_cqe));
                insert_mmap(ucontext, mm);
        }
        PDBG("created cqid 0x%0x chp %p size 0x%0x, dma_addr 0x%0llx\n",
@@ -1414,6 +1427,7 @@ int iwch_register_device(struct iwch_dev *dev)
        dev->ibdev.post_send = iwch_post_send;
        dev->ibdev.post_recv = iwch_post_receive;
        dev->ibdev.get_protocol_stats = iwch_get_mib;
+       dev->ibdev.uverbs_abi_ver = IWCH_UVERBS_ABI_VERSION;
 
        dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
        if (!dev->ibdev.iwcm)
index c64d27b..0993137 100644 (file)
@@ -802,14 +802,12 @@ int iwch_post_terminate(struct iwch_qp *qhp, struct respQ_msg_t *rsp_msg)
 /*
  * Assumes qhp lock is held.
  */
-static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
+static void __flush_qp(struct iwch_qp *qhp, struct iwch_cq *rchp,
+                               struct iwch_cq *schp, unsigned long *flag)
 {
-       struct iwch_cq *rchp, *schp;
        int count;
        int flushed;
 
-       rchp = get_chp(qhp->rhp, qhp->attr.rcq);
-       schp = get_chp(qhp->rhp, qhp->attr.scq);
 
        PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
        /* take a ref on the qhp since we must release the lock */
@@ -847,10 +845,23 @@ static void __flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 
 static void flush_qp(struct iwch_qp *qhp, unsigned long *flag)
 {
-       if (qhp->ibqp.uobject)
+       struct iwch_cq *rchp, *schp;
+
+       rchp = get_chp(qhp->rhp, qhp->attr.rcq);
+       schp = get_chp(qhp->rhp, qhp->attr.scq);
+
+       if (qhp->ibqp.uobject) {
                cxio_set_wq_in_error(&qhp->wq);
-       else
-               __flush_qp(qhp, flag);
+               cxio_set_cq_in_error(&rchp->cq);
+               (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
+               if (schp != rchp) {
+                       cxio_set_cq_in_error(&schp->cq);
+                       (*schp->ibcq.comp_handler)(&schp->ibcq,
+                                                  schp->ibcq.cq_context);
+               }
+               return;
+       }
+       __flush_qp(qhp, rchp, schp, flag);
 }
 
 
index cb7086f..a277c31 100644 (file)
@@ -45,10 +45,18 @@ struct iwch_create_cq_req {
        __u64 user_rptr_addr;
 };
 
+struct iwch_create_cq_resp_v0 {
+       __u64 key;
+       __u32 cqid;
+       __u32 size_log2;
+};
+
 struct iwch_create_cq_resp {
        __u64 key;
        __u32 cqid;
        __u32 size_log2;
+       __u32 memsize;
+       __u32 reserved;
 };
 
 struct iwch_create_qp_resp {
index e31a499..cd20b13 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -Idrivers/net/cxgb4
+ccflags-y := -Idrivers/net/cxgb4
 
 obj-$(CONFIG_INFINIBAND_CXGB4) += iw_cxgb4.o
 
index 32d352a..0dc62b1 100644 (file)
@@ -117,9 +117,9 @@ static int rcv_win = 256 * 1024;
 module_param(rcv_win, int, 0644);
 MODULE_PARM_DESC(rcv_win, "TCP receive window in bytes (default=256KB)");
 
-static int snd_win = 32 * 1024;
+static int snd_win = 128 * 1024;
 module_param(snd_win, int, 0644);
-MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=32KB)");
+MODULE_PARM_DESC(snd_win, "TCP send window in bytes (default=128KB)");
 
 static struct workqueue_struct *workq;
 
@@ -172,7 +172,7 @@ static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb,
        error = cxgb4_l2t_send(rdev->lldi.ports[0], skb, l2e);
        if (error < 0)
                kfree_skb(skb);
-       return error;
+       return error < 0 ? error : 0;
 }
 
 int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb)
@@ -187,7 +187,7 @@ int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb)
        error = cxgb4_ofld_send(rdev->lldi.ports[0], skb);
        if (error < 0)
                kfree_skb(skb);
-       return error;
+       return error < 0 ? error : 0;
 }
 
 static void release_tid(struct c4iw_rdev *rdev, u32 hwtid, struct sk_buff *skb)
@@ -219,12 +219,11 @@ static void set_emss(struct c4iw_ep *ep, u16 opt)
 
 static enum c4iw_ep_state state_read(struct c4iw_ep_common *epc)
 {
-       unsigned long flags;
        enum c4iw_ep_state state;
 
-       spin_lock_irqsave(&epc->lock, flags);
+       mutex_lock(&epc->mutex);
        state = epc->state;
-       spin_unlock_irqrestore(&epc->lock, flags);
+       mutex_unlock(&epc->mutex);
        return state;
 }
 
@@ -235,12 +234,10 @@ static void __state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new)
 
 static void state_set(struct c4iw_ep_common *epc, enum c4iw_ep_state new)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&epc->lock, flags);
+       mutex_lock(&epc->mutex);
        PDBG("%s - %s -> %s\n", __func__, states[epc->state], states[new]);
        __state_set(epc, new);
-       spin_unlock_irqrestore(&epc->lock, flags);
+       mutex_unlock(&epc->mutex);
        return;
 }
 
@@ -251,8 +248,8 @@ static void *alloc_ep(int size, gfp_t gfp)
        epc = kzalloc(size, gfp);
        if (epc) {
                kref_init(&epc->kref);
-               spin_lock_init(&epc->lock);
-               init_waitqueue_head(&epc->waitq);
+               mutex_init(&epc->mutex);
+               c4iw_init_wr_wait(&epc->wr_wait);
        }
        PDBG("%s alloc ep %p\n", __func__, epc);
        return epc;
@@ -1131,7 +1128,6 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
 {
        struct c4iw_ep *ep;
        struct cpl_abort_rpl_rss *rpl = cplhdr(skb);
-       unsigned long flags;
        int release = 0;
        unsigned int tid = GET_TID(rpl);
        struct tid_info *t = dev->rdev.lldi.tids;
@@ -1139,7 +1135,7 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        ep = lookup_tid(t, tid);
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        BUG_ON(!ep);
-       spin_lock_irqsave(&ep->com.lock, flags);
+       mutex_lock(&ep->com.mutex);
        switch (ep->com.state) {
        case ABORTING:
                __state_set(&ep->com, DEAD);
@@ -1150,7 +1146,7 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
                     __func__, ep, ep->com.state);
                break;
        }
-       spin_unlock_irqrestore(&ep->com.lock, flags);
+       mutex_unlock(&ep->com.mutex);
 
        if (release)
                release_ep_resources(ep);
@@ -1213,9 +1209,9 @@ static int pass_open_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        }
        PDBG("%s ep %p status %d error %d\n", __func__, ep,
             rpl->status, status2errno(rpl->status));
-       ep->com.rpl_err = status2errno(rpl->status);
-       ep->com.rpl_done = 1;
-       wake_up(&ep->com.waitq);
+       ep->com.wr_wait.ret = status2errno(rpl->status);
+       ep->com.wr_wait.done = 1;
+       wake_up(&ep->com.wr_wait.wait);
 
        return 0;
 }
@@ -1249,9 +1245,9 @@ static int close_listsrv_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        struct c4iw_listen_ep *ep = lookup_stid(t, stid);
 
        PDBG("%s ep %p\n", __func__, ep);
-       ep->com.rpl_err = status2errno(rpl->status);
-       ep->com.rpl_done = 1;
-       wake_up(&ep->com.waitq);
+       ep->com.wr_wait.ret = status2errno(rpl->status);
+       ep->com.wr_wait.done = 1;
+       wake_up(&ep->com.wr_wait.wait);
        return 0;
 }
 
@@ -1478,7 +1474,6 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
        struct cpl_peer_close *hdr = cplhdr(skb);
        struct c4iw_ep *ep;
        struct c4iw_qp_attributes attrs;
-       unsigned long flags;
        int disconnect = 1;
        int release = 0;
        int closing = 0;
@@ -1489,7 +1484,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        dst_confirm(ep->dst);
 
-       spin_lock_irqsave(&ep->com.lock, flags);
+       mutex_lock(&ep->com.mutex);
        switch (ep->com.state) {
        case MPA_REQ_WAIT:
                __state_set(&ep->com, CLOSING);
@@ -1507,17 +1502,17 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
                 * in rdma connection migration (see c4iw_accept_cr()).
                 */
                __state_set(&ep->com, CLOSING);
-               ep->com.rpl_done = 1;
-               ep->com.rpl_err = -ECONNRESET;
+               ep->com.wr_wait.done = 1;
+               ep->com.wr_wait.ret = -ECONNRESET;
                PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-               wake_up(&ep->com.waitq);
+               wake_up(&ep->com.wr_wait.wait);
                break;
        case MPA_REP_SENT:
                __state_set(&ep->com, CLOSING);
-               ep->com.rpl_done = 1;
-               ep->com.rpl_err = -ECONNRESET;
+               ep->com.wr_wait.done = 1;
+               ep->com.wr_wait.ret = -ECONNRESET;
                PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-               wake_up(&ep->com.waitq);
+               wake_up(&ep->com.wr_wait.wait);
                break;
        case FPDU_MODE:
                start_ep_timer(ep);
@@ -1550,7 +1545,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
        default:
                BUG_ON(1);
        }
-       spin_unlock_irqrestore(&ep->com.lock, flags);
+       mutex_unlock(&ep->com.mutex);
        if (closing) {
                attrs.next_state = C4IW_QP_STATE_CLOSING;
                c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
@@ -1581,7 +1576,6 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
        struct c4iw_qp_attributes attrs;
        int ret;
        int release = 0;
-       unsigned long flags;
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int tid = GET_TID(req);
 
@@ -1591,9 +1585,17 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
                     ep->hwtid);
                return 0;
        }
-       spin_lock_irqsave(&ep->com.lock, flags);
        PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
             ep->com.state);
+
+       /*
+        * Wake up any threads in rdma_init() or rdma_fini().
+        */
+       ep->com.wr_wait.done = 1;
+       ep->com.wr_wait.ret = -ECONNRESET;
+       wake_up(&ep->com.wr_wait.wait);
+
+       mutex_lock(&ep->com.mutex);
        switch (ep->com.state) {
        case CONNECTING:
                break;
@@ -1605,23 +1607,8 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
                connect_reply_upcall(ep, -ECONNRESET);
                break;
        case MPA_REP_SENT:
-               ep->com.rpl_done = 1;
-               ep->com.rpl_err = -ECONNRESET;
-               PDBG("waking up ep %p\n", ep);
-               wake_up(&ep->com.waitq);
                break;
        case MPA_REQ_RCVD:
-
-               /*
-                * We're gonna mark this puppy DEAD, but keep
-                * the reference on it until the ULP accepts or
-                * rejects the CR. Also wake up anyone waiting
-                * in rdma connection migration (see c4iw_accept_cr()).
-                */
-               ep->com.rpl_done = 1;
-               ep->com.rpl_err = -ECONNRESET;
-               PDBG("waking up ep %p tid %u\n", ep, ep->hwtid);
-               wake_up(&ep->com.waitq);
                break;
        case MORIBUND:
        case CLOSING:
@@ -1644,7 +1631,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
                break;
        case DEAD:
                PDBG("%s PEER_ABORT IN DEAD STATE!!!!\n", __func__);
-               spin_unlock_irqrestore(&ep->com.lock, flags);
+               mutex_unlock(&ep->com.mutex);
                return 0;
        default:
                BUG_ON(1);
@@ -1655,7 +1642,7 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb)
                __state_set(&ep->com, DEAD);
                release = 1;
        }
-       spin_unlock_irqrestore(&ep->com.lock, flags);
+       mutex_unlock(&ep->com.mutex);
 
        rpl_skb = get_skb(skb, sizeof(*rpl), GFP_KERNEL);
        if (!rpl_skb) {
@@ -1681,7 +1668,6 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        struct c4iw_ep *ep;
        struct c4iw_qp_attributes attrs;
        struct cpl_close_con_rpl *rpl = cplhdr(skb);
-       unsigned long flags;
        int release = 0;
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int tid = GET_TID(rpl);
@@ -1692,7 +1678,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        BUG_ON(!ep);
 
        /* The cm_id may be null if we failed to connect */
-       spin_lock_irqsave(&ep->com.lock, flags);
+       mutex_lock(&ep->com.mutex);
        switch (ep->com.state) {
        case CLOSING:
                __state_set(&ep->com, MORIBUND);
@@ -1717,7 +1703,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
                BUG_ON(1);
                break;
        }
-       spin_unlock_irqrestore(&ep->com.lock, flags);
+       mutex_unlock(&ep->com.mutex);
        if (release)
                release_ep_resources(ep);
        return 0;
@@ -1725,23 +1711,24 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
 
 static int terminate(struct c4iw_dev *dev, struct sk_buff *skb)
 {
-       struct c4iw_ep *ep;
-       struct cpl_rdma_terminate *term = cplhdr(skb);
+       struct cpl_rdma_terminate *rpl = cplhdr(skb);
        struct tid_info *t = dev->rdev.lldi.tids;
-       unsigned int tid = GET_TID(term);
+       unsigned int tid = GET_TID(rpl);
+       struct c4iw_ep *ep;
+       struct c4iw_qp_attributes attrs;
 
        ep = lookup_tid(t, tid);
+       BUG_ON(!ep);
 
-       if (state_read(&ep->com) != FPDU_MODE)
-               return 0;
+       if (ep->com.qp) {
+               printk(KERN_WARNING MOD "TERM received tid %u qpid %u\n", tid,
+                      ep->com.qp->wq.sq.qid);
+               attrs.next_state = C4IW_QP_STATE_TERMINATE;
+               c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+                              C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
+       } else
+               printk(KERN_WARNING MOD "TERM received tid %u no qp\n", tid);
 
-       PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
-       skb_pull(skb, sizeof *term);
-       PDBG("%s saving %d bytes of term msg\n", __func__, skb->len);
-       skb_copy_from_linear_data(skb, ep->com.qp->attr.terminate_buffer,
-                                 skb->len);
-       ep->com.qp->attr.terminate_msg_len = skb->len;
-       ep->com.qp->attr.is_terminate_local = 0;
        return 0;
 }
 
@@ -1762,8 +1749,8 @@ static int fw4_ack(struct c4iw_dev *dev, struct sk_buff *skb)
        ep = lookup_tid(t, tid);
        PDBG("%s ep %p tid %u credits %u\n", __func__, ep, ep->hwtid, credits);
        if (credits == 0) {
-               PDBG(KERN_ERR "%s 0 credit ack ep %p tid %u state %u\n",
-                       __func__, ep, ep->hwtid, state_read(&ep->com));
+               PDBG("%s 0 credit ack ep %p tid %u state %u\n",
+                    __func__, ep, ep->hwtid, state_read(&ep->com));
                return 0;
        }
 
@@ -2042,6 +2029,7 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
        }
 
        state_set(&ep->com, LISTEN);
+       c4iw_init_wr_wait(&ep->com.wr_wait);
        err = cxgb4_create_server(ep->com.dev->rdev.lldi.ports[0], ep->stid,
                                  ep->com.local_addr.sin_addr.s_addr,
                                  ep->com.local_addr.sin_port,
@@ -2050,15 +2038,8 @@ int c4iw_create_listen(struct iw_cm_id *cm_id, int backlog)
                goto fail3;
 
        /* wait for pass_open_rpl */
-       wait_event_timeout(ep->com.waitq, ep->com.rpl_done, C4IW_WR_TO);
-       if (ep->com.rpl_done)
-               err = ep->com.rpl_err;
-       else {
-               printk(KERN_ERR MOD "Device %s not responding!\n",
-                      pci_name(ep->com.dev->rdev.lldi.pdev));
-               ep->com.dev->rdev.flags = T4_FATAL_ERROR;
-               err = -EIO;
-       }
+       err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0,
+                                 __func__);
        if (!err) {
                cm_id->provider_data = ep;
                goto out;
@@ -2082,20 +2063,12 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id)
 
        might_sleep();
        state_set(&ep->com, DEAD);
-       ep->com.rpl_done = 0;
-       ep->com.rpl_err = 0;
+       c4iw_init_wr_wait(&ep->com.wr_wait);
        err = listen_stop(ep);
        if (err)
                goto done;
-       wait_event_timeout(ep->com.waitq, ep->com.rpl_done, C4IW_WR_TO);
-       if (ep->com.rpl_done)
-               err = ep->com.rpl_err;
-       else {
-               printk(KERN_ERR MOD "Device %s not responding!\n",
-                      pci_name(ep->com.dev->rdev.lldi.pdev));
-               ep->com.dev->rdev.flags = T4_FATAL_ERROR;
-               err = -EIO;
-       }
+       err = c4iw_wait_for_reply(&ep->com.dev->rdev, &ep->com.wr_wait, 0, 0,
+                                 __func__);
        cxgb4_free_stid(ep->com.dev->rdev.lldi.tids, ep->stid, PF_INET);
 done:
        cm_id->rem_ref(cm_id);
@@ -2106,12 +2079,11 @@ done:
 int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
 {
        int ret = 0;
-       unsigned long flags;
        int close = 0;
        int fatal = 0;
        struct c4iw_rdev *rdev;
 
-       spin_lock_irqsave(&ep->com.lock, flags);
+       mutex_lock(&ep->com.mutex);
 
        PDBG("%s ep %p state %s, abrupt %d\n", __func__, ep,
             states[ep->com.state], abrupt);
@@ -2158,7 +2130,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
                break;
        }
 
-       spin_unlock_irqrestore(&ep->com.lock, flags);
+       mutex_unlock(&ep->com.mutex);
        if (close) {
                if (abrupt)
                        ret = abort_connection(ep, NULL, gfp);
@@ -2172,6 +2144,13 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
        return ret;
 }
 
+static int async_event(struct c4iw_dev *dev, struct sk_buff *skb)
+{
+       struct cpl_fw6_msg *rpl = cplhdr(skb);
+       c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]);
+       return 0;
+}
+
 /*
  * These are the real handlers that are called from a
  * work queue.
@@ -2190,7 +2169,8 @@ static c4iw_handler_func work_handlers[NUM_CPL_CMDS] = {
        [CPL_ABORT_REQ_RSS] = peer_abort,
        [CPL_CLOSE_CON_RPL] = close_con_rpl,
        [CPL_RDMA_TERMINATE] = terminate,
-       [CPL_FW4_ACK] = fw4_ack
+       [CPL_FW4_ACK] = fw4_ack,
+       [CPL_FW6_MSG] = async_event
 };
 
 static void process_timeout(struct c4iw_ep *ep)
@@ -2198,7 +2178,7 @@ static void process_timeout(struct c4iw_ep *ep)
        struct c4iw_qp_attributes attrs;
        int abort = 1;
 
-       spin_lock_irq(&ep->com.lock);
+       mutex_lock(&ep->com.mutex);
        PDBG("%s ep %p tid %u state %d\n", __func__, ep, ep->hwtid,
             ep->com.state);
        switch (ep->com.state) {
@@ -2225,7 +2205,7 @@ static void process_timeout(struct c4iw_ep *ep)
                WARN_ON(1);
                abort = 0;
        }
-       spin_unlock_irq(&ep->com.lock);
+       mutex_unlock(&ep->com.mutex);
        if (abort)
                abort_connection(ep, NULL, GFP_KERNEL);
        c4iw_put_ep(&ep->com);
@@ -2309,6 +2289,7 @@ static int set_tcb_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
                printk(KERN_ERR MOD "Unexpected SET_TCB_RPL status %u "
                       "for tid %u\n", rpl->status, GET_TID(rpl));
        }
+       kfree_skb(skb);
        return 0;
 }
 
@@ -2323,20 +2304,25 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
        switch (rpl->type) {
        case 1:
                ret = (int)((be64_to_cpu(rpl->data[0]) >> 8) & 0xff);
-               wr_waitp = (__force struct c4iw_wr_wait *)rpl->data[1];
+               wr_waitp = (struct c4iw_wr_wait *)(__force unsigned long) rpl->data[1];
                PDBG("%s wr_waitp %p ret %u\n", __func__, wr_waitp, ret);
                if (wr_waitp) {
-                       wr_waitp->ret = ret;
+                       if (ret)
+                               wr_waitp->ret = -ret;
+                       else
+                               wr_waitp->ret = 0;
                        wr_waitp->done = 1;
                        wake_up(&wr_waitp->wait);
                }
+               kfree_skb(skb);
                break;
        case 2:
-               c4iw_ev_dispatch(dev, (struct t4_cqe *)&rpl->data[0]);
+               sched(dev, skb);
                break;
        default:
                printk(KERN_ERR MOD "%s unexpected fw6 msg type %u\n", __func__,
                       rpl->type);
+               kfree_skb(skb);
                break;
        }
        return 0;
index b3daf39..8d8f8ad 100644 (file)
@@ -55,7 +55,7 @@ static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
                        V_FW_RI_RES_WR_NRES(1) |
                        FW_WR_COMPL(1));
        res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-       res_wr->cookie = (u64)&wr_wait;
+       res_wr->cookie = (unsigned long) &wr_wait;
        res = res_wr->res;
        res->u.cq.restype = FW_RI_RES_TYPE_CQ;
        res->u.cq.op = FW_RI_RES_OP_RESET;
@@ -64,14 +64,7 @@ static int destroy_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
        c4iw_init_wr_wait(&wr_wait);
        ret = c4iw_ofld_send(rdev, skb);
        if (!ret) {
-               wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-               if (!wr_wait.done) {
-                       printk(KERN_ERR MOD "Device %s not responding!\n",
-                              pci_name(rdev->lldi.pdev));
-                       rdev->flags = T4_FATAL_ERROR;
-                       ret = -EIO;
-               } else
-                       ret = wr_wait.ret;
+               ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
        }
 
        kfree(cq->sw_queue);
@@ -132,7 +125,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
                        V_FW_RI_RES_WR_NRES(1) |
                        FW_WR_COMPL(1));
        res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-       res_wr->cookie = (u64)&wr_wait;
+       res_wr->cookie = (unsigned long) &wr_wait;
        res = res_wr->res;
        res->u.cq.restype = FW_RI_RES_TYPE_CQ;
        res->u.cq.op = FW_RI_RES_OP_WRITE;
@@ -157,14 +150,7 @@ static int create_cq(struct c4iw_rdev *rdev, struct t4_cq *cq,
        if (ret)
                goto err4;
        PDBG("%s wait_event wr_wait %p\n", __func__, &wr_wait);
-       wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-       if (!wr_wait.done) {
-               printk(KERN_ERR MOD "Device %s not responding!\n",
-                      pci_name(rdev->lldi.pdev));
-               rdev->flags = T4_FATAL_ERROR;
-               ret = -EIO;
-       } else
-               ret = wr_wait.ret;
+       ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
        if (ret)
                goto err4;
 
@@ -476,6 +462,11 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
                goto proc_cqe;
        }
 
+       if (CQE_OPCODE(hw_cqe) == FW_RI_TERMINATE) {
+               ret = -EAGAIN;
+               goto skip_cqe;
+       }
+
        /*
         * RECV completion.
         */
@@ -696,6 +687,7 @@ static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc)
                case T4_ERR_MSN_RANGE:
                case T4_ERR_IRD_OVERFLOW:
                case T4_ERR_OPCODE:
+               case T4_ERR_INTERNAL_ERR:
                        wc->status = IB_WC_FATAL_ERR;
                        break;
                case T4_ERR_SWFLUSH:
index 9bbf491..54fbc11 100644 (file)
@@ -49,29 +49,33 @@ static DEFINE_MUTEX(dev_mutex);
 
 static struct dentry *c4iw_debugfs_root;
 
-struct debugfs_qp_data {
+struct c4iw_debugfs_data {
        struct c4iw_dev *devp;
        char *buf;
        int bufsize;
        int pos;
 };
 
-static int count_qps(int id, void *p, void *data)
+static int count_idrs(int id, void *p, void *data)
 {
-       struct c4iw_qp *qp = p;
        int *countp = data;
 
-       if (id != qp->wq.sq.qid)
-               return 0;
-
        *countp = *countp + 1;
        return 0;
 }
 
-static int dump_qps(int id, void *p, void *data)
+static ssize_t debugfs_read(struct file *file, char __user *buf, size_t count,
+                           loff_t *ppos)
+{
+       struct c4iw_debugfs_data *d = file->private_data;
+
+       return simple_read_from_buffer(buf, count, ppos, d->buf, d->pos);
+}
+
+static int dump_qp(int id, void *p, void *data)
 {
        struct c4iw_qp *qp = p;
-       struct debugfs_qp_data *qpd = data;
+       struct c4iw_debugfs_data *qpd = data;
        int space;
        int cc;
 
@@ -101,7 +105,7 @@ static int dump_qps(int id, void *p, void *data)
 
 static int qp_release(struct inode *inode, struct file *file)
 {
-       struct debugfs_qp_data *qpd = file->private_data;
+       struct c4iw_debugfs_data *qpd = file->private_data;
        if (!qpd) {
                printk(KERN_INFO "%s null qpd?\n", __func__);
                return 0;
@@ -113,7 +117,7 @@ static int qp_release(struct inode *inode, struct file *file)
 
 static int qp_open(struct inode *inode, struct file *file)
 {
-       struct debugfs_qp_data *qpd;
+       struct c4iw_debugfs_data *qpd;
        int ret = 0;
        int count = 1;
 
@@ -126,7 +130,7 @@ static int qp_open(struct inode *inode, struct file *file)
        qpd->pos = 0;
 
        spin_lock_irq(&qpd->devp->lock);
-       idr_for_each(&qpd->devp->qpidr, count_qps, &count);
+       idr_for_each(&qpd->devp->qpidr, count_idrs, &count);
        spin_unlock_irq(&qpd->devp->lock);
 
        qpd->bufsize = count * 128;
@@ -137,7 +141,7 @@ static int qp_open(struct inode *inode, struct file *file)
        }
 
        spin_lock_irq(&qpd->devp->lock);
-       idr_for_each(&qpd->devp->qpidr, dump_qps, qpd);
+       idr_for_each(&qpd->devp->qpidr, dump_qp, qpd);
        spin_unlock_irq(&qpd->devp->lock);
 
        qpd->buf[qpd->pos++] = 0;
@@ -149,43 +153,86 @@ out:
        return ret;
 }
 
-static ssize_t qp_read(struct file *file, char __user *buf, size_t count,
-                       loff_t *ppos)
+static const struct file_operations qp_debugfs_fops = {
+       .owner   = THIS_MODULE,
+       .open    = qp_open,
+       .release = qp_release,
+       .read    = debugfs_read,
+       .llseek  = default_llseek,
+};
+
+static int dump_stag(int id, void *p, void *data)
 {
-       struct debugfs_qp_data *qpd = file->private_data;
-       loff_t pos = *ppos;
-       loff_t avail = qpd->pos;
+       struct c4iw_debugfs_data *stagd = data;
+       int space;
+       int cc;
 
-       if (pos < 0)
-               return -EINVAL;
-       if (pos >= avail)
+       space = stagd->bufsize - stagd->pos - 1;
+       if (space == 0)
+               return 1;
+
+       cc = snprintf(stagd->buf + stagd->pos, space, "0x%x\n", id<<8);
+       if (cc < space)
+               stagd->pos += cc;
+       return 0;
+}
+
+static int stag_release(struct inode *inode, struct file *file)
+{
+       struct c4iw_debugfs_data *stagd = file->private_data;
+       if (!stagd) {
+               printk(KERN_INFO "%s null stagd?\n", __func__);
                return 0;
-       if (count > avail - pos)
-               count = avail - pos;
+       }
+       kfree(stagd->buf);
+       kfree(stagd);
+       return 0;
+}
 
-       while (count) {
-               size_t len = 0;
+static int stag_open(struct inode *inode, struct file *file)
+{
+       struct c4iw_debugfs_data *stagd;
+       int ret = 0;
+       int count = 1;
 
-               len = min((int)count, (int)qpd->pos - (int)pos);
-               if (copy_to_user(buf, qpd->buf + pos, len))
-                       return -EFAULT;
-               if (len == 0)
-                       return -EINVAL;
+       stagd = kmalloc(sizeof *stagd, GFP_KERNEL);
+       if (!stagd) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       stagd->devp = inode->i_private;
+       stagd->pos = 0;
+
+       spin_lock_irq(&stagd->devp->lock);
+       idr_for_each(&stagd->devp->mmidr, count_idrs, &count);
+       spin_unlock_irq(&stagd->devp->lock);
 
-               buf += len;
-               pos += len;
-               count -= len;
+       stagd->bufsize = count * sizeof("0x12345678\n");
+       stagd->buf = kmalloc(stagd->bufsize, GFP_KERNEL);
+       if (!stagd->buf) {
+               ret = -ENOMEM;
+               goto err1;
        }
-       count = pos - *ppos;
-       *ppos = pos;
-       return count;
+
+       spin_lock_irq(&stagd->devp->lock);
+       idr_for_each(&stagd->devp->mmidr, dump_stag, stagd);
+       spin_unlock_irq(&stagd->devp->lock);
+
+       stagd->buf[stagd->pos++] = 0;
+       file->private_data = stagd;
+       goto out;
+err1:
+       kfree(stagd);
+out:
+       return ret;
 }
 
-static const struct file_operations qp_debugfs_fops = {
+static const struct file_operations stag_debugfs_fops = {
        .owner   = THIS_MODULE,
-       .open    = qp_open,
-       .release = qp_release,
-       .read    = qp_read,
+       .open    = stag_open,
+       .release = stag_release,
+       .read    = debugfs_read,
+       .llseek  = default_llseek,
 };
 
 static int setup_debugfs(struct c4iw_dev *devp)
@@ -199,6 +246,11 @@ static int setup_debugfs(struct c4iw_dev *devp)
                                 (void *)devp, &qp_debugfs_fops);
        if (de && de->d_inode)
                de->d_inode->i_size = 4096;
+
+       de = debugfs_create_file("stags", S_IWUSR, devp->debugfs_root,
+                                (void *)devp, &stag_debugfs_fops);
+       if (de && de->d_inode)
+               de->d_inode->i_size = 4096;
        return 0;
 }
 
@@ -290,7 +342,14 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
                printk(KERN_ERR MOD "error %d initializing rqt pool\n", err);
                goto err3;
        }
+       err = c4iw_ocqp_pool_create(rdev);
+       if (err) {
+               printk(KERN_ERR MOD "error %d initializing ocqp pool\n", err);
+               goto err4;
+       }
        return 0;
+err4:
+       c4iw_rqtpool_destroy(rdev);
 err3:
        c4iw_pblpool_destroy(rdev);
 err2:
@@ -317,6 +376,7 @@ static void c4iw_remove(struct c4iw_dev *dev)
        idr_destroy(&dev->cqidr);
        idr_destroy(&dev->qpidr);
        idr_destroy(&dev->mmidr);
+       iounmap(dev->rdev.oc_mw_kva);
        ib_dealloc_device(&dev->ibdev);
 }
 
@@ -332,6 +392,17 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop)
        }
        devp->rdev.lldi = *infop;
 
+       devp->rdev.oc_mw_pa = pci_resource_start(devp->rdev.lldi.pdev, 2) +
+               (pci_resource_len(devp->rdev.lldi.pdev, 2) -
+                roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size));
+       devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa,
+                                              devp->rdev.lldi.vr->ocq.size);
+
+       printk(KERN_INFO MOD "ocq memory: "
+              "hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n",
+              devp->rdev.lldi.vr->ocq.start, devp->rdev.lldi.vr->ocq.size,
+              devp->rdev.oc_mw_pa, devp->rdev.oc_mw_kva);
+
        mutex_lock(&dev_mutex);
 
        ret = c4iw_rdev_open(&devp->rdev);
@@ -383,46 +454,6 @@ out:
        return dev;
 }
 
-static struct sk_buff *t4_pktgl_to_skb(const struct pkt_gl *gl,
-                                      unsigned int skb_len,
-                                      unsigned int pull_len)
-{
-       struct sk_buff *skb;
-       struct skb_shared_info *ssi;
-
-       if (gl->tot_len <= 512) {
-               skb = alloc_skb(gl->tot_len, GFP_ATOMIC);
-               if (unlikely(!skb))
-                       goto out;
-               __skb_put(skb, gl->tot_len);
-               skb_copy_to_linear_data(skb, gl->va, gl->tot_len);
-       } else {
-               skb = alloc_skb(skb_len, GFP_ATOMIC);
-               if (unlikely(!skb))
-                       goto out;
-               __skb_put(skb, pull_len);
-               skb_copy_to_linear_data(skb, gl->va, pull_len);
-
-               ssi = skb_shinfo(skb);
-               ssi->frags[0].page = gl->frags[0].page;
-               ssi->frags[0].page_offset = gl->frags[0].page_offset + pull_len;
-               ssi->frags[0].size = gl->frags[0].size - pull_len;
-               if (gl->nfrags > 1)
-                       memcpy(&ssi->frags[1], &gl->frags[1],
-                              (gl->nfrags - 1) * sizeof(skb_frag_t));
-               ssi->nr_frags = gl->nfrags;
-
-               skb->len = gl->tot_len;
-               skb->data_len = skb->len - pull_len;
-               skb->truesize += skb->data_len;
-
-               /* Get a reference for the last page, we don't own it */
-               get_page(gl->frags[gl->nfrags - 1].page);
-       }
-out:
-       return skb;
-}
-
 static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
                        const struct pkt_gl *gl)
 {
@@ -447,7 +478,7 @@ static int c4iw_uld_rx_handler(void *handle, const __be64 *rsp,
                c4iw_ev_handler(dev, qid);
                return 0;
        } else {
-               skb = t4_pktgl_to_skb(gl, 128, 128);
+               skb = cxgb4_pktgl_to_skb(gl, 128, 128);
                if (unlikely(!skb))
                        goto nomem;
        }
index 491e76a..c13041a 100644 (file)
@@ -60,7 +60,7 @@ static void post_qp_event(struct c4iw_dev *dev, struct c4iw_cq *chp,
        if (qhp->attr.state == C4IW_QP_STATE_RTS) {
                attrs.next_state = C4IW_QP_STATE_TERMINATE;
                c4iw_modify_qp(qhp->rhp, qhp, C4IW_QP_ATTR_NEXT_STATE,
-                              &attrs, 1);
+                              &attrs, 0);
        }
 
        event.event = ib_event;
index ed459b8..16032cd 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/kfifo.h>
+#include <linux/mutex.h>
 
 #include <asm/byteorder.h>
 
@@ -79,21 +80,6 @@ static inline void *cplhdr(struct sk_buff *skb)
        return skb->data;
 }
 
-#define C4IW_WR_TO (10*HZ)
-
-struct c4iw_wr_wait {
-       wait_queue_head_t wait;
-       int done;
-       int ret;
-};
-
-static inline void c4iw_init_wr_wait(struct c4iw_wr_wait *wr_waitp)
-{
-       wr_waitp->ret = 0;
-       wr_waitp->done = 0;
-       init_waitqueue_head(&wr_waitp->wait);
-}
-
 struct c4iw_resource {
        struct kfifo tpt_fifo;
        spinlock_t tpt_fifo_lock;
@@ -127,8 +113,11 @@ struct c4iw_rdev {
        struct c4iw_dev_ucontext uctx;
        struct gen_pool *pbl_pool;
        struct gen_pool *rqt_pool;
+       struct gen_pool *ocqp_pool;
        u32 flags;
        struct cxgb4_lld_info lldi;
+       unsigned long oc_mw_pa;
+       void __iomem *oc_mw_kva;
 };
 
 static inline int c4iw_fatal_error(struct c4iw_rdev *rdev)
@@ -141,6 +130,44 @@ static inline int c4iw_num_stags(struct c4iw_rdev *rdev)
        return min((int)T4_MAX_NUM_STAG, (int)(rdev->lldi.vr->stag.size >> 5));
 }
 
+#define C4IW_WR_TO (10*HZ)
+
+struct c4iw_wr_wait {
+       wait_queue_head_t wait;
+       int done;
+       int ret;
+};
+
+static inline void c4iw_init_wr_wait(struct c4iw_wr_wait *wr_waitp)
+{
+       wr_waitp->ret = 0;
+       wr_waitp->done = 0;
+       init_waitqueue_head(&wr_waitp->wait);
+}
+
+static inline int c4iw_wait_for_reply(struct c4iw_rdev *rdev,
+                                struct c4iw_wr_wait *wr_waitp,
+                                u32 hwtid, u32 qpid,
+                                const char *func)
+{
+       unsigned to = C4IW_WR_TO;
+       do {
+
+               wait_event_timeout(wr_waitp->wait, wr_waitp->done, to);
+               if (!wr_waitp->done) {
+                       printk(KERN_ERR MOD "%s - Device %s not responding - "
+                              "tid %u qpid %u\n", func,
+                              pci_name(rdev->lldi.pdev), hwtid, qpid);
+                       to = to << 2;
+               }
+       } while (!wr_waitp->done);
+       if (wr_waitp->ret)
+               printk(KERN_WARNING MOD "%s: FW reply %d tid %u qpid %u\n",
+                      pci_name(rdev->lldi.pdev), wr_waitp->ret, hwtid, qpid);
+       return wr_waitp->ret;
+}
+
+
 struct c4iw_dev {
        struct ib_device ibdev;
        struct c4iw_rdev rdev;
@@ -327,6 +354,7 @@ struct c4iw_qp {
        struct c4iw_qp_attributes attr;
        struct t4_wq wq;
        spinlock_t lock;
+       struct mutex mutex;
        atomic_t refcnt;
        wait_queue_head_t wait;
        struct timer_list timer;
@@ -579,12 +607,10 @@ struct c4iw_ep_common {
        struct c4iw_dev *dev;
        enum c4iw_ep_state state;
        struct kref kref;
-       spinlock_t lock;
+       struct mutex mutex;
        struct sockaddr_in local_addr;
        struct sockaddr_in remote_addr;
-       wait_queue_head_t waitq;
-       int rpl_done;
-       int rpl_err;
+       struct c4iw_wr_wait wr_wait;
        unsigned long flags;
 };
 
@@ -654,8 +680,10 @@ int c4iw_init_resource(struct c4iw_rdev *rdev, u32 nr_tpt, u32 nr_pdid);
 int c4iw_init_ctrl_qp(struct c4iw_rdev *rdev);
 int c4iw_pblpool_create(struct c4iw_rdev *rdev);
 int c4iw_rqtpool_create(struct c4iw_rdev *rdev);
+int c4iw_ocqp_pool_create(struct c4iw_rdev *rdev);
 void c4iw_pblpool_destroy(struct c4iw_rdev *rdev);
 void c4iw_rqtpool_destroy(struct c4iw_rdev *rdev);
+void c4iw_ocqp_pool_destroy(struct c4iw_rdev *rdev);
 void c4iw_destroy_resource(struct c4iw_resource *rscp);
 int c4iw_destroy_ctrl_qp(struct c4iw_rdev *rdev);
 int c4iw_register_device(struct c4iw_dev *dev);
@@ -721,6 +749,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size);
 void c4iw_rqtpool_free(struct c4iw_rdev *rdev, u32 addr, int size);
 u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size);
 void c4iw_pblpool_free(struct c4iw_rdev *rdev, u32 addr, int size);
+u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size);
+void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size);
 int c4iw_ofld_send(struct c4iw_rdev *rdev, struct sk_buff *skb);
 void c4iw_flush_hw_cq(struct t4_cq *cq);
 void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count);
index 269373a..273ffe4 100644 (file)
@@ -71,7 +71,7 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
                if (i == (num_wqe-1)) {
                        req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR) |
                                                    FW_WR_COMPL(1));
-                       req->wr.wr_lo = (__force __be64)&wr_wait;
+                       req->wr.wr_lo = (__force __be64)(unsigned long) &wr_wait;
                } else
                        req->wr.wr_hi = cpu_to_be32(FW_WR_OP(FW_ULPTX_WR));
                req->wr.wr_mid = cpu_to_be32(
@@ -103,14 +103,7 @@ static int write_adapter_mem(struct c4iw_rdev *rdev, u32 addr, u32 len,
                len -= C4IW_MAX_INLINE_SIZE;
        }
 
-       wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-       if (!wr_wait.done) {
-               printk(KERN_ERR MOD "Device %s not responding!\n",
-                      pci_name(rdev->lldi.pdev));
-               rdev->flags = T4_FATAL_ERROR;
-               ret = -EIO;
-       } else
-               ret = wr_wait.ret;
+       ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, 0, __func__);
        return ret;
 }
 
index 8f645c8..f66dd8b 100644 (file)
@@ -54,9 +54,9 @@
 
 #include "iw_cxgb4.h"
 
-static int fastreg_support;
+static int fastreg_support = 1;
 module_param(fastreg_support, int, 0644);
-MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=0)");
+MODULE_PARM_DESC(fastreg_support, "Advertise fastreg support (default=1)");
 
 static int c4iw_modify_port(struct ib_device *ibdev,
                            u8 port, int port_modify_mask,
@@ -149,19 +149,28 @@ static int c4iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
        addr = mm->addr;
        kfree(mm);
 
-       if ((addr >= pci_resource_start(rdev->lldi.pdev, 2)) &&
-           (addr < (pci_resource_start(rdev->lldi.pdev, 2) +
-                      pci_resource_len(rdev->lldi.pdev, 2)))) {
+       if ((addr >= pci_resource_start(rdev->lldi.pdev, 0)) &&
+           (addr < (pci_resource_start(rdev->lldi.pdev, 0) +
+                   pci_resource_len(rdev->lldi.pdev, 0)))) {
 
                /*
-                * Map T4 DB register.
+                * MA_SYNC register...
                 */
-               if (vma->vm_flags & VM_READ)
-                       return -EPERM;
-
                vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-               vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
-               vma->vm_flags &= ~VM_MAYREAD;
+               ret = io_remap_pfn_range(vma, vma->vm_start,
+                                        addr >> PAGE_SHIFT,
+                                        len, vma->vm_page_prot);
+       } else if ((addr >= pci_resource_start(rdev->lldi.pdev, 2)) &&
+                  (addr < (pci_resource_start(rdev->lldi.pdev, 2) +
+                   pci_resource_len(rdev->lldi.pdev, 2)))) {
+
+               /*
+                * Map user DB or OCQP memory...
+                */
+               if (addr >= rdev->oc_mw_pa)
+                       vma->vm_page_prot = t4_pgprot_wc(vma->vm_page_prot);
+               else
+                       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
                ret = io_remap_pfn_range(vma, vma->vm_start,
                                         addr >> PAGE_SHIFT,
                                         len, vma->vm_page_prot);
@@ -382,7 +391,17 @@ static ssize_t show_board(struct device *dev, struct device_attribute *attr,
 static int c4iw_get_mib(struct ib_device *ibdev,
                        union rdma_protocol_stats *stats)
 {
-       return -ENOSYS;
+       struct tp_tcp_stats v4, v6;
+       struct c4iw_dev *c4iw_dev = to_c4iw_dev(ibdev);
+
+       cxgb4_get_tcp_stats(c4iw_dev->rdev.lldi.pdev, &v4, &v6);
+       memset(stats, 0, sizeof *stats);
+       stats->iw.tcpInSegs = v4.tcpInSegs + v6.tcpInSegs;
+       stats->iw.tcpOutSegs = v4.tcpOutSegs + v6.tcpOutSegs;
+       stats->iw.tcpRetransSegs = v4.tcpRetransSegs + v6.tcpRetransSegs;
+       stats->iw.tcpOutRsts = v4.tcpOutRsts + v6.tcpOutSegs;
+
+       return 0;
 }
 
 static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
@@ -472,6 +491,7 @@ int c4iw_register_device(struct c4iw_dev *dev)
        dev->ibdev.post_send = c4iw_post_send;
        dev->ibdev.post_recv = c4iw_post_receive;
        dev->ibdev.get_protocol_stats = c4iw_get_mib;
+       dev->ibdev.uverbs_abi_ver = C4IW_UVERBS_ABI_VERSION;
 
        dev->ibdev.iwcm = kmalloc(sizeof(struct iw_cm_verbs), GFP_KERNEL);
        if (!dev->ibdev.iwcm)
index 93f6e5b..057cb25 100644 (file)
  */
 #include "iw_cxgb4.h"
 
+static int ocqp_support;
+module_param(ocqp_support, int, 0644);
+MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=0)");
+
+static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
+{
+       unsigned long flag;
+       spin_lock_irqsave(&qhp->lock, flag);
+       qhp->attr.state = state;
+       spin_unlock_irqrestore(&qhp->lock, flag);
+}
+
+static void dealloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+       c4iw_ocqp_pool_free(rdev, sq->dma_addr, sq->memsize);
+}
+
+static void dealloc_host_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+       dma_free_coherent(&(rdev->lldi.pdev->dev), sq->memsize, sq->queue,
+                         pci_unmap_addr(sq, mapping));
+}
+
+static void dealloc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+       if (t4_sq_onchip(sq))
+               dealloc_oc_sq(rdev, sq);
+       else
+               dealloc_host_sq(rdev, sq);
+}
+
+static int alloc_oc_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+       if (!ocqp_support || !t4_ocqp_supported())
+               return -ENOSYS;
+       sq->dma_addr = c4iw_ocqp_pool_alloc(rdev, sq->memsize);
+       if (!sq->dma_addr)
+               return -ENOMEM;
+       sq->phys_addr = rdev->oc_mw_pa + sq->dma_addr -
+                       rdev->lldi.vr->ocq.start;
+       sq->queue = (__force union t4_wr *)(rdev->oc_mw_kva + sq->dma_addr -
+                                           rdev->lldi.vr->ocq.start);
+       sq->flags |= T4_SQ_ONCHIP;
+       return 0;
+}
+
+static int alloc_host_sq(struct c4iw_rdev *rdev, struct t4_sq *sq)
+{
+       sq->queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev), sq->memsize,
+                                      &(sq->dma_addr), GFP_KERNEL);
+       if (!sq->queue)
+               return -ENOMEM;
+       sq->phys_addr = virt_to_phys(sq->queue);
+       pci_unmap_addr_set(sq, mapping, sq->dma_addr);
+       return 0;
+}
+
 static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
                      struct c4iw_dev_ucontext *uctx)
 {
@@ -41,9 +98,7 @@ static int destroy_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
        dma_free_coherent(&(rdev->lldi.pdev->dev),
                          wq->rq.memsize, wq->rq.queue,
                          dma_unmap_addr(&wq->rq, mapping));
-       dma_free_coherent(&(rdev->lldi.pdev->dev),
-                         wq->sq.memsize, wq->sq.queue,
-                         dma_unmap_addr(&wq->sq, mapping));
+       dealloc_sq(rdev, &wq->sq);
        c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);
        kfree(wq->rq.sw_rq);
        kfree(wq->sq.sw_sq);
@@ -93,11 +148,12 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
        if (!wq->rq.rqt_hwaddr)
                goto err4;
 
-       wq->sq.queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev),
-                                         wq->sq.memsize, &(wq->sq.dma_addr),
-                                         GFP_KERNEL);
-       if (!wq->sq.queue)
-               goto err5;
+       if (user) {
+               if (alloc_oc_sq(rdev, &wq->sq) && alloc_host_sq(rdev, &wq->sq))
+                       goto err5;
+       } else
+               if (alloc_host_sq(rdev, &wq->sq))
+                       goto err5;
        memset(wq->sq.queue, 0, wq->sq.memsize);
        dma_unmap_addr_set(&wq->sq, mapping, wq->sq.dma_addr);
 
@@ -144,7 +200,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
                        V_FW_RI_RES_WR_NRES(2) |
                        FW_WR_COMPL(1));
        res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
-       res_wr->cookie = (u64)&wr_wait;
+       res_wr->cookie = (unsigned long) &wr_wait;
        res = res_wr->res;
        res->u.sqrq.restype = FW_RI_RES_TYPE_SQ;
        res->u.sqrq.op = FW_RI_RES_OP_WRITE;
@@ -158,6 +214,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
                V_FW_RI_RES_WR_HOSTFCMODE(0) |  /* no host cidx updates */
                V_FW_RI_RES_WR_CPRIO(0) |       /* don't keep in chip cache */
                V_FW_RI_RES_WR_PCIECHN(0) |     /* set by uP at ri_init time */
+               t4_sq_onchip(&wq->sq) ? F_FW_RI_RES_WR_ONCHIP : 0 |
                V_FW_RI_RES_WR_IQID(scq->cqid));
        res->u.sqrq.dcaen_to_eqsize = cpu_to_be32(
                V_FW_RI_RES_WR_DCAEN(0) |
@@ -198,14 +255,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
        ret = c4iw_ofld_send(rdev, skb);
        if (ret)
                goto err7;
-       wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-       if (!wr_wait.done) {
-               printk(KERN_ERR MOD "Device %s not responding!\n",
-                      pci_name(rdev->lldi.pdev));
-               rdev->flags = T4_FATAL_ERROR;
-               ret = -EIO;
-       } else
-               ret = wr_wait.ret;
+       ret = c4iw_wait_for_reply(rdev, &wr_wait, 0, wq->sq.qid, __func__);
        if (ret)
                goto err7;
 
@@ -219,9 +269,7 @@ err7:
                          wq->rq.memsize, wq->rq.queue,
                          dma_unmap_addr(&wq->rq, mapping));
 err6:
-       dma_free_coherent(&(rdev->lldi.pdev->dev),
-                         wq->sq.memsize, wq->sq.queue,
-                         dma_unmap_addr(&wq->sq, mapping));
+       dealloc_sq(rdev, &wq->sq);
 err5:
        c4iw_rqtpool_free(rdev, wq->rq.rqt_hwaddr, wq->rq.rqt_size);
 err4:
@@ -263,6 +311,9 @@ static int build_immd(struct t4_sq *sq, struct fw_ri_immd *immdp,
                        rem -= len;
                }
        }
+       len = roundup(plen + sizeof *immdp, 16) - (plen + sizeof *immdp);
+       if (len)
+               memset(dstp, 0, len);
        immdp->op = FW_RI_DATA_IMMD;
        immdp->r1 = 0;
        immdp->r2 = 0;
@@ -292,6 +343,7 @@ static int build_isgl(__be64 *queue_start, __be64 *queue_end,
                if (++flitp == queue_end)
                        flitp = queue_start;
        }
+       *flitp = (__force __be64)0;
        isglp->op = FW_RI_DATA_ISGL;
        isglp->r1 = 0;
        isglp->nsge = cpu_to_be16(num_sge);
@@ -453,13 +505,15 @@ static int build_rdma_recv(struct c4iw_qp *qhp, union t4_recv_wr *wqe,
        return 0;
 }
 
-static int build_fastreg(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16)
+static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe,
+                        struct ib_send_wr *wr, u8 *len16)
 {
 
        struct fw_ri_immd *imdp;
        __be64 *p;
        int i;
        int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32);
+       int rem;
 
        if (wr->wr.fast_reg.page_list_len > T4_MAX_FR_DEPTH)
                return -EINVAL;
@@ -474,32 +528,28 @@ static int build_fastreg(union t4_wr *wqe, struct ib_send_wr *wr, u8 *len16)
        wqe->fr.va_hi = cpu_to_be32(wr->wr.fast_reg.iova_start >> 32);
        wqe->fr.va_lo_fbo = cpu_to_be32(wr->wr.fast_reg.iova_start &
                                        0xffffffff);
-       if (pbllen > T4_MAX_FR_IMMD) {
-               struct c4iw_fr_page_list *c4pl =
-                               to_c4iw_fr_page_list(wr->wr.fast_reg.page_list);
-               struct fw_ri_dsgl *sglp;
-
-               sglp = (struct fw_ri_dsgl *)(&wqe->fr + 1);
-               sglp->op = FW_RI_DATA_DSGL;
-               sglp->r1 = 0;
-               sglp->nsge = cpu_to_be16(1);
-               sglp->addr0 = cpu_to_be64(c4pl->dma_addr);
-               sglp->len0 = cpu_to_be32(pbllen);
-
-               *len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *sglp, 16);
-       } else {
-               imdp = (struct fw_ri_immd *)(&wqe->fr + 1);
-               imdp->op = FW_RI_DATA_IMMD;
-               imdp->r1 = 0;
-               imdp->r2 = 0;
-               imdp->immdlen = cpu_to_be32(pbllen);
-               p = (__be64 *)(imdp + 1);
-               for (i = 0; i < wr->wr.fast_reg.page_list_len; i++, p++)
-                       *p = cpu_to_be64(
-                               (u64)wr->wr.fast_reg.page_list->page_list[i]);
-               *len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *imdp + pbllen,
-                                     16);
+       WARN_ON(pbllen > T4_MAX_FR_IMMD);
+       imdp = (struct fw_ri_immd *)(&wqe->fr + 1);
+       imdp->op = FW_RI_DATA_IMMD;
+       imdp->r1 = 0;
+       imdp->r2 = 0;
+       imdp->immdlen = cpu_to_be32(pbllen);
+       p = (__be64 *)(imdp + 1);
+       rem = pbllen;
+       for (i = 0; i < wr->wr.fast_reg.page_list_len; i++) {
+               *p = cpu_to_be64((u64)wr->wr.fast_reg.page_list->page_list[i]);
+               rem -= sizeof *p;
+               if (++p == (__be64 *)&sq->queue[sq->size])
+                       p = (__be64 *)sq->queue;
        }
+       BUG_ON(rem < 0);
+       while (rem) {
+               *p = 0;
+               rem -= sizeof *p;
+               if (++p == (__be64 *)&sq->queue[sq->size])
+                       p = (__be64 *)sq->queue;
+       }
+       *len16 = DIV_ROUND_UP(sizeof wqe->fr + sizeof *imdp + pbllen, 16);
        return 0;
 }
 
@@ -587,7 +637,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        fw_opcode = FW_RI_RDMA_READ_WR;
                        swsqe->opcode = FW_RI_READ_REQ;
                        if (wr->opcode == IB_WR_RDMA_READ_WITH_INV)
-                               fw_flags |= FW_RI_RDMA_READ_INVALIDATE;
+                               fw_flags = FW_RI_RDMA_READ_INVALIDATE;
                        else
                                fw_flags = 0;
                        err = build_rdma_read(wqe, wr, &len16);
@@ -600,7 +650,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                case IB_WR_FAST_REG_MR:
                        fw_opcode = FW_RI_FR_NSMR_WR;
                        swsqe->opcode = FW_RI_FAST_REGISTER;
-                       err = build_fastreg(wqe, wr, &len16);
+                       err = build_fastreg(&qhp->wq.sq, wqe, wr, &len16);
                        break;
                case IB_WR_LOCAL_INV:
                        if (wr->send_flags & IB_SEND_FENCE)
@@ -905,46 +955,38 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe,
  * Assumes qhp lock is held.
  */
 static void __flush_qp(struct c4iw_qp *qhp, struct c4iw_cq *rchp,
-                      struct c4iw_cq *schp, unsigned long *flag)
+                      struct c4iw_cq *schp)
 {
        int count;
        int flushed;
+       unsigned long flag;
 
        PDBG("%s qhp %p rchp %p schp %p\n", __func__, qhp, rchp, schp);
-       /* take a ref on the qhp since we must release the lock */
-       atomic_inc(&qhp->refcnt);
-       spin_unlock_irqrestore(&qhp->lock, *flag);
 
        /* locking hierarchy: cq lock first, then qp lock. */
-       spin_lock_irqsave(&rchp->lock, *flag);
+       spin_lock_irqsave(&rchp->lock, flag);
        spin_lock(&qhp->lock);
        c4iw_flush_hw_cq(&rchp->cq);
        c4iw_count_rcqes(&rchp->cq, &qhp->wq, &count);
        flushed = c4iw_flush_rq(&qhp->wq, &rchp->cq, count);
        spin_unlock(&qhp->lock);
-       spin_unlock_irqrestore(&rchp->lock, *flag);
+       spin_unlock_irqrestore(&rchp->lock, flag);
        if (flushed)
                (*rchp->ibcq.comp_handler)(&rchp->ibcq, rchp->ibcq.cq_context);
 
        /* locking hierarchy: cq lock first, then qp lock. */
-       spin_lock_irqsave(&schp->lock, *flag);
+       spin_lock_irqsave(&schp->lock, flag);
        spin_lock(&qhp->lock);
        c4iw_flush_hw_cq(&schp->cq);
        c4iw_count_scqes(&schp->cq, &qhp->wq, &count);
        flushed = c4iw_flush_sq(&qhp->wq, &schp->cq, count);
        spin_unlock(&qhp->lock);
-       spin_unlock_irqrestore(&schp->lock, *flag);
+       spin_unlock_irqrestore(&schp->lock, flag);
        if (flushed)
                (*schp->ibcq.comp_handler)(&schp->ibcq, schp->ibcq.cq_context);
-
-       /* deref */
-       if (atomic_dec_and_test(&qhp->refcnt))
-               wake_up(&qhp->wait);
-
-       spin_lock_irqsave(&qhp->lock, *flag);
 }
 
-static void flush_qp(struct c4iw_qp *qhp, unsigned long *flag)
+static void flush_qp(struct c4iw_qp *qhp)
 {
        struct c4iw_cq *rchp, *schp;
 
@@ -958,7 +1000,7 @@ static void flush_qp(struct c4iw_qp *qhp, unsigned long *flag)
                        t4_set_cq_in_error(&schp->cq);
                return;
        }
-       __flush_qp(qhp, rchp, schp, flag);
+       __flush_qp(qhp, rchp, schp);
 }
 
 static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
@@ -966,7 +1008,6 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 {
        struct fw_ri_wr *wqe;
        int ret;
-       struct c4iw_wr_wait wr_wait;
        struct sk_buff *skb;
 
        PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
@@ -985,28 +1026,16 @@ static int rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
        wqe->flowid_len16 = cpu_to_be32(
                FW_WR_FLOWID(ep->hwtid) |
                FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16)));
-       wqe->cookie = (u64)&wr_wait;
+       wqe->cookie = (unsigned long) &ep->com.wr_wait;
 
        wqe->u.fini.type = FW_RI_TYPE_FINI;
-       c4iw_init_wr_wait(&wr_wait);
+       c4iw_init_wr_wait(&ep->com.wr_wait);
        ret = c4iw_ofld_send(&rhp->rdev, skb);
        if (ret)
                goto out;
 
-       wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-       if (!wr_wait.done) {
-               printk(KERN_ERR MOD "Device %s not responding!\n",
-                      pci_name(rhp->rdev.lldi.pdev));
-               rhp->rdev.flags = T4_FATAL_ERROR;
-               ret = -EIO;
-       } else {
-               ret = wr_wait.ret;
-               if (ret)
-                       printk(KERN_WARNING MOD
-                              "%s: Abnormal close qpid %d ret %u\n",
-                              pci_name(rhp->rdev.lldi.pdev), qhp->wq.sq.qid,
-                              ret);
-       }
+       ret = c4iw_wait_for_reply(&rhp->rdev, &ep->com.wr_wait, qhp->ep->hwtid,
+                            qhp->wq.sq.qid, __func__);
 out:
        PDBG("%s ret %d\n", __func__, ret);
        return ret;
@@ -1040,7 +1069,6 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
 {
        struct fw_ri_wr *wqe;
        int ret;
-       struct c4iw_wr_wait wr_wait;
        struct sk_buff *skb;
 
        PDBG("%s qhp %p qid 0x%x tid %u\n", __func__, qhp, qhp->wq.sq.qid,
@@ -1060,7 +1088,7 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
                FW_WR_FLOWID(qhp->ep->hwtid) |
                FW_WR_LEN16(DIV_ROUND_UP(sizeof *wqe, 16)));
 
-       wqe->cookie = (u64)&wr_wait;
+       wqe->cookie = (unsigned long) &qhp->ep->com.wr_wait;
 
        wqe->u.init.type = FW_RI_TYPE_INIT;
        wqe->u.init.mpareqbit_p2ptype =
@@ -1097,19 +1125,13 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp)
        if (qhp->attr.mpa_attr.initiator)
                build_rtr_msg(qhp->attr.mpa_attr.p2p_type, &wqe->u.init);
 
-       c4iw_init_wr_wait(&wr_wait);
+       c4iw_init_wr_wait(&qhp->ep->com.wr_wait);
        ret = c4iw_ofld_send(&rhp->rdev, skb);
        if (ret)
                goto out;
 
-       wait_event_timeout(wr_wait.wait, wr_wait.done, C4IW_WR_TO);
-       if (!wr_wait.done) {
-               printk(KERN_ERR MOD "Device %s not responding!\n",
-                      pci_name(rhp->rdev.lldi.pdev));
-               rhp->rdev.flags = T4_FATAL_ERROR;
-               ret = -EIO;
-       } else
-               ret = wr_wait.ret;
+       ret = c4iw_wait_for_reply(&rhp->rdev, &qhp->ep->com.wr_wait,
+                                 qhp->ep->hwtid, qhp->wq.sq.qid, __func__);
 out:
        PDBG("%s ret %d\n", __func__, ret);
        return ret;
@@ -1122,7 +1144,6 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
 {
        int ret = 0;
        struct c4iw_qp_attributes newattr = qhp->attr;
-       unsigned long flag;
        int disconnect = 0;
        int terminate = 0;
        int abort = 0;
@@ -1133,7 +1154,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
             qhp, qhp->wq.sq.qid, qhp->wq.rq.qid, qhp->ep, qhp->attr.state,
             (mask & C4IW_QP_ATTR_NEXT_STATE) ? attrs->next_state : -1);
 
-       spin_lock_irqsave(&qhp->lock, flag);
+       mutex_lock(&qhp->mutex);
 
        /* Process attr changes if in IDLE */
        if (mask & C4IW_QP_ATTR_VALID_MODIFY) {
@@ -1184,7 +1205,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                        qhp->attr.mpa_attr = attrs->mpa_attr;
                        qhp->attr.llp_stream_handle = attrs->llp_stream_handle;
                        qhp->ep = qhp->attr.llp_stream_handle;
-                       qhp->attr.state = C4IW_QP_STATE_RTS;
+                       set_state(qhp, C4IW_QP_STATE_RTS);
 
                        /*
                         * Ref the endpoint here and deref when we
@@ -1193,15 +1214,13 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                         * transition.
                         */
                        c4iw_get_ep(&qhp->ep->com);
-                       spin_unlock_irqrestore(&qhp->lock, flag);
                        ret = rdma_init(rhp, qhp);
-                       spin_lock_irqsave(&qhp->lock, flag);
                        if (ret)
                                goto err;
                        break;
                case C4IW_QP_STATE_ERROR:
-                       qhp->attr.state = C4IW_QP_STATE_ERROR;
-                       flush_qp(qhp, &flag);
+                       set_state(qhp, C4IW_QP_STATE_ERROR);
+                       flush_qp(qhp);
                        break;
                default:
                        ret = -EINVAL;
@@ -1212,38 +1231,38 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                switch (attrs->next_state) {
                case C4IW_QP_STATE_CLOSING:
                        BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2);
-                       qhp->attr.state = C4IW_QP_STATE_CLOSING;
+                       set_state(qhp, C4IW_QP_STATE_CLOSING);
                        ep = qhp->ep;
                        if (!internal) {
                                abort = 0;
                                disconnect = 1;
-                               c4iw_get_ep(&ep->com);
+                               c4iw_get_ep(&qhp->ep->com);
                        }
-                       spin_unlock_irqrestore(&qhp->lock, flag);
                        ret = rdma_fini(rhp, qhp, ep);
-                       spin_lock_irqsave(&qhp->lock, flag);
                        if (ret) {
-                               c4iw_get_ep(&ep->com);
+                               if (internal)
+                                       c4iw_get_ep(&qhp->ep->com);
                                disconnect = abort = 1;
                                goto err;
                        }
                        break;
                case C4IW_QP_STATE_TERMINATE:
-                       qhp->attr.state = C4IW_QP_STATE_TERMINATE;
+                       set_state(qhp, C4IW_QP_STATE_TERMINATE);
                        if (qhp->ibqp.uobject)
                                t4_set_wq_in_error(&qhp->wq);
                        ep = qhp->ep;
-                       c4iw_get_ep(&ep->com);
-                       terminate = 1;
+                       if (!internal)
+                               terminate = 1;
                        disconnect = 1;
+                       c4iw_get_ep(&qhp->ep->com);
                        break;
                case C4IW_QP_STATE_ERROR:
-                       qhp->attr.state = C4IW_QP_STATE_ERROR;
+                       set_state(qhp, C4IW_QP_STATE_ERROR);
                        if (!internal) {
                                abort = 1;
                                disconnect = 1;
                                ep = qhp->ep;
-                               c4iw_get_ep(&ep->com);
+                               c4iw_get_ep(&qhp->ep->com);
                        }
                        goto err;
                        break;
@@ -1259,8 +1278,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                }
                switch (attrs->next_state) {
                case C4IW_QP_STATE_IDLE:
-                       flush_qp(qhp, &flag);
-                       qhp->attr.state = C4IW_QP_STATE_IDLE;
+                       flush_qp(qhp);
+                       set_state(qhp, C4IW_QP_STATE_IDLE);
                        qhp->attr.llp_stream_handle = NULL;
                        c4iw_put_ep(&qhp->ep->com);
                        qhp->ep = NULL;
@@ -1282,7 +1301,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                        ret = -EINVAL;
                        goto out;
                }
-               qhp->attr.state = C4IW_QP_STATE_IDLE;
+               set_state(qhp, C4IW_QP_STATE_IDLE);
                break;
        case C4IW_QP_STATE_TERMINATE:
                if (!internal) {
@@ -1305,15 +1324,16 @@ err:
 
        /* disassociate the LLP connection */
        qhp->attr.llp_stream_handle = NULL;
-       ep = qhp->ep;
+       if (!ep)
+               ep = qhp->ep;
        qhp->ep = NULL;
-       qhp->attr.state = C4IW_QP_STATE_ERROR;
+       set_state(qhp, C4IW_QP_STATE_ERROR);
        free = 1;
        wake_up(&qhp->wait);
        BUG_ON(!ep);
-       flush_qp(qhp, &flag);
+       flush_qp(qhp);
 out:
-       spin_unlock_irqrestore(&qhp->lock, flag);
+       mutex_unlock(&qhp->mutex);
 
        if (terminate)
                post_terminate(qhp, NULL, internal ? GFP_ATOMIC : GFP_KERNEL);
@@ -1335,7 +1355,6 @@ out:
         */
        if (free)
                c4iw_put_ep(&ep->com);
-
        PDBG("%s exit state %d\n", __func__, qhp->attr.state);
        return ret;
 }
@@ -1380,7 +1399,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        int sqsize, rqsize;
        struct c4iw_ucontext *ucontext;
        int ret;
-       struct c4iw_mm_entry *mm1, *mm2, *mm3, *mm4;
+       struct c4iw_mm_entry *mm1, *mm2, *mm3, *mm4, *mm5 = NULL;
 
        PDBG("%s ib_pd %p\n", __func__, pd);
 
@@ -1450,6 +1469,7 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
        qhp->attr.max_ord = 1;
        qhp->attr.max_ird = 1;
        spin_lock_init(&qhp->lock);
+       mutex_init(&qhp->mutex);
        init_waitqueue_head(&qhp->wait);
        atomic_set(&qhp->refcnt, 1);
 
@@ -1478,7 +1498,15 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
                        ret = -ENOMEM;
                        goto err6;
                }
-
+               if (t4_sq_onchip(&qhp->wq.sq)) {
+                       mm5 = kmalloc(sizeof *mm5, GFP_KERNEL);
+                       if (!mm5) {
+                               ret = -ENOMEM;
+                               goto err7;
+                       }
+                       uresp.flags = C4IW_QPF_ONCHIP;
+               } else
+                       uresp.flags = 0;
                uresp.qid_mask = rhp->rdev.qpmask;
                uresp.sqid = qhp->wq.sq.qid;
                uresp.sq_size = qhp->wq.sq.size;
@@ -1487,6 +1515,10 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
                uresp.rq_size = qhp->wq.rq.size;
                uresp.rq_memsize = qhp->wq.rq.memsize;
                spin_lock(&ucontext->mmap_lock);
+               if (mm5) {
+                       uresp.ma_sync_key = ucontext->key;
+                       ucontext->key += PAGE_SIZE;
+               }
                uresp.sq_key = ucontext->key;
                ucontext->key += PAGE_SIZE;
                uresp.rq_key = ucontext->key;
@@ -1498,9 +1530,9 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
                spin_unlock(&ucontext->mmap_lock);
                ret = ib_copy_to_udata(udata, &uresp, sizeof uresp);
                if (ret)
-                       goto err7;
+                       goto err8;
                mm1->key = uresp.sq_key;
-               mm1->addr = virt_to_phys(qhp->wq.sq.queue);
+               mm1->addr = qhp->wq.sq.phys_addr;
                mm1->len = PAGE_ALIGN(qhp->wq.sq.memsize);
                insert_mmap(ucontext, mm1);
                mm2->key = uresp.rq_key;
@@ -1515,6 +1547,13 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
                mm4->addr = qhp->wq.rq.udb;
                mm4->len = PAGE_SIZE;
                insert_mmap(ucontext, mm4);
+               if (mm5) {
+                       mm5->key = uresp.ma_sync_key;
+                       mm5->addr = (pci_resource_start(rhp->rdev.lldi.pdev, 0)
+                                   + A_PCIE_MA_SYNC) & PAGE_MASK;
+                       mm5->len = PAGE_SIZE;
+                       insert_mmap(ucontext, mm5);
+               }
        }
        qhp->ibqp.qp_num = qhp->wq.sq.qid;
        init_timer(&(qhp->timer));
@@ -1522,6 +1561,8 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs,
             __func__, qhp, qhp->attr.sq_num_entries, qhp->attr.rq_num_entries,
             qhp->wq.sq.qid);
        return &qhp->ibqp;
+err8:
+       kfree(mm5);
 err7:
        kfree(mm4);
 err6:
index 83b23df..4fb50d5 100644 (file)
@@ -311,6 +311,9 @@ u32 c4iw_pblpool_alloc(struct c4iw_rdev *rdev, int size)
 {
        unsigned long addr = gen_pool_alloc(rdev->pbl_pool, size);
        PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
+       if (!addr && printk_ratelimit())
+               printk(KERN_WARNING MOD "%s: Out of PBL memory\n",
+                      pci_name(rdev->lldi.pdev));
        return (u32)addr;
 }
 
@@ -370,6 +373,9 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size)
 {
        unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6);
        PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6);
+       if (!addr && printk_ratelimit())
+               printk(KERN_WARNING MOD "%s: Out of RQT memory\n",
+                      pci_name(rdev->lldi.pdev));
        return (u32)addr;
 }
 
@@ -416,3 +422,59 @@ void c4iw_rqtpool_destroy(struct c4iw_rdev *rdev)
 {
        gen_pool_destroy(rdev->rqt_pool);
 }
+
+/*
+ * On-Chip QP Memory.
+ */
+#define MIN_OCQP_SHIFT 12      /* 4KB == min ocqp size */
+
+u32 c4iw_ocqp_pool_alloc(struct c4iw_rdev *rdev, int size)
+{
+       unsigned long addr = gen_pool_alloc(rdev->ocqp_pool, size);
+       PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size);
+       return (u32)addr;
+}
+
+void c4iw_ocqp_pool_free(struct c4iw_rdev *rdev, u32 addr, int size)
+{
+       PDBG("%s addr 0x%x size %d\n", __func__, addr, size);
+       gen_pool_free(rdev->ocqp_pool, (unsigned long)addr, size);
+}
+
+int c4iw_ocqp_pool_create(struct c4iw_rdev *rdev)
+{
+       unsigned start, chunk, top;
+
+       rdev->ocqp_pool = gen_pool_create(MIN_OCQP_SHIFT, -1);
+       if (!rdev->ocqp_pool)
+               return -ENOMEM;
+
+       start = rdev->lldi.vr->ocq.start;
+       chunk = rdev->lldi.vr->ocq.size;
+       top = start + chunk;
+
+       while (start < top) {
+               chunk = min(top - start + 1, chunk);
+               if (gen_pool_add(rdev->ocqp_pool, start, chunk, -1)) {
+                       PDBG("%s failed to add OCQP chunk (%x/%x)\n",
+                            __func__, start, chunk);
+                       if (chunk <= 1024 << MIN_OCQP_SHIFT) {
+                               printk(KERN_WARNING MOD
+                                      "Failed to add all OCQP chunks (%x/%x)\n",
+                                      start, top - start);
+                               return 0;
+                       }
+                       chunk >>= 1;
+               } else {
+                       PDBG("%s added OCQP chunk (%x/%x)\n",
+                            __func__, start, chunk);
+                       start += chunk;
+               }
+       }
+       return 0;
+}
+
+void c4iw_ocqp_pool_destroy(struct c4iw_rdev *rdev)
+{
+       gen_pool_destroy(rdev->ocqp_pool);
+}
index 24f3690..7000442 100644 (file)
@@ -52,6 +52,7 @@
 #define T4_STAG_UNSET 0xffffffff
 #define T4_FW_MAJ 0
 #define T4_EQ_STATUS_ENTRIES (L1_CACHE_BYTES > 64 ? 2 : 1)
+#define A_PCIE_MA_SYNC 0x30b4
 
 struct t4_status_page {
        __be32 rsvd1;   /* flit 0 - hw owns */
@@ -65,7 +66,7 @@ struct t4_status_page {
 
 #define T4_EQ_ENTRY_SIZE 64
 
-#define T4_SQ_NUM_SLOTS 4
+#define T4_SQ_NUM_SLOTS 5
 #define T4_SQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_SQ_NUM_SLOTS)
 #define T4_MAX_SEND_SGE ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_send_wr) - \
                        sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge))
@@ -78,7 +79,7 @@ struct t4_status_page {
                        sizeof(struct fw_ri_rdma_write_wr) - \
                        sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge))
 #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \
-                       sizeof(struct fw_ri_immd)))
+                       sizeof(struct fw_ri_immd)) & ~31UL)
 #define T4_MAX_FR_DEPTH (T4_MAX_FR_IMMD / sizeof(u64))
 
 #define T4_RQ_NUM_SLOTS 2
@@ -266,10 +267,36 @@ struct t4_swsqe {
        u16                     idx;
 };
 
+static inline pgprot_t t4_pgprot_wc(pgprot_t prot)
+{
+#if defined(__i386__) || defined(__x86_64__)
+       return pgprot_writecombine(prot);
+#elif defined(CONFIG_PPC64)
+       return __pgprot((pgprot_val(prot) | _PAGE_NO_CACHE) &
+                       ~(pgprot_t)_PAGE_GUARDED);
+#else
+       return pgprot_noncached(prot);
+#endif
+}
+
+static inline int t4_ocqp_supported(void)
+{
+#if defined(__i386__) || defined(__x86_64__) || defined(CONFIG_PPC64)
+       return 1;
+#else
+       return 0;
+#endif
+}
+
+enum {
+       T4_SQ_ONCHIP = (1<<0),
+};
+
 struct t4_sq {
        union t4_wr *queue;
        dma_addr_t dma_addr;
        DEFINE_DMA_UNMAP_ADDR(mapping);
+       unsigned long phys_addr;
        struct t4_swsqe *sw_sq;
        struct t4_swsqe *oldest_read;
        u64 udb;
@@ -280,6 +307,7 @@ struct t4_sq {
        u16 cidx;
        u16 pidx;
        u16 wq_pidx;
+       u16 flags;
 };
 
 struct t4_swrqe {
@@ -350,6 +378,11 @@ static inline void t4_rq_consume(struct t4_wq *wq)
                wq->rq.cidx = 0;
 }
 
+static inline int t4_sq_onchip(struct t4_sq *sq)
+{
+       return sq->flags & T4_SQ_ONCHIP;
+}
+
 static inline int t4_sq_empty(struct t4_wq *wq)
 {
        return wq->sq.in_use == 0;
@@ -396,30 +429,27 @@ static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc)
 
 static inline int t4_wq_in_error(struct t4_wq *wq)
 {
-       return wq->sq.queue[wq->sq.size].status.qp_err;
+       return wq->rq.queue[wq->rq.size].status.qp_err;
 }
 
 static inline void t4_set_wq_in_error(struct t4_wq *wq)
 {
-       wq->sq.queue[wq->sq.size].status.qp_err = 1;
        wq->rq.queue[wq->rq.size].status.qp_err = 1;
 }
 
 static inline void t4_disable_wq_db(struct t4_wq *wq)
 {
-       wq->sq.queue[wq->sq.size].status.db_off = 1;
        wq->rq.queue[wq->rq.size].status.db_off = 1;
 }
 
 static inline void t4_enable_wq_db(struct t4_wq *wq)
 {
-       wq->sq.queue[wq->sq.size].status.db_off = 0;
        wq->rq.queue[wq->rq.size].status.db_off = 0;
 }
 
 static inline int t4_wq_db_enabled(struct t4_wq *wq)
 {
-       return !wq->sq.queue[wq->sq.size].status.db_off;
+       return !wq->rq.queue[wq->rq.size].status.db_off;
 }
 
 struct t4_cq {
index ed6414a..e6669d5 100644 (file)
@@ -50,7 +50,13 @@ struct c4iw_create_cq_resp {
        __u32 qid_mask;
 };
 
+
+enum {
+       C4IW_QPF_ONCHIP = (1<<0)
+};
+
 struct c4iw_create_qp_resp {
+       __u64 ma_sync_key;
        __u64 sq_key;
        __u64 rq_key;
        __u64 sq_db_gts_key;
@@ -62,5 +68,6 @@ struct c4iw_create_qp_resp {
        __u32 sq_size;
        __u32 rq_size;
        __u32 qid_mask;
+       __u32 flags;
 };
 #endif
index 53f4cd4..43cae84 100644 (file)
@@ -171,7 +171,7 @@ struct ib_mr *ehca_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
                }
 
                ret = ehca_reg_maxmr(shca, e_maxmr,
-                                    (void *)ehca_map_vaddr((void *)KERNELBASE),
+                                    (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)),
                                     mr_access_flags, e_pd,
                                     &e_maxmr->ib.ib_mr.lkey,
                                     &e_maxmr->ib.ib_mr.rkey);
@@ -1636,7 +1636,7 @@ int ehca_reg_internal_maxmr(
 
        /* register internal max-MR on HCA */
        size_maxmr = ehca_mr_len;
-       iova_start = (u64 *)ehca_map_vaddr((void *)KERNELBASE);
+       iova_start = (u64 *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START));
        ib_pbuf.addr = 0;
        ib_pbuf.size = size_maxmr;
        num_kpages = NUM_CHUNKS(((u64)iova_start % PAGE_SIZE) + size_maxmr,
@@ -2209,7 +2209,7 @@ int ehca_mr_is_maxmr(u64 size,
 {
        /* a MR is treated as max-MR only if it fits following: */
        if ((size == ehca_mr_len) &&
-           (iova_start == (void *)ehca_map_vaddr((void *)KERNELBASE))) {
+           (iova_start == (void *)ehca_map_vaddr((void *)(KERNELBASE + PHYSICAL_START)))) {
                ehca_gen_dbg("this is a max-MR");
                return 1;
        } else
index fa3df82..4496f28 100644 (file)
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS += -DIPATH_IDSTR='"QLogic kernel.org driver"' \
+ccflags-y := -DIPATH_IDSTR='"QLogic kernel.org driver"' \
        -DIPATH_KERN_TYPE=0
 
 obj-$(CONFIG_INFINIBAND_IPATH) += ib_ipath.o
index 11a236f..4b8f9c4 100644 (file)
  * SOFTWARE.
  */
 
+#include <rdma/ib_addr.h>
+#include <rdma/ib_cache.h>
+
 #include <linux/slab.h>
+#include <linux/inet.h>
+#include <linux/string.h>
 
 #include "mlx4_ib.h"
 
-struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr,
+                       u8 *mac, int *is_mcast, u8 port)
 {
-       struct mlx4_dev *dev = to_mdev(pd->device)->dev;
-       struct mlx4_ib_ah *ah;
+       struct in6_addr in6;
 
-       ah = kmalloc(sizeof *ah, GFP_ATOMIC);
-       if (!ah)
-               return ERR_PTR(-ENOMEM);
+       *is_mcast = 0;
 
-       memset(&ah->av, 0, sizeof ah->av);
+       memcpy(&in6, ah_attr->grh.dgid.raw, sizeof in6);
+       if (rdma_link_local_addr(&in6))
+               rdma_get_ll_mac(&in6, mac);
+       else if (rdma_is_multicast_addr(&in6)) {
+               rdma_get_mcast_mac(&in6, mac);
+               *is_mcast = 1;
+       } else
+               return -EINVAL;
 
-       ah->av.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
-       ah->av.g_slid  = ah_attr->src_path_bits;
-       ah->av.dlid    = cpu_to_be16(ah_attr->dlid);
-       if (ah_attr->static_rate) {
-               ah->av.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
-               while (ah->av.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
-                      !(1 << ah->av.stat_rate & dev->caps.stat_rate_support))
-                       --ah->av.stat_rate;
-       }
-       ah->av.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
+       return 0;
+}
+
+static struct ib_ah *create_ib_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+                                 struct mlx4_ib_ah *ah)
+{
+       struct mlx4_dev *dev = to_mdev(pd->device)->dev;
+
+       ah->av.ib.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
+       ah->av.ib.g_slid  = ah_attr->src_path_bits;
        if (ah_attr->ah_flags & IB_AH_GRH) {
-               ah->av.g_slid   |= 0x80;
-               ah->av.gid_index = ah_attr->grh.sgid_index;
-               ah->av.hop_limit = ah_attr->grh.hop_limit;
-               ah->av.sl_tclass_flowlabel |=
+               ah->av.ib.g_slid   |= 0x80;
+               ah->av.ib.gid_index = ah_attr->grh.sgid_index;
+               ah->av.ib.hop_limit = ah_attr->grh.hop_limit;
+               ah->av.ib.sl_tclass_flowlabel |=
                        cpu_to_be32((ah_attr->grh.traffic_class << 20) |
                                    ah_attr->grh.flow_label);
-               memcpy(ah->av.dgid, ah_attr->grh.dgid.raw, 16);
+               memcpy(ah->av.ib.dgid, ah_attr->grh.dgid.raw, 16);
+       }
+
+       ah->av.ib.dlid    = cpu_to_be16(ah_attr->dlid);
+       if (ah_attr->static_rate) {
+               ah->av.ib.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
+               while (ah->av.ib.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
+                      !(1 << ah->av.ib.stat_rate & dev->caps.stat_rate_support))
+                       --ah->av.ib.stat_rate;
        }
+       ah->av.ib.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
 
        return &ah->ibah;
 }
 
+static struct ib_ah *create_iboe_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr,
+                                   struct mlx4_ib_ah *ah)
+{
+       struct mlx4_ib_dev *ibdev = to_mdev(pd->device);
+       struct mlx4_dev *dev = ibdev->dev;
+       union ib_gid sgid;
+       u8 mac[6];
+       int err;
+       int is_mcast;
+       u16 vlan_tag;
+
+       err = mlx4_ib_resolve_grh(ibdev, ah_attr, mac, &is_mcast, ah_attr->port_num);
+       if (err)
+               return ERR_PTR(err);
+
+       memcpy(ah->av.eth.mac, mac, 6);
+       err = ib_get_cached_gid(pd->device, ah_attr->port_num, ah_attr->grh.sgid_index, &sgid);
+       if (err)
+               return ERR_PTR(err);
+       vlan_tag = rdma_get_vlan_id(&sgid);
+       if (vlan_tag < 0x1000)
+               vlan_tag |= (ah_attr->sl & 7) << 13;
+       ah->av.eth.port_pd = cpu_to_be32(to_mpd(pd)->pdn | (ah_attr->port_num << 24));
+       ah->av.eth.gid_index = ah_attr->grh.sgid_index;
+       ah->av.eth.vlan = cpu_to_be16(vlan_tag);
+       if (ah_attr->static_rate) {
+               ah->av.eth.stat_rate = ah_attr->static_rate + MLX4_STAT_RATE_OFFSET;
+               while (ah->av.eth.stat_rate > IB_RATE_2_5_GBPS + MLX4_STAT_RATE_OFFSET &&
+                      !(1 << ah->av.eth.stat_rate & dev->caps.stat_rate_support))
+                       --ah->av.eth.stat_rate;
+       }
+
+       /*
+        * HW requires multicast LID so we just choose one.
+        */
+       if (is_mcast)
+               ah->av.ib.dlid = cpu_to_be16(0xc000);
+
+       memcpy(ah->av.eth.dgid, ah_attr->grh.dgid.raw, 16);
+       ah->av.eth.sl_tclass_flowlabel = cpu_to_be32(ah_attr->sl << 28);
+
+       return &ah->ibah;
+}
+
+struct ib_ah *mlx4_ib_create_ah(struct ib_pd *pd, struct ib_ah_attr *ah_attr)
+{
+       struct mlx4_ib_ah *ah;
+       struct ib_ah *ret;
+
+       ah = kzalloc(sizeof *ah, GFP_ATOMIC);
+       if (!ah)
+               return ERR_PTR(-ENOMEM);
+
+       if (rdma_port_get_link_layer(pd->device, ah_attr->port_num) == IB_LINK_LAYER_ETHERNET) {
+               if (!(ah_attr->ah_flags & IB_AH_GRH)) {
+                       ret = ERR_PTR(-EINVAL);
+               } else {
+                       /*
+                        * TBD: need to handle the case when we get
+                        * called in an atomic context and there we
+                        * might sleep.  We don't expect this
+                        * currently since we're working with link
+                        * local addresses which we can translate
+                        * without going to sleep.
+                        */
+                       ret = create_iboe_ah(pd, ah_attr, ah);
+               }
+
+               if (IS_ERR(ret))
+                       kfree(ah);
+
+               return ret;
+       } else
+               return create_ib_ah(pd, ah_attr, ah); /* never fails */
+}
+
 int mlx4_ib_query_ah(struct ib_ah *ibah, struct ib_ah_attr *ah_attr)
 {
        struct mlx4_ib_ah *ah = to_mah(ibah);
+       enum rdma_link_layer ll;
 
        memset(ah_attr, 0, sizeof *ah_attr);
-       ah_attr->dlid          = be16_to_cpu(ah->av.dlid);
-       ah_attr->sl            = be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28;
-       ah_attr->port_num      = be32_to_cpu(ah->av.port_pd) >> 24;
-       if (ah->av.stat_rate)
-               ah_attr->static_rate = ah->av.stat_rate - MLX4_STAT_RATE_OFFSET;
-       ah_attr->src_path_bits = ah->av.g_slid & 0x7F;
+       ah_attr->sl = be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+       ah_attr->port_num = be32_to_cpu(ah->av.ib.port_pd) >> 24;
+       ll = rdma_port_get_link_layer(ibah->device, ah_attr->port_num);
+       ah_attr->dlid = ll == IB_LINK_LAYER_INFINIBAND ? be16_to_cpu(ah->av.ib.dlid) : 0;
+       if (ah->av.ib.stat_rate)
+               ah_attr->static_rate = ah->av.ib.stat_rate - MLX4_STAT_RATE_OFFSET;
+       ah_attr->src_path_bits = ah->av.ib.g_slid & 0x7F;
 
        if (mlx4_ib_ah_grh_present(ah)) {
                ah_attr->ah_flags = IB_AH_GRH;
 
                ah_attr->grh.traffic_class =
-                       be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20;
+                       be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 20;
                ah_attr->grh.flow_label =
-                       be32_to_cpu(ah->av.sl_tclass_flowlabel) & 0xfffff;
-               ah_attr->grh.hop_limit  = ah->av.hop_limit;
-               ah_attr->grh.sgid_index = ah->av.gid_index;
-               memcpy(ah_attr->grh.dgid.raw, ah->av.dgid, 16);
+                       be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) & 0xfffff;
+               ah_attr->grh.hop_limit  = ah->av.ib.hop_limit;
+               ah_attr->grh.sgid_index = ah->av.ib.gid_index;
+               memcpy(ah_attr->grh.dgid.raw, ah->av.ib.dgid, 16);
        }
 
        return 0;
index f38d5b1..c9a8dd6 100644 (file)
@@ -311,19 +311,25 @@ int mlx4_ib_mad_init(struct mlx4_ib_dev *dev)
        struct ib_mad_agent *agent;
        int p, q;
        int ret;
+       enum rdma_link_layer ll;
 
-       for (p = 0; p < dev->num_ports; ++p)
+       for (p = 0; p < dev->num_ports; ++p) {
+               ll = rdma_port_get_link_layer(&dev->ib_dev, p + 1);
                for (q = 0; q <= 1; ++q) {
-                       agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
-                                                     q ? IB_QPT_GSI : IB_QPT_SMI,
-                                                     NULL, 0, send_handler,
-                                                     NULL, NULL);
-                       if (IS_ERR(agent)) {
-                               ret = PTR_ERR(agent);
-                               goto err;
-                       }
-                       dev->send_agent[p][q] = agent;
+                       if (ll == IB_LINK_LAYER_INFINIBAND) {
+                               agent = ib_register_mad_agent(&dev->ib_dev, p + 1,
+                                                             q ? IB_QPT_GSI : IB_QPT_SMI,
+                                                             NULL, 0, send_handler,
+                                                             NULL, NULL);
+                               if (IS_ERR(agent)) {
+                                       ret = PTR_ERR(agent);
+                                       goto err;
+                               }
+                               dev->send_agent[p][q] = agent;
+                       } else
+                               dev->send_agent[p][q] = NULL;
                }
+       }
 
        return 0;
 
@@ -344,8 +350,10 @@ void mlx4_ib_mad_cleanup(struct mlx4_ib_dev *dev)
        for (p = 0; p < dev->num_ports; ++p) {
                for (q = 0; q <= 1; ++q) {
                        agent = dev->send_agent[p][q];
-                       dev->send_agent[p][q] = NULL;
-                       ib_unregister_mad_agent(agent);
+                       if (agent) {
+                               dev->send_agent[p][q] = NULL;
+                               ib_unregister_mad_agent(agent);
+                       }
                }
 
                if (dev->sm_ah[p])
index 4e94e36..bf3e20c 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
 
 #include <rdma/ib_smi.h>
 #include <rdma/ib_user_verbs.h>
+#include <rdma/ib_addr.h>
 
 #include <linux/mlx4/driver.h>
 #include <linux/mlx4/cmd.h>
@@ -58,6 +63,15 @@ static const char mlx4_ib_version[] =
        DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
        DRV_VERSION " (" DRV_RELDATE ")\n";
 
+struct update_gid_work {
+       struct work_struct      work;
+       union ib_gid            gids[128];
+       struct mlx4_ib_dev     *dev;
+       int                     port;
+};
+
+static struct workqueue_struct *wq;
+
 static void init_query_mad(struct ib_smp *mad)
 {
        mad->base_version  = 1;
@@ -66,6 +80,8 @@ static void init_query_mad(struct ib_smp *mad)
        mad->method        = IB_MGMT_METHOD_GET;
 }
 
+static union ib_gid zgid;
+
 static int mlx4_ib_query_device(struct ib_device *ibdev,
                                struct ib_device_attr *props)
 {
@@ -135,7 +151,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->max_srq             = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
        props->max_srq_wr          = dev->dev->caps.max_srq_wqes - 1;
        props->max_srq_sge         = dev->dev->caps.max_srq_sge;
-       props->max_fast_reg_page_list_len = PAGE_SIZE / sizeof (u64);
+       props->max_fast_reg_page_list_len = MLX4_MAX_FAST_REG_PAGES;
        props->local_ca_ack_delay  = dev->dev->caps.local_ca_ack_delay;
        props->atomic_cap          = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
                IB_ATOMIC_HCA : IB_ATOMIC_NONE;
@@ -154,28 +170,19 @@ out:
        return err;
 }
 
-static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
-                             struct ib_port_attr *props)
+static enum rdma_link_layer
+mlx4_ib_port_link_layer(struct ib_device *device, u8 port_num)
 {
-       struct ib_smp *in_mad  = NULL;
-       struct ib_smp *out_mad = NULL;
-       int err = -ENOMEM;
-
-       in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
-       out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
-       if (!in_mad || !out_mad)
-               goto out;
-
-       memset(props, 0, sizeof *props);
-
-       init_query_mad(in_mad);
-       in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
-       in_mad->attr_mod = cpu_to_be32(port);
+       struct mlx4_dev *dev = to_mdev(device)->dev;
 
-       err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad);
-       if (err)
-               goto out;
+       return dev->caps.port_mask & (1 << (port_num - 1)) ?
+               IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
+}
 
+static int ib_link_query_port(struct ib_device *ibdev, u8 port,
+                             struct ib_port_attr *props,
+                             struct ib_smp *out_mad)
+{
        props->lid              = be16_to_cpup((__be16 *) (out_mad->data + 16));
        props->lmc              = out_mad->data[34] & 0x7;
        props->sm_lid           = be16_to_cpup((__be16 *) (out_mad->data + 18));
@@ -196,6 +203,80 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
        props->max_vl_num       = out_mad->data[37] >> 4;
        props->init_type_reply  = out_mad->data[41] >> 4;
 
+       return 0;
+}
+
+static u8 state_to_phys_state(enum ib_port_state state)
+{
+       return state == IB_PORT_ACTIVE ? 5 : 3;
+}
+
+static int eth_link_query_port(struct ib_device *ibdev, u8 port,
+                              struct ib_port_attr *props,
+                              struct ib_smp *out_mad)
+{
+       struct mlx4_ib_iboe *iboe = &to_mdev(ibdev)->iboe;
+       struct net_device *ndev;
+       enum ib_mtu tmp;
+
+       props->active_width     = IB_WIDTH_4X;
+       props->active_speed     = 4;
+       props->port_cap_flags   = IB_PORT_CM_SUP;
+       props->gid_tbl_len      = to_mdev(ibdev)->dev->caps.gid_table_len[port];
+       props->max_msg_sz       = to_mdev(ibdev)->dev->caps.max_msg_sz;
+       props->pkey_tbl_len     = 1;
+       props->bad_pkey_cntr    = be16_to_cpup((__be16 *) (out_mad->data + 46));
+       props->qkey_viol_cntr   = be16_to_cpup((__be16 *) (out_mad->data + 48));
+       props->max_mtu          = IB_MTU_2048;
+       props->subnet_timeout   = 0;
+       props->max_vl_num       = out_mad->data[37] >> 4;
+       props->init_type_reply  = 0;
+       props->state            = IB_PORT_DOWN;
+       props->phys_state       = state_to_phys_state(props->state);
+       props->active_mtu       = IB_MTU_256;
+       spin_lock(&iboe->lock);
+       ndev = iboe->netdevs[port - 1];
+       if (!ndev)
+               goto out;
+
+       tmp = iboe_get_mtu(ndev->mtu);
+       props->active_mtu = tmp ? min(props->max_mtu, tmp) : IB_MTU_256;
+
+       props->state            = netif_running(ndev) &&  netif_oper_up(ndev) ?
+                                       IB_PORT_ACTIVE : IB_PORT_DOWN;
+       props->phys_state       = state_to_phys_state(props->state);
+
+out:
+       spin_unlock(&iboe->lock);
+       return 0;
+}
+
+static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
+                             struct ib_port_attr *props)
+{
+       struct ib_smp *in_mad  = NULL;
+       struct ib_smp *out_mad = NULL;
+       int err = -ENOMEM;
+
+       in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
+       out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
+       if (!in_mad || !out_mad)
+               goto out;
+
+       memset(props, 0, sizeof *props);
+
+       init_query_mad(in_mad);
+       in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
+       in_mad->attr_mod = cpu_to_be32(port);
+
+       err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad);
+       if (err)
+               goto out;
+
+       err = mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ?
+               ib_link_query_port(ibdev, port, props, out_mad) :
+               eth_link_query_port(ibdev, port, props, out_mad);
+
 out:
        kfree(in_mad);
        kfree(out_mad);
@@ -203,8 +284,8 @@ out:
        return err;
 }
 
-static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
-                            union ib_gid *gid)
+static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+                              union ib_gid *gid)
 {
        struct ib_smp *in_mad  = NULL;
        struct ib_smp *out_mad = NULL;
@@ -241,6 +322,25 @@ out:
        return err;
 }
 
+static int iboe_query_gid(struct ib_device *ibdev, u8 port, int index,
+                         union ib_gid *gid)
+{
+       struct mlx4_ib_dev *dev = to_mdev(ibdev);
+
+       *gid = dev->iboe.gid_table[port - 1][index];
+
+       return 0;
+}
+
+static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+                            union ib_gid *gid)
+{
+       if (rdma_port_get_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND)
+               return __mlx4_ib_query_gid(ibdev, port, index, gid);
+       else
+               return iboe_query_gid(ibdev, port, index, gid);
+}
+
 static int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
                              u16 *pkey)
 {
@@ -272,14 +372,32 @@ out:
 static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
                                 struct ib_device_modify *props)
 {
+       struct mlx4_cmd_mailbox *mailbox;
+
        if (mask & ~IB_DEVICE_MODIFY_NODE_DESC)
                return -EOPNOTSUPP;
 
-       if (mask & IB_DEVICE_MODIFY_NODE_DESC) {
-               spin_lock(&to_mdev(ibdev)->sm_lock);
-               memcpy(ibdev->node_desc, props->node_desc, 64);
-               spin_unlock(&to_mdev(ibdev)->sm_lock);
-       }
+       if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))
+               return 0;
+
+       spin_lock(&to_mdev(ibdev)->sm_lock);
+       memcpy(ibdev->node_desc, props->node_desc, 64);
+       spin_unlock(&to_mdev(ibdev)->sm_lock);
+
+       /*
+        * If possible, pass node desc to FW, so it can generate
+        * a 144 trap.  If cmd fails, just ignore.
+        */
+       mailbox = mlx4_alloc_cmd_mailbox(to_mdev(ibdev)->dev);
+       if (IS_ERR(mailbox))
+               return 0;
+
+       memset(mailbox->buf, 0, 256);
+       memcpy(mailbox->buf, props->node_desc, 64);
+       mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0,
+                MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A);
+
+       mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox);
 
        return 0;
 }
@@ -289,6 +407,7 @@ static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols,
 {
        struct mlx4_cmd_mailbox *mailbox;
        int err;
+       u8 is_eth = dev->dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH;
 
        mailbox = mlx4_alloc_cmd_mailbox(dev->dev);
        if (IS_ERR(mailbox))
@@ -304,7 +423,7 @@ static int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols,
                ((__be32 *) mailbox->buf)[1] = cpu_to_be32(cap_mask);
        }
 
-       err = mlx4_cmd(dev->dev, mailbox->dma, port, 0, MLX4_CMD_SET_PORT,
+       err = mlx4_cmd(dev->dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT,
                       MLX4_CMD_TIME_CLASS_B);
 
        mlx4_free_cmd_mailbox(dev->dev, mailbox);
@@ -447,18 +566,132 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
        return 0;
 }
 
+static int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid)
+{
+       struct mlx4_ib_qp *mqp = to_mqp(ibqp);
+       struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
+       struct mlx4_ib_gid_entry *ge;
+
+       ge = kzalloc(sizeof *ge, GFP_KERNEL);
+       if (!ge)
+               return -ENOMEM;
+
+       ge->gid = *gid;
+       if (mlx4_ib_add_mc(mdev, mqp, gid)) {
+               ge->port = mqp->port;
+               ge->added = 1;
+       }
+
+       mutex_lock(&mqp->mutex);
+       list_add_tail(&ge->list, &mqp->gid_list);
+       mutex_unlock(&mqp->mutex);
+
+       return 0;
+}
+
+int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
+                  union ib_gid *gid)
+{
+       u8 mac[6];
+       struct net_device *ndev;
+       int ret = 0;
+
+       if (!mqp->port)
+               return 0;
+
+       spin_lock(&mdev->iboe.lock);
+       ndev = mdev->iboe.netdevs[mqp->port - 1];
+       if (ndev)
+               dev_hold(ndev);
+       spin_unlock(&mdev->iboe.lock);
+
+       if (ndev) {
+               rdma_get_mcast_mac((struct in6_addr *)gid, mac);
+               rtnl_lock();
+               dev_mc_add(mdev->iboe.netdevs[mqp->port - 1], mac);
+               ret = 1;
+               rtnl_unlock();
+               dev_put(ndev);
+       }
+
+       return ret;
+}
+
 static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 {
-       return mlx4_multicast_attach(to_mdev(ibqp->device)->dev,
-                                    &to_mqp(ibqp)->mqp, gid->raw,
-                                    !!(to_mqp(ibqp)->flags &
-                                       MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
+       int err;
+       struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
+       struct mlx4_ib_qp *mqp = to_mqp(ibqp);
+
+       err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, !!(mqp->flags &
+                                   MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
+       if (err)
+               return err;
+
+       err = add_gid_entry(ibqp, gid);
+       if (err)
+               goto err_add;
+
+       return 0;
+
+err_add:
+       mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw);
+       return err;
+}
+
+static struct mlx4_ib_gid_entry *find_gid_entry(struct mlx4_ib_qp *qp, u8 *raw)
+{
+       struct mlx4_ib_gid_entry *ge;
+       struct mlx4_ib_gid_entry *tmp;
+       struct mlx4_ib_gid_entry *ret = NULL;
+
+       list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) {
+               if (!memcmp(raw, ge->gid.raw, 16)) {
+                       ret = ge;
+                       break;
+               }
+       }
+
+       return ret;
 }
 
 static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 {
-       return mlx4_multicast_detach(to_mdev(ibqp->device)->dev,
-                                    &to_mqp(ibqp)->mqp, gid->raw);
+       int err;
+       struct mlx4_ib_dev *mdev = to_mdev(ibqp->device);
+       struct mlx4_ib_qp *mqp = to_mqp(ibqp);
+       u8 mac[6];
+       struct net_device *ndev;
+       struct mlx4_ib_gid_entry *ge;
+
+       err = mlx4_multicast_detach(mdev->dev,
+                                   &mqp->mqp, gid->raw);
+       if (err)
+               return err;
+
+       mutex_lock(&mqp->mutex);
+       ge = find_gid_entry(mqp, gid->raw);
+       if (ge) {
+               spin_lock(&mdev->iboe.lock);
+               ndev = ge->added ? mdev->iboe.netdevs[ge->port - 1] : NULL;
+               if (ndev)
+                       dev_hold(ndev);
+               spin_unlock(&mdev->iboe.lock);
+               rdma_get_mcast_mac((struct in6_addr *)gid, mac);
+               if (ndev) {
+                       rtnl_lock();
+                       dev_mc_del(mdev->iboe.netdevs[ge->port - 1], mac);
+                       rtnl_unlock();
+                       dev_put(ndev);
+               }
+               list_del(&ge->list);
+               kfree(ge);
+       } else
+               printk(KERN_WARNING "could not find mgid entry\n");
+
+       mutex_unlock(&mqp->mutex);
+
+       return 0;
 }
 
 static int init_node_data(struct mlx4_ib_dev *dev)
@@ -543,15 +776,215 @@ static struct device_attribute *mlx4_class_attributes[] = {
        &dev_attr_board_id
 };
 
+static void mlx4_addrconf_ifid_eui48(u8 *eui, u16 vlan_id, struct net_device *dev)
+{
+       memcpy(eui, dev->dev_addr, 3);
+       memcpy(eui + 5, dev->dev_addr + 3, 3);
+       if (vlan_id < 0x1000) {
+               eui[3] = vlan_id >> 8;
+               eui[4] = vlan_id & 0xff;
+       } else {
+               eui[3] = 0xff;
+               eui[4] = 0xfe;
+       }
+       eui[0] ^= 2;
+}
+
+static void update_gids_task(struct work_struct *work)
+{
+       struct update_gid_work *gw = container_of(work, struct update_gid_work, work);
+       struct mlx4_cmd_mailbox *mailbox;
+       union ib_gid *gids;
+       int err;
+       struct mlx4_dev *dev = gw->dev->dev;
+       struct ib_event event;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox)) {
+               printk(KERN_WARNING "update gid table failed %ld\n", PTR_ERR(mailbox));
+               return;
+       }
+
+       gids = mailbox->buf;
+       memcpy(gids, gw->gids, sizeof gw->gids);
+
+       err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port,
+                      1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B);
+       if (err)
+               printk(KERN_WARNING "set port command failed\n");
+       else {
+               memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids);
+               event.device = &gw->dev->ib_dev;
+               event.element.port_num = gw->port;
+               event.event    = IB_EVENT_LID_CHANGE;
+               ib_dispatch_event(&event);
+       }
+
+       mlx4_free_cmd_mailbox(dev, mailbox);
+       kfree(gw);
+}
+
+static int update_ipv6_gids(struct mlx4_ib_dev *dev, int port, int clear)
+{
+       struct net_device *ndev = dev->iboe.netdevs[port - 1];
+       struct update_gid_work *work;
+       struct net_device *tmp;
+       int i;
+       u8 *hits;
+       int ret;
+       union ib_gid gid;
+       int free;
+       int found;
+       int need_update = 0;
+       u16 vid;
+
+       work = kzalloc(sizeof *work, GFP_ATOMIC);
+       if (!work)
+               return -ENOMEM;
+
+       hits = kzalloc(128, GFP_ATOMIC);
+       if (!hits) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       read_lock(&dev_base_lock);
+       for_each_netdev(&init_net, tmp) {
+               if (ndev && (tmp == ndev || rdma_vlan_dev_real_dev(tmp) == ndev)) {
+                       gid.global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL);
+                       vid = rdma_vlan_dev_vlan_id(tmp);
+                       mlx4_addrconf_ifid_eui48(&gid.raw[8], vid, ndev);
+                       found = 0;
+                       free = -1;
+                       for (i = 0; i < 128; ++i) {
+                               if (free < 0 &&
+                                   !memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid))
+                                       free = i;
+                               if (!memcmp(&dev->iboe.gid_table[port - 1][i], &gid, sizeof gid)) {
+                                       hits[i] = 1;
+                                       found = 1;
+                                       break;
+                               }
+                       }
+
+                       if (!found) {
+                               if (tmp == ndev &&
+                                   (memcmp(&dev->iboe.gid_table[port - 1][0],
+                                           &gid, sizeof gid) ||
+                                    !memcmp(&dev->iboe.gid_table[port - 1][0],
+                                            &zgid, sizeof gid))) {
+                                       dev->iboe.gid_table[port - 1][0] = gid;
+                                       ++need_update;
+                                       hits[0] = 1;
+                               } else if (free >= 0) {
+                                       dev->iboe.gid_table[port - 1][free] = gid;
+                                       hits[free] = 1;
+                                       ++need_update;
+                               }
+                       }
+               }
+       }
+       read_unlock(&dev_base_lock);
+
+       for (i = 0; i < 128; ++i)
+               if (!hits[i]) {
+                       if (memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid))
+                               ++need_update;
+                       dev->iboe.gid_table[port - 1][i] = zgid;
+               }
+
+       if (need_update) {
+               memcpy(work->gids, dev->iboe.gid_table[port - 1], sizeof work->gids);
+               INIT_WORK(&work->work, update_gids_task);
+               work->port = port;
+               work->dev = dev;
+               queue_work(wq, &work->work);
+       } else
+               kfree(work);
+
+       kfree(hits);
+       return 0;
+
+out:
+       kfree(work);
+       return ret;
+}
+
+static void handle_en_event(struct mlx4_ib_dev *dev, int port, unsigned long event)
+{
+       switch (event) {
+       case NETDEV_UP:
+       case NETDEV_CHANGEADDR:
+               update_ipv6_gids(dev, port, 0);
+               break;
+
+       case NETDEV_DOWN:
+               update_ipv6_gids(dev, port, 1);
+               dev->iboe.netdevs[port - 1] = NULL;
+       }
+}
+
+static void netdev_added(struct mlx4_ib_dev *dev, int port)
+{
+       update_ipv6_gids(dev, port, 0);
+}
+
+static void netdev_removed(struct mlx4_ib_dev *dev, int port)
+{
+       update_ipv6_gids(dev, port, 1);
+}
+
+static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event,
+                               void *ptr)
+{
+       struct net_device *dev = ptr;
+       struct mlx4_ib_dev *ibdev;
+       struct net_device *oldnd;
+       struct mlx4_ib_iboe *iboe;
+       int port;
+
+       if (!net_eq(dev_net(dev), &init_net))
+               return NOTIFY_DONE;
+
+       ibdev = container_of(this, struct mlx4_ib_dev, iboe.nb);
+       iboe = &ibdev->iboe;
+
+       spin_lock(&iboe->lock);
+       mlx4_foreach_ib_transport_port(port, ibdev->dev) {
+               oldnd = iboe->netdevs[port - 1];
+               iboe->netdevs[port - 1] =
+                       mlx4_get_protocol_dev(ibdev->dev, MLX4_PROTOCOL_EN, port);
+               if (oldnd != iboe->netdevs[port - 1]) {
+                       if (iboe->netdevs[port - 1])
+                               netdev_added(ibdev, port);
+                       else
+                               netdev_removed(ibdev, port);
+               }
+       }
+
+       if (dev == iboe->netdevs[0] ||
+           (iboe->netdevs[0] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[0]))
+               handle_en_event(ibdev, 1, event);
+       else if (dev == iboe->netdevs[1]
+                || (iboe->netdevs[1] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[1]))
+               handle_en_event(ibdev, 2, event);
+
+       spin_unlock(&iboe->lock);
+
+       return NOTIFY_DONE;
+}
+
 static void *mlx4_ib_add(struct mlx4_dev *dev)
 {
        struct mlx4_ib_dev *ibdev;
        int num_ports = 0;
        int i;
+       int err;
+       struct mlx4_ib_iboe *iboe;
 
        printk_once(KERN_INFO "%s", mlx4_ib_version);
 
-       mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+       mlx4_foreach_ib_transport_port(i, dev)
                num_ports++;
 
        /* No point in registering a device with no ports... */
@@ -564,6 +997,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                return NULL;
        }
 
+       iboe = &ibdev->iboe;
+
        if (mlx4_pd_alloc(dev, &ibdev->priv_pdn))
                goto err_dealloc;
 
@@ -612,6 +1047,7 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 
        ibdev->ib_dev.query_device      = mlx4_ib_query_device;
        ibdev->ib_dev.query_port        = mlx4_ib_query_port;
+       ibdev->ib_dev.get_link_layer    = mlx4_ib_port_link_layer;
        ibdev->ib_dev.query_gid         = mlx4_ib_query_gid;
        ibdev->ib_dev.query_pkey        = mlx4_ib_query_pkey;
        ibdev->ib_dev.modify_device     = mlx4_ib_modify_device;
@@ -656,6 +1092,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        ibdev->ib_dev.unmap_fmr         = mlx4_ib_unmap_fmr;
        ibdev->ib_dev.dealloc_fmr       = mlx4_ib_fmr_dealloc;
 
+       spin_lock_init(&iboe->lock);
+
        if (init_node_data(ibdev))
                goto err_map;
 
@@ -668,16 +1106,28 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        if (mlx4_ib_mad_init(ibdev))
                goto err_reg;
 
+       if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE && !iboe->nb.notifier_call) {
+               iboe->nb.notifier_call = mlx4_ib_netdev_event;
+               err = register_netdevice_notifier(&iboe->nb);
+               if (err)
+                       goto err_reg;
+       }
+
        for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) {
                if (device_create_file(&ibdev->ib_dev.dev,
                                       mlx4_class_attributes[i]))
-                       goto err_reg;
+                       goto err_notif;
        }
 
        ibdev->ib_active = true;
 
        return ibdev;
 
+err_notif:
+       if (unregister_netdevice_notifier(&ibdev->iboe.nb))
+               printk(KERN_WARNING "failure unregistering notifier\n");
+       flush_workqueue(wq);
+
 err_reg:
        ib_unregister_device(&ibdev->ib_dev);
 
@@ -703,11 +1153,16 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
 
        mlx4_ib_mad_cleanup(ibdev);
        ib_unregister_device(&ibdev->ib_dev);
+       if (ibdev->iboe.nb.notifier_call) {
+               if (unregister_netdevice_notifier(&ibdev->iboe.nb))
+                       printk(KERN_WARNING "failure unregistering notifier\n");
+               ibdev->iboe.nb.notifier_call = NULL;
+       }
+       iounmap(ibdev->uar_map);
 
-       for (p = 1; p <= ibdev->num_ports; ++p)
+       mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB)
                mlx4_CLOSE_PORT(dev, p);
 
-       iounmap(ibdev->uar_map);
        mlx4_uar_free(dev, &ibdev->priv_uar);
        mlx4_pd_free(dev, ibdev->priv_pdn);
        ib_dealloc_device(&ibdev->ib_dev);
@@ -747,19 +1202,33 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
 }
 
 static struct mlx4_interface mlx4_ib_interface = {
-       .add    = mlx4_ib_add,
-       .remove = mlx4_ib_remove,
-       .event  = mlx4_ib_event
+       .add            = mlx4_ib_add,
+       .remove         = mlx4_ib_remove,
+       .event          = mlx4_ib_event,
+       .protocol       = MLX4_PROTOCOL_IB
 };
 
 static int __init mlx4_ib_init(void)
 {
-       return mlx4_register_interface(&mlx4_ib_interface);
+       int err;
+
+       wq = create_singlethread_workqueue("mlx4_ib");
+       if (!wq)
+               return -ENOMEM;
+
+       err = mlx4_register_interface(&mlx4_ib_interface);
+       if (err) {
+               destroy_workqueue(wq);
+               return err;
+       }
+
+       return 0;
 }
 
 static void __exit mlx4_ib_cleanup(void)
 {
        mlx4_unregister_interface(&mlx4_ib_interface);
+       destroy_workqueue(wq);
 }
 
 module_init(mlx4_ib_init);
index 3486d76..2a322f2 100644 (file)
@@ -112,6 +112,13 @@ enum mlx4_ib_qp_flags {
        MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK     = 1 << 1,
 };
 
+struct mlx4_ib_gid_entry {
+       struct list_head        list;
+       union ib_gid            gid;
+       int                     added;
+       u8                      port;
+};
+
 struct mlx4_ib_qp {
        struct ib_qp            ibqp;
        struct mlx4_qp          mqp;
@@ -138,6 +145,8 @@ struct mlx4_ib_qp {
        u8                      resp_depth;
        u8                      sq_no_prefetch;
        u8                      state;
+       int                     mlx_type;
+       struct list_head        gid_list;
 };
 
 struct mlx4_ib_srq {
@@ -157,7 +166,14 @@ struct mlx4_ib_srq {
 
 struct mlx4_ib_ah {
        struct ib_ah            ibah;
-       struct mlx4_av          av;
+       union mlx4_ext_av       av;
+};
+
+struct mlx4_ib_iboe {
+       spinlock_t              lock;
+       struct net_device      *netdevs[MLX4_MAX_PORTS];
+       struct notifier_block   nb;
+       union ib_gid            gid_table[MLX4_MAX_PORTS][128];
 };
 
 struct mlx4_ib_dev {
@@ -176,6 +192,7 @@ struct mlx4_ib_dev {
 
        struct mutex            cap_mask_mutex;
        bool                    ib_active;
+       struct mlx4_ib_iboe     iboe;
 };
 
 static inline struct mlx4_ib_dev *to_mdev(struct ib_device *ibdev)
@@ -314,9 +331,20 @@ int mlx4_ib_map_phys_fmr(struct ib_fmr *ibfmr, u64 *page_list, int npages,
 int mlx4_ib_unmap_fmr(struct list_head *fmr_list);
 int mlx4_ib_fmr_dealloc(struct ib_fmr *fmr);
 
+int mlx4_ib_resolve_grh(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah_attr,
+                       u8 *mac, int *is_mcast, u8 port);
+
 static inline int mlx4_ib_ah_grh_present(struct mlx4_ib_ah *ah)
 {
-       return !!(ah->av.g_slid & 0x80);
+       u8 port = be32_to_cpu(ah->av.ib.port_pd) >> 24 & 3;
+
+       if (rdma_port_get_link_layer(ah->ibah.device, port) == IB_LINK_LAYER_ETHERNET)
+               return 1;
+
+       return !!(ah->av.ib.g_slid & 0x80);
 }
 
+int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp,
+                  union ib_gid *gid);
+
 #endif /* MLX4_IB_H */
index 1d27b9a..dca55b1 100644 (file)
@@ -226,7 +226,7 @@ struct ib_fast_reg_page_list *mlx4_ib_alloc_fast_reg_page_list(struct ib_device
        struct mlx4_ib_fast_reg_page_list *mfrpl;
        int size = page_list_len * sizeof (u64);
 
-       if (size > PAGE_SIZE)
+       if (page_list_len > MLX4_MAX_FAST_REG_PAGES)
                return ERR_PTR(-EINVAL);
 
        mfrpl = kmalloc(sizeof *mfrpl, GFP_KERNEL);
index 6a60827..9a7794a 100644 (file)
 
 #include <linux/log2.h>
 #include <linux/slab.h>
+#include <linux/netdevice.h>
 
 #include <rdma/ib_cache.h>
 #include <rdma/ib_pack.h>
+#include <rdma/ib_addr.h>
 
 #include <linux/mlx4/qp.h>
 
@@ -48,17 +50,26 @@ enum {
 
 enum {
        MLX4_IB_DEFAULT_SCHED_QUEUE     = 0x83,
-       MLX4_IB_DEFAULT_QP0_SCHED_QUEUE = 0x3f
+       MLX4_IB_DEFAULT_QP0_SCHED_QUEUE = 0x3f,
+       MLX4_IB_LINK_TYPE_IB            = 0,
+       MLX4_IB_LINK_TYPE_ETH           = 1
 };
 
 enum {
        /*
-        * Largest possible UD header: send with GRH and immediate data.
+        * Largest possible UD header: send with GRH and immediate
+        * data plus 18 bytes for an Ethernet header with VLAN/802.1Q
+        * tag.  (LRH would only use 8 bytes, so Ethernet is the
+        * biggest case)
         */
-       MLX4_IB_UD_HEADER_SIZE          = 72,
+       MLX4_IB_UD_HEADER_SIZE          = 82,
        MLX4_IB_LSO_HEADER_SPARE        = 128,
 };
 
+enum {
+       MLX4_IB_IBOE_ETHERTYPE          = 0x8915
+};
+
 struct mlx4_ib_sqp {
        struct mlx4_ib_qp       qp;
        int                     pkey_index;
@@ -462,6 +473,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
        mutex_init(&qp->mutex);
        spin_lock_init(&qp->sq.lock);
        spin_lock_init(&qp->rq.lock);
+       INIT_LIST_HEAD(&qp->gid_list);
 
        qp->state        = IB_QPS_RESET;
        if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR)
@@ -649,6 +661,16 @@ static void mlx4_ib_unlock_cqs(struct mlx4_ib_cq *send_cq, struct mlx4_ib_cq *re
        }
 }
 
+static void del_gid_entries(struct mlx4_ib_qp *qp)
+{
+       struct mlx4_ib_gid_entry *ge, *tmp;
+
+       list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) {
+               list_del(&ge->list);
+               kfree(ge);
+       }
+}
+
 static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
                              int is_user)
 {
@@ -695,6 +717,8 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp,
                if (!qp->ibqp.srq)
                        mlx4_db_free(dev->dev, &qp->db);
        }
+
+       del_gid_entries(qp);
 }
 
 struct ib_qp *mlx4_ib_create_qp(struct ib_pd *pd,
@@ -852,6 +876,14 @@ static void mlx4_set_sched(struct mlx4_qp_path *path, u8 port)
 static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
                         struct mlx4_qp_path *path, u8 port)
 {
+       int err;
+       int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port) ==
+               IB_LINK_LAYER_ETHERNET;
+       u8 mac[6];
+       int is_mcast;
+       u16 vlan_tag;
+       int vidx;
+
        path->grh_mylmc     = ah->src_path_bits & 0x7f;
        path->rlid          = cpu_to_be16(ah->dlid);
        if (ah->static_rate) {
@@ -879,12 +911,49 @@ static int mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah,
                memcpy(path->rgid, ah->grh.dgid.raw, 16);
        }
 
-       path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
-               ((port - 1) << 6) | ((ah->sl & 0xf) << 2);
+       if (is_eth) {
+               path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
+                       ((port - 1) << 6) | ((ah->sl & 7) << 3) | ((ah->sl & 8) >> 1);
+
+               if (!(ah->ah_flags & IB_AH_GRH))
+                       return -1;
+
+               err = mlx4_ib_resolve_grh(dev, ah, mac, &is_mcast, port);
+               if (err)
+                       return err;
+
+               memcpy(path->dmac, mac, 6);
+               path->ackto = MLX4_IB_LINK_TYPE_ETH;
+               /* use index 0 into MAC table for IBoE */
+               path->grh_mylmc &= 0x80;
+
+               vlan_tag = rdma_get_vlan_id(&dev->iboe.gid_table[port - 1][ah->grh.sgid_index]);
+               if (vlan_tag < 0x1000) {
+                       if (mlx4_find_cached_vlan(dev->dev, port, vlan_tag, &vidx))
+                               return -ENOENT;
+
+                       path->vlan_index = vidx;
+                       path->fl = 1 << 6;
+               }
+       } else
+               path->sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE |
+                       ((port - 1) << 6) | ((ah->sl & 0xf) << 2);
 
        return 0;
 }
 
+static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp)
+{
+       struct mlx4_ib_gid_entry *ge, *tmp;
+
+       list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) {
+               if (!ge->added && mlx4_ib_add_mc(dev, qp, &ge->gid)) {
+                       ge->added = 1;
+                       ge->port = qp->port;
+               }
+       }
+}
+
 static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
                               const struct ib_qp_attr *attr, int attr_mask,
                               enum ib_qp_state cur_state, enum ib_qp_state new_state)
@@ -980,7 +1049,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
        }
 
        if (attr_mask & IB_QP_TIMEOUT) {
-               context->pri_path.ackto = attr->timeout << 3;
+               context->pri_path.ackto |= attr->timeout << 3;
                optpar |= MLX4_QP_OPTPAR_ACK_TIMEOUT;
        }
 
@@ -1118,8 +1187,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
                qp->atomic_rd_en = attr->qp_access_flags;
        if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
                qp->resp_depth = attr->max_dest_rd_atomic;
-       if (attr_mask & IB_QP_PORT)
+       if (attr_mask & IB_QP_PORT) {
                qp->port = attr->port_num;
+               update_mcg_macs(dev, qp);
+       }
        if (attr_mask & IB_QP_ALT_PATH)
                qp->alt_port = attr->alt_port_num;
 
@@ -1221,40 +1292,59 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
        struct mlx4_wqe_mlx_seg *mlx = wqe;
        struct mlx4_wqe_inline_seg *inl = wqe + sizeof *mlx;
        struct mlx4_ib_ah *ah = to_mah(wr->wr.ud.ah);
+       union ib_gid sgid;
        u16 pkey;
        int send_size;
        int header_size;
        int spc;
        int i;
+       int is_eth;
+       int is_vlan = 0;
+       int is_grh;
+       u16 vlan;
 
        send_size = 0;
        for (i = 0; i < wr->num_sge; ++i)
                send_size += wr->sg_list[i].length;
 
-       ib_ud_header_init(send_size, mlx4_ib_ah_grh_present(ah), 0, &sqp->ud_header);
+       is_eth = rdma_port_get_link_layer(sqp->qp.ibqp.device, sqp->qp.port) == IB_LINK_LAYER_ETHERNET;
+       is_grh = mlx4_ib_ah_grh_present(ah);
+       if (is_eth) {
+               ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.ib.port_pd) >> 24,
+                                 ah->av.ib.gid_index, &sgid);
+               vlan = rdma_get_vlan_id(&sgid);
+               is_vlan = vlan < 0x1000;
+       }
+       ib_ud_header_init(send_size, !is_eth, is_eth, is_vlan, is_grh, 0, &sqp->ud_header);
+
+       if (!is_eth) {
+               sqp->ud_header.lrh.service_level =
+                       be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 28;
+               sqp->ud_header.lrh.destination_lid = ah->av.ib.dlid;
+               sqp->ud_header.lrh.source_lid = cpu_to_be16(ah->av.ib.g_slid & 0x7f);
+       }
 
-       sqp->ud_header.lrh.service_level   =
-               be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 28;
-       sqp->ud_header.lrh.destination_lid = ah->av.dlid;
-       sqp->ud_header.lrh.source_lid      = cpu_to_be16(ah->av.g_slid & 0x7f);
-       if (mlx4_ib_ah_grh_present(ah)) {
+       if (is_grh) {
                sqp->ud_header.grh.traffic_class =
-                       (be32_to_cpu(ah->av.sl_tclass_flowlabel) >> 20) & 0xff;
+                       (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 20) & 0xff;
                sqp->ud_header.grh.flow_label    =
-                       ah->av.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
-               sqp->ud_header.grh.hop_limit     = ah->av.hop_limit;
-               ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.port_pd) >> 24,
-                                 ah->av.gid_index, &sqp->ud_header.grh.source_gid);
+                       ah->av.ib.sl_tclass_flowlabel & cpu_to_be32(0xfffff);
+               sqp->ud_header.grh.hop_limit     = ah->av.ib.hop_limit;
+               ib_get_cached_gid(ib_dev, be32_to_cpu(ah->av.ib.port_pd) >> 24,
+                                 ah->av.ib.gid_index, &sqp->ud_header.grh.source_gid);
                memcpy(sqp->ud_header.grh.destination_gid.raw,
-                      ah->av.dgid, 16);
+                      ah->av.ib.dgid, 16);
        }
 
        mlx->flags &= cpu_to_be32(MLX4_WQE_CTRL_CQ_UPDATE);
-       mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MLX4_WQE_MLX_VL15 : 0) |
-                                 (sqp->ud_header.lrh.destination_lid ==
-                                  IB_LID_PERMISSIVE ? MLX4_WQE_MLX_SLR : 0) |
-                                 (sqp->ud_header.lrh.service_level << 8));
-       mlx->rlid   = sqp->ud_header.lrh.destination_lid;
+
+       if (!is_eth) {
+               mlx->flags |= cpu_to_be32((!sqp->qp.ibqp.qp_num ? MLX4_WQE_MLX_VL15 : 0) |
+                                         (sqp->ud_header.lrh.destination_lid ==
+                                          IB_LID_PERMISSIVE ? MLX4_WQE_MLX_SLR : 0) |
+                                         (sqp->ud_header.lrh.service_level << 8));
+               mlx->rlid = sqp->ud_header.lrh.destination_lid;
+       }
 
        switch (wr->opcode) {
        case IB_WR_SEND:
@@ -1270,9 +1360,29 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr,
                return -EINVAL;
        }
 
-       sqp->ud_header.lrh.virtual_lane    = !sqp->qp.ibqp.qp_num ? 15 : 0;
-       if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
-               sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
+       if (is_eth) {
+               u8 *smac;
+
+               memcpy(sqp->ud_header.eth.dmac_h, ah->av.eth.mac, 6);
+               /* FIXME: cache smac value? */
+               smac = to_mdev(sqp->qp.ibqp.device)->iboe.netdevs[sqp->qp.port - 1]->dev_addr;
+               memcpy(sqp->ud_header.eth.smac_h, smac, 6);
+               if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6))
+                       mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK);
+               if (!is_vlan) {
+                       sqp->ud_header.eth.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE);
+               } else {
+                       u16 pcp;
+
+                       sqp->ud_header.vlan.type = cpu_to_be16(MLX4_IB_IBOE_ETHERTYPE);
+                       pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 27 & 3) << 13;
+                       sqp->ud_header.vlan.tag = cpu_to_be16(vlan | pcp);
+               }
+       } else {
+               sqp->ud_header.lrh.virtual_lane    = !sqp->qp.ibqp.qp_num ? 15 : 0;
+               if (sqp->ud_header.lrh.destination_lid == IB_LID_PERMISSIVE)
+                       sqp->ud_header.lrh.source_lid = IB_LID_PERMISSIVE;
+       }
        sqp->ud_header.bth.solicited_event = !!(wr->send_flags & IB_SEND_SOLICITED);
        if (!sqp->qp.ibqp.qp_num)
                ib_get_cached_pkey(ib_dev, sqp->qp.port, sqp->pkey_index, &pkey);
@@ -1429,11 +1539,14 @@ static void set_masked_atomic_seg(struct mlx4_wqe_masked_atomic_seg *aseg,
 }
 
 static void set_datagram_seg(struct mlx4_wqe_datagram_seg *dseg,
-                            struct ib_send_wr *wr)
+                            struct ib_send_wr *wr, __be16 *vlan)
 {
        memcpy(dseg->av, &to_mah(wr->wr.ud.ah)->av, sizeof (struct mlx4_av));
        dseg->dqpn = cpu_to_be32(wr->wr.ud.remote_qpn);
        dseg->qkey = cpu_to_be32(wr->wr.ud.remote_qkey);
+       dseg->vlan = to_mah(wr->wr.ud.ah)->av.eth.vlan;
+       memcpy(dseg->mac, to_mah(wr->wr.ud.ah)->av.eth.mac, 6);
+       *vlan = dseg->vlan;
 }
 
 static void set_mlx_icrc_seg(void *dseg)
@@ -1536,6 +1649,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
        __be32 uninitialized_var(lso_hdr_sz);
        __be32 blh;
        int i;
+       __be16 vlan = cpu_to_be16(0xffff);
 
        spin_lock_irqsave(&qp->sq.lock, flags);
 
@@ -1639,7 +1753,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                        break;
 
                case IB_QPT_UD:
-                       set_datagram_seg(wqe, wr);
+                       set_datagram_seg(wqe, wr, &vlan);
                        wqe  += sizeof (struct mlx4_wqe_datagram_seg);
                        size += sizeof (struct mlx4_wqe_datagram_seg) / 16;
 
@@ -1717,6 +1831,11 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
                ctrl->owner_opcode = mlx4_ib_opcode[wr->opcode] |
                        (ind & qp->sq.wqe_cnt ? cpu_to_be32(1 << 31) : 0) | blh;
 
+               if (be16_to_cpu(vlan) < 0x1000) {
+                       ctrl->ins_vlan = 1 << 6;
+                       ctrl->vlan_tag = vlan;
+               }
+
                stamp = ind + qp->sq_spare_wqes;
                ind += DIV_ROUND_UP(size * 16, 1U << qp->sq.wqe_shift);
 
@@ -1866,17 +1985,27 @@ static int to_ib_qp_access_flags(int mlx4_flags)
        return ib_flags;
 }
 
-static void to_ib_ah_attr(struct mlx4_dev *dev, struct ib_ah_attr *ib_ah_attr,
+static void to_ib_ah_attr(struct mlx4_ib_dev *ibdev, struct ib_ah_attr *ib_ah_attr,
                                struct mlx4_qp_path *path)
 {
+       struct mlx4_dev *dev = ibdev->dev;
+       int is_eth;
+
        memset(ib_ah_attr, 0, sizeof *ib_ah_attr);
        ib_ah_attr->port_num      = path->sched_queue & 0x40 ? 2 : 1;
 
        if (ib_ah_attr->port_num == 0 || ib_ah_attr->port_num > dev->caps.num_ports)
                return;
 
+       is_eth = rdma_port_get_link_layer(&ibdev->ib_dev, ib_ah_attr->port_num) ==
+               IB_LINK_LAYER_ETHERNET;
+       if (is_eth)
+               ib_ah_attr->sl = ((path->sched_queue >> 3) & 0x7) |
+               ((path->sched_queue & 4) << 1);
+       else
+               ib_ah_attr->sl = (path->sched_queue >> 2) & 0xf;
+
        ib_ah_attr->dlid          = be16_to_cpu(path->rlid);
-       ib_ah_attr->sl            = (path->sched_queue >> 2) & 0xf;
        ib_ah_attr->src_path_bits = path->grh_mylmc & 0x7f;
        ib_ah_attr->static_rate   = path->static_rate ? path->static_rate - 5 : 0;
        ib_ah_attr->ah_flags      = (path->grh_mylmc & (1 << 7)) ? IB_AH_GRH : 0;
@@ -1929,8 +2058,8 @@ int mlx4_ib_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr
                to_ib_qp_access_flags(be32_to_cpu(context.params2));
 
        if (qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) {
-               to_ib_ah_attr(dev->dev, &qp_attr->ah_attr, &context.pri_path);
-               to_ib_ah_attr(dev->dev, &qp_attr->alt_ah_attr, &context.alt_path);
+               to_ib_ah_attr(dev, &qp_attr->ah_attr, &context.pri_path);
+               to_ib_ah_attr(dev, &qp_attr->alt_ah_attr, &context.alt_path);
                qp_attr->alt_pkey_index = context.alt_path.pkey_index & 0x7f;
                qp_attr->alt_port_num   = qp_attr->alt_ah_attr.port_num;
        }
index d2d172e..a34c9d3 100644 (file)
@@ -1493,7 +1493,7 @@ static int build_mlx_header(struct mthca_dev *dev, struct mthca_sqp *sqp,
        int err;
        u16 pkey;
 
-       ib_ud_header_init(256, /* assume a MAD */
+       ib_ud_header_init(256, /* assume a MAD */ 1, 0, 0,
                          mthca_ah_grh_present(to_mah(wr->wr.ud.ah)), 0,
                          &sqp->ud_header);
 
index 6220d9d..25ad0f9 100644 (file)
@@ -1424,7 +1424,6 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
 {
 
        int     reset = 0;      /* whether to send reset in case of err.. */
-       int     passive_state;
        atomic_inc(&cm_resets_recvd);
        nes_debug(NES_DBG_CM, "Received Reset, cm_node = %p, state = %u."
                        " refcnt=%d\n", cm_node, cm_node->state,
@@ -1439,7 +1438,7 @@ static void handle_rst_pkt(struct nes_cm_node *cm_node, struct sk_buff *skb,
                active_open_err(cm_node, skb, reset);
                break;
        case NES_CM_STATE_MPAREQ_RCVD:
-               passive_state = atomic_add_return(1, &cm_node->passive_state);
+               atomic_inc(&cm_node->passive_state);
                dev_kfree_skb_any(skb);
                break;
        case NES_CM_STATE_ESTABLISHED:
index 10560c7..3892e2c 100644 (file)
@@ -271,6 +271,7 @@ static int nes_netdev_stop(struct net_device *netdev)
 
        if (netif_msg_ifdown(nesvnic))
                printk(KERN_INFO PFX "%s: disabling interface\n", netdev->name);
+       netif_carrier_off(netdev);
 
        /* Disable network packets */
        napi_disable(&nesvnic->napi);
index 546fc22..99933e4 100644 (file)
@@ -476,9 +476,9 @@ static struct ib_fast_reg_page_list *nes_alloc_fast_reg_page_list(
        }
        nes_debug(NES_DBG_MR, "nes_alloc_fast_reg_pbl: nes_frpl = %p, "
                  "ibfrpl = %p, ibfrpl.page_list = %p, pbl.kva = %p, "
-                 "pbl.paddr= %p\n", pnesfrpl, &pnesfrpl->ibfrpl,
+                 "pbl.paddr = %llx\n", pnesfrpl, &pnesfrpl->ibfrpl,
                  pnesfrpl->ibfrpl.page_list, pnesfrpl->nes_wqe_pbl.kva,
-                 (void *)pnesfrpl->nes_wqe_pbl.paddr);
+                 (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr);
 
        return pifrpl;
 }
@@ -584,7 +584,9 @@ static int nes_query_port(struct ib_device *ibdev, u8 port, struct ib_port_attr
        props->lmc = 0;
        props->sm_lid = 0;
        props->sm_sl = 0;
-       if (nesvnic->linkup)
+       if (netif_queue_stopped(netdev))
+               props->state = IB_PORT_DOWN;
+       else if (nesvnic->linkup)
                props->state = IB_PORT_ACTIVE;
        else
                props->state = IB_PORT_DOWN;
@@ -3483,13 +3485,13 @@ static int nes_post_send(struct ib_qp *ibqp, struct ib_send_wr *ib_wr,
                        for (i = 0; i < ib_wr->wr.fast_reg.page_list_len; i++)
                                dst_page_list[i] = cpu_to_le64(src_page_list[i]);
 
-                       nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %p, "
-                                 "length: %d, rkey: %0x, pgl_paddr: %p, "
+                       nes_debug(NES_DBG_IW_TX, "SQ_FMR: iova_start: %llx, "
+                                 "length: %d, rkey: %0x, pgl_paddr: %llx, "
                                  "page_list_len: %u, wqe_misc: %x\n",
-                                 (void *)ib_wr->wr.fast_reg.iova_start,
+                                 (unsigned long long) ib_wr->wr.fast_reg.iova_start,
                                  ib_wr->wr.fast_reg.length,
                                  ib_wr->wr.fast_reg.rkey,
-                                 (void *)pnesfrpl->nes_wqe_pbl.paddr,
+                                 (unsigned long long) pnesfrpl->nes_wqe_pbl.paddr,
                                  ib_wr->wr.fast_reg.page_list_len,
                                  wqe_misc);
                        break;
index 61de065..64c9e7d 100644 (file)
@@ -1406,7 +1406,7 @@ extern struct mutex qib_mutex;
  */
 #define qib_early_err(dev, fmt, ...) \
        do { \
-               dev_info(dev, KERN_ERR QIB_DRV_NAME ": " fmt, ##__VA_ARGS__); \
+               dev_err(dev, fmt, ##__VA_ARGS__); \
        } while (0)
 
 #define qib_dev_err(dd, fmt, ...) \
index f1d16d3..f3b5039 100644 (file)
@@ -1243,6 +1243,7 @@ static int __devinit qib_init_one(struct pci_dev *pdev,
                qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot "
                      "work if CONFIG_PCI_MSI is not enabled\n",
                      ent->device);
+               dd = ERR_PTR(-ENODEV);
 #endif
                break;
 
index 7fa6e55..48b6674 100644 (file)
@@ -103,16 +103,20 @@ int qib_pcie_init(struct pci_dev *pdev, const struct pci_device_id *ent)
                ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
        } else
                ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
-       if (ret)
+       if (ret) {
                qib_early_err(&pdev->dev,
                              "Unable to set DMA consistent mask: %d\n", ret);
+               goto bail;
+       }
 
        pci_set_master(pdev);
        ret = pci_enable_pcie_error_reporting(pdev);
-       if (ret)
+       if (ret) {
                qib_early_err(&pdev->dev,
                              "Unable to enable pcie error reporting: %d\n",
                              ret);
+               ret = 0;
+       }
        goto done;
 
 bail:
index a093111..955fb71 100644 (file)
@@ -2068,7 +2068,10 @@ send_last:
                        goto nack_op_err;
                if (!ret)
                        goto rnr_nak;
-               goto send_last_imm;
+               wc.ex.imm_data = ohdr->u.rc.imm_data;
+               hdrsize += 4;
+               wc.wc_flags = IB_WC_WITH_IMM;
+               goto send_last;
 
        case OP(RDMA_READ_REQUEST): {
                struct qib_ack_entry *e;
index b9c8b63..32ccf3c 100644 (file)
@@ -457,8 +457,10 @@ rdma_first:
                }
                if (opcode == OP(RDMA_WRITE_ONLY))
                        goto rdma_last;
-               else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE))
+               else if (opcode == OP(RDMA_WRITE_ONLY_WITH_IMMEDIATE)) {
+                       wc.ex.imm_data = ohdr->u.rc.imm_data;
                        goto rdma_last_imm;
+               }
                /* FALLTHROUGH */
        case OP(RDMA_WRITE_MIDDLE):
                /* Check for invalid length PMTU or posted rwqe len. */
@@ -471,8 +473,8 @@ rdma_first:
                break;
 
        case OP(RDMA_WRITE_LAST_WITH_IMMEDIATE):
-rdma_last_imm:
                wc.ex.imm_data = ohdr->u.imm_data;
+rdma_last_imm:
                hdrsize += 4;
                wc.wc_flags = IB_WC_WITH_IMM;
 
index ec6b4fb..dfa7190 100644 (file)
@@ -223,6 +223,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        unsigned int wr_id = wc->wr_id & ~IPOIB_OP_RECV;
        struct sk_buff *skb;
        u64 mapping[IPOIB_UD_RX_SG];
+       union ib_gid *dgid;
 
        ipoib_dbg_data(priv, "recv completion: id %d, status: %d\n",
                       wr_id, wc->status);
@@ -271,6 +272,16 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        ipoib_ud_dma_unmap_rx(priv, mapping);
        ipoib_ud_skb_put_frags(priv, skb, wc->byte_len);
 
+       /* First byte of dgid signals multicast when 0xff */
+       dgid = &((struct ib_grh *)skb->data)->dgid;
+
+       if (!(wc->wc_flags & IB_WC_GRH) || dgid->raw[0] != 0xff)
+               skb->pkt_type = PACKET_HOST;
+       else if (memcmp(dgid, dev->broadcast + 4, sizeof(union ib_gid)) == 0)
+               skb->pkt_type = PACKET_BROADCAST;
+       else
+               skb->pkt_type = PACKET_MULTICAST;
+
        skb_pull(skb, IB_GRH_BYTES);
 
        skb->protocol = ((struct ipoib_header *) skb->data)->proto;
@@ -281,9 +292,6 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
        dev->stats.rx_bytes += skb->len;
 
        skb->dev = dev;
-       /* XXX get correct PACKET_ type here */
-       skb->pkt_type = PACKET_HOST;
-
        if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
                skb->ip_summed = CHECKSUM_UNNECESSARY;
 
index b4b2257..9ff7bc7 100644 (file)
@@ -1240,6 +1240,7 @@ static struct net_device *ipoib_add_port(const char *format,
                goto alloc_mem_failed;
 
        SET_NETDEV_DEV(priv->dev, hca->dma_device);
+       priv->dev->dev_id = port - 1;
 
        if (!ib_query_port(hca, port, &attr))
                priv->max_ib_mtu = ib_mtu_enum_to_int(attr.max_mtu);
@@ -1362,6 +1363,8 @@ static void ipoib_add_one(struct ib_device *device)
        }
 
        for (p = s; p <= e; ++p) {
+               if (rdma_port_get_link_layer(device, p) != IB_LINK_LAYER_INFINIBAND)
+                       continue;
                dev = ipoib_add_port("ib%d", device, p);
                if (!IS_ERR(dev)) {
                        priv = netdev_priv(dev);
@@ -1409,8 +1412,7 @@ static int __init ipoib_init_module(void)
 
        ipoib_sendq_size = roundup_pow_of_two(ipoib_sendq_size);
        ipoib_sendq_size = min(ipoib_sendq_size, IPOIB_MAX_QUEUE_SIZE);
-       ipoib_sendq_size = max(ipoib_sendq_size, max(2 * MAX_SEND_CQE,
-                                                    IPOIB_MIN_QUEUE_SIZE));
+       ipoib_sendq_size = max3(ipoib_sendq_size, 2 * MAX_SEND_CQE, IPOIB_MIN_QUEUE_SIZE);
 #ifdef CONFIG_INFINIBAND_IPOIB_CM
        ipoib_max_conn_qp = min(ipoib_max_conn_qp, IPOIB_CM_MAX_CONN_QP);
 #endif
index 7f8f16b..cfc1d65 100644 (file)
@@ -291,7 +291,7 @@ static void srp_free_target_ib(struct srp_target_port *target)
 
        for (i = 0; i < SRP_RQ_SIZE; ++i)
                srp_free_iu(target->srp_host, target->rx_ring[i]);
-       for (i = 0; i < SRP_SQ_SIZE + 1; ++i)
+       for (i = 0; i < SRP_SQ_SIZE; ++i)
                srp_free_iu(target->srp_host, target->tx_ring[i]);
 }
 
@@ -811,6 +811,75 @@ static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
        return len;
 }
 
+/*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.  Lock cannot be dropped between call here and
+ * call to __srp_post_send().
+ *
+ * Note:
+ * An upper limit for the number of allocated information units for each
+ * request type is:
+ * - SRP_IU_CMD: SRP_CMD_SQ_SIZE, since the SCSI mid-layer never queues
+ *   more than Scsi_Host.can_queue requests.
+ * - SRP_IU_TSK_MGMT: SRP_TSK_MGMT_SQ_SIZE.
+ * - SRP_IU_RSP: 1, since a conforming SRP target never sends more than
+ *   one unanswered SRP request to an initiator.
+ */
+static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
+                                     enum srp_iu_type iu_type)
+{
+       s32 rsv = (iu_type == SRP_IU_TSK_MGMT) ? 0 : SRP_TSK_MGMT_SQ_SIZE;
+       struct srp_iu *iu;
+
+       srp_send_completion(target->send_cq, target);
+
+       if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
+               return NULL;
+
+       /* Initiator responses to target requests do not consume credits */
+       if (target->req_lim <= rsv && iu_type != SRP_IU_RSP) {
+               ++target->zero_req_lim;
+               return NULL;
+       }
+
+       iu = target->tx_ring[target->tx_head & SRP_SQ_MASK];
+       iu->type = iu_type;
+       return iu;
+}
+
+/*
+ * Must be called with target->scsi_host->host_lock held to protect
+ * req_lim and tx_head.
+ */
+static int __srp_post_send(struct srp_target_port *target,
+                          struct srp_iu *iu, int len)
+{
+       struct ib_sge list;
+       struct ib_send_wr wr, *bad_wr;
+       int ret = 0;
+
+       list.addr   = iu->dma;
+       list.length = len;
+       list.lkey   = target->srp_host->srp_dev->mr->lkey;
+
+       wr.next       = NULL;
+       wr.wr_id      = target->tx_head & SRP_SQ_MASK;
+       wr.sg_list    = &list;
+       wr.num_sge    = 1;
+       wr.opcode     = IB_WR_SEND;
+       wr.send_flags = IB_SEND_SIGNALED;
+
+       ret = ib_post_send(target->qp, &wr, &bad_wr);
+
+       if (!ret) {
+               ++target->tx_head;
+               if (iu->type != SRP_IU_RSP)
+                       --target->req_lim;
+       }
+
+       return ret;
+}
+
 static int srp_post_recv(struct srp_target_port *target)
 {
        unsigned long flags;
@@ -822,7 +891,7 @@ static int srp_post_recv(struct srp_target_port *target)
 
        spin_lock_irqsave(target->scsi_host->host_lock, flags);
 
-       next     = target->rx_head & (SRP_RQ_SIZE - 1);
+       next     = target->rx_head & SRP_RQ_MASK;
        wr.wr_id = next;
        iu       = target->rx_ring[next];
 
@@ -896,6 +965,71 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp)
        spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
 }
 
+static int srp_response_common(struct srp_target_port *target, s32 req_delta,
+                              void *rsp, int len)
+{
+       struct ib_device *dev;
+       unsigned long flags;
+       struct srp_iu *iu;
+       int err = 1;
+
+       dev = target->srp_host->srp_dev->dev;
+
+       spin_lock_irqsave(target->scsi_host->host_lock, flags);
+       target->req_lim += req_delta;
+
+       iu = __srp_get_tx_iu(target, SRP_IU_RSP);
+       if (!iu) {
+               shost_printk(KERN_ERR, target->scsi_host, PFX
+                            "no IU available to send response\n");
+               goto out;
+       }
+
+       ib_dma_sync_single_for_cpu(dev, iu->dma, len, DMA_TO_DEVICE);
+       memcpy(iu->buf, rsp, len);
+       ib_dma_sync_single_for_device(dev, iu->dma, len, DMA_TO_DEVICE);
+
+       err = __srp_post_send(target, iu, len);
+       if (err)
+               shost_printk(KERN_ERR, target->scsi_host, PFX
+                            "unable to post response: %d\n", err);
+
+out:
+       spin_unlock_irqrestore(target->scsi_host->host_lock, flags);
+       return err;
+}
+
+static void srp_process_cred_req(struct srp_target_port *target,
+                                struct srp_cred_req *req)
+{
+       struct srp_cred_rsp rsp = {
+               .opcode = SRP_CRED_RSP,
+               .tag = req->tag,
+       };
+       s32 delta = be32_to_cpu(req->req_lim_delta);
+
+       if (srp_response_common(target, delta, &rsp, sizeof rsp))
+               shost_printk(KERN_ERR, target->scsi_host, PFX
+                            "problems processing SRP_CRED_REQ\n");
+}
+
+static void srp_process_aer_req(struct srp_target_port *target,
+                               struct srp_aer_req *req)
+{
+       struct srp_aer_rsp rsp = {
+               .opcode = SRP_AER_RSP,
+               .tag = req->tag,
+       };
+       s32 delta = be32_to_cpu(req->req_lim_delta);
+
+       shost_printk(KERN_ERR, target->scsi_host, PFX
+                    "ignoring AER for LUN %llu\n", be64_to_cpu(req->lun));
+
+       if (srp_response_common(target, delta, &rsp, sizeof rsp))
+               shost_printk(KERN_ERR, target->scsi_host, PFX
+                            "problems processing SRP_AER_REQ\n");
+}
+
 static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
 {
        struct ib_device *dev;
@@ -923,6 +1057,14 @@ static void srp_handle_recv(struct srp_target_port *target, struct ib_wc *wc)
                srp_process_rsp(target, iu->buf);
                break;
 
+       case SRP_CRED_REQ:
+               srp_process_cred_req(target, iu->buf);
+               break;
+
+       case SRP_AER_REQ:
+               srp_process_aer_req(target, iu->buf);
+               break;
+
        case SRP_T_LOGOUT:
                /* XXX Handle target logout */
                shost_printk(KERN_WARNING, target->scsi_host,
@@ -981,61 +1123,6 @@ static void srp_send_completion(struct ib_cq *cq, void *target_ptr)
        }
 }
 
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.  Lock cannot be dropped between call here and
- * call to __srp_post_send().
- */
-static struct srp_iu *__srp_get_tx_iu(struct srp_target_port *target,
-                                       enum srp_request_type req_type)
-{
-       s32 min = (req_type == SRP_REQ_TASK_MGMT) ? 1 : 2;
-
-       srp_send_completion(target->send_cq, target);
-
-       if (target->tx_head - target->tx_tail >= SRP_SQ_SIZE)
-               return NULL;
-
-       if (target->req_lim < min) {
-               ++target->zero_req_lim;
-               return NULL;
-       }
-
-       return target->tx_ring[target->tx_head & SRP_SQ_SIZE];
-}
-
-/*
- * Must be called with target->scsi_host->host_lock held to protect
- * req_lim and tx_head.
- */
-static int __srp_post_send(struct srp_target_port *target,
-                          struct srp_iu *iu, int len)
-{
-       struct ib_sge list;
-       struct ib_send_wr wr, *bad_wr;
-       int ret = 0;
-
-       list.addr   = iu->dma;
-       list.length = len;
-       list.lkey   = target->srp_host->srp_dev->mr->lkey;
-
-       wr.next       = NULL;
-       wr.wr_id      = target->tx_head & SRP_SQ_SIZE;
-       wr.sg_list    = &list;
-       wr.num_sge    = 1;
-       wr.opcode     = IB_WR_SEND;
-       wr.send_flags = IB_SEND_SIGNALED;
-
-       ret = ib_post_send(target->qp, &wr, &bad_wr);
-
-       if (!ret) {
-               ++target->tx_head;
-               --target->req_lim;
-       }
-
-       return ret;
-}
-
 static int srp_queuecommand(struct scsi_cmnd *scmnd,
                            void (*done)(struct scsi_cmnd *))
 {
@@ -1056,7 +1143,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
                return 0;
        }
 
-       iu = __srp_get_tx_iu(target, SRP_REQ_NORMAL);
+       iu = __srp_get_tx_iu(target, SRP_IU_CMD);
        if (!iu)
                goto err;
 
@@ -1064,7 +1151,7 @@ static int srp_queuecommand(struct scsi_cmnd *scmnd,
        ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
                                   DMA_TO_DEVICE);
 
-       req = list_entry(target->free_reqs.next, struct srp_request, list);
+       req = list_first_entry(&target->free_reqs, struct srp_request, list);
 
        scmnd->scsi_done     = done;
        scmnd->result        = 0;
@@ -1121,7 +1208,7 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target)
                        goto err;
        }
 
-       for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+       for (i = 0; i < SRP_SQ_SIZE; ++i) {
                target->tx_ring[i] = srp_alloc_iu(target->srp_host,
                                                  srp_max_iu_len,
                                                  GFP_KERNEL, DMA_TO_DEVICE);
@@ -1137,7 +1224,7 @@ err:
                target->rx_ring[i] = NULL;
        }
 
-       for (i = 0; i < SRP_SQ_SIZE + 1; ++i) {
+       for (i = 0; i < SRP_SQ_SIZE; ++i) {
                srp_free_iu(target->srp_host, target->tx_ring[i]);
                target->tx_ring[i] = NULL;
        }
@@ -1252,8 +1339,13 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
                        target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);
                        target->req_lim       = be32_to_cpu(rsp->req_lim_delta);
 
-                       target->scsi_host->can_queue = min(target->req_lim,
-                                                          target->scsi_host->can_queue);
+                       /*
+                        * Reserve credits for task management so we don't
+                        * bounce requests back to the SCSI mid-layer.
+                        */
+                       target->scsi_host->can_queue
+                               = min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
+                                     target->scsi_host->can_queue);
                } else {
                        shost_printk(KERN_WARNING, target->scsi_host,
                                    PFX "Unhandled RSP opcode %#x\n", opcode);
@@ -1350,6 +1442,7 @@ static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 static int srp_send_tsk_mgmt(struct srp_target_port *target,
                             struct srp_request *req, u8 func)
 {
+       struct ib_device *dev = target->srp_host->srp_dev->dev;
        struct srp_iu *iu;
        struct srp_tsk_mgmt *tsk_mgmt;
 
@@ -1363,10 +1456,12 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
 
        init_completion(&req->done);
 
-       iu = __srp_get_tx_iu(target, SRP_REQ_TASK_MGMT);
+       iu = __srp_get_tx_iu(target, SRP_IU_TSK_MGMT);
        if (!iu)
                goto out;
 
+       ib_dma_sync_single_for_cpu(dev, iu->dma, sizeof *tsk_mgmt,
+                                  DMA_TO_DEVICE);
        tsk_mgmt = iu->buf;
        memset(tsk_mgmt, 0, sizeof *tsk_mgmt);
 
@@ -1376,6 +1471,8 @@ static int srp_send_tsk_mgmt(struct srp_target_port *target,
        tsk_mgmt->tsk_mgmt_func = func;
        tsk_mgmt->task_tag      = req->index;
 
+       ib_dma_sync_single_for_device(dev, iu->dma, sizeof *tsk_mgmt,
+                                     DMA_TO_DEVICE);
        if (__srp_post_send(target, iu, sizeof *tsk_mgmt))
                goto out;
 
@@ -1626,9 +1723,9 @@ static struct scsi_host_template srp_template = {
        .eh_abort_handler               = srp_abort,
        .eh_device_reset_handler        = srp_reset_device,
        .eh_host_reset_handler          = srp_reset_host,
-       .can_queue                      = SRP_SQ_SIZE,
+       .can_queue                      = SRP_CMD_SQ_SIZE,
        .this_id                        = -1,
-       .cmd_per_lun                    = SRP_SQ_SIZE,
+       .cmd_per_lun                    = SRP_CMD_SQ_SIZE,
        .use_clustering                 = ENABLE_CLUSTERING,
        .shost_attrs                    = srp_host_attrs
 };
@@ -1813,7 +1910,7 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
                                printk(KERN_WARNING PFX "bad max cmd_per_lun parameter '%s'\n", p);
                                goto out;
                        }
-                       target->scsi_host->cmd_per_lun = min(token, SRP_SQ_SIZE);
+                       target->scsi_host->cmd_per_lun = min(token, SRP_CMD_SQ_SIZE);
                        break;
 
                case SRP_OPT_IO_CLASS:
@@ -1891,7 +1988,7 @@ static ssize_t srp_create_target(struct device *dev,
 
        INIT_LIST_HEAD(&target->free_reqs);
        INIT_LIST_HEAD(&target->req_queue);
-       for (i = 0; i < SRP_SQ_SIZE; ++i) {
+       for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
                target->req_ring[i].index = i;
                list_add_tail(&target->req_ring[i].list, &target->free_reqs);
        }
@@ -2159,6 +2256,9 @@ static int __init srp_init_module(void)
 {
        int ret;
 
+       BUILD_BUG_ON_NOT_POWER_OF_2(SRP_SQ_SIZE);
+       BUILD_BUG_ON_NOT_POWER_OF_2(SRP_RQ_SIZE);
+
        if (srp_sg_tablesize > 255) {
                printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
                srp_sg_tablesize = 255;
index 5a80eac..ed0dce9 100644 (file)
@@ -59,7 +59,14 @@ enum {
 
        SRP_RQ_SHIFT            = 6,
        SRP_RQ_SIZE             = 1 << SRP_RQ_SHIFT,
-       SRP_SQ_SIZE             = SRP_RQ_SIZE - 1,
+       SRP_RQ_MASK             = SRP_RQ_SIZE - 1,
+
+       SRP_SQ_SIZE             = SRP_RQ_SIZE,
+       SRP_SQ_MASK             = SRP_SQ_SIZE - 1,
+       SRP_RSP_SQ_SIZE         = 1,
+       SRP_REQ_SQ_SIZE         = SRP_SQ_SIZE - SRP_RSP_SQ_SIZE,
+       SRP_TSK_MGMT_SQ_SIZE    = 1,
+       SRP_CMD_SQ_SIZE         = SRP_REQ_SQ_SIZE - SRP_TSK_MGMT_SQ_SIZE,
 
        SRP_TAG_TSK_MGMT        = 1 << (SRP_RQ_SHIFT + 1),
 
@@ -75,9 +82,10 @@ enum srp_target_state {
        SRP_TARGET_REMOVED
 };
 
-enum srp_request_type {
-       SRP_REQ_NORMAL,
-       SRP_REQ_TASK_MGMT,
+enum srp_iu_type {
+       SRP_IU_CMD,
+       SRP_IU_TSK_MGMT,
+       SRP_IU_RSP,
 };
 
 struct srp_device {
@@ -144,11 +152,11 @@ struct srp_target_port {
 
        unsigned                tx_head;
        unsigned                tx_tail;
-       struct srp_iu          *tx_ring[SRP_SQ_SIZE + 1];
+       struct srp_iu          *tx_ring[SRP_SQ_SIZE];
 
        struct list_head        free_reqs;
        struct list_head        req_queue;
-       struct srp_request      req_ring[SRP_SQ_SIZE];
+       struct srp_request      req_ring[SRP_CMD_SQ_SIZE];
 
        struct work_struct      work;
 
@@ -164,6 +172,7 @@ struct srp_iu {
        void                   *buf;
        size_t                  size;
        enum dma_data_direction direction;
+       enum srp_iu_type        type;
 };
 
 #endif /* IB_SRP_H */
index 947d4af..30e6195 100644 (file)
@@ -482,7 +482,7 @@ static s32 pm121_correct(s32 new_setpoint,
        new_min += correction->offset;
        new_min = (new_min >> 16) + min;
 
-       return max(new_setpoint, max(new_min, 0));
+       return max3(new_setpoint, new_min, 0);
 }
 
 static s32 pm121_connect(unsigned int control_id, s32 setpoint)
index 0b61792..2129cdb 100644 (file)
@@ -254,7 +254,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw,
         * Issue the synchronous I/O from a different thread
         * to avoid generic_make_request recursion.
         */
-       INIT_WORK_ON_STACK(&req.work, do_metadata);
+       INIT_WORK_ONSTACK(&req.work, do_metadata);
        queue_work(ps->metadata_wq, &req.work);
        flush_workqueue(ps->metadata_wq);
 
index 1f69743..5a74db7 100644 (file)
@@ -4,7 +4,6 @@
 
 menuconfig MISC_DEVICES
        bool "Misc devices"
-       default y
        ---help---
          Say Y here to get to see options for device drivers from various
          different categories. This option alone does not add any kernel code.
@@ -24,7 +23,8 @@ config AD525X_DPOT
          AD5260, AD5262, AD5263, AD5290, AD5291, AD5292, AD5293,
          AD7376, AD8400, AD8402, AD8403, ADN2850, AD5241, AD5242,
          AD5243, AD5245, AD5246, AD5247, AD5248, AD5280, AD5282,
-         ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173
+         ADN2860, AD5273, AD5171, AD5170, AD5172, AD5173, AD5270,
+         AD5271, AD5272, AD5274
          digital potentiometer chips.
 
          See Documentation/misc-devices/ad525x_dpot.txt for the
@@ -284,6 +284,16 @@ config SGI_GRU_DEBUG
        This option enables addition debugging code for the SGI GRU driver. If
        you are unsure, say N.
 
+config APDS9802ALS
+       tristate "Medfield Avago APDS9802 ALS Sensor module"
+       depends on I2C
+       help
+         If you say yes here you get support for the ALS APDS9802 ambient
+         light sensor.
+
+         This driver can also be built as a module.  If so, the module
+         will be called apds9802als.
+
 config ISL29003
        tristate "Intersil ISL29003 ambient light sensor"
        depends on I2C && SYSFS
@@ -294,6 +304,16 @@ config ISL29003
          This driver can also be built as a module.  If so, the module
          will be called isl29003.
 
+config ISL29020
+       tristate "Intersil ISL29020 ambient light sensor"
+       depends on I2C
+       help
+         If you say yes here you get support for the Intersil ISL29020
+         ambient light sensor.
+
+         This driver can also be built as a module.  If so, the module
+         will be called isl29020.
+
 config SENSORS_TSL2550
        tristate "Taos TSL2550 ambient light sensor"
        depends on I2C && SYSFS
@@ -314,6 +334,27 @@ config SENSORS_BH1780
          This driver can also be built as a module.  If so, the module
          will be called bh1780gli.
 
+config SENSORS_BH1770
+         tristate "BH1770GLC / SFH7770 combined ALS - Proximity sensor"
+         depends on I2C
+         ---help---
+           Say Y here if you want to build a driver for BH1770GLC (ROHM) or
+          SFH7770 (Osram) combined ambient light and proximity sensor chip.
+
+           To compile this driver as a module, choose M here: the
+           module will be called bh1770glc. If unsure, say N here.
+
+config SENSORS_APDS990X
+        tristate "APDS990X combined als and proximity sensors"
+        depends on I2C
+        default n
+        ---help---
+          Say Y here if you want to build a driver for Avago APDS990x
+          combined ambient light and proximity sensor chip.
+
+          To compile this driver as a module, choose M here: the
+          module will be called apds990x. If unsure, say N here.
+
 config HMC6352
        tristate "Honeywell HMC6352 compass"
        depends on I2C
index 9f2986b..4be5c6f 100644 (file)
@@ -16,6 +16,8 @@ obj-$(CONFIG_TIFM_CORE)               += tifm_core.o
 obj-$(CONFIG_TIFM_7XX1)        += tifm_7xx1.o
 obj-$(CONFIG_PHANTOM)          += phantom.o
 obj-$(CONFIG_SENSORS_BH1780)   += bh1780gli.o
+obj-$(CONFIG_SENSORS_BH1770)   += bh1770glc.o
+obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
 obj-$(CONFIG_SGI_IOC4)         += ioc4.o
 obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o
 obj-$(CONFIG_KGDB_TESTS)       += kgdbts.o
@@ -23,7 +25,9 @@ obj-$(CONFIG_SGI_XP)          += sgi-xp/
 obj-$(CONFIG_SGI_GRU)          += sgi-gru/
 obj-$(CONFIG_CS5535_MFGPT)     += cs5535-mfgpt.o
 obj-$(CONFIG_HP_ILO)           += hpilo.o
+obj-$(CONFIG_APDS9802ALS)      += apds9802als.o
 obj-$(CONFIG_ISL29003)         += isl29003.o
+obj-$(CONFIG_ISL29020)         += isl29020.o
 obj-$(CONFIG_SENSORS_TSL2550)  += tsl2550.o
 obj-$(CONFIG_EP93XX_PWM)       += ep93xx_pwm.o
 obj-$(CONFIG_DS1682)           += ds1682.o
index 374352a..4ff73c2 100644 (file)
@@ -102,6 +102,8 @@ static const struct i2c_device_id ad_dpot_id[] = {
        {"ad5170", AD5170_ID},
        {"ad5172", AD5172_ID},
        {"ad5173", AD5173_ID},
+       {"ad5272", AD5272_ID},
+       {"ad5274", AD5274_ID},
        {}
 };
 MODULE_DEVICE_TABLE(i2c, ad_dpot_id);
index b8c6df9..7f9a55a 100644 (file)
@@ -38,6 +38,8 @@ static const struct ad_dpot_id ad_dpot_spi_devlist[] = {
        {.name = "ad8402", .devid = AD8402_ID},
        {.name = "ad8403", .devid = AD8403_ID},
        {.name = "adn2850", .devid = ADN2850_ID},
+       {.name = "ad5270", .devid = AD5270_ID},
+       {.name = "ad5271", .devid = AD5271_ID},
        {}
 };
 
@@ -53,13 +55,13 @@ static int write8(void *client, u8 val)
 static int write16(void *client, u8 reg, u8 val)
 {
        u8 data[2] = {reg, val};
-       return spi_write(client, data, 1);
+       return spi_write(client, data, 2);
 }
 
 static int write24(void *client, u8 reg, u16 val)
 {
        u8 data[3] = {reg, val >> 8, val};
-       return spi_write(client, data, 1);
+       return spi_write(client, data, 3);
 }
 
 static int read8(void *client)
index 5e6fa84..7cb9110 100644 (file)
@@ -29,9 +29,9 @@
  * AD5262              2               256             20, 50, 200
  * AD5263              4               256             20, 50, 200
  * AD5290              1               256             10, 50, 100
- * AD5291              1               256             20
- * AD5292              1               1024            20
- * AD5293              1               1024            20
+ * AD5291              1               256             20, 50, 100  (20-TP)
+ * AD5292              1               1024            20, 50, 100  (20-TP)
+ * AD5293              1               1024            20, 50, 100
  * AD7376              1               128             10, 50, 100, 1M
  * AD8400              1               256             1, 10, 50, 100
  * AD8402              2               256             1, 10, 50, 100
  * AD5170              1               256             2.5, 10, 50, 100 (OTP)
  * AD5172              2               256             2.5, 10, 50, 100 (OTP)
  * AD5173              2               256             2.5, 10, 50, 100 (OTP)
+ * AD5270              1               1024            20, 50, 100 (50-TP)
+ * AD5271              1               256             20, 50, 100 (50-TP)
+ * AD5272              1               1024            20, 50, 100 (50-TP)
+ * AD5274              1               256             20, 50, 100 (50-TP)
  *
  * See Documentation/misc-devices/ad525x_dpot.txt for more info.
  *
@@ -126,18 +130,38 @@ static inline int dpot_write_r8d16(struct dpot_data *dpot, u8 reg, u16 val)
 static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
 {
        unsigned ctrl = 0;
+       int value;
 
        if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
 
                if (dpot->feat & F_RDACS_WONLY)
                        return dpot->rdac_cache[reg & DPOT_RDAC_MASK];
-
                if (dpot->uid == DPOT_UID(AD5291_ID) ||
                        dpot->uid == DPOT_UID(AD5292_ID) ||
-                       dpot->uid == DPOT_UID(AD5293_ID))
-                       return dpot_read_r8d8(dpot,
+                       dpot->uid == DPOT_UID(AD5293_ID)) {
+
+                       value = dpot_read_r8d8(dpot,
                                DPOT_AD5291_READ_RDAC << 2);
 
+                       if (dpot->uid == DPOT_UID(AD5291_ID))
+                               value = value >> 2;
+
+                       return value;
+               } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+                       dpot->uid == DPOT_UID(AD5271_ID)) {
+
+                       value = dpot_read_r8d8(dpot,
+                               DPOT_AD5270_1_2_4_READ_RDAC << 2);
+
+                       if (value < 0)
+                               return value;
+
+                       if (dpot->uid == DPOT_UID(AD5271_ID))
+                               value = value >> 2;
+
+                       return value;
+               }
+
                ctrl = DPOT_SPI_READ_RDAC;
        } else if (reg & DPOT_ADDR_EEPROM) {
                ctrl = DPOT_SPI_READ_EEPROM;
@@ -153,6 +177,7 @@ static s32 dpot_read_spi(struct dpot_data *dpot, u8 reg)
 
 static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
 {
+       int value;
        unsigned ctrl = 0;
        switch (dpot->uid) {
        case DPOT_UID(AD5246_ID):
@@ -166,7 +191,7 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
        case DPOT_UID(AD5280_ID):
        case DPOT_UID(AD5282_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5291_RDAC_AB;
+                       0 : DPOT_AD5282_RDAC_AB;
                return dpot_read_r8d8(dpot, ctrl);
        case DPOT_UID(AD5170_ID):
        case DPOT_UID(AD5171_ID):
@@ -175,8 +200,27 @@ static s32 dpot_read_i2c(struct dpot_data *dpot, u8 reg)
        case DPOT_UID(AD5172_ID):
        case DPOT_UID(AD5173_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5272_3_A0;
+                       0 : DPOT_AD5172_3_A0;
                return dpot_read_r8d8(dpot, ctrl);
+       case DPOT_UID(AD5272_ID):
+       case DPOT_UID(AD5274_ID):
+                       dpot_write_r8d8(dpot,
+                               (DPOT_AD5270_1_2_4_READ_RDAC << 2), 0);
+
+                       value = dpot_read_r8d16(dpot,
+                               DPOT_AD5270_1_2_4_RDAC << 2);
+
+                       if (value < 0)
+                               return value;
+                       /*
+                        * AD5272/AD5274 returns high byte first, however
+                        * underling smbus expects low byte first.
+                        */
+                       value = swab16(value);
+
+                       if (dpot->uid == DPOT_UID(AD5271_ID))
+                               value = value >> 2;
+               return value;
        default:
                if ((reg & DPOT_REG_TOL) || (dpot->max_pos > 256))
                        return dpot_read_r8d16(dpot, (reg & 0xF8) |
@@ -198,7 +242,7 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
 {
        unsigned val = 0;
 
-       if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD))) {
+       if (!(reg & (DPOT_ADDR_EEPROM | DPOT_ADDR_CMD | DPOT_ADDR_OTP))) {
                if (dpot->feat & F_RDACS_WONLY)
                        dpot->rdac_cache[reg & DPOT_RDAC_MASK] = value;
 
@@ -219,11 +263,30 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
                } else {
                        if (dpot->uid == DPOT_UID(AD5291_ID) ||
                                dpot->uid == DPOT_UID(AD5292_ID) ||
-                               dpot->uid == DPOT_UID(AD5293_ID))
+                               dpot->uid == DPOT_UID(AD5293_ID)) {
+
+                               dpot_write_r8d8(dpot, DPOT_AD5291_CTRLREG << 2,
+                                               DPOT_AD5291_UNLOCK_CMD);
+
+                               if (dpot->uid == DPOT_UID(AD5291_ID))
+                                       value = value << 2;
+
                                return dpot_write_r8d8(dpot,
                                        (DPOT_AD5291_RDAC << 2) |
                                        (value >> 8), value & 0xFF);
+                       } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+                               dpot->uid == DPOT_UID(AD5271_ID)) {
+                               dpot_write_r8d8(dpot,
+                                               DPOT_AD5270_1_2_4_CTRLREG << 2,
+                                               DPOT_AD5270_1_2_4_UNLOCK_CMD);
+
+                               if (dpot->uid == DPOT_UID(AD5271_ID))
+                                       value = value << 2;
 
+                               return dpot_write_r8d8(dpot,
+                                       (DPOT_AD5270_1_2_4_RDAC << 2) |
+                                       (value >> 8), value & 0xFF);
+                       }
                        val = DPOT_SPI_RDAC | (reg & DPOT_RDAC_MASK);
                }
        } else if (reg & DPOT_ADDR_EEPROM) {
@@ -243,6 +306,16 @@ static s32 dpot_write_spi(struct dpot_data *dpot, u8 reg, u16 value)
                        val = DPOT_SPI_INC_ALL;
                        break;
                }
+       } else if (reg & DPOT_ADDR_OTP) {
+               if (dpot->uid == DPOT_UID(AD5291_ID) ||
+                       dpot->uid == DPOT_UID(AD5292_ID)) {
+                       return dpot_write_r8d8(dpot,
+                               DPOT_AD5291_STORE_XTPM << 2, 0);
+               } else if (dpot->uid == DPOT_UID(AD5270_ID) ||
+                       dpot->uid == DPOT_UID(AD5271_ID)) {
+                       return dpot_write_r8d8(dpot,
+                               DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
+               }
        } else
                BUG();
 
@@ -273,7 +346,7 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
        case DPOT_UID(AD5280_ID):
        case DPOT_UID(AD5282_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5291_RDAC_AB;
+                       0 : DPOT_AD5282_RDAC_AB;
                return dpot_write_r8d8(dpot, ctrl, value);
                break;
        case DPOT_UID(AD5171_ID):
@@ -289,12 +362,12 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
        case DPOT_UID(AD5172_ID):
        case DPOT_UID(AD5173_ID):
                ctrl = ((reg & DPOT_RDAC_MASK) == DPOT_RDAC0) ?
-                       0 : DPOT_AD5272_3_A0;
+                       0 : DPOT_AD5172_3_A0;
                if (reg & DPOT_ADDR_OTP) {
                        tmp = dpot_read_r8d16(dpot, ctrl);
                        if (tmp >> 14) /* Ready to Program? */
                                return -EFAULT;
-                       ctrl |= DPOT_AD5270_2_3_FUSE;
+                       ctrl |= DPOT_AD5170_2_3_FUSE;
                }
                return dpot_write_r8d8(dpot, ctrl, value);
                break;
@@ -303,10 +376,25 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
                        tmp = dpot_read_r8d16(dpot, tmp);
                        if (tmp >> 14) /* Ready to Program? */
                                return -EFAULT;
-                       ctrl = DPOT_AD5270_2_3_FUSE;
+                       ctrl = DPOT_AD5170_2_3_FUSE;
                }
                return dpot_write_r8d8(dpot, ctrl, value);
                break;
+       case DPOT_UID(AD5272_ID):
+       case DPOT_UID(AD5274_ID):
+               dpot_write_r8d8(dpot, DPOT_AD5270_1_2_4_CTRLREG << 2,
+                               DPOT_AD5270_1_2_4_UNLOCK_CMD);
+
+               if (reg & DPOT_ADDR_OTP)
+                       return dpot_write_r8d8(dpot,
+                                       DPOT_AD5270_1_2_4_STORE_XTPM << 2, 0);
+
+               if (dpot->uid == DPOT_UID(AD5274_ID))
+                       value = value << 2;
+
+               return dpot_write_r8d8(dpot, (DPOT_AD5270_1_2_4_RDAC << 2) |
+                                      (value >> 8), value & 0xFF);
+               break;
        default:
                if (reg & DPOT_ADDR_CMD)
                        return dpot_write_d8(dpot, reg);
@@ -320,7 +408,6 @@ static s32 dpot_write_i2c(struct dpot_data *dpot, u8 reg, u16 value)
        }
 }
 
-
 static s32 dpot_write(struct dpot_data *dpot, u8 reg, u16 value)
 {
        if (dpot->feat & F_SPI)
index 78b89fd..a662f59 100644 (file)
@@ -47,9 +47,9 @@ enum dpot_devid {
        AD5258_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 6, 0), /* I2C */
        AD5259_ID = DPOT_CONF(F_RDACS_RW_TOL, BRDAC0, 8, 1),
        AD5251_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
-                       BRDAC0 | BRDAC3, 6, 2),
+                       BRDAC1 | BRDAC3, 6, 2),
        AD5252_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
-                       BRDAC0 | BRDAC3, 8, 3),
+                       BRDAC1 | BRDAC3, 8, 3),
        AD5253_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
                        BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 6, 4),
        AD5254_ID = DPOT_CONF(F_RDACS_RW_TOL | F_CMD_INC,
@@ -93,8 +93,10 @@ enum dpot_devid {
                        BRDAC0 | BRDAC1 | BRDAC2 | BRDAC3, 8, 23),
        AD5290_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
                        BRDAC0, 8, 24),
-       AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 8, 25),
-       AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 26),
+       AD5291_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP,
+                       BRDAC0, 8, 25),
+       AD5292_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT | F_CMD_OTP,
+                       BRDAC0, 10, 26),
        AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),
        AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
                        BRDAC0, 7, 28),
@@ -122,6 +124,12 @@ enum dpot_devid {
        AD5170_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 45),
        AD5172_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 46),
        AD5173_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0 | BRDAC1, 8, 47),
+       AD5270_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT,
+                       BRDAC0, 10, 48),
+       AD5271_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP | F_SPI_16BIT,
+                       BRDAC0, 8, 49),
+       AD5272_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 10, 50),
+       AD5274_ID = DPOT_CONF(F_RDACS_RW | F_CMD_OTP, BRDAC0, 8, 51),
 };
 
 #define DPOT_RDAC0             0
@@ -165,15 +173,24 @@ enum dpot_devid {
 /* AD5291/2/3 use special commands */
 #define DPOT_AD5291_RDAC       0x01
 #define DPOT_AD5291_READ_RDAC  0x02
+#define DPOT_AD5291_STORE_XTPM 0x03
+#define DPOT_AD5291_CTRLREG    0x06
+#define DPOT_AD5291_UNLOCK_CMD 0x03
 
-/* AD524x use special commands */
-#define DPOT_AD5291_RDAC_AB    0x80
+/* AD5270/1/2/4 use special commands */
+#define DPOT_AD5270_1_2_4_RDAC         0x01
+#define DPOT_AD5270_1_2_4_READ_RDAC    0x02
+#define DPOT_AD5270_1_2_4_STORE_XTPM   0x03
+#define DPOT_AD5270_1_2_4_CTRLREG      0x07
+#define DPOT_AD5270_1_2_4_UNLOCK_CMD   0x03
+
+#define DPOT_AD5282_RDAC_AB    0x80
 
 #define DPOT_AD5273_FUSE       0x80
-#define DPOT_AD5270_2_3_FUSE   0x20
-#define DPOT_AD5270_2_3_OW     0x08
-#define DPOT_AD5272_3_A0       0x08
-#define DPOT_AD5270_2FUSE      0x80
+#define DPOT_AD5170_2_3_FUSE   0x20
+#define DPOT_AD5170_2_3_OW     0x08
+#define DPOT_AD5172_3_A0       0x08
+#define DPOT_AD5170_2FUSE      0x80
 
 struct dpot_data;
 
diff --git a/drivers/misc/apds9802als.c b/drivers/misc/apds9802als.c
new file mode 100644 (file)
index 0000000..f9b91ba
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * apds9802als.c - apds9802  ALS Driver
+ *
+ * Copyright (C) 2009 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+
+#define ALS_MIN_RANGE_VAL 1
+#define ALS_MAX_RANGE_VAL 2
+#define POWER_STA_ENABLE 1
+#define POWER_STA_DISABLE 0
+
+#define DRIVER_NAME "apds9802als"
+
+struct als_data {
+       struct mutex mutex;
+};
+
+static ssize_t als_sensing_range_show(struct device *dev,
+                       struct device_attribute *attr,  char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int  val;
+
+       val = i2c_smbus_read_byte_data(client, 0x81);
+       if (val < 0)
+               return val;
+       if (val & 1)
+               return sprintf(buf, "4095\n");
+       else
+               return sprintf(buf, "65535\n");
+}
+
+static int als_wait_for_data_ready(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int ret;
+       int retry = 10;
+
+       do {
+               msleep(30);
+               ret = i2c_smbus_read_byte_data(client, 0x86);
+       } while (!(ret & 0x80) && retry--);
+
+       if (!retry) {
+               dev_warn(dev, "timeout waiting for data ready\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static ssize_t als_lux0_input_data_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct als_data *data = i2c_get_clientdata(client);
+       int ret_val;
+       int temp;
+
+       /* Protect against parallel reads */
+       pm_runtime_get_sync(dev);
+       mutex_lock(&data->mutex);
+
+       /* clear EOC interrupt status */
+       i2c_smbus_write_byte(client, 0x40);
+       /* start measurement */
+       temp = i2c_smbus_read_byte_data(client, 0x81);
+       i2c_smbus_write_byte_data(client, 0x81, temp | 0x08);
+
+       ret_val = als_wait_for_data_ready(dev);
+       if (ret_val < 0)
+               goto failed;
+
+       temp = i2c_smbus_read_byte_data(client, 0x8C); /* LSB data */
+       if (temp < 0) {
+               ret_val = temp;
+               goto failed;
+       }
+       ret_val = i2c_smbus_read_byte_data(client, 0x8D); /* MSB data */
+       if (ret_val < 0)
+               goto failed;
+
+       mutex_unlock(&data->mutex);
+       pm_runtime_put_sync(dev);
+
+       temp = (ret_val << 8) | temp;
+       return sprintf(buf, "%d\n", temp);
+failed:
+       mutex_unlock(&data->mutex);
+       pm_runtime_put_sync(dev);
+       return ret_val;
+}
+
+static ssize_t als_sensing_range_store(struct device *dev,
+               struct device_attribute *attr, const  char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct als_data *data = i2c_get_clientdata(client);
+       unsigned int ret_val;
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val))
+               return -EINVAL;
+
+       if (val < 4096)
+               val = 1;
+       else if (val < 65536)
+               val = 2;
+       else
+               return -ERANGE;
+
+       pm_runtime_get_sync(dev);
+
+       /* Make sure nobody else reads/modifies/writes 0x81 while we
+          are active */
+       mutex_lock(&data->mutex);
+
+       ret_val = i2c_smbus_read_byte_data(client, 0x81);
+       if (ret_val < 0)
+               goto fail;
+
+       /* Reset the bits before setting them */
+       ret_val = ret_val & 0xFA;
+
+       if (val == 1) /* Setting detection range up to 4k LUX */
+               ret_val = (ret_val | 0x01);
+       else /* Setting detection range up to 64k LUX*/
+               ret_val = (ret_val | 0x00);
+
+       ret_val = i2c_smbus_write_byte_data(client, 0x81, ret_val);
+
+       if (ret_val >= 0) {
+               /* All OK */
+               mutex_unlock(&data->mutex);
+               pm_runtime_put_sync(dev);
+               return count;
+       }
+fail:
+       mutex_unlock(&data->mutex);
+       pm_runtime_put_sync(dev);
+       return ret_val;
+}
+
+static int als_set_power_state(struct i2c_client *client, bool on_off)
+{
+       int ret_val;
+       struct als_data *data = i2c_get_clientdata(client);
+
+       mutex_lock(&data->mutex);
+       ret_val = i2c_smbus_read_byte_data(client, 0x80);
+       if (ret_val < 0)
+               goto fail;
+       if (on_off)
+               ret_val = ret_val | 0x01;
+       else
+               ret_val = ret_val & 0xFE;
+       ret_val = i2c_smbus_write_byte_data(client, 0x80, ret_val);
+fail:
+       mutex_unlock(&data->mutex);
+       return ret_val;
+}
+
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
+       als_sensing_range_show, als_sensing_range_store);
+static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux0_input_data_show, NULL);
+
+static struct attribute *mid_att_als[] = {
+       &dev_attr_lux0_sensor_range.attr,
+       &dev_attr_lux0_input.attr,
+       NULL
+};
+
+static struct attribute_group m_als_gr = {
+       .name = "apds9802als",
+       .attrs = mid_att_als
+};
+
+static int als_set_default_config(struct i2c_client *client)
+{
+       int ret_val;
+       /* Write the command and then switch on */
+       ret_val = i2c_smbus_write_byte_data(client, 0x80, 0x01);
+       if (ret_val < 0) {
+               dev_err(&client->dev, "failed default switch on write\n");
+               return ret_val;
+       }
+       /* detection range: 1~64K Lux, maunal measurement */
+       ret_val = i2c_smbus_write_byte_data(client, 0x81, 0x08);
+       if (ret_val < 0)
+               dev_err(&client->dev, "failed default LUX on write\n");
+
+       /*  We always get 0 for the 1st measurement after system power on,
+        *  so make sure it is finished before user asks for data.
+        */
+       als_wait_for_data_ready(&client->dev);
+
+       return ret_val;
+}
+
+static int apds9802als_probe(struct i2c_client *client,
+                            const struct i2c_device_id *id)
+{
+       int res;
+       struct als_data *data;
+
+       data = kzalloc(sizeof(struct als_data), GFP_KERNEL);
+       if (data == NULL) {
+               dev_err(&client->dev, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+       i2c_set_clientdata(client, data);
+       res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
+       if (res) {
+               dev_err(&client->dev, "device create file failed\n");
+               goto als_error1;
+       }
+       dev_info(&client->dev, "ALS chip found\n");
+       als_set_default_config(client);
+       mutex_init(&data->mutex);
+
+       pm_runtime_enable(&client->dev);
+       pm_runtime_get(&client->dev);
+       pm_runtime_put(&client->dev);
+
+       return res;
+als_error1:
+       i2c_set_clientdata(client, NULL);
+       kfree(data);
+       return res;
+}
+
+static int apds9802als_remove(struct i2c_client *client)
+{
+       struct als_data *data = i2c_get_clientdata(client);
+
+       als_set_power_state(client, false);
+       sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+       kfree(data);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int apds9802als_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       als_set_power_state(client, false);
+       return 0;
+}
+
+static int apds9802als_resume(struct i2c_client *client)
+{
+       als_set_default_config(client);
+
+       pm_runtime_get(&client->dev);
+       pm_runtime_put(&client->dev);
+       return 0;
+}
+
+static int apds9802als_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       als_set_power_state(client, false);
+       return 0;
+}
+
+static int apds9802als_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+
+       als_set_power_state(client, true);
+       return 0;
+}
+
+static const struct dev_pm_ops apds9802als_pm_ops = {
+       .runtime_suspend = apds9802als_runtime_suspend,
+       .runtime_resume = apds9802als_runtime_resume,
+};
+
+#define APDS9802ALS_PM_OPS (&apds9802als_pm_ops)
+
+#else  /* CONFIG_PM */
+#define apds9802als_suspend NULL
+#define apds9802als_resume NULL
+#define APDS9802ALS_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static struct i2c_device_id apds9802als_id[] = {
+       { DRIVER_NAME, 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, apds9802als_id);
+
+static struct i2c_driver apds9802als_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .pm = APDS9802ALS_PM_OPS,
+       },
+       .probe = apds9802als_probe,
+       .remove = apds9802als_remove,
+       .suspend = apds9802als_suspend,
+       .resume = apds9802als_resume,
+       .id_table = apds9802als_id,
+};
+
+static int __init sensor_apds9802als_init(void)
+{
+       return i2c_add_driver(&apds9802als_driver);
+}
+
+static void  __exit sensor_apds9802als_exit(void)
+{
+       i2c_del_driver(&apds9802als_driver);
+}
+module_init(sensor_apds9802als_init);
+module_exit(sensor_apds9802als_exit);
+
+MODULE_AUTHOR("Anantha Narayanan <Anantha.Narayanan@intel.com");
+MODULE_DESCRIPTION("Avago apds9802als ALS Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
new file mode 100644 (file)
index 0000000..200311f
--- /dev/null
@@ -0,0 +1,1295 @@
+/*
+ * This file is part of the APDS990x sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+#include <linux/i2c/apds990x.h>
+
+/* Register map */
+#define APDS990X_ENABLE         0x00 /* Enable of states and interrupts */
+#define APDS990X_ATIME  0x01 /* ALS ADC time  */
+#define APDS990X_PTIME  0x02 /* Proximity ADC time  */
+#define APDS990X_WTIME  0x03 /* Wait time  */
+#define APDS990X_AILTL  0x04 /* ALS interrupt low threshold low byte */
+#define APDS990X_AILTH  0x05 /* ALS interrupt low threshold hi byte */
+#define APDS990X_AIHTL  0x06 /* ALS interrupt hi threshold low byte */
+#define APDS990X_AIHTH  0x07 /* ALS interrupt hi threshold hi byte */
+#define APDS990X_PILTL  0x08 /* Proximity interrupt low threshold low byte */
+#define APDS990X_PILTH  0x09 /* Proximity interrupt low threshold hi byte */
+#define APDS990X_PIHTL  0x0a /* Proximity interrupt hi threshold low byte */
+#define APDS990X_PIHTH  0x0b /* Proximity interrupt hi threshold hi byte */
+#define APDS990X_PERS   0x0c /* Interrupt persistence filters */
+#define APDS990X_CONFIG         0x0d /* Configuration */
+#define APDS990X_PPCOUNT 0x0e /* Proximity pulse count */
+#define APDS990X_CONTROL 0x0f /* Gain control register */
+#define APDS990X_REV    0x11 /* Revision Number */
+#define APDS990X_ID     0x12 /* Device ID */
+#define APDS990X_STATUS         0x13 /* Device status */
+#define APDS990X_CDATAL         0x14 /* Clear ADC low data register */
+#define APDS990X_CDATAH         0x15 /* Clear ADC high data register */
+#define APDS990X_IRDATAL 0x16 /* IR ADC low data register */
+#define APDS990X_IRDATAH 0x17 /* IR ADC high data register */
+#define APDS990X_PDATAL         0x18 /* Proximity ADC low data register */
+#define APDS990X_PDATAH         0x19 /* Proximity ADC high data register */
+
+/* Control */
+#define APDS990X_MAX_AGAIN     3
+
+/* Enable register */
+#define APDS990X_EN_PIEN       (0x1 << 5)
+#define APDS990X_EN_AIEN       (0x1 << 4)
+#define APDS990X_EN_WEN                (0x1 << 3)
+#define APDS990X_EN_PEN                (0x1 << 2)
+#define APDS990X_EN_AEN                (0x1 << 1)
+#define APDS990X_EN_PON                (0x1 << 0)
+#define APDS990X_EN_DISABLE_ALL 0
+
+/* Status register */
+#define APDS990X_ST_PINT       (0x1 << 5)
+#define APDS990X_ST_AINT       (0x1 << 4)
+
+/* I2C access types */
+#define APDS990x_CMD_TYPE_MASK (0x03 << 5)
+#define APDS990x_CMD_TYPE_RB   (0x00 << 5) /* Repeated byte */
+#define APDS990x_CMD_TYPE_INC  (0x01 << 5) /* Auto increment */
+#define APDS990x_CMD_TYPE_SPE  (0x03 << 5) /* Special function */
+
+#define APDS990x_ADDR_SHIFT    0
+#define APDS990x_CMD           0x80
+
+/* Interrupt ack commands */
+#define APDS990X_INT_ACK_ALS   0x6
+#define APDS990X_INT_ACK_PS    0x5
+#define APDS990X_INT_ACK_BOTH  0x7
+
+/* ptime */
+#define APDS990X_PTIME_DEFAULT 0xff /* Recommended conversion time 2.7ms*/
+
+/* wtime */
+#define APDS990X_WTIME_DEFAULT 0xee /* ~50ms wait time */
+
+#define APDS990X_TIME_TO_ADC   1024 /* One timetick as ADC count value */
+
+/* Persistence */
+#define APDS990X_APERS_SHIFT   0
+#define APDS990X_PPERS_SHIFT   4
+
+/* Supported ID:s */
+#define APDS990X_ID_0          0x0
+#define APDS990X_ID_4          0x4
+#define APDS990X_ID_29         0x29
+
+/* pgain and pdiode settings */
+#define APDS_PGAIN_1X         0x0
+#define APDS_PDIODE_IR        0x2
+
+#define APDS990X_LUX_OUTPUT_SCALE 10
+
+/* Reverse chip factors for threshold calculation */
+struct reverse_factors {
+       u32 afactor;
+       int cf1;
+       int irf1;
+       int cf2;
+       int irf2;
+};
+
+struct apds990x_chip {
+       struct apds990x_platform_data   *pdata;
+       struct i2c_client               *client;
+       struct mutex                    mutex; /* avoid parallel access */
+       struct regulator_bulk_data      regs[2];
+       wait_queue_head_t               wait;
+
+       int     prox_en;
+       bool    prox_continuous_mode;
+       bool    lux_wait_fresh_res;
+
+       /* Chip parameters */
+       struct  apds990x_chip_factors   cf;
+       struct  reverse_factors         rcf;
+       u16     atime;          /* als integration time */
+       u16     arate;          /* als reporting rate */
+       u16     a_max_result;   /* Max possible ADC value with current atime */
+       u8      again_meas;     /* Gain used in last measurement */
+       u8      again_next;     /* Next calculated gain */
+       u8      pgain;
+       u8      pdiode;
+       u8      pdrive;
+       u8      lux_persistence;
+       u8      prox_persistence;
+
+       u32     lux_raw;
+       u32     lux;
+       u16     lux_clear;
+       u16     lux_ir;
+       u16     lux_calib;
+       u32     lux_thres_hi;
+       u32     lux_thres_lo;
+
+       u32     prox_thres;
+       u16     prox_data;
+       u16     prox_calib;
+
+       char    chipname[10];
+       u8      revision;
+};
+
+#define APDS_CALIB_SCALER              8192
+#define APDS_LUX_NEUTRAL_CALIB_VALUE   (1 * APDS_CALIB_SCALER)
+#define APDS_PROX_NEUTRAL_CALIB_VALUE  (1 * APDS_CALIB_SCALER)
+
+#define APDS_PROX_DEF_THRES            600
+#define APDS_PROX_HYSTERESIS           50
+#define APDS_LUX_DEF_THRES_HI          101
+#define APDS_LUX_DEF_THRES_LO          100
+#define APDS_DEFAULT_PROX_PERS         1
+
+#define APDS_TIMEOUT                   2000
+#define APDS_STARTUP_DELAY             25000 /* us */
+#define APDS_RANGE                     65535
+#define APDS_PROX_RANGE                        1023
+#define APDS_LUX_GAIN_LO_LIMIT         100
+#define APDS_LUX_GAIN_LO_LIMIT_STRICT  25
+
+#define TIMESTEP                       87 /* 2.7ms is about 87 / 32 */
+#define TIME_STEP_SCALER               32
+
+#define APDS_LUX_AVERAGING_TIME                50 /* tolerates 50/60Hz ripple */
+#define APDS_LUX_DEFAULT_RATE          200
+
+static const u8 again[]        = {1, 8, 16, 120}; /* ALS gain steps */
+static const u8 ir_currents[]  = {100, 50, 25, 12}; /* IRled currents in mA */
+
+/* Following two tables must match i.e 10Hz rate means 1 as persistence value */
+static const u16 arates_hz[] = {10, 5, 2, 1};
+static const u8 apersis[] = {1, 2, 4, 5};
+
+/* Regulators */
+static const char reg_vcc[] = "Vdd";
+static const char reg_vled[] = "Vled";
+
+static int apds990x_read_byte(struct apds990x_chip *chip, u8 reg, u8 *data)
+{
+       struct i2c_client *client = chip->client;
+       s32 ret;
+
+       reg &= ~APDS990x_CMD_TYPE_MASK;
+       reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB;
+
+       ret = i2c_smbus_read_byte_data(client, reg);
+       *data = ret;
+       return (int)ret;
+}
+
+static int apds990x_read_word(struct apds990x_chip *chip, u8 reg, u16 *data)
+{
+       struct i2c_client *client = chip->client;
+       s32 ret;
+
+       reg &= ~APDS990x_CMD_TYPE_MASK;
+       reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC;
+
+       ret = i2c_smbus_read_word_data(client, reg);
+       *data = ret;
+       return (int)ret;
+}
+
+static int apds990x_write_byte(struct apds990x_chip *chip, u8 reg, u8 data)
+{
+       struct i2c_client *client = chip->client;
+       s32 ret;
+
+       reg &= ~APDS990x_CMD_TYPE_MASK;
+       reg |= APDS990x_CMD | APDS990x_CMD_TYPE_RB;
+
+       ret = i2c_smbus_write_byte_data(client, reg, data);
+       return (int)ret;
+}
+
+static int apds990x_write_word(struct apds990x_chip *chip, u8 reg, u16 data)
+{
+       struct i2c_client *client = chip->client;
+       s32 ret;
+
+       reg &= ~APDS990x_CMD_TYPE_MASK;
+       reg |= APDS990x_CMD | APDS990x_CMD_TYPE_INC;
+
+       ret = i2c_smbus_write_word_data(client, reg, data);
+       return (int)ret;
+}
+
+static int apds990x_mode_on(struct apds990x_chip *chip)
+{
+       /* ALS is mandatory, proximity optional */
+       u8 reg = APDS990X_EN_AIEN | APDS990X_EN_PON | APDS990X_EN_AEN |
+               APDS990X_EN_WEN;
+
+       if (chip->prox_en)
+               reg |= APDS990X_EN_PIEN | APDS990X_EN_PEN;
+
+       return apds990x_write_byte(chip, APDS990X_ENABLE, reg);
+}
+
+static u16 apds990x_lux_to_threshold(struct apds990x_chip *chip, u32 lux)
+{
+       u32 thres;
+       u32 cpl;
+       u32 ir;
+
+       if (lux == 0)
+               return 0;
+       else if (lux == APDS_RANGE)
+               return APDS_RANGE;
+
+       /*
+        * Reported LUX value is a combination of the IR and CLEAR channel
+        * values. However, interrupt threshold is only for clear channel.
+        * This function approximates needed HW threshold value for a given
+        * LUX value in the current lightning type.
+        * IR level compared to visible light varies heavily depending on the
+        * source of the light
+        *
+        * Calculate threshold value for the next measurement period.
+        * Math: threshold = lux * cpl where
+        * cpl = atime * again / (glass_attenuation * device_factor)
+        * (count-per-lux)
+        *
+        * First remove calibration. Division by four is to avoid overflow
+        */
+       lux = lux * (APDS_CALIB_SCALER / 4) / (chip->lux_calib / 4);
+
+       /* Multiplication by 64 is to increase accuracy */
+       cpl = ((u32)chip->atime * (u32)again[chip->again_next] *
+               APDS_PARAM_SCALE * 64) / (chip->cf.ga * chip->cf.df);
+
+       thres = lux * cpl / 64;
+       /*
+        * Convert IR light from the latest result to match with
+        * new gain step. This helps to adapt with the current
+        * source of light.
+        */
+       ir = (u32)chip->lux_ir * (u32)again[chip->again_next] /
+               (u32)again[chip->again_meas];
+
+       /*
+        * Compensate count with IR light impact
+        * IAC1 > IAC2 (see apds990x_get_lux for formulas)
+        */
+       if (chip->lux_clear * APDS_PARAM_SCALE >=
+               chip->rcf.afactor * chip->lux_ir)
+               thres = (chip->rcf.cf1 * thres + chip->rcf.irf1 * ir) /
+                       APDS_PARAM_SCALE;
+       else
+               thres = (chip->rcf.cf2 * thres + chip->rcf.irf2 * ir) /
+                       APDS_PARAM_SCALE;
+
+       if (thres >= chip->a_max_result)
+               thres = chip->a_max_result - 1;
+       return thres;
+}
+
+static inline int apds990x_set_atime(struct apds990x_chip *chip, u32 time_ms)
+{
+       u8 reg_value;
+
+       chip->atime = time_ms;
+       /* Formula is specified in the data sheet */
+       reg_value = 256 - ((time_ms * TIME_STEP_SCALER) / TIMESTEP);
+       /* Calculate max ADC value for given integration time */
+       chip->a_max_result = (u16)(256 - reg_value) * APDS990X_TIME_TO_ADC;
+       return apds990x_write_byte(chip, APDS990X_ATIME, reg_value);
+}
+
+/* Called always with mutex locked */
+static int apds990x_refresh_pthres(struct apds990x_chip *chip, int data)
+{
+       int ret, lo, hi;
+
+       /* If the chip is not in use, don't try to access it */
+       if (pm_runtime_suspended(&chip->client->dev))
+               return 0;
+
+       if (data < chip->prox_thres) {
+               lo = 0;
+               hi = chip->prox_thres;
+       } else {
+               lo = chip->prox_thres - APDS_PROX_HYSTERESIS;
+               if (chip->prox_continuous_mode)
+                       hi = chip->prox_thres;
+               else
+                       hi = APDS_RANGE;
+       }
+
+       ret = apds990x_write_word(chip, APDS990X_PILTL, lo);
+       ret |= apds990x_write_word(chip, APDS990X_PIHTL, hi);
+       return ret;
+}
+
+/* Called always with mutex locked */
+static int apds990x_refresh_athres(struct apds990x_chip *chip)
+{
+       int ret;
+       /* If the chip is not in use, don't try to access it */
+       if (pm_runtime_suspended(&chip->client->dev))
+               return 0;
+
+       ret = apds990x_write_word(chip, APDS990X_AILTL,
+                       apds990x_lux_to_threshold(chip, chip->lux_thres_lo));
+       ret |= apds990x_write_word(chip, APDS990X_AIHTL,
+                       apds990x_lux_to_threshold(chip, chip->lux_thres_hi));
+
+       return ret;
+}
+
+/* Called always with mutex locked */
+static void apds990x_force_a_refresh(struct apds990x_chip *chip)
+{
+       /* This will force ALS interrupt after the next measurement. */
+       apds990x_write_word(chip, APDS990X_AILTL, APDS_LUX_DEF_THRES_LO);
+       apds990x_write_word(chip, APDS990X_AIHTL, APDS_LUX_DEF_THRES_HI);
+}
+
+/* Called always with mutex locked */
+static void apds990x_force_p_refresh(struct apds990x_chip *chip)
+{
+       /* This will force proximity interrupt after the next measurement. */
+       apds990x_write_word(chip, APDS990X_PILTL, APDS_PROX_DEF_THRES - 1);
+       apds990x_write_word(chip, APDS990X_PIHTL, APDS_PROX_DEF_THRES);
+}
+
+/* Called always with mutex locked */
+static int apds990x_calc_again(struct apds990x_chip *chip)
+{
+       int curr_again = chip->again_meas;
+       int next_again = chip->again_meas;
+       int ret = 0;
+
+       /* Calculate suitable als gain */
+       if (chip->lux_clear == chip->a_max_result)
+               next_again -= 2; /* ALS saturated. Decrease gain by 2 steps */
+       else if (chip->lux_clear > chip->a_max_result / 2)
+               next_again--;
+       else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT)
+               next_again += 2; /* Too dark. Increase gain by 2 steps */
+       else if (chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT)
+               next_again++;
+
+       /* Limit gain to available range */
+       if (next_again < 0)
+               next_again = 0;
+       else if (next_again > APDS990X_MAX_AGAIN)
+               next_again = APDS990X_MAX_AGAIN;
+
+       /* Let's check can we trust the measured result */
+       if (chip->lux_clear == chip->a_max_result)
+               /* Result can be totally garbage due to saturation */
+               ret = -ERANGE;
+       else if (next_again != curr_again &&
+               chip->lux_clear < APDS_LUX_GAIN_LO_LIMIT_STRICT)
+               /*
+                * Gain is changed and measurement result is very small.
+                * Result can be totally garbage due to underflow
+                */
+               ret = -ERANGE;
+
+       chip->again_next = next_again;
+       apds990x_write_byte(chip, APDS990X_CONTROL,
+                       (chip->pdrive << 6) |
+                       (chip->pdiode << 4) |
+                       (chip->pgain << 2) |
+                       (chip->again_next << 0));
+
+       /*
+        * Error means bad result -> re-measurement is needed. The forced
+        * refresh uses fastest possible persistence setting to get result
+        * as soon as possible.
+        */
+       if (ret < 0)
+               apds990x_force_a_refresh(chip);
+       else
+               apds990x_refresh_athres(chip);
+
+       return ret;
+}
+
+/* Called always with mutex locked */
+static int apds990x_get_lux(struct apds990x_chip *chip, int clear, int ir)
+{
+       int iac, iac1, iac2; /* IR adjusted counts */
+       u32 lpc; /* Lux per count */
+
+       /* Formulas:
+        * iac1 = CF1 * CLEAR_CH - IRF1 * IR_CH
+        * iac2 = CF2 * CLEAR_CH - IRF2 * IR_CH
+        */
+       iac1 = (chip->cf.cf1 * clear - chip->cf.irf1 * ir) / APDS_PARAM_SCALE;
+       iac2 = (chip->cf.cf2 * clear - chip->cf.irf2 * ir) / APDS_PARAM_SCALE;
+
+       iac = max(iac1, iac2);
+       iac = max(iac, 0);
+
+       lpc = APDS990X_LUX_OUTPUT_SCALE * (chip->cf.df * chip->cf.ga) /
+               (u32)(again[chip->again_meas] * (u32)chip->atime);
+
+       return (iac * lpc) / APDS_PARAM_SCALE;
+}
+
+static int apds990x_ack_int(struct apds990x_chip *chip, u8 mode)
+{
+       struct i2c_client *client = chip->client;
+       s32 ret;
+       u8 reg = APDS990x_CMD | APDS990x_CMD_TYPE_SPE;
+
+       switch (mode & (APDS990X_ST_AINT | APDS990X_ST_PINT)) {
+       case APDS990X_ST_AINT:
+               reg |= APDS990X_INT_ACK_ALS;
+               break;
+       case APDS990X_ST_PINT:
+               reg |= APDS990X_INT_ACK_PS;
+               break;
+       default:
+               reg |= APDS990X_INT_ACK_BOTH;
+               break;
+       }
+
+       ret = i2c_smbus_read_byte_data(client, reg);
+       return (int)ret;
+}
+
+static irqreturn_t apds990x_irq(int irq, void *data)
+{
+       struct apds990x_chip *chip = data;
+       u8 status;
+
+       apds990x_read_byte(chip, APDS990X_STATUS, &status);
+       apds990x_ack_int(chip, status);
+
+       mutex_lock(&chip->mutex);
+       if (!pm_runtime_suspended(&chip->client->dev)) {
+               if (status & APDS990X_ST_AINT) {
+                       apds990x_read_word(chip, APDS990X_CDATAL,
+                                       &chip->lux_clear);
+                       apds990x_read_word(chip, APDS990X_IRDATAL,
+                                       &chip->lux_ir);
+                       /* Store used gain for calculations */
+                       chip->again_meas = chip->again_next;
+
+                       chip->lux_raw = apds990x_get_lux(chip,
+                                                       chip->lux_clear,
+                                                       chip->lux_ir);
+
+                       if (apds990x_calc_again(chip) == 0) {
+                               /* Result is valid */
+                               chip->lux = chip->lux_raw;
+                               chip->lux_wait_fresh_res = false;
+                               wake_up(&chip->wait);
+                               sysfs_notify(&chip->client->dev.kobj,
+                                       NULL, "lux0_input");
+                       }
+               }
+
+               if ((status & APDS990X_ST_PINT) && chip->prox_en) {
+                       u16 clr_ch;
+
+                       apds990x_read_word(chip, APDS990X_CDATAL, &clr_ch);
+                       /*
+                        * If ALS channel is saturated at min gain,
+                        * proximity gives false posivite values.
+                        * Just ignore them.
+                        */
+                       if (chip->again_meas == 0 &&
+                               clr_ch == chip->a_max_result)
+                               chip->prox_data = 0;
+                       else
+                               apds990x_read_word(chip,
+                                               APDS990X_PDATAL,
+                                               &chip->prox_data);
+
+                       apds990x_refresh_pthres(chip, chip->prox_data);
+                       if (chip->prox_data < chip->prox_thres)
+                               chip->prox_data = 0;
+                       else if (!chip->prox_continuous_mode)
+                               chip->prox_data = APDS_PROX_RANGE;
+                       sysfs_notify(&chip->client->dev.kobj,
+                               NULL, "prox0_raw");
+               }
+       }
+       mutex_unlock(&chip->mutex);
+       return IRQ_HANDLED;
+}
+
+static int apds990x_configure(struct apds990x_chip *chip)
+{
+       /* It is recommended to use disabled mode during these operations */
+       apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL);
+
+       /* conversion and wait times for different state machince states */
+       apds990x_write_byte(chip, APDS990X_PTIME, APDS990X_PTIME_DEFAULT);
+       apds990x_write_byte(chip, APDS990X_WTIME, APDS990X_WTIME_DEFAULT);
+       apds990x_set_atime(chip, APDS_LUX_AVERAGING_TIME);
+
+       apds990x_write_byte(chip, APDS990X_CONFIG, 0);
+
+       /* Persistence levels */
+       apds990x_write_byte(chip, APDS990X_PERS,
+                       (chip->lux_persistence << APDS990X_APERS_SHIFT) |
+                       (chip->prox_persistence << APDS990X_PPERS_SHIFT));
+
+       apds990x_write_byte(chip, APDS990X_PPCOUNT, chip->pdata->ppcount);
+
+       /* Start with relatively small gain */
+       chip->again_meas = 1;
+       chip->again_next = 1;
+       apds990x_write_byte(chip, APDS990X_CONTROL,
+                       (chip->pdrive << 6) |
+                       (chip->pdiode << 4) |
+                       (chip->pgain << 2) |
+                       (chip->again_next << 0));
+       return 0;
+}
+
+static int apds990x_detect(struct apds990x_chip *chip)
+{
+       struct i2c_client *client = chip->client;
+       int ret;
+       u8 id;
+
+       ret = apds990x_read_byte(chip, APDS990X_ID, &id);
+       if (ret < 0) {
+               dev_err(&client->dev, "ID read failed\n");
+               return ret;
+       }
+
+       ret = apds990x_read_byte(chip, APDS990X_REV, &chip->revision);
+       if (ret < 0) {
+               dev_err(&client->dev, "REV read failed\n");
+               return ret;
+       }
+
+       switch (id) {
+       case APDS990X_ID_0:
+       case APDS990X_ID_4:
+       case APDS990X_ID_29:
+               snprintf(chip->chipname, sizeof(chip->chipname), "APDS-990x");
+               break;
+       default:
+               ret = -ENODEV;
+               break;
+       }
+       return ret;
+}
+
+static int apds990x_chip_on(struct apds990x_chip *chip)
+{
+       int err  = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
+                                       chip->regs);
+       if (err < 0)
+               return err;
+
+       usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY);
+
+       /* Refresh all configs in case of regulators were off */
+       chip->prox_data = 0;
+       apds990x_configure(chip);
+       apds990x_mode_on(chip);
+       return 0;
+}
+
+static int apds990x_chip_off(struct apds990x_chip *chip)
+{
+       apds990x_write_byte(chip, APDS990X_ENABLE, APDS990X_EN_DISABLE_ALL);
+       regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+       return 0;
+}
+
+static ssize_t apds990x_lux_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip = dev_get_drvdata(dev);
+       ssize_t ret;
+       u32 result;
+       long timeout;
+
+       if (pm_runtime_suspended(dev))
+               return -EIO;
+
+       timeout = wait_event_interruptible_timeout(chip->wait,
+                                               !chip->lux_wait_fresh_res,
+                                               msecs_to_jiffies(APDS_TIMEOUT));
+       if (!timeout)
+               return -EIO;
+
+       mutex_lock(&chip->mutex);
+       result = (chip->lux * chip->lux_calib) / APDS_CALIB_SCALER;
+       if (result > (APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE))
+               result = APDS_RANGE * APDS990X_LUX_OUTPUT_SCALE;
+
+       ret = sprintf(buf, "%d.%d\n",
+               result / APDS990X_LUX_OUTPUT_SCALE,
+               result % APDS990X_LUX_OUTPUT_SCALE);
+       mutex_unlock(&chip->mutex);
+       return ret;
+}
+
+static DEVICE_ATTR(lux0_input, S_IRUGO, apds990x_lux_show, NULL);
+
+static ssize_t apds990x_lux_range_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", APDS_RANGE);
+}
+
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, apds990x_lux_range_show, NULL);
+
+static ssize_t apds990x_lux_calib_format_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", APDS_CALIB_SCALER);
+}
+
+static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO,
+               apds990x_lux_calib_format_show, NULL);
+
+static ssize_t apds990x_lux_calib_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%u\n", chip->lux_calib);
+}
+
+static ssize_t apds990x_lux_calib_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip = dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       if (chip->lux_calib > APDS_RANGE)
+               return -EINVAL;
+
+       chip->lux_calib = value;
+
+       return len;
+}
+
+static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, apds990x_lux_calib_show,
+               apds990x_lux_calib_store);
+
+static ssize_t apds990x_rate_avail(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int i;
+       int pos = 0;
+       for (i = 0; i < ARRAY_SIZE(arates_hz); i++)
+               pos += sprintf(buf + pos, "%d ", arates_hz[i]);
+       sprintf(buf + pos - 1, "\n");
+       return pos;
+}
+
+static ssize_t apds990x_rate_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->arate);
+}
+
+static int apds990x_set_arate(struct apds990x_chip *chip, int rate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(arates_hz); i++)
+               if (rate >= arates_hz[i])
+                       break;
+
+       if (i == ARRAY_SIZE(arates_hz))
+               return -EINVAL;
+
+       /* Pick up corresponding persistence value */
+       chip->lux_persistence = apersis[i];
+       chip->arate = arates_hz[i];
+
+       /* If the chip is not in use, don't try to access it */
+       if (pm_runtime_suspended(&chip->client->dev))
+               return 0;
+
+       /* Persistence levels */
+       return apds990x_write_byte(chip, APDS990X_PERS,
+                       (chip->lux_persistence << APDS990X_APERS_SHIFT) |
+                       (chip->prox_persistence << APDS990X_PPERS_SHIFT));
+}
+
+static ssize_t apds990x_rate_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+       int ret;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       ret = apds990x_set_arate(chip, value);
+       mutex_unlock(&chip->mutex);
+
+       if (ret < 0)
+               return ret;
+       return len;
+}
+
+static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, apds990x_rate_avail, NULL);
+
+static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, apds990x_rate_show,
+                                                apds990x_rate_store);
+
+static ssize_t apds990x_prox_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       ssize_t ret;
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       if (pm_runtime_suspended(dev) || !chip->prox_en)
+               return -EIO;
+
+       mutex_lock(&chip->mutex);
+       ret = sprintf(buf, "%d\n", chip->prox_data);
+       mutex_unlock(&chip->mutex);
+       return ret;
+}
+
+static DEVICE_ATTR(prox0_raw, S_IRUGO, apds990x_prox_show, NULL);
+
+static ssize_t apds990x_prox_range_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", APDS_PROX_RANGE);
+}
+
+static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, apds990x_prox_range_show, NULL);
+
+static ssize_t apds990x_prox_enable_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->prox_en);
+}
+
+static ssize_t apds990x_prox_enable_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+
+       if (!chip->prox_en)
+               chip->prox_data = 0;
+
+       if (value)
+               chip->prox_en++;
+       else if (chip->prox_en > 0)
+               chip->prox_en--;
+
+       if (!pm_runtime_suspended(dev))
+               apds990x_mode_on(chip);
+       mutex_unlock(&chip->mutex);
+       return len;
+}
+
+static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, apds990x_prox_enable_show,
+                                                  apds990x_prox_enable_store);
+
+static const char reporting_modes[][9] = {"trigger", "periodic"};
+
+static ssize_t apds990x_prox_reporting_mode_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%s\n",
+               reporting_modes[!!chip->prox_continuous_mode]);
+}
+
+static ssize_t apds990x_prox_reporting_mode_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+
+       if (sysfs_streq(buf, reporting_modes[0]))
+               chip->prox_continuous_mode = 0;
+       else if (sysfs_streq(buf, reporting_modes[1]))
+               chip->prox_continuous_mode = 1;
+       else
+               return -EINVAL;
+       return len;
+}
+
+static DEVICE_ATTR(prox0_reporting_mode, S_IRUGO | S_IWUSR,
+               apds990x_prox_reporting_mode_show,
+               apds990x_prox_reporting_mode_store);
+
+static ssize_t apds990x_prox_reporting_avail_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s %s\n", reporting_modes[0], reporting_modes[1]);
+}
+
+static DEVICE_ATTR(prox0_reporting_mode_avail, S_IRUGO | S_IWUSR,
+               apds990x_prox_reporting_avail_show, NULL);
+
+
+static ssize_t apds990x_lux_thresh_above_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->lux_thres_hi);
+}
+
+static ssize_t apds990x_lux_thresh_below_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->lux_thres_lo);
+}
+
+static ssize_t apds990x_set_lux_thresh(struct apds990x_chip *chip, u32 *target,
+                               const char *buf)
+{
+       int ret = 0;
+       unsigned long thresh;
+
+       if (strict_strtoul(buf, 0, &thresh))
+               return -EINVAL;
+
+       if (thresh > APDS_RANGE)
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       *target = thresh;
+       /*
+        * Don't update values in HW if we are still waiting for
+        * first interrupt to come after device handle open call.
+        */
+       if (!chip->lux_wait_fresh_res)
+               apds990x_refresh_athres(chip);
+       mutex_unlock(&chip->mutex);
+       return ret;
+
+}
+
+static ssize_t apds990x_lux_thresh_above_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_hi, buf);
+       if (ret < 0)
+               return ret;
+       return len;
+}
+
+static ssize_t apds990x_lux_thresh_below_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       int ret = apds990x_set_lux_thresh(chip, &chip->lux_thres_lo, buf);
+       if (ret < 0)
+               return ret;
+       return len;
+}
+
+static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR,
+               apds990x_lux_thresh_above_show,
+               apds990x_lux_thresh_above_store);
+
+static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR,
+               apds990x_lux_thresh_below_show,
+               apds990x_lux_thresh_below_store);
+
+static ssize_t apds990x_prox_threshold_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->prox_thres);
+}
+
+static ssize_t apds990x_prox_threshold_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       if ((value > APDS_RANGE) || (value == 0) ||
+               (value < APDS_PROX_HYSTERESIS))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       chip->prox_thres = value;
+
+       apds990x_force_p_refresh(chip);
+       mutex_unlock(&chip->mutex);
+       return len;
+}
+
+static DEVICE_ATTR(prox0_thresh_above_value, S_IRUGO | S_IWUSR,
+               apds990x_prox_threshold_show,
+               apds990x_prox_threshold_store);
+
+static ssize_t apds990x_power_state_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", !pm_runtime_suspended(dev));
+       return 0;
+}
+
+static ssize_t apds990x_power_state_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+       if (value) {
+               pm_runtime_get_sync(dev);
+               mutex_lock(&chip->mutex);
+               chip->lux_wait_fresh_res = true;
+               apds990x_force_a_refresh(chip);
+               apds990x_force_p_refresh(chip);
+               mutex_unlock(&chip->mutex);
+       } else {
+               if (!pm_runtime_suspended(dev))
+                       pm_runtime_put(dev);
+       }
+       return len;
+}
+
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR,
+               apds990x_power_state_show,
+               apds990x_power_state_store);
+
+static ssize_t apds990x_chip_id_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct apds990x_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%s %d\n", chip->chipname, chip->revision);
+}
+
+static DEVICE_ATTR(chip_id, S_IRUGO, apds990x_chip_id_show, NULL);
+
+static struct attribute *sysfs_attrs_ctrl[] = {
+       &dev_attr_lux0_calibscale.attr,
+       &dev_attr_lux0_calibscale_default.attr,
+       &dev_attr_lux0_input.attr,
+       &dev_attr_lux0_sensor_range.attr,
+       &dev_attr_lux0_rate.attr,
+       &dev_attr_lux0_rate_avail.attr,
+       &dev_attr_lux0_thresh_above_value.attr,
+       &dev_attr_lux0_thresh_below_value.attr,
+       &dev_attr_prox0_raw_en.attr,
+       &dev_attr_prox0_raw.attr,
+       &dev_attr_prox0_sensor_range.attr,
+       &dev_attr_prox0_thresh_above_value.attr,
+       &dev_attr_prox0_reporting_mode.attr,
+       &dev_attr_prox0_reporting_mode_avail.attr,
+       &dev_attr_chip_id.attr,
+       &dev_attr_power_state.attr,
+       NULL
+};
+
+static struct attribute_group apds990x_attribute_group[] = {
+       {.attrs = sysfs_attrs_ctrl },
+};
+
+static int __devinit apds990x_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct apds990x_chip *chip;
+       int err;
+
+       chip = kzalloc(sizeof *chip, GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, chip);
+       chip->client  = client;
+
+       init_waitqueue_head(&chip->wait);
+       mutex_init(&chip->mutex);
+       chip->pdata     = client->dev.platform_data;
+
+       if (chip->pdata == NULL) {
+               dev_err(&client->dev, "platform data is mandatory\n");
+               err = -EINVAL;
+               goto fail1;
+       }
+
+       if (chip->pdata->cf.ga == 0) {
+               /* set uncovered sensor default parameters */
+               chip->cf.ga = 1966; /* 0.48 * APDS_PARAM_SCALE */
+               chip->cf.cf1 = 4096; /* 1.00 * APDS_PARAM_SCALE */
+               chip->cf.irf1 = 9134; /* 2.23 * APDS_PARAM_SCALE */
+               chip->cf.cf2 = 2867; /* 0.70 * APDS_PARAM_SCALE */
+               chip->cf.irf2 = 5816; /* 1.42 * APDS_PARAM_SCALE */
+               chip->cf.df = 52;
+       } else {
+               chip->cf = chip->pdata->cf;
+       }
+
+       /* precalculate inverse chip factors for threshold control */
+       chip->rcf.afactor =
+               (chip->cf.irf1 - chip->cf.irf2) * APDS_PARAM_SCALE /
+               (chip->cf.cf1 - chip->cf.cf2);
+       chip->rcf.cf1 = APDS_PARAM_SCALE * APDS_PARAM_SCALE /
+               chip->cf.cf1;
+       chip->rcf.irf1 = chip->cf.irf1 * APDS_PARAM_SCALE /
+               chip->cf.cf1;
+       chip->rcf.cf2 = APDS_PARAM_SCALE * APDS_PARAM_SCALE /
+               chip->cf.cf2;
+       chip->rcf.irf2 = chip->cf.irf2 * APDS_PARAM_SCALE /
+               chip->cf.cf2;
+
+       /* Set something to start with */
+       chip->lux_thres_hi = APDS_LUX_DEF_THRES_HI;
+       chip->lux_thres_lo = APDS_LUX_DEF_THRES_LO;
+       chip->lux_calib = APDS_LUX_NEUTRAL_CALIB_VALUE;
+
+       chip->prox_thres = APDS_PROX_DEF_THRES;
+       chip->pdrive = chip->pdata->pdrive;
+       chip->pdiode = APDS_PDIODE_IR;
+       chip->pgain = APDS_PGAIN_1X;
+       chip->prox_calib = APDS_PROX_NEUTRAL_CALIB_VALUE;
+       chip->prox_persistence = APDS_DEFAULT_PROX_PERS;
+       chip->prox_continuous_mode = false;
+
+       chip->regs[0].supply = reg_vcc;
+       chip->regs[1].supply = reg_vled;
+
+       err = regulator_bulk_get(&client->dev,
+                                ARRAY_SIZE(chip->regs), chip->regs);
+       if (err < 0) {
+               dev_err(&client->dev, "Cannot get regulators\n");
+               goto fail1;
+       }
+
+       err = regulator_bulk_enable(ARRAY_SIZE(chip->regs), chip->regs);
+       if (err < 0) {
+               dev_err(&client->dev, "Cannot enable regulators\n");
+               goto fail2;
+       }
+
+       usleep_range(APDS_STARTUP_DELAY, 2 * APDS_STARTUP_DELAY);
+
+       err = apds990x_detect(chip);
+       if (err < 0) {
+               dev_err(&client->dev, "APDS990X not found\n");
+               goto fail3;
+       }
+
+       pm_runtime_set_active(&client->dev);
+
+       apds990x_configure(chip);
+       apds990x_set_arate(chip, APDS_LUX_DEFAULT_RATE);
+       apds990x_mode_on(chip);
+
+       pm_runtime_enable(&client->dev);
+
+       if (chip->pdata->setup_resources) {
+               err = chip->pdata->setup_resources();
+               if (err) {
+                       err = -EINVAL;
+                       goto fail3;
+               }
+       }
+
+       err = sysfs_create_group(&chip->client->dev.kobj,
+                               apds990x_attribute_group);
+       if (err < 0) {
+               dev_err(&chip->client->dev, "Sysfs registration failed\n");
+               goto fail4;
+       }
+
+       err = request_threaded_irq(client->irq, NULL,
+                               apds990x_irq,
+                               IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW |
+                               IRQF_ONESHOT,
+                               "apds990x", chip);
+       if (err) {
+               dev_err(&client->dev, "could not get IRQ %d\n",
+                       client->irq);
+               goto fail5;
+       }
+       return err;
+fail5:
+       sysfs_remove_group(&chip->client->dev.kobj,
+                       &apds990x_attribute_group[0]);
+fail4:
+       if (chip->pdata && chip->pdata->release_resources)
+               chip->pdata->release_resources();
+fail3:
+       regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+fail2:
+       regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+fail1:
+       kfree(chip);
+       return err;
+}
+
+static int __devexit apds990x_remove(struct i2c_client *client)
+{
+       struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+       free_irq(client->irq, chip);
+       sysfs_remove_group(&chip->client->dev.kobj,
+                       apds990x_attribute_group);
+
+       if (chip->pdata && chip->pdata->release_resources)
+               chip->pdata->release_resources();
+
+       if (!pm_runtime_suspended(&client->dev))
+               apds990x_chip_off(chip);
+
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+
+       regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+
+       kfree(chip);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int apds990x_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+       apds990x_chip_off(chip);
+       return 0;
+}
+
+static int apds990x_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+       /*
+        * If we were enabled at suspend time, it is expected
+        * everything works nice and smoothly. Chip_on is enough
+        */
+       apds990x_chip_on(chip);
+
+       return 0;
+}
+#else
+#define apds990x_suspend  NULL
+#define apds990x_resume          NULL
+#define apds990x_shutdown NULL
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int apds990x_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+       apds990x_chip_off(chip);
+       return 0;
+}
+
+static int apds990x_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct apds990x_chip *chip = i2c_get_clientdata(client);
+
+       apds990x_chip_on(chip);
+       return 0;
+}
+
+#endif
+
+static const struct i2c_device_id apds990x_id[] = {
+       {"apds990x", 0 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, apds990x_id);
+
+static const struct dev_pm_ops apds990x_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(apds990x_suspend, apds990x_resume)
+       SET_RUNTIME_PM_OPS(apds990x_runtime_suspend,
+                       apds990x_runtime_resume,
+                       NULL)
+};
+
+static struct i2c_driver apds990x_driver = {
+       .driver  = {
+               .name   = "apds990x",
+               .owner  = THIS_MODULE,
+               .pm     = &apds990x_pm_ops,
+       },
+       .probe    = apds990x_probe,
+       .remove   = __devexit_p(apds990x_remove),
+       .id_table = apds990x_id,
+};
+
+static int __init apds990x_init(void)
+{
+       return i2c_add_driver(&apds990x_driver);
+}
+
+static void __exit apds990x_exit(void)
+{
+       i2c_del_driver(&apds990x_driver);
+}
+
+MODULE_DESCRIPTION("APDS990X combined ALS and proximity sensor");
+MODULE_AUTHOR("Samu Onkalo, Nokia Corporation");
+MODULE_LICENSE("GPL v2");
+
+module_init(apds990x_init);
+module_exit(apds990x_exit);
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
new file mode 100644 (file)
index 0000000..cee632e
--- /dev/null
@@ -0,0 +1,1413 @@
+/*
+ * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/i2c/bh1770glc.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+
+#define BH1770_ALS_CONTROL     0x80 /* ALS operation mode control */
+#define BH1770_PS_CONTROL      0x81 /* PS operation mode control */
+#define BH1770_I_LED           0x82 /* active LED and LED1, LED2 current */
+#define BH1770_I_LED3          0x83 /* LED3 current setting */
+#define BH1770_ALS_PS_MEAS     0x84 /* Forced mode trigger */
+#define BH1770_PS_MEAS_RATE    0x85 /* PS meas. rate at stand alone mode */
+#define BH1770_ALS_MEAS_RATE   0x86 /* ALS meas. rate at stand alone mode */
+#define BH1770_PART_ID         0x8a /* Part number and revision ID */
+#define BH1770_MANUFACT_ID     0x8b /* Manufacturerer ID */
+#define BH1770_ALS_DATA_0      0x8c /* ALS DATA low byte */
+#define BH1770_ALS_DATA_1      0x8d /* ALS DATA high byte */
+#define BH1770_ALS_PS_STATUS   0x8e /* Measurement data and int status */
+#define BH1770_PS_DATA_LED1    0x8f /* PS data from LED1 */
+#define BH1770_PS_DATA_LED2    0x90 /* PS data from LED2 */
+#define BH1770_PS_DATA_LED3    0x91 /* PS data from LED3 */
+#define BH1770_INTERRUPT       0x92 /* Interrupt setting */
+#define BH1770_PS_TH_LED1      0x93 /* PS interrupt threshold for LED1 */
+#define BH1770_PS_TH_LED2      0x94 /* PS interrupt threshold for LED2 */
+#define BH1770_PS_TH_LED3      0x95 /* PS interrupt threshold for LED3 */
+#define BH1770_ALS_TH_UP_0     0x96 /* ALS upper threshold low byte */
+#define BH1770_ALS_TH_UP_1     0x97 /* ALS upper threshold high byte */
+#define BH1770_ALS_TH_LOW_0    0x98 /* ALS lower threshold low byte */
+#define BH1770_ALS_TH_LOW_1    0x99 /* ALS lower threshold high byte */
+
+/* MANUFACT_ID */
+#define BH1770_MANUFACT_ROHM   0x01
+#define BH1770_MANUFACT_OSRAM  0x03
+
+/* PART_ID */
+#define BH1770_PART            0x90
+#define BH1770_PART_MASK       0xf0
+#define BH1770_REV_MASK                0x0f
+#define BH1770_REV_SHIFT       0
+#define BH1770_REV_0           0x00
+#define BH1770_REV_1           0x01
+
+/* Operating modes for both */
+#define BH1770_STANDBY         0x00
+#define BH1770_FORCED          0x02
+#define BH1770_STANDALONE      0x03
+#define BH1770_SWRESET         (0x01 << 2)
+
+#define BH1770_PS_TRIG_MEAS    (1 << 0)
+#define BH1770_ALS_TRIG_MEAS   (1 << 1)
+
+/* Interrupt control */
+#define BH1770_INT_OUTPUT_MODE (1 << 3) /* 0 = latched */
+#define BH1770_INT_POLARITY    (1 << 2) /* 1 = active high */
+#define BH1770_INT_ALS_ENA     (1 << 1)
+#define BH1770_INT_PS_ENA      (1 << 0)
+
+/* Interrupt status */
+#define BH1770_INT_LED1_DATA   (1 << 0)
+#define BH1770_INT_LED1_INT    (1 << 1)
+#define BH1770_INT_LED2_DATA   (1 << 2)
+#define BH1770_INT_LED2_INT    (1 << 3)
+#define BH1770_INT_LED3_DATA   (1 << 4)
+#define BH1770_INT_LED3_INT    (1 << 5)
+#define BH1770_INT_LEDS_INT    ((1 << 1) | (1 << 3) | (1 << 5))
+#define BH1770_INT_ALS_DATA    (1 << 6)
+#define BH1770_INT_ALS_INT     (1 << 7)
+
+/* Led channels */
+#define BH1770_LED1            0x00
+
+#define BH1770_DISABLE         0
+#define BH1770_ENABLE          1
+#define BH1770_PROX_CHANNELS   1
+
+#define BH1770_LUX_DEFAULT_RATE        1 /* Index to lux rate table */
+#define BH1770_PROX_DEFAULT_RATE 1 /* Direct HW value =~ 50Hz */
+#define BH1770_PROX_DEF_RATE_THRESH 6 /* Direct HW value =~ 5 Hz */
+#define BH1770_STARTUP_DELAY   50
+#define BH1770_RESET_TIME      10
+#define BH1770_TIMEOUT         2100 /* Timeout in 2.1 seconds */
+
+#define BH1770_LUX_RANGE       65535
+#define BH1770_PROX_RANGE      255
+#define BH1770_COEF_SCALER     1024
+#define BH1770_CALIB_SCALER    8192
+#define BH1770_LUX_NEUTRAL_CALIB_VALUE (1 * BH1770_CALIB_SCALER)
+#define BH1770_LUX_DEF_THRES   1000
+#define BH1770_PROX_DEF_THRES  70
+#define BH1770_PROX_DEF_ABS_THRES   100
+#define BH1770_DEFAULT_PERSISTENCE  10
+#define BH1770_PROX_MAX_PERSISTENCE 50
+#define BH1770_LUX_GA_SCALE    16384
+#define BH1770_LUX_CF_SCALE    2048 /* CF ChipFactor */
+#define BH1770_NEUTRAL_CF      BH1770_LUX_CF_SCALE
+#define BH1770_LUX_CORR_SCALE  4096
+
+#define PROX_ABOVE_THRESHOLD   1
+#define PROX_BELOW_THRESHOLD   0
+
+#define PROX_IGNORE_LUX_LIMIT  500
+
+struct bh1770_chip {
+       struct bh1770_platform_data     *pdata;
+       char                            chipname[10];
+       u8                              revision;
+       struct i2c_client               *client;
+       struct regulator_bulk_data      regs[2];
+       struct mutex                    mutex; /* avoid parallel access */
+       wait_queue_head_t               wait;
+
+       bool                    int_mode_prox;
+       bool                    int_mode_lux;
+       struct delayed_work     prox_work;
+       u32     lux_cf; /* Chip specific factor */
+       u32     lux_ga;
+       u32     lux_calib;
+       int     lux_rate_index;
+       u32     lux_corr;
+       u16     lux_data_raw;
+       u16     lux_threshold_hi;
+       u16     lux_threshold_lo;
+       u16     lux_thres_hi_onchip;
+       u16     lux_thres_lo_onchip;
+       bool    lux_wait_result;
+
+       int     prox_enable_count;
+       u16     prox_coef;
+       u16     prox_const;
+       int     prox_rate;
+       int     prox_rate_threshold;
+       u8      prox_persistence;
+       u8      prox_persistence_counter;
+       u8      prox_data;
+       u8      prox_threshold;
+       u8      prox_threshold_hw;
+       bool    prox_force_update;
+       u8      prox_abs_thres;
+       u8      prox_led;
+};
+
+static const char reg_vcc[] = "Vcc";
+static const char reg_vleds[] = "Vleds";
+
+/*
+ * Supported stand alone rates in ms from chip data sheet
+ * {10, 20, 30, 40, 70, 100, 200, 500, 1000, 2000};
+ */
+static const s16 prox_rates_hz[] = {100, 50, 33, 25, 14, 10, 5, 2};
+static const s16 prox_rates_ms[] = {10, 20, 30, 40, 70, 100, 200, 500};
+
+/* Supported IR-led currents in mA */
+static const u8 prox_curr_ma[] = {5, 10, 20, 50, 100, 150, 200};
+
+/*
+ * Supported stand alone rates in ms from chip data sheet
+ * {100, 200, 500, 1000, 2000};
+ */
+static const s16 lux_rates_hz[] = {10, 5, 2, 1, 0};
+
+/*
+ * interrupt control functions are called while keeping chip->mutex
+ * excluding module probe / remove
+ */
+static inline int bh1770_lux_interrupt_control(struct bh1770_chip *chip,
+                                       int lux)
+{
+       chip->int_mode_lux = lux;
+       /* Set interrupt modes, interrupt active low, latched */
+       return i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_INTERRUPT,
+                                       (lux << 1) | chip->int_mode_prox);
+}
+
+static inline int bh1770_prox_interrupt_control(struct bh1770_chip *chip,
+                                       int ps)
+{
+       chip->int_mode_prox = ps;
+       return i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_INTERRUPT,
+                                       (chip->int_mode_lux << 1) | (ps << 0));
+}
+
+/* chip->mutex is always kept here */
+static int bh1770_lux_rate(struct bh1770_chip *chip, int rate_index)
+{
+       /* sysfs may call this when the chip is powered off */
+       if (pm_runtime_suspended(&chip->client->dev))
+               return 0;
+
+       /* Proper proximity response needs fastest lux rate (100ms) */
+       if (chip->prox_enable_count)
+               rate_index = 0;
+
+       return i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_ALS_MEAS_RATE,
+                                       rate_index);
+}
+
+static int bh1770_prox_rate(struct bh1770_chip *chip, int mode)
+{
+       int rate;
+
+       rate = (mode == PROX_ABOVE_THRESHOLD) ?
+               chip->prox_rate_threshold : chip->prox_rate;
+
+       return i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_PS_MEAS_RATE,
+                                       rate);
+}
+
+/* InfraredLED is controlled by the chip during proximity scanning */
+static inline int bh1770_led_cfg(struct bh1770_chip *chip)
+{
+       /* LED cfg, current for leds 1 and 2 */
+       return i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_I_LED,
+                                       (BH1770_LED1 << 6) |
+                                       (BH1770_LED_5mA << 3) |
+                                       chip->prox_led);
+}
+
+/*
+ * Following two functions converts raw ps values from HW to normalized
+ * values. Purpose is to compensate differences between different sensor
+ * versions and variants so that result means about the same between
+ * versions.
+ */
+static inline u8 bh1770_psraw_to_adjusted(struct bh1770_chip *chip, u8 psraw)
+{
+       u16 adjusted;
+       adjusted = (u16)(((u32)(psraw + chip->prox_const) * chip->prox_coef) /
+               BH1770_COEF_SCALER);
+       if (adjusted > BH1770_PROX_RANGE)
+               adjusted = BH1770_PROX_RANGE;
+       return adjusted;
+}
+
+static inline u8 bh1770_psadjusted_to_raw(struct bh1770_chip *chip, u8 ps)
+{
+       u16 raw;
+
+       raw = (((u32)ps * BH1770_COEF_SCALER) / chip->prox_coef);
+       if (raw > chip->prox_const)
+               raw = raw - chip->prox_const;
+       else
+               raw = 0;
+       return raw;
+}
+
+/*
+ * Following two functions converts raw lux values from HW to normalized
+ * values. Purpose is to compensate differences between different sensor
+ * versions and variants so that result means about the same between
+ * versions. Chip->mutex is kept when this is called.
+ */
+static int bh1770_prox_set_threshold(struct bh1770_chip *chip)
+{
+       u8 tmp = 0;
+
+       /* sysfs may call this when the chip is powered off */
+       if (pm_runtime_suspended(&chip->client->dev))
+               return 0;
+
+       tmp = bh1770_psadjusted_to_raw(chip, chip->prox_threshold);
+       chip->prox_threshold_hw = tmp;
+
+       return  i2c_smbus_write_byte_data(chip->client, BH1770_PS_TH_LED1,
+                                       tmp);
+}
+
+static inline u16 bh1770_lux_raw_to_adjusted(struct bh1770_chip *chip, u16 raw)
+{
+       u32 lux;
+       lux = ((u32)raw * chip->lux_corr) / BH1770_LUX_CORR_SCALE;
+       return min(lux, (u32)BH1770_LUX_RANGE);
+}
+
+static inline u16 bh1770_lux_adjusted_to_raw(struct bh1770_chip *chip,
+                                       u16 adjusted)
+{
+       return (u32)adjusted * BH1770_LUX_CORR_SCALE / chip->lux_corr;
+}
+
+/* chip->mutex is kept when this is called */
+static int bh1770_lux_update_thresholds(struct bh1770_chip *chip,
+                                       u16 threshold_hi, u16 threshold_lo)
+{
+       u8 data[4];
+       int ret;
+
+       /* sysfs may call this when the chip is powered off */
+       if (pm_runtime_suspended(&chip->client->dev))
+               return 0;
+
+       /*
+        * Compensate threshold values with the correction factors if not
+        * set to minimum or maximum.
+        * Min & max values disables interrupts.
+        */
+       if (threshold_hi != BH1770_LUX_RANGE && threshold_hi != 0)
+               threshold_hi = bh1770_lux_adjusted_to_raw(chip, threshold_hi);
+
+       if (threshold_lo != BH1770_LUX_RANGE && threshold_lo != 0)
+               threshold_lo = bh1770_lux_adjusted_to_raw(chip, threshold_lo);
+
+       if (chip->lux_thres_hi_onchip == threshold_hi &&
+           chip->lux_thres_lo_onchip == threshold_lo)
+               return 0;
+
+       chip->lux_thres_hi_onchip = threshold_hi;
+       chip->lux_thres_lo_onchip = threshold_lo;
+
+       data[0] = threshold_hi;
+       data[1] = threshold_hi >> 8;
+       data[2] = threshold_lo;
+       data[3] = threshold_lo >> 8;
+
+       ret = i2c_smbus_write_i2c_block_data(chip->client,
+                                       BH1770_ALS_TH_UP_0,
+                                       ARRAY_SIZE(data),
+                                       data);
+       return ret;
+}
+
+static int bh1770_lux_get_result(struct bh1770_chip *chip)
+{
+       u16 data;
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_0);
+       if (ret < 0)
+               return ret;
+
+       data = ret & 0xff;
+       ret = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_DATA_1);
+       if (ret < 0)
+               return ret;
+
+       chip->lux_data_raw = data | ((ret & 0xff) << 8);
+
+       return 0;
+}
+
+/* Calculate correction value which contains chip and device specific parts */
+static u32 bh1770_get_corr_value(struct bh1770_chip *chip)
+{
+       u32 tmp;
+       /* Impact of glass attenuation correction */
+       tmp = (BH1770_LUX_CORR_SCALE * chip->lux_ga) / BH1770_LUX_GA_SCALE;
+       /* Impact of chip factor correction */
+       tmp = (tmp * chip->lux_cf) / BH1770_LUX_CF_SCALE;
+       /* Impact of Device specific calibration correction */
+       tmp = (tmp * chip->lux_calib) / BH1770_CALIB_SCALER;
+       return tmp;
+}
+
+static int bh1770_lux_read_result(struct bh1770_chip *chip)
+{
+       bh1770_lux_get_result(chip);
+       return bh1770_lux_raw_to_adjusted(chip, chip->lux_data_raw);
+}
+
+/*
+ * Chip on / off functions are called while keeping mutex except probe
+ * or remove phase
+ */
+static int bh1770_chip_on(struct bh1770_chip *chip)
+{
+       int ret = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
+                                       chip->regs);
+       if (ret < 0)
+               return ret;
+
+       usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2);
+
+       /* Reset the chip */
+       i2c_smbus_write_byte_data(chip->client, BH1770_ALS_CONTROL,
+                               BH1770_SWRESET);
+       usleep_range(BH1770_RESET_TIME, BH1770_RESET_TIME * 2);
+
+       /*
+        * ALS is started always since proximity needs als results
+        * for realibility estimation.
+        * Let's assume dark until the first ALS measurement is ready.
+        */
+       chip->lux_data_raw = 0;
+       chip->prox_data = 0;
+       ret = i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_ALS_CONTROL, BH1770_STANDALONE);
+
+       /* Assume reset defaults */
+       chip->lux_thres_hi_onchip = BH1770_LUX_RANGE;
+       chip->lux_thres_lo_onchip = 0;
+
+       return ret;
+}
+
+static void bh1770_chip_off(struct bh1770_chip *chip)
+{
+       i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_INTERRUPT, BH1770_DISABLE);
+       i2c_smbus_write_byte_data(chip->client,
+                               BH1770_ALS_CONTROL, BH1770_STANDBY);
+       i2c_smbus_write_byte_data(chip->client,
+                               BH1770_PS_CONTROL, BH1770_STANDBY);
+       regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+}
+
+/* chip->mutex is kept when this is called */
+static int bh1770_prox_mode_control(struct bh1770_chip *chip)
+{
+       if (chip->prox_enable_count) {
+               chip->prox_force_update = true; /* Force immediate update */
+
+               bh1770_lux_rate(chip, chip->lux_rate_index);
+               bh1770_prox_set_threshold(chip);
+               bh1770_led_cfg(chip);
+               bh1770_prox_rate(chip, PROX_BELOW_THRESHOLD);
+               bh1770_prox_interrupt_control(chip, BH1770_ENABLE);
+               i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_PS_CONTROL, BH1770_STANDALONE);
+       } else {
+               chip->prox_data = 0;
+               bh1770_lux_rate(chip, chip->lux_rate_index);
+               bh1770_prox_interrupt_control(chip, BH1770_DISABLE);
+               i2c_smbus_write_byte_data(chip->client,
+                                       BH1770_PS_CONTROL, BH1770_STANDBY);
+       }
+       return 0;
+}
+
+/* chip->mutex is kept when this is called */
+static int bh1770_prox_read_result(struct bh1770_chip *chip)
+{
+       int ret;
+       bool above;
+       u8 mode;
+
+       ret = i2c_smbus_read_byte_data(chip->client, BH1770_PS_DATA_LED1);
+       if (ret < 0)
+               goto out;
+
+       if (ret > chip->prox_threshold_hw)
+               above = true;
+       else
+               above = false;
+
+       /*
+        * when ALS levels goes above limit, proximity result may be
+        * false proximity. Thus ignore the result. With real proximity
+        * there is a shadow causing low als levels.
+        */
+       if (chip->lux_data_raw > PROX_IGNORE_LUX_LIMIT)
+               ret = 0;
+
+       chip->prox_data = bh1770_psraw_to_adjusted(chip, ret);
+
+       /* Strong proximity level or force mode requires immediate response */
+       if (chip->prox_data >= chip->prox_abs_thres ||
+           chip->prox_force_update)
+               chip->prox_persistence_counter = chip->prox_persistence;
+
+       chip->prox_force_update = false;
+
+       /* Persistence filttering to reduce false proximity events */
+       if (likely(above)) {
+               if (chip->prox_persistence_counter < chip->prox_persistence) {
+                       chip->prox_persistence_counter++;
+                       ret = -ENODATA;
+               } else {
+                       mode = PROX_ABOVE_THRESHOLD;
+                       ret = 0;
+               }
+       } else {
+               chip->prox_persistence_counter = 0;
+               mode = PROX_BELOW_THRESHOLD;
+               chip->prox_data = 0;
+               ret = 0;
+       }
+
+       /* Set proximity detection rate based on above or below value */
+       if (ret == 0) {
+               bh1770_prox_rate(chip, mode);
+               sysfs_notify(&chip->client->dev.kobj, NULL, "prox0_raw");
+       }
+out:
+       return ret;
+}
+
+static int bh1770_detect(struct bh1770_chip *chip)
+{
+       struct i2c_client *client = chip->client;
+       s32 ret;
+       u8 manu, part;
+
+       ret = i2c_smbus_read_byte_data(client, BH1770_MANUFACT_ID);
+       if (ret < 0)
+               goto error;
+       manu = (u8)ret;
+
+       ret = i2c_smbus_read_byte_data(client, BH1770_PART_ID);
+       if (ret < 0)
+               goto error;
+       part = (u8)ret;
+
+       chip->revision = (part & BH1770_REV_MASK) >> BH1770_REV_SHIFT;
+       chip->prox_coef = BH1770_COEF_SCALER;
+       chip->prox_const = 0;
+       chip->lux_cf = BH1770_NEUTRAL_CF;
+
+       if ((manu == BH1770_MANUFACT_ROHM) &&
+           ((part & BH1770_PART_MASK) == BH1770_PART)) {
+               snprintf(chip->chipname, sizeof(chip->chipname), "BH1770GLC");
+               return 0;
+       }
+
+       if ((manu == BH1770_MANUFACT_OSRAM) &&
+           ((part & BH1770_PART_MASK) == BH1770_PART)) {
+               snprintf(chip->chipname, sizeof(chip->chipname), "SFH7770");
+               /* Values selected by comparing different versions */
+               chip->prox_coef = 819; /* 0.8 * BH1770_COEF_SCALER */
+               chip->prox_const = 40;
+               return 0;
+       }
+
+       ret = -ENODEV;
+error:
+       dev_dbg(&client->dev, "BH1770 or SFH7770 not found\n");
+
+       return ret;
+}
+
+/*
+ * This work is re-scheduled at every proximity interrupt.
+ * If this work is running, it means that there hasn't been any
+ * proximity interrupt in time. Situation is handled as no-proximity.
+ * It would be nice to have low-threshold interrupt or interrupt
+ * when measurement and hi-threshold are both 0. But neither of those exists.
+ * This is a workaroud for missing HW feature.
+ */
+
+static void bh1770_prox_work(struct work_struct *work)
+{
+       struct bh1770_chip *chip =
+               container_of(work, struct bh1770_chip, prox_work.work);
+
+       mutex_lock(&chip->mutex);
+       bh1770_prox_read_result(chip);
+       mutex_unlock(&chip->mutex);
+}
+
+/* This is threaded irq handler */
+static irqreturn_t bh1770_irq(int irq, void *data)
+{
+       struct bh1770_chip *chip = data;
+       int status;
+       int rate = 0;
+
+       mutex_lock(&chip->mutex);
+       status = i2c_smbus_read_byte_data(chip->client, BH1770_ALS_PS_STATUS);
+
+       /* Acknowledge interrupt by reading this register */
+       i2c_smbus_read_byte_data(chip->client, BH1770_INTERRUPT);
+
+       /*
+        * Check if there is fresh data available for als.
+        * If this is the very first data, update thresholds after that.
+        */
+       if (status & BH1770_INT_ALS_DATA) {
+               bh1770_lux_get_result(chip);
+               if (unlikely(chip->lux_wait_result)) {
+                       chip->lux_wait_result = false;
+                       wake_up(&chip->wait);
+                       bh1770_lux_update_thresholds(chip,
+                                               chip->lux_threshold_hi,
+                                               chip->lux_threshold_lo);
+               }
+       }
+
+       /* Disable interrupt logic to guarantee acknowledgement */
+       i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT,
+                                 (0 << 1) | (0 << 0));
+
+       if ((status & BH1770_INT_ALS_INT))
+               sysfs_notify(&chip->client->dev.kobj, NULL, "lux0_input");
+
+       if (chip->int_mode_prox && (status & BH1770_INT_LEDS_INT)) {
+               rate = prox_rates_ms[chip->prox_rate_threshold];
+               bh1770_prox_read_result(chip);
+       }
+
+       /* Re-enable interrupt logic */
+       i2c_smbus_write_byte_data(chip->client, BH1770_INTERRUPT,
+                                 (chip->int_mode_lux << 1) |
+                                 (chip->int_mode_prox << 0));
+       mutex_unlock(&chip->mutex);
+
+       /*
+        * Can't cancel work while keeping mutex since the work uses the
+        * same mutex.
+        */
+       if (rate) {
+               /*
+                * Simulate missing no-proximity interrupt 50ms after the
+                * next expected interrupt time.
+                */
+               cancel_delayed_work_sync(&chip->prox_work);
+               schedule_delayed_work(&chip->prox_work,
+                               msecs_to_jiffies(rate + 50));
+       }
+       return IRQ_HANDLED;
+}
+
+static ssize_t bh1770_power_state_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+       size_t ret;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       if (value) {
+               pm_runtime_get_sync(dev);
+
+               ret = bh1770_lux_rate(chip, chip->lux_rate_index);
+               ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE);
+
+               if (ret < 0) {
+                       pm_runtime_put(dev);
+                       goto leave;
+               }
+
+               /* This causes interrupt after the next measurement cycle */
+               bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES,
+                                       BH1770_LUX_DEF_THRES);
+               /* Inform that we are waiting for a result from ALS */
+               chip->lux_wait_result = true;
+               bh1770_prox_mode_control(chip);
+       } else if (!pm_runtime_suspended(dev)) {
+               pm_runtime_put(dev);
+       }
+       ret = count;
+leave:
+       mutex_unlock(&chip->mutex);
+       return ret;
+}
+
+static ssize_t bh1770_power_state_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", !pm_runtime_suspended(dev));
+}
+
+static ssize_t bh1770_lux_result_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       ssize_t ret;
+       long timeout;
+
+       if (pm_runtime_suspended(dev))
+               return -EIO; /* Chip is not enabled at all */
+
+       timeout = wait_event_interruptible_timeout(chip->wait,
+                                       !chip->lux_wait_result,
+                                       msecs_to_jiffies(BH1770_TIMEOUT));
+       if (!timeout)
+               return -EIO;
+
+       mutex_lock(&chip->mutex);
+       ret = sprintf(buf, "%d\n", bh1770_lux_read_result(chip));
+       mutex_unlock(&chip->mutex);
+
+       return ret;
+}
+
+static ssize_t bh1770_lux_range_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", BH1770_LUX_RANGE);
+}
+
+static ssize_t bh1770_prox_enable_store(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       /* Assume no proximity. Sensor will tell real state soon */
+       if (!chip->prox_enable_count)
+               chip->prox_data = 0;
+
+       if (value)
+               chip->prox_enable_count++;
+       else if (chip->prox_enable_count > 0)
+               chip->prox_enable_count--;
+       else
+               goto leave;
+
+       /* Run control only when chip is powered on */
+       if (!pm_runtime_suspended(dev))
+               bh1770_prox_mode_control(chip);
+leave:
+       mutex_unlock(&chip->mutex);
+       return count;
+}
+
+static ssize_t bh1770_prox_enable_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       ssize_t len;
+
+       mutex_lock(&chip->mutex);
+       len = sprintf(buf, "%d\n", chip->prox_enable_count);
+       mutex_unlock(&chip->mutex);
+       return len;
+}
+
+static ssize_t bh1770_prox_result_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       ssize_t ret;
+
+       mutex_lock(&chip->mutex);
+       if (chip->prox_enable_count && !pm_runtime_suspended(dev))
+               ret = sprintf(buf, "%d\n", chip->prox_data);
+       else
+               ret = -EIO;
+       mutex_unlock(&chip->mutex);
+       return ret;
+}
+
+static ssize_t bh1770_prox_range_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", BH1770_PROX_RANGE);
+}
+
+static ssize_t bh1770_get_prox_rate_avail(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int i;
+       int pos = 0;
+       for (i = 0; i < ARRAY_SIZE(prox_rates_hz); i++)
+               pos += sprintf(buf + pos, "%d ", prox_rates_hz[i]);
+       sprintf(buf + pos - 1, "\n");
+       return pos;
+}
+
+static ssize_t bh1770_get_prox_rate_above(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate_threshold]);
+}
+
+static ssize_t bh1770_get_prox_rate_below(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", prox_rates_hz[chip->prox_rate]);
+}
+
+static int bh1770_prox_rate_validate(int rate)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(prox_rates_hz) - 1; i++)
+               if (rate >= prox_rates_hz[i])
+                       break;
+       return i;
+}
+
+static ssize_t bh1770_set_prox_rate_above(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       chip->prox_rate_threshold = bh1770_prox_rate_validate(value);
+       mutex_unlock(&chip->mutex);
+       return count;
+}
+
+static ssize_t bh1770_set_prox_rate_below(struct device *dev,
+                                       struct device_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       chip->prox_rate = bh1770_prox_rate_validate(value);
+       mutex_unlock(&chip->mutex);
+       return count;
+}
+
+static ssize_t bh1770_get_prox_thres(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->prox_threshold);
+}
+
+static ssize_t bh1770_set_prox_thres(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       unsigned long value;
+       int ret;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+       if (value > BH1770_PROX_RANGE)
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       chip->prox_threshold = value;
+       ret = bh1770_prox_set_threshold(chip);
+       mutex_unlock(&chip->mutex);
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+static ssize_t bh1770_prox_persistence_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%u\n", chip->prox_persistence);
+}
+
+static ssize_t bh1770_prox_persistence_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t len)
+{
+       struct bh1770_chip *chip = dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       if (value > BH1770_PROX_MAX_PERSISTENCE)
+               return -EINVAL;
+
+       chip->prox_persistence = value;
+
+       return len;
+}
+
+static ssize_t bh1770_prox_abs_thres_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip = dev_get_drvdata(dev);
+       return sprintf(buf, "%u\n", chip->prox_abs_thres);
+}
+
+static ssize_t bh1770_prox_abs_thres_store(struct device *dev,
+                               struct device_attribute *attr,
+                               const char *buf, size_t len)
+{
+       struct bh1770_chip *chip = dev_get_drvdata(dev);
+       unsigned long value;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       if (value > BH1770_PROX_RANGE)
+               return -EINVAL;
+
+       chip->prox_abs_thres = value;
+
+       return len;
+}
+
+static ssize_t bh1770_chip_id_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%s rev %d\n", chip->chipname, chip->revision);
+}
+
+static ssize_t bh1770_lux_calib_default_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", BH1770_CALIB_SCALER);
+}
+
+static ssize_t bh1770_lux_calib_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip = dev_get_drvdata(dev);
+       ssize_t len;
+
+       mutex_lock(&chip->mutex);
+       len = sprintf(buf, "%u\n", chip->lux_calib);
+       mutex_unlock(&chip->mutex);
+       return len;
+}
+
+static ssize_t bh1770_lux_calib_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct bh1770_chip *chip = dev_get_drvdata(dev);
+       unsigned long value;
+       u32 old_calib;
+       u32 new_corr;
+
+       if (strict_strtoul(buf, 0, &value))
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       old_calib = chip->lux_calib;
+       chip->lux_calib = value;
+       new_corr = bh1770_get_corr_value(chip);
+       if (new_corr == 0) {
+               chip->lux_calib = old_calib;
+               mutex_unlock(&chip->mutex);
+               return -EINVAL;
+       }
+       chip->lux_corr = new_corr;
+       /* Refresh thresholds on HW after changing correction value */
+       bh1770_lux_update_thresholds(chip, chip->lux_threshold_hi,
+                               chip->lux_threshold_lo);
+
+       mutex_unlock(&chip->mutex);
+
+       return len;
+}
+
+static ssize_t bh1770_get_lux_rate_avail(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int i;
+       int pos = 0;
+       for (i = 0; i < ARRAY_SIZE(lux_rates_hz); i++)
+               pos += sprintf(buf + pos, "%d ", lux_rates_hz[i]);
+       sprintf(buf + pos - 1, "\n");
+       return pos;
+}
+
+static ssize_t bh1770_get_lux_rate(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", lux_rates_hz[chip->lux_rate_index]);
+}
+
+static ssize_t bh1770_set_lux_rate(struct device *dev,
+                                     struct device_attribute *attr,
+                                     const char *buf, size_t count)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       unsigned long rate_hz;
+       int ret, i;
+
+       if (strict_strtoul(buf, 0, &rate_hz))
+               return -EINVAL;
+
+       for (i = 0; i < ARRAY_SIZE(lux_rates_hz) - 1; i++)
+               if (rate_hz >= lux_rates_hz[i])
+                       break;
+
+       mutex_lock(&chip->mutex);
+       chip->lux_rate_index = i;
+       ret = bh1770_lux_rate(chip, i);
+       mutex_unlock(&chip->mutex);
+
+       if (ret < 0)
+               return ret;
+
+       return count;
+}
+
+static ssize_t bh1770_get_lux_thresh_above(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->lux_threshold_hi);
+}
+
+static ssize_t bh1770_get_lux_thresh_below(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", chip->lux_threshold_lo);
+}
+
+static ssize_t bh1770_set_lux_thresh(struct bh1770_chip *chip, u16 *target,
+                               const char *buf)
+{
+       int ret = 0;
+       unsigned long thresh;
+
+       if (strict_strtoul(buf, 0, &thresh))
+               return -EINVAL;
+
+       if (thresh > BH1770_LUX_RANGE)
+               return -EINVAL;
+
+       mutex_lock(&chip->mutex);
+       *target = thresh;
+       /*
+        * Don't update values in HW if we are still waiting for
+        * first interrupt to come after device handle open call.
+        */
+       if (!chip->lux_wait_result)
+               ret = bh1770_lux_update_thresholds(chip,
+                                               chip->lux_threshold_hi,
+                                               chip->lux_threshold_lo);
+       mutex_unlock(&chip->mutex);
+       return ret;
+
+}
+
+static ssize_t bh1770_set_lux_thresh_above(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_hi, buf);
+       if (ret < 0)
+               return ret;
+       return len;
+}
+
+static ssize_t bh1770_set_lux_thresh_below(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t len)
+{
+       struct bh1770_chip *chip =  dev_get_drvdata(dev);
+       int ret = bh1770_set_lux_thresh(chip, &chip->lux_threshold_lo, buf);
+       if (ret < 0)
+               return ret;
+       return len;
+}
+
+static DEVICE_ATTR(prox0_raw_en, S_IRUGO | S_IWUSR, bh1770_prox_enable_show,
+                                               bh1770_prox_enable_store);
+static DEVICE_ATTR(prox0_thresh_above1_value, S_IRUGO | S_IWUSR,
+                                               bh1770_prox_abs_thres_show,
+                                               bh1770_prox_abs_thres_store);
+static DEVICE_ATTR(prox0_thresh_above0_value, S_IRUGO | S_IWUSR,
+                                               bh1770_get_prox_thres,
+                                               bh1770_set_prox_thres);
+static DEVICE_ATTR(prox0_raw, S_IRUGO, bh1770_prox_result_show, NULL);
+static DEVICE_ATTR(prox0_sensor_range, S_IRUGO, bh1770_prox_range_show, NULL);
+static DEVICE_ATTR(prox0_thresh_above_count, S_IRUGO | S_IWUSR,
+                                               bh1770_prox_persistence_show,
+                                               bh1770_prox_persistence_store);
+static DEVICE_ATTR(prox0_rate_above, S_IRUGO | S_IWUSR,
+                                               bh1770_get_prox_rate_above,
+                                               bh1770_set_prox_rate_above);
+static DEVICE_ATTR(prox0_rate_below, S_IRUGO | S_IWUSR,
+                                               bh1770_get_prox_rate_below,
+                                               bh1770_set_prox_rate_below);
+static DEVICE_ATTR(prox0_rate_avail, S_IRUGO, bh1770_get_prox_rate_avail, NULL);
+
+static DEVICE_ATTR(lux0_calibscale, S_IRUGO | S_IWUSR, bh1770_lux_calib_show,
+                                               bh1770_lux_calib_store);
+static DEVICE_ATTR(lux0_calibscale_default, S_IRUGO,
+                                               bh1770_lux_calib_default_show,
+                                               NULL);
+static DEVICE_ATTR(lux0_input, S_IRUGO, bh1770_lux_result_show, NULL);
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO, bh1770_lux_range_show, NULL);
+static DEVICE_ATTR(lux0_rate, S_IRUGO | S_IWUSR, bh1770_get_lux_rate,
+                                               bh1770_set_lux_rate);
+static DEVICE_ATTR(lux0_rate_avail, S_IRUGO, bh1770_get_lux_rate_avail, NULL);
+static DEVICE_ATTR(lux0_thresh_above_value, S_IRUGO | S_IWUSR,
+                                               bh1770_get_lux_thresh_above,
+                                               bh1770_set_lux_thresh_above);
+static DEVICE_ATTR(lux0_thresh_below_value, S_IRUGO | S_IWUSR,
+                                               bh1770_get_lux_thresh_below,
+                                               bh1770_set_lux_thresh_below);
+static DEVICE_ATTR(chip_id, S_IRUGO, bh1770_chip_id_show, NULL);
+static DEVICE_ATTR(power_state, S_IRUGO | S_IWUSR, bh1770_power_state_show,
+                                                bh1770_power_state_store);
+
+
+static struct attribute *sysfs_attrs[] = {
+       &dev_attr_lux0_calibscale.attr,
+       &dev_attr_lux0_calibscale_default.attr,
+       &dev_attr_lux0_input.attr,
+       &dev_attr_lux0_sensor_range.attr,
+       &dev_attr_lux0_rate.attr,
+       &dev_attr_lux0_rate_avail.attr,
+       &dev_attr_lux0_thresh_above_value.attr,
+       &dev_attr_lux0_thresh_below_value.attr,
+       &dev_attr_prox0_raw.attr,
+       &dev_attr_prox0_sensor_range.attr,
+       &dev_attr_prox0_raw_en.attr,
+       &dev_attr_prox0_thresh_above_count.attr,
+       &dev_attr_prox0_rate_above.attr,
+       &dev_attr_prox0_rate_below.attr,
+       &dev_attr_prox0_rate_avail.attr,
+       &dev_attr_prox0_thresh_above0_value.attr,
+       &dev_attr_prox0_thresh_above1_value.attr,
+       &dev_attr_chip_id.attr,
+       &dev_attr_power_state.attr,
+       NULL
+};
+
+static struct attribute_group bh1770_attribute_group = {
+       .attrs = sysfs_attrs
+};
+
+static int __devinit bh1770_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct bh1770_chip *chip;
+       int err;
+
+       chip = kzalloc(sizeof *chip, GFP_KERNEL);
+       if (!chip)
+               return -ENOMEM;
+
+       i2c_set_clientdata(client, chip);
+       chip->client  = client;
+
+       mutex_init(&chip->mutex);
+       init_waitqueue_head(&chip->wait);
+       INIT_DELAYED_WORK(&chip->prox_work, bh1770_prox_work);
+
+       if (client->dev.platform_data == NULL) {
+               dev_err(&client->dev, "platform data is mandatory\n");
+               err = -EINVAL;
+               goto fail1;
+       }
+
+       chip->pdata             = client->dev.platform_data;
+       chip->lux_calib         = BH1770_LUX_NEUTRAL_CALIB_VALUE;
+       chip->lux_rate_index    = BH1770_LUX_DEFAULT_RATE;
+       chip->lux_threshold_lo  = BH1770_LUX_DEF_THRES;
+       chip->lux_threshold_hi  = BH1770_LUX_DEF_THRES;
+
+       if (chip->pdata->glass_attenuation == 0)
+               chip->lux_ga = BH1770_NEUTRAL_GA;
+       else
+               chip->lux_ga = chip->pdata->glass_attenuation;
+
+       chip->prox_threshold    = BH1770_PROX_DEF_THRES;
+       chip->prox_led          = chip->pdata->led_def_curr;
+       chip->prox_abs_thres    = BH1770_PROX_DEF_ABS_THRES;
+       chip->prox_persistence  = BH1770_DEFAULT_PERSISTENCE;
+       chip->prox_rate_threshold = BH1770_PROX_DEF_RATE_THRESH;
+       chip->prox_rate         = BH1770_PROX_DEFAULT_RATE;
+       chip->prox_data         = 0;
+
+       chip->regs[0].supply = reg_vcc;
+       chip->regs[1].supply = reg_vleds;
+
+       err = regulator_bulk_get(&client->dev,
+                                ARRAY_SIZE(chip->regs), chip->regs);
+       if (err < 0) {
+               dev_err(&client->dev, "Cannot get regulators\n");
+               goto fail1;
+       }
+
+       err = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
+                               chip->regs);
+       if (err < 0) {
+               dev_err(&client->dev, "Cannot enable regulators\n");
+               goto fail2;
+       }
+
+       usleep_range(BH1770_STARTUP_DELAY, BH1770_STARTUP_DELAY * 2);
+       err = bh1770_detect(chip);
+       if (err < 0)
+               goto fail3;
+
+       /* Start chip */
+       bh1770_chip_on(chip);
+       pm_runtime_set_active(&client->dev);
+       pm_runtime_enable(&client->dev);
+
+       chip->lux_corr = bh1770_get_corr_value(chip);
+       if (chip->lux_corr == 0) {
+               dev_err(&client->dev, "Improper correction values\n");
+               err = -EINVAL;
+               goto fail3;
+       }
+
+       if (chip->pdata->setup_resources) {
+               err = chip->pdata->setup_resources();
+               if (err) {
+                       err = -EINVAL;
+                       goto fail3;
+               }
+       }
+
+       err = sysfs_create_group(&chip->client->dev.kobj,
+                               &bh1770_attribute_group);
+       if (err < 0) {
+               dev_err(&chip->client->dev, "Sysfs registration failed\n");
+               goto fail4;
+       }
+
+       /*
+        * Chip needs level triggered interrupt to work. However,
+        * level triggering doesn't work always correctly with power
+        * management. Select both
+        */
+       err = request_threaded_irq(client->irq, NULL,
+                               bh1770_irq,
+                               IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
+                               IRQF_TRIGGER_LOW,
+                               "bh1770", chip);
+       if (err) {
+               dev_err(&client->dev, "could not get IRQ %d\n",
+                       client->irq);
+               goto fail5;
+       }
+       regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+       return err;
+fail5:
+       sysfs_remove_group(&chip->client->dev.kobj,
+                       &bh1770_attribute_group);
+fail4:
+       if (chip->pdata->release_resources)
+               chip->pdata->release_resources();
+fail3:
+       regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
+fail2:
+       regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+fail1:
+       kfree(chip);
+       return err;
+}
+
+static int __devexit bh1770_remove(struct i2c_client *client)
+{
+       struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+       free_irq(client->irq, chip);
+
+       sysfs_remove_group(&chip->client->dev.kobj,
+                       &bh1770_attribute_group);
+
+       if (chip->pdata->release_resources)
+               chip->pdata->release_resources();
+
+       cancel_delayed_work_sync(&chip->prox_work);
+
+       if (!pm_runtime_suspended(&client->dev))
+               bh1770_chip_off(chip);
+
+       pm_runtime_disable(&client->dev);
+       pm_runtime_set_suspended(&client->dev);
+
+       regulator_bulk_free(ARRAY_SIZE(chip->regs), chip->regs);
+       kfree(chip);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int bh1770_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+       bh1770_chip_off(chip);
+
+       return 0;
+}
+
+static int bh1770_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct bh1770_chip *chip = i2c_get_clientdata(client);
+       int ret = 0;
+
+       bh1770_chip_on(chip);
+
+       if (!pm_runtime_suspended(dev)) {
+               /*
+                * If we were enabled at suspend time, it is expected
+                * everything works nice and smoothly
+                */
+               ret = bh1770_lux_rate(chip, chip->lux_rate_index);
+               ret |= bh1770_lux_interrupt_control(chip, BH1770_ENABLE);
+
+               /* This causes interrupt after the next measurement cycle */
+               bh1770_lux_update_thresholds(chip, BH1770_LUX_DEF_THRES,
+                                       BH1770_LUX_DEF_THRES);
+               /* Inform that we are waiting for a result from ALS */
+               chip->lux_wait_result = true;
+               bh1770_prox_mode_control(chip);
+       }
+       return ret;
+}
+
+#else
+#define bh1770_suspend NULL
+#define bh1770_shutdown NULL
+#define bh1770_resume  NULL
+#endif
+
+#ifdef CONFIG_PM_RUNTIME
+static int bh1770_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+       bh1770_chip_off(chip);
+
+       return 0;
+}
+
+static int bh1770_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+       struct bh1770_chip *chip = i2c_get_clientdata(client);
+
+       bh1770_chip_on(chip);
+
+       return 0;
+}
+#endif
+
+static const struct i2c_device_id bh1770_id[] = {
+       {"bh1770glc", 0 },
+       {"sfh7770", 0 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bh1770_id);
+
+static const struct dev_pm_ops bh1770_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(bh1770_suspend, bh1770_resume)
+       SET_RUNTIME_PM_OPS(bh1770_runtime_suspend, bh1770_runtime_resume, NULL)
+};
+
+static struct i2c_driver bh1770_driver = {
+       .driver  = {
+               .name   = "bh1770glc",
+               .owner  = THIS_MODULE,
+               .pm     = &bh1770_pm_ops,
+       },
+       .probe    = bh1770_probe,
+       .remove   = __devexit_p(bh1770_remove),
+       .id_table = bh1770_id,
+};
+
+static int __init bh1770_init(void)
+{
+       return i2c_add_driver(&bh1770_driver);
+}
+
+static void __exit bh1770_exit(void)
+{
+       i2c_del_driver(&bh1770_driver);
+}
+
+MODULE_DESCRIPTION("BH1770GLC / SFH7770 combined ALS and proximity sensor");
+MODULE_AUTHOR("Samu Onkalo, Nokia Corporation");
+MODULE_LICENSE("GPL v2");
+
+module_init(bh1770_init);
+module_exit(bh1770_exit);
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
new file mode 100644 (file)
index 0000000..34fe835
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * isl29020.c - Intersil  ALS Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * Data sheet at: http://www.intersil.com/data/fn/fn6505.pdf
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/sysfs.h>
+#include <linux/pm_runtime.h>
+
+static DEFINE_MUTEX(mutex);
+
+static ssize_t als_sensing_range_show(struct device *dev,
+                       struct device_attribute *attr,  char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int  val;
+
+       val = i2c_smbus_read_byte_data(client, 0x00);
+
+       if (val < 0)
+               return val;
+       return sprintf(buf, "%d000\n", 1 << (2 * (val & 3)));
+
+}
+
+static ssize_t als_lux_input_data_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       int ret_val, val;
+       unsigned long int lux;
+       int temp;
+
+       pm_runtime_get_sync(dev);
+       msleep(100);
+
+       mutex_lock(&mutex);
+       temp = i2c_smbus_read_byte_data(client, 0x02); /* MSB data */
+       if (temp < 0) {
+               pm_runtime_put_sync(dev);
+               mutex_unlock(&mutex);
+               return temp;
+       }
+
+       ret_val = i2c_smbus_read_byte_data(client, 0x01); /* LSB data */
+       mutex_unlock(&mutex);
+
+       if (ret_val < 0) {
+               pm_runtime_put_sync(dev);
+               return ret_val;
+       }
+
+       ret_val |= temp << 8;
+       val = i2c_smbus_read_byte_data(client, 0x00);
+       pm_runtime_put_sync(dev);
+       if (val < 0)
+               return val;
+       lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / 65536;
+       return sprintf(buf, "%ld\n", lux);
+}
+
+static ssize_t als_sensing_range_store(struct device *dev,
+               struct device_attribute *attr, const  char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       unsigned int ret_val;
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val))
+               return -EINVAL;
+       if (val < 1 || val > 64000)
+               return -EINVAL;
+
+       /* Pick the smallest sensor range that will meet our requirements */
+       if (val <= 1000)
+               val = 1;
+       else if (val <= 4000)
+               val = 2;
+       else if (val <= 16000)
+               val = 3;
+       else
+               val = 4;
+
+       ret_val = i2c_smbus_read_byte_data(client, 0x00);
+
+       ret_val &= 0xFC; /*reset the bit before setting them */
+       ret_val |= val - 1;
+       ret_val = i2c_smbus_write_byte_data(client, 0x00, ret_val);
+
+       if (ret_val < 0)
+               return ret_val;
+       return count;
+}
+
+static void als_set_power_state(struct i2c_client *client, int enable)
+{
+       int ret_val;
+
+       ret_val = i2c_smbus_read_byte_data(client, 0x00);
+       if (ret_val < 0)
+               return;
+
+       if (enable)
+               ret_val |= 0x80;
+       else
+               ret_val &= 0x7F;
+
+       i2c_smbus_write_byte_data(client, 0x00, ret_val);
+}
+
+static DEVICE_ATTR(lux0_sensor_range, S_IRUGO | S_IWUSR,
+       als_sensing_range_show, als_sensing_range_store);
+static DEVICE_ATTR(lux0_input, S_IRUGO, als_lux_input_data_show, NULL);
+
+static struct attribute *mid_att_als[] = {
+       &dev_attr_lux0_sensor_range.attr,
+       &dev_attr_lux0_input.attr,
+       NULL
+};
+
+static struct attribute_group m_als_gr = {
+       .name = "isl29020",
+       .attrs = mid_att_als
+};
+
+static int als_set_default_config(struct i2c_client *client)
+{
+       int retval;
+
+       retval = i2c_smbus_write_byte_data(client, 0x00, 0xc0);
+       if (retval < 0) {
+               dev_err(&client->dev, "default write failed.");
+               return retval;
+       }
+       return 0;;
+}
+
+static int  isl29020_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       int res;
+
+       res = als_set_default_config(client);
+       if (res <  0)
+               return res;
+
+       res = sysfs_create_group(&client->dev.kobj, &m_als_gr);
+       if (res) {
+               dev_err(&client->dev, "isl29020: device create file failed\n");
+               return res;
+       }
+       dev_info(&client->dev, "%s isl29020: ALS chip found\n", client->name);
+       als_set_power_state(client, 0);
+       pm_runtime_enable(&client->dev);
+       return res;
+}
+
+static int isl29020_remove(struct i2c_client *client)
+{
+       struct als_data *data = i2c_get_clientdata(client);
+       sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+       kfree(data);
+       return 0;
+}
+
+static struct i2c_device_id isl29020_id[] = {
+       { "isl29020", 0 },
+       { }
+};
+
+MODULE_DEVICE_TABLE(i2c, isl29020_id);
+
+#ifdef CONFIG_PM
+
+static int isl29020_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       als_set_power_state(client, 0);
+       return 0;
+}
+
+static int isl29020_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       als_set_power_state(client, 1);
+       return 0;
+}
+
+static const struct dev_pm_ops isl29020_pm_ops = {
+       .runtime_suspend = isl29020_runtime_suspend,
+       .runtime_resume = isl29020_runtime_resume,
+};
+
+#define ISL29020_PM_OPS (&isl29020_pm_ops)
+#else  /* CONFIG_PM */
+#define ISL29020_PM_OPS NULL
+#endif /* CONFIG_PM */
+
+static struct i2c_driver isl29020_driver = {
+       .driver = {
+               .name = "isl29020",
+               .pm = ISL29020_PM_OPS,
+       },
+       .probe = isl29020_probe,
+       .remove = isl29020_remove,
+       .id_table = isl29020_id,
+};
+
+static int __init sensor_isl29020_init(void)
+{
+       return i2c_add_driver(&isl29020_driver);
+}
+
+static void  __exit sensor_isl29020_exit(void)
+{
+       i2c_del_driver(&isl29020_driver);
+}
+
+module_init(sensor_isl29020_init);
+module_exit(sensor_isl29020_exit);
+
+MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
+MODULE_DESCRIPTION("Intersil isl29020 ALS Driver");
+MODULE_LICENSE("GPL v2");
index 343b5d8..81d7fa4 100644 (file)
 #define REC_NUM_DEFAULT 10
 
 enum cname {
-       INVALID,
-       INT_HARDWARE_ENTRY,
-       INT_HW_IRQ_EN,
-       INT_TASKLET_ENTRY,
-       FS_DEVRW,
-       MEM_SWAPOUT,
-       TIMERADD,
-       SCSI_DISPATCH_CMD,
-       IDE_CORE_CP,
-       DIRECT,
+       CN_INVALID,
+       CN_INT_HARDWARE_ENTRY,
+       CN_INT_HW_IRQ_EN,
+       CN_INT_TASKLET_ENTRY,
+       CN_FS_DEVRW,
+       CN_MEM_SWAPOUT,
+       CN_TIMERADD,
+       CN_SCSI_DISPATCH_CMD,
+       CN_IDE_CORE_CP,
+       CN_DIRECT,
 };
 
 enum ctype {
-       NONE,
-       PANIC,
-       BUG,
-       EXCEPTION,
-       LOOP,
-       OVERFLOW,
-       CORRUPT_STACK,
-       UNALIGNED_LOAD_STORE_WRITE,
-       OVERWRITE_ALLOCATION,
-       WRITE_AFTER_FREE,
-       SOFTLOCKUP,
-       HARDLOCKUP,
-       HUNG_TASK,
+       CT_NONE,
+       CT_PANIC,
+       CT_BUG,
+       CT_EXCEPTION,
+       CT_LOOP,
+       CT_OVERFLOW,
+       CT_CORRUPT_STACK,
+       CT_UNALIGNED_LOAD_STORE_WRITE,
+       CT_OVERWRITE_ALLOCATION,
+       CT_WRITE_AFTER_FREE,
+       CT_SOFTLOCKUP,
+       CT_HARDLOCKUP,
+       CT_HUNG_TASK,
 };
 
 static char* cp_name[] = {
@@ -117,8 +117,8 @@ static char* cpoint_type;
 static int cpoint_count = DEFAULT_COUNT;
 static int recur_count = REC_NUM_DEFAULT;
 
-static enum cname cpoint = INVALID;
-static enum ctype cptype = NONE;
+static enum cname cpoint = CN_INVALID;
+static enum ctype cptype = CT_NONE;
 static int count = DEFAULT_COUNT;
 
 module_param(recur_count, int, 0644);
@@ -207,12 +207,12 @@ static enum ctype parse_cp_type(const char *what, size_t count)
                        return i + 1;
        }
 
-       return NONE;
+       return CT_NONE;
 }
 
 static const char *cp_type_to_str(enum ctype type)
 {
-       if (type == NONE || type < 0 || type > ARRAY_SIZE(cp_type))
+       if (type == CT_NONE || type < 0 || type > ARRAY_SIZE(cp_type))
                return "None";
 
        return cp_type[type - 1];
@@ -220,7 +220,7 @@ static const char *cp_type_to_str(enum ctype type)
 
 static const char *cp_name_to_str(enum cname name)
 {
-       if (name == INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
+       if (name == CN_INVALID || name < 0 || name > ARRAY_SIZE(cp_name))
                return "INVALID";
 
        return cp_name[name - 1];
@@ -245,7 +245,7 @@ static int lkdtm_parse_commandline(void)
                return -EINVAL;
 
        cptype = parse_cp_type(cpoint_type, strlen(cpoint_type));
-       if (cptype == NONE)
+       if (cptype == CT_NONE)
                return -EINVAL;
 
        for (i = 0; i < ARRAY_SIZE(cp_name); i++) {
@@ -274,30 +274,30 @@ static int recursive_loop(int a)
 static void lkdtm_do_action(enum ctype which)
 {
        switch (which) {
-       case PANIC:
+       case CT_PANIC:
                panic("dumptest");
                break;
-       case BUG:
+       case CT_BUG:
                BUG();
                break;
-       case EXCEPTION:
+       case CT_EXCEPTION:
                *((int *) 0) = 0;
                break;
-       case LOOP:
+       case CT_LOOP:
                for (;;)
                        ;
                break;
-       case OVERFLOW:
+       case CT_OVERFLOW:
                (void) recursive_loop(0);
                break;
-       case CORRUPT_STACK: {
+       case CT_CORRUPT_STACK: {
                volatile u32 data[8];
                volatile u32 *p = data;
 
                p[12] = 0x12345678;
                break;
        }
-       case UNALIGNED_LOAD_STORE_WRITE: {
+       case CT_UNALIGNED_LOAD_STORE_WRITE: {
                static u8 data[5] __attribute__((aligned(4))) = {1, 2,
                                3, 4, 5};
                u32 *p;
@@ -309,7 +309,7 @@ static void lkdtm_do_action(enum ctype which)
                *p = val;
                 break;
        }
-       case OVERWRITE_ALLOCATION: {
+       case CT_OVERWRITE_ALLOCATION: {
                size_t len = 1020;
                u32 *data = kmalloc(len, GFP_KERNEL);
 
@@ -317,7 +317,7 @@ static void lkdtm_do_action(enum ctype which)
                kfree(data);
                break;
        }
-       case WRITE_AFTER_FREE: {
+       case CT_WRITE_AFTER_FREE: {
                size_t len = 1024;
                u32 *data = kmalloc(len, GFP_KERNEL);
 
@@ -326,21 +326,21 @@ static void lkdtm_do_action(enum ctype which)
                memset(data, 0x78, len);
                break;
        }
-       case SOFTLOCKUP:
+       case CT_SOFTLOCKUP:
                preempt_disable();
                for (;;)
                        cpu_relax();
                break;
-       case HARDLOCKUP:
+       case CT_HARDLOCKUP:
                local_irq_disable();
                for (;;)
                        cpu_relax();
                break;
-       case HUNG_TASK:
+       case CT_HUNG_TASK:
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule();
                break;
-       case NONE:
+       case CT_NONE:
        default:
                break;
        }
@@ -363,43 +363,43 @@ static int lkdtm_register_cpoint(enum cname which)
 {
        int ret;
 
-       cpoint = INVALID;
+       cpoint = CN_INVALID;
        if (lkdtm.entry != NULL)
                unregister_jprobe(&lkdtm);
 
        switch (which) {
-       case DIRECT:
+       case CN_DIRECT:
                lkdtm_do_action(cptype);
                return 0;
-       case INT_HARDWARE_ENTRY:
+       case CN_INT_HARDWARE_ENTRY:
                lkdtm.kp.symbol_name = "do_IRQ";
                lkdtm.entry = (kprobe_opcode_t*) jp_do_irq;
                break;
-       case INT_HW_IRQ_EN:
+       case CN_INT_HW_IRQ_EN:
                lkdtm.kp.symbol_name = "handle_IRQ_event";
                lkdtm.entry = (kprobe_opcode_t*) jp_handle_irq_event;
                break;
-       case INT_TASKLET_ENTRY:
+       case CN_INT_TASKLET_ENTRY:
                lkdtm.kp.symbol_name = "tasklet_action";
                lkdtm.entry = (kprobe_opcode_t*) jp_tasklet_action;
                break;
-       case FS_DEVRW:
+       case CN_FS_DEVRW:
                lkdtm.kp.symbol_name = "ll_rw_block";
                lkdtm.entry = (kprobe_opcode_t*) jp_ll_rw_block;
                break;
-       case MEM_SWAPOUT:
+       case CN_MEM_SWAPOUT:
                lkdtm.kp.symbol_name = "shrink_inactive_list";
                lkdtm.entry = (kprobe_opcode_t*) jp_shrink_inactive_list;
                break;
-       case TIMERADD:
+       case CN_TIMERADD:
                lkdtm.kp.symbol_name = "hrtimer_start";
                lkdtm.entry = (kprobe_opcode_t*) jp_hrtimer_start;
                break;
-       case SCSI_DISPATCH_CMD:
+       case CN_SCSI_DISPATCH_CMD:
                lkdtm.kp.symbol_name = "scsi_dispatch_cmd";
                lkdtm.entry = (kprobe_opcode_t*) jp_scsi_dispatch_cmd;
                break;
-       case IDE_CORE_CP:
+       case CN_IDE_CORE_CP:
 #ifdef CONFIG_IDE
                lkdtm.kp.symbol_name = "generic_ide_ioctl";
                lkdtm.entry = (kprobe_opcode_t*) jp_generic_ide_ioctl;
@@ -416,7 +416,7 @@ static int lkdtm_register_cpoint(enum cname which)
        cpoint = which;
        if ((ret = register_jprobe(&lkdtm)) < 0) {
                printk(KERN_INFO "lkdtm: Couldn't register jprobe\n");
-               cpoint = INVALID;
+               cpoint = CN_INVALID;
        }
 
        return ret;
@@ -445,7 +445,7 @@ static ssize_t do_register_entry(enum cname which, struct file *f,
        cptype = parse_cp_type(buf, count);
        free_page((unsigned long) buf);
 
-       if (cptype == NONE)
+       if (cptype == CT_NONE)
                return -EINVAL;
 
        err = lkdtm_register_cpoint(which);
@@ -487,49 +487,49 @@ static int lkdtm_debugfs_open(struct inode *inode, struct file *file)
 static ssize_t int_hardware_entry(struct file *f, const char __user *buf,
                size_t count, loff_t *off)
 {
-       return do_register_entry(INT_HARDWARE_ENTRY, f, buf, count, off);
+       return do_register_entry(CN_INT_HARDWARE_ENTRY, f, buf, count, off);
 }
 
 static ssize_t int_hw_irq_en(struct file *f, const char __user *buf,
                size_t count, loff_t *off)
 {
-       return do_register_entry(INT_HW_IRQ_EN, f, buf, count, off);
+       return do_register_entry(CN_INT_HW_IRQ_EN, f, buf, count, off);
 }
 
 static ssize_t int_tasklet_entry(struct file *f, const char __user *buf,
                size_t count, loff_t *off)
 {
-       return do_register_entry(INT_TASKLET_ENTRY, f, buf, count, off);
+       return do_register_entry(CN_INT_TASKLET_ENTRY, f, buf, count, off);
 }
 
 static ssize_t fs_devrw_entry(struct file *f, const char __user *buf,
                size_t count, loff_t *off)
 {
-       return do_register_entry(FS_DEVRW, f, buf, count, off);
+       return do_register_entry(CN_FS_DEVRW, f, buf, count, off);
 }
 
 static ssize_t mem_swapout_entry(struct file *f, const char __user *buf,
                size_t count, loff_t *off)
 {
-       return do_register_entry(MEM_SWAPOUT, f, buf, count, off);
+       return do_register_entry(CN_MEM_SWAPOUT, f, buf, count, off);
 }
 
 static ssize_t timeradd_entry(struct file *f, const char __user *buf,
                size_t count, loff_t *off)
 {
-       return do_register_entry(TIMERADD, f, buf, count, off);
+       return do_register_entry(CN_TIMERADD, f, buf, count, off);
 }
 
 static ssize_t scsi_dispatch_cmd_entry(struct file *f,
                const char __user *buf, size_t count, loff_t *off)
 {
-       return do_register_entry(SCSI_DISPATCH_CMD, f, buf, count, off);
+       return do_register_entry(CN_SCSI_DISPATCH_CMD, f, buf, count, off);
 }
 
 static ssize_t ide_core_cp_entry(struct file *f, const char __user *buf,
                size_t count, loff_t *off)
 {
-       return do_register_entry(IDE_CORE_CP, f, buf, count, off);
+       return do_register_entry(CN_IDE_CORE_CP, f, buf, count, off);
 }
 
 /* Special entry to just crash directly. Available without KPROBEs */
@@ -557,7 +557,7 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf,
 
        type = parse_cp_type(buf, count);
        free_page((unsigned long) buf);
-       if (type == NONE)
+       if (type == CT_NONE)
                return -EINVAL;
 
        printk(KERN_INFO "lkdtm: Performing direct entry %s\n",
@@ -649,7 +649,7 @@ static int __init lkdtm_module_init(void)
                goto out_err;
        }
 
-       if (cpoint != INVALID && cptype != NONE) {
+       if (cpoint != CN_INVALID && cptype != CT_NONE) {
                ret = lkdtm_register_cpoint(cpoint);
                if (ret < 0) {
                        printk(KERN_INFO "lkdtm: Invalid crash point %d\n",
index 4197a3c..b05db55 100644 (file)
@@ -343,8 +343,10 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
        int retval;
 
        retval = pci_enable_device(pdev);
-       if (retval)
+       if (retval) {
+               dev_err(&pdev->dev, "pci_enable_device failed!\n");
                goto err;
+       }
 
        minor = phantom_get_free();
        if (minor == PHANTOM_MAX_MINORS) {
@@ -356,8 +358,10 @@ static int __devinit phantom_probe(struct pci_dev *pdev,
        phantom_devices[minor] = 1;
 
        retval = pci_request_regions(pdev, "phantom");
-       if (retval)
+       if (retval) {
+               dev_err(&pdev->dev, "pci_request_regions failed!\n");
                goto err_null;
+       }
 
        retval = -ENOMEM;
        pht = kzalloc(sizeof(*pht), GFP_KERNEL);
index 1f59ee2..17bbacb 100644 (file)
@@ -417,6 +417,7 @@ xpc_process_activate_IRQ_rcvd_uv(void)
 static void
 xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
                              struct xpc_activate_mq_msghdr_uv *msg_hdr,
+                             int part_setup,
                              int *wakeup_hb_checker)
 {
        unsigned long irq_flags;
@@ -481,6 +482,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
        case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREQUEST_UV: {
                struct xpc_activate_mq_msg_chctl_closerequest_uv *msg;
 
+               if (!part_setup)
+                       break;
+
                msg = container_of(msg_hdr, struct
                                   xpc_activate_mq_msg_chctl_closerequest_uv,
                                   hdr);
@@ -497,6 +501,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
        case XPC_ACTIVATE_MQ_MSG_CHCTL_CLOSEREPLY_UV: {
                struct xpc_activate_mq_msg_chctl_closereply_uv *msg;
 
+               if (!part_setup)
+                       break;
+
                msg = container_of(msg_hdr, struct
                                   xpc_activate_mq_msg_chctl_closereply_uv,
                                   hdr);
@@ -511,6 +518,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
        case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREQUEST_UV: {
                struct xpc_activate_mq_msg_chctl_openrequest_uv *msg;
 
+               if (!part_setup)
+                       break;
+
                msg = container_of(msg_hdr, struct
                                   xpc_activate_mq_msg_chctl_openrequest_uv,
                                   hdr);
@@ -528,6 +538,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
        case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENREPLY_UV: {
                struct xpc_activate_mq_msg_chctl_openreply_uv *msg;
 
+               if (!part_setup)
+                       break;
+
                msg = container_of(msg_hdr, struct
                                   xpc_activate_mq_msg_chctl_openreply_uv, hdr);
                args = &part->remote_openclose_args[msg->ch_number];
@@ -545,6 +558,9 @@ xpc_handle_activate_mq_msg_uv(struct xpc_partition *part,
        case XPC_ACTIVATE_MQ_MSG_CHCTL_OPENCOMPLETE_UV: {
                struct xpc_activate_mq_msg_chctl_opencomplete_uv *msg;
 
+               if (!part_setup)
+                       break;
+
                msg = container_of(msg_hdr, struct
                                xpc_activate_mq_msg_chctl_opencomplete_uv, hdr);
                spin_lock_irqsave(&part->chctl_lock, irq_flags);
@@ -621,6 +637,7 @@ xpc_handle_activate_IRQ_uv(int irq, void *dev_id)
 
                        part_referenced = xpc_part_ref(part);
                        xpc_handle_activate_mq_msg_uv(part, msg_hdr,
+                                                     part_referenced,
                                                      &wakeup_hb_checker);
                        if (part_referenced)
                                xpc_part_deref(part);
index 68d1279..1a02611 100644 (file)
@@ -237,7 +237,7 @@ endchoice
 
 config MMC_ATMELMCI_DMA
        bool "Atmel MCI DMA support (EXPERIMENTAL)"
-       depends on MMC_ATMELMCI && AVR32 && DMA_ENGINE && EXPERIMENTAL
+       depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE && EXPERIMENTAL
        help
          Say Y here to have the Atmel MCI driver use a DMA engine to
          do data transfers and thus increase the throughput and
index 4526d27..4693e62 100644 (file)
@@ -364,6 +364,7 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 {
        struct regulator *reg;
        int ret = 0;
+       int ocr_value = 0;
 
        switch (host->id) {
        case OMAP_MMC1_DEVID:
@@ -396,6 +397,17 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
                }
        } else {
                host->vcc = reg;
+               ocr_value = mmc_regulator_get_ocrmask(reg);
+               if (!mmc_slot(host).ocr_mask) {
+                       mmc_slot(host).ocr_mask = ocr_value;
+               } else {
+                       if (!(mmc_slot(host).ocr_mask & ocr_value)) {
+                               pr_err("MMC%d ocrmask %x is not supported\n",
+                                       host->id, mmc_slot(host).ocr_mask);
+                               mmc_slot(host).ocr_mask = 0;
+                               return -EINVAL;
+                       }
+               }
                mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg);
 
                /* Allow an aux regulator */
@@ -982,6 +994,17 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
        OMAP_HSMMC_WRITE(host->base, SYSCTL,
                         OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
 
+       /*
+        * OMAP4 ES2 and greater has an updated reset logic.
+        * Monitor a 0->1 transition first
+        */
+       if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {
+               while ((!(OMAP_HSMMC_READ(host, SYSCTL) & bit))
+                                       && (i++ < limit))
+                       cpu_relax();
+       }
+       i = 0;
+
        while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
                (i++ < limit))
                cpu_relax();
@@ -2003,6 +2026,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        if (res == NULL || irq < 0)
                return -ENXIO;
 
+       res->start += pdata->reg_offset;
+       res->end += pdata->reg_offset;
        res = request_mem_region(res->start, res->end - res->start + 1,
                                                        pdev->name);
        if (res == NULL)
@@ -2116,23 +2141,9 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
        mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                     MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
 
-       switch (mmc_slot(host).wires) {
-       case 8:
-               mmc->caps |= MMC_CAP_8_BIT_DATA;
-               /* Fall through */
-       case 4:
+       mmc->caps |= mmc_slot(host).caps;
+       if (mmc->caps & MMC_CAP_8_BIT_DATA)
                mmc->caps |= MMC_CAP_4_BIT_DATA;
-               break;
-       case 1:
-               /* Nothing to crib here */
-       case 0:
-               /* Assuming nothing was given by board, Core use's 1-Bit */
-               break;
-       default:
-               /* Completely unexpected.. Core goes with 1-Bit Width */
-               dev_crit(mmc_dev(host->mmc), "Invalid width %d\n used!"
-                       "using 1 instead\n", mmc_slot(host).wires);
-       }
 
        if (mmc_slot(host).nonremovable)
                mmc->caps |= MMC_CAP_NONREMOVABLE;
index 702f598..86fe67f 100644 (file)
@@ -883,14 +883,6 @@ config BFIN_RX_DESC_NUM
        help
          Set the number of buffer packets used in driver.
 
-config BFIN_MAC_RMII
-       bool "RMII PHY Interface"
-       depends on BFIN_MAC
-       default y if BFIN527_EZKIT
-       default n if BFIN537_STAMP
-       help
-         Use Reduced PHY MII Interface
-
 config BFIN_MAC_USE_HWSTAMP
        bool "Use IEEE 1588 hwstamp"
        depends on BFIN_MAC && BF518
index f723319..ce1e5e9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Blackfin On-Chip MAC Driver
  *
- * Copyright 2004-2007 Analog Devices Inc.
+ * Copyright 2004-2010 Analog Devices Inc.
  *
  * Enter bugs at http://blackfin.uclinux.org/
  *
@@ -23,7 +23,6 @@
 #include <linux/device.h>
 #include <linux/spinlock.h>
 #include <linux/mii.h>
-#include <linux/phy.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -76,12 +75,6 @@ static struct net_dma_desc_tx *current_tx_ptr;
 static struct net_dma_desc_tx *tx_desc;
 static struct net_dma_desc_rx *rx_desc;
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-static u16 pin_req[] = P_RMII0;
-#else
-static u16 pin_req[] = P_MII0;
-#endif
-
 static void desc_list_free(void)
 {
        struct net_dma_desc_rx *r;
@@ -347,23 +340,23 @@ static void bfin_mac_adjust_link(struct net_device *dev)
                }
 
                if (phydev->speed != lp->old_speed) {
-#if defined(CONFIG_BFIN_MAC_RMII)
-                       u32 opmode = bfin_read_EMAC_OPMODE();
-                       switch (phydev->speed) {
-                       case 10:
-                               opmode |= RMII_10;
-                               break;
-                       case 100:
-                               opmode &= ~(RMII_10);
-                               break;
-                       default:
-                               printk(KERN_WARNING
-                                       "%s: Ack!  Speed (%d) is not 10/100!\n",
-                                       DRV_NAME, phydev->speed);
-                               break;
+                       if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+                               u32 opmode = bfin_read_EMAC_OPMODE();
+                               switch (phydev->speed) {
+                               case 10:
+                                       opmode |= RMII_10;
+                                       break;
+                               case 100:
+                                       opmode &= ~RMII_10;
+                                       break;
+                               default:
+                                       printk(KERN_WARNING
+                                               "%s: Ack!  Speed (%d) is not 10/100!\n",
+                                               DRV_NAME, phydev->speed);
+                                       break;
+                               }
+                               bfin_write_EMAC_OPMODE(opmode);
                        }
-                       bfin_write_EMAC_OPMODE(opmode);
-#endif
 
                        new_state = 1;
                        lp->old_speed = phydev->speed;
@@ -392,7 +385,7 @@ static void bfin_mac_adjust_link(struct net_device *dev)
 /* MDC  = 2.5 MHz */
 #define MDC_CLK 2500000
 
-static int mii_probe(struct net_device *dev)
+static int mii_probe(struct net_device *dev, int phy_mode)
 {
        struct bfin_mac_local *lp = netdev_priv(dev);
        struct phy_device *phydev = NULL;
@@ -411,8 +404,8 @@ static int mii_probe(struct net_device *dev)
        sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div);
        bfin_write_EMAC_SYSCTL(sysctl);
 
-       /* search for connect PHY device */
-       for (i = 0; i < PHY_MAX_ADDR; i++) {
+       /* search for connected PHY device */
+       for (i = 0; i < PHY_MAX_ADDR; ++i) {
                struct phy_device *const tmp_phydev = lp->mii_bus->phy_map[i];
 
                if (!tmp_phydev)
@@ -429,13 +422,14 @@ static int mii_probe(struct net_device *dev)
                return -ENODEV;
        }
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-       phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-                       0, PHY_INTERFACE_MODE_RMII);
-#else
+       if (phy_mode != PHY_INTERFACE_MODE_RMII &&
+               phy_mode != PHY_INTERFACE_MODE_MII) {
+               printk(KERN_INFO "%s: Invalid phy interface mode\n", dev->name);
+               return -EINVAL;
+       }
+
        phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link,
-                       0, PHY_INTERFACE_MODE_MII);
-#endif
+                       0, phy_mode);
 
        if (IS_ERR(phydev)) {
                printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
@@ -570,6 +564,8 @@ static const struct ethtool_ops bfin_mac_ethtool_ops = {
 /**************************************************************************/
 void setup_system_regs(struct net_device *dev)
 {
+       struct bfin_mac_local *lp = netdev_priv(dev);
+       int i;
        unsigned short sysctl;
 
        /*
@@ -577,6 +573,15 @@ void setup_system_regs(struct net_device *dev)
         * Configure checksum support and rcve frame word alignment
         */
        sysctl = bfin_read_EMAC_SYSCTL();
+       /*
+        * check if interrupt is requested for any PHY,
+        * enable PHY interrupt only if needed
+        */
+       for (i = 0; i < PHY_MAX_ADDR; ++i)
+               if (lp->mii_bus->irq[i] != PHY_POLL)
+                       break;
+       if (i < PHY_MAX_ADDR)
+               sysctl |= PHYIE;
        sysctl |= RXDWA;
 #if defined(BFIN_MAC_CSUM_OFFLOAD)
        sysctl |= RXCKS;
@@ -1203,7 +1208,7 @@ static void bfin_mac_disable(void)
 /*
  * Enable Interrupts, Receive, and Transmit
  */
-static int bfin_mac_enable(void)
+static int bfin_mac_enable(struct phy_device *phydev)
 {
        int ret;
        u32 opmode;
@@ -1233,12 +1238,13 @@ static int bfin_mac_enable(void)
                opmode |= DRO | DC | PSF;
        opmode |= RE;
 
-#if defined(CONFIG_BFIN_MAC_RMII)
-       opmode |= RMII; /* For Now only 100MBit are supported */
+       if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
+               opmode |= RMII; /* For Now only 100MBit are supported */
 #if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2
-       opmode |= TE;
-#endif
+               opmode |= TE;
 #endif
+       }
+
        /* Turn on the EMAC rx */
        bfin_write_EMAC_OPMODE(opmode);
 
@@ -1270,7 +1276,7 @@ static void bfin_mac_timeout(struct net_device *dev)
        if (netif_queue_stopped(lp->ndev))
                netif_wake_queue(lp->ndev);
 
-       bfin_mac_enable();
+       bfin_mac_enable(lp->phydev);
 
        /* We can accept TX packets again */
        dev->trans_start = jiffies; /* prevent tx timeout */
@@ -1342,11 +1348,19 @@ static void bfin_mac_set_multicast_list(struct net_device *dev)
 
 static int bfin_mac_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
 {
+       struct bfin_mac_local *lp = netdev_priv(netdev);
+
+       if (!netif_running(netdev))
+               return -EINVAL;
+
        switch (cmd) {
        case SIOCSHWTSTAMP:
                return bfin_mac_hwtstamp_ioctl(netdev, ifr, cmd);
        default:
-               return -EOPNOTSUPP;
+               if (lp->phydev)
+                       return phy_mii_ioctl(lp->phydev, ifr, cmd);
+               else
+                       return -EOPNOTSUPP;
        }
 }
 
@@ -1394,7 +1408,7 @@ static int bfin_mac_open(struct net_device *dev)
        setup_mac_addr(dev->dev_addr);
 
        bfin_mac_disable();
-       ret = bfin_mac_enable();
+       ret = bfin_mac_enable(lp->phydev);
        if (ret)
                return ret;
        pr_debug("hardware init finished\n");
@@ -1450,6 +1464,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
        struct net_device *ndev;
        struct bfin_mac_local *lp;
        struct platform_device *pd;
+       struct bfin_mii_bus_platform_data *mii_bus_data;
        int rc;
 
        ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
@@ -1501,11 +1516,12 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev)
        if (!lp->mii_bus) {
                dev_err(&pdev->dev, "Cannot get mii_bus!\n");
                rc = -ENODEV;
-               goto out_err_mii_bus_probe;
+               goto out_err_probe_mac;
        }
        lp->mii_bus->priv = ndev;
+       mii_bus_data = pd->dev.platform_data;
 
-       rc = mii_probe(ndev);
+       rc = mii_probe(ndev, mii_bus_data->phy_mode);
        if (rc) {
                dev_err(&pdev->dev, "MII Probe failed!\n");
                goto out_err_mii_probe;
@@ -1552,8 +1568,6 @@ out_err_request_irq:
 out_err_mii_probe:
        mdiobus_unregister(lp->mii_bus);
        mdiobus_free(lp->mii_bus);
-out_err_mii_bus_probe:
-       peripheral_free_list(pin_req);
 out_err_probe_mac:
        platform_set_drvdata(pdev, NULL);
        free_netdev(ndev);
@@ -1576,8 +1590,6 @@ static int __devexit bfin_mac_remove(struct platform_device *pdev)
 
        free_netdev(ndev);
 
-       peripheral_free_list(pin_req);
-
        return 0;
 }
 
@@ -1623,12 +1635,21 @@ static int bfin_mac_resume(struct platform_device *pdev)
 static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
 {
        struct mii_bus *miibus;
+       struct bfin_mii_bus_platform_data *mii_bus_pd;
+       const unsigned short *pin_req;
        int rc, i;
 
+       mii_bus_pd = dev_get_platdata(&pdev->dev);
+       if (!mii_bus_pd) {
+               dev_err(&pdev->dev, "No peripherals in platform data!\n");
+               return -EINVAL;
+       }
+
        /*
         * We are setting up a network card,
         * so set the GPIO pins to Ethernet mode
         */
+       pin_req = mii_bus_pd->mac_peripherals;
        rc = peripheral_request_list(pin_req, DRV_NAME);
        if (rc) {
                dev_err(&pdev->dev, "Requesting peripherals failed!\n");
@@ -1645,13 +1666,30 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
 
        miibus->parent = &pdev->dev;
        miibus->name = "bfin_mii_bus";
+       miibus->phy_mask = mii_bus_pd->phy_mask;
+
        snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
        miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
-       if (miibus->irq == NULL)
-               goto out_err_alloc;
-       for (i = 0; i < PHY_MAX_ADDR; ++i)
+       if (!miibus->irq)
+               goto out_err_irq_alloc;
+
+       for (i = rc; i < PHY_MAX_ADDR; ++i)
                miibus->irq[i] = PHY_POLL;
 
+       rc = clamp(mii_bus_pd->phydev_number, 0, PHY_MAX_ADDR);
+       if (rc != mii_bus_pd->phydev_number)
+               dev_err(&pdev->dev, "Invalid number (%i) of phydevs\n",
+                       mii_bus_pd->phydev_number);
+       for (i = 0; i < rc; ++i) {
+               unsigned short phyaddr = mii_bus_pd->phydev_data[i].addr;
+               if (phyaddr < PHY_MAX_ADDR)
+                       miibus->irq[phyaddr] = mii_bus_pd->phydev_data[i].irq;
+               else
+                       dev_err(&pdev->dev,
+                               "Invalid PHY address %i for phydev %i\n",
+                               phyaddr, i);
+       }
+
        rc = mdiobus_register(miibus);
        if (rc) {
                dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
@@ -1663,6 +1701,7 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
 
 out_err_mdiobus_register:
        kfree(miibus->irq);
+out_err_irq_alloc:
        mdiobus_free(miibus);
 out_err_alloc:
        peripheral_free_list(pin_req);
@@ -1673,11 +1712,15 @@ out_err_alloc:
 static int __devexit bfin_mii_bus_remove(struct platform_device *pdev)
 {
        struct mii_bus *miibus = platform_get_drvdata(pdev);
+       struct bfin_mii_bus_platform_data *mii_bus_pd =
+               dev_get_platdata(&pdev->dev);
+
        platform_set_drvdata(pdev, NULL);
        mdiobus_unregister(miibus);
        kfree(miibus->irq);
        mdiobus_free(miibus);
-       peripheral_free_list(pin_req);
+       peripheral_free_list(mii_bus_pd->mac_peripherals);
+
        return 0;
 }
 
index 04e4050..aed68be 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/clocksource.h>
 #include <linux/timecompare.h>
 #include <linux/timer.h>
+#include <linux/etherdevice.h>
+#include <linux/bfin_mac.h>
 
 #define BFIN_MAC_CSUM_OFFLOAD
 
index 1439064..f6e0d40 100644 (file)
@@ -124,6 +124,13 @@ static int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
        return 0;
 }
 
+static void *mlx4_en_get_netdev(struct mlx4_dev *dev, void *ctx, u8 port)
+{
+       struct mlx4_en_dev *endev = ctx;
+
+       return endev->pndev[port];
+}
+
 static void mlx4_en_event(struct mlx4_dev *dev, void *endev_ptr,
                          enum mlx4_dev_event event, int port)
 {
@@ -282,9 +289,11 @@ err_free_res:
 }
 
 static struct mlx4_interface mlx4_en_interface = {
-       .add    = mlx4_en_add,
-       .remove = mlx4_en_remove,
-       .event  = mlx4_en_event,
+       .add            = mlx4_en_add,
+       .remove         = mlx4_en_remove,
+       .event          = mlx4_en_event,
+       .get_dev        = mlx4_en_get_netdev,
+       .protocol       = MLX4_PROTOCOL_EN,
 };
 
 static int __init mlx4_en_init(void)
index 79478bd..6d6806b 100644 (file)
@@ -69,6 +69,7 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
        int err;
+       int idx;
 
        if (!priv->vlgrp)
                return;
@@ -83,7 +84,10 @@ static void mlx4_en_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
                if (err)
                        en_err(priv, "Failed configuring VLAN filter\n");
        }
+       if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx))
+               en_err(priv, "failed adding vlan %d\n", vid);
        mutex_unlock(&mdev->state_lock);
+
 }
 
 static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
@@ -91,6 +95,7 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
        int err;
+       int idx;
 
        if (!priv->vlgrp)
                return;
@@ -101,6 +106,11 @@ static void mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
        /* Remove VID from port VLAN filter */
        mutex_lock(&mdev->state_lock);
+       if (!mlx4_find_cached_vlan(mdev->dev, priv->port, vid, &idx))
+               mlx4_unregister_vlan(mdev->dev, priv->port, idx);
+       else
+               en_err(priv, "could not find vid %d in cache\n", vid);
+
        if (mdev->device_up && priv->port_up) {
                err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
                if (err)
index aa3ef2a..7f5a322 100644 (file)
@@ -127,8 +127,8 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
        memset(context, 0, sizeof *context);
 
        context->base_qpn = cpu_to_be32(base_qpn);
-       context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT | base_qpn);
-       context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_SHIFT | base_qpn);
+       context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
+       context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_MODE_SHIFT | base_qpn);
        context->intra_no_vlan = 0;
        context->no_vlan = MLX4_NO_VLAN_IDX;
        context->intra_vlan_miss = 0;
index f6511aa..092e814 100644 (file)
@@ -36,7 +36,8 @@
 
 
 #define SET_PORT_GEN_ALL_VALID 0x7
-#define SET_PORT_PROMISC_SHIFT 31
+#define SET_PORT_PROMISC_EN_SHIFT      31
+#define SET_PORT_PROMISC_MODE_SHIFT    30
 
 enum {
        MLX4_CMD_SET_VLAN_FLTR  = 0x47,
index b716e1a..b68eee2 100644 (file)
@@ -98,7 +98,8 @@ static void dump_dev_cap_flags(struct mlx4_dev *dev, u32 flags)
                [20] = "Address vector port checking support",
                [21] = "UD multicast support",
                [24] = "Demand paging support",
-               [25] = "Router support"
+               [25] = "Router support",
+               [30] = "IBoE support"
        };
        int i;
 
index 5550678..73c94fc 100644 (file)
@@ -161,3 +161,24 @@ void mlx4_unregister_device(struct mlx4_dev *dev)
 
        mutex_unlock(&intf_mutex);
 }
+
+void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port)
+{
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       struct mlx4_device_context *dev_ctx;
+       unsigned long flags;
+       void *result = NULL;
+
+       spin_lock_irqsave(&priv->ctx_lock, flags);
+
+       list_for_each_entry(dev_ctx, &priv->ctx_list, list)
+               if (dev_ctx->intf->protocol == proto && dev_ctx->intf->get_dev) {
+                       result = dev_ctx->intf->get_dev(dev, dev_ctx->context, port);
+                       break;
+               }
+
+       spin_unlock_irqrestore(&priv->ctx_lock, flags);
+
+       return result;
+}
+EXPORT_SYMBOL_GPL(mlx4_get_protocol_dev);
index 569fa3d..782f11d 100644 (file)
@@ -103,7 +103,7 @@ MODULE_PARM_DESC(use_prio, "Enable steering by VLAN priority on ETH ports "
 
 static int log_mtts_per_seg = ilog2(MLX4_MTT_ENTRY_PER_SEG);
 module_param_named(log_mtts_per_seg, log_mtts_per_seg, int, 0444);
-MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-5)");
+MODULE_PARM_DESC(log_mtts_per_seg, "Log2 number of MTT entries per segment (1-7)");
 
 int mlx4_check_port_params(struct mlx4_dev *dev,
                           enum mlx4_port_type *port_type)
@@ -1310,7 +1310,7 @@ static int __init mlx4_verify_params(void)
                return -1;
        }
 
-       if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 5)) {
+       if ((log_mtts_per_seg < 1) || (log_mtts_per_seg > 7)) {
                pr_warning("mlx4_core: bad log_mtts_per_seg: %d\n", log_mtts_per_seg);
                return -1;
        }
index 1fc16ab..dfed6a0 100644 (file)
@@ -475,6 +475,7 @@ struct mlx4_en_priv {
        char *mc_addrs;
        int mc_addrs_cnt;
        struct mlx4_en_stat_out_mbox hw_stats;
+       int vids[128];
 };
 
 
index 606aa58..56371ef 100644 (file)
@@ -182,6 +182,25 @@ static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
        return err;
 }
 
+int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx)
+{
+       struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
+       int i;
+
+       for (i = 0; i < MLX4_MAX_VLAN_NUM; ++i) {
+               if (table->refs[i] &&
+                   (vid == (MLX4_VLAN_MASK &
+                             be32_to_cpu(table->entries[i])))) {
+                       /* VLAN already registered, increase reference count */
+                       *idx = i;
+                       return 0;
+               }
+       }
+
+       return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(mlx4_find_cached_vlan);
+
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
 {
        struct mlx4_vlan_table *table = &mlx4_priv(dev)->port[port].vlan_table;
index f3f8be5..14f0955 100644 (file)
@@ -430,8 +430,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
        }
 
        /* Get the protocol type of the ethernet frame that arrived */
-       proto_type = ((in_be32(addr + XEL_HEADER_OFFSET +
-                       XEL_RXBUFF_OFFSET) >> XEL_HEADER_SHIFT) &
+       proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET +
+                       XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
                        XEL_RPLR_LENGTH_MASK);
 
        /* Check if received ethernet frame is a raw ethernet frame
@@ -439,9 +439,9 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data)
        if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
 
                if (proto_type == ETH_P_IP) {
-                       length = ((in_be32(addr +
+                       length = ((ntohl(in_be32(addr +
                                        XEL_HEADER_IP_LENGTH_OFFSET +
-                                       XEL_RXBUFF_OFFSET) >>
+                                       XEL_RXBUFF_OFFSET)) >>
                                        XEL_HEADER_SHIFT) &
                                        XEL_RPLR_LENGTH_MASK);
                        length += ETH_HLEN + ETH_FCS_LEN;
index 0bab84e..19bc736 100644 (file)
@@ -12,11 +12,12 @@ void pnp_unregister_protocol(struct pnp_protocol *protocol);
 
 #define PNP_EISA_ID_MASK 0x7fffffff
 void pnp_eisa_id_to_string(u32 id, char *str);
-struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id, char *pnpid);
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *, int id,
+                             const char *pnpid);
 struct pnp_card *pnp_alloc_card(struct pnp_protocol *, int id, char *pnpid);
 
 int pnp_add_device(struct pnp_dev *dev);
-struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id);
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id);
 
 int pnp_add_card(struct pnp_card *card);
 void pnp_remove_card(struct pnp_card *card);
index 88b3cde..0f34d96 100644 (file)
@@ -124,7 +124,8 @@ static void pnp_release_device(struct device *dmdev)
        kfree(dev);
 }
 
-struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id, char *pnpid)
+struct pnp_dev *pnp_alloc_dev(struct pnp_protocol *protocol, int id,
+                             const char *pnpid)
 {
        struct pnp_dev *dev;
        struct pnp_id *dev_id;
@@ -194,8 +195,9 @@ int pnp_add_device(struct pnp_dev *dev)
        for (id = dev->id; id; id = id->next)
                len += scnprintf(buf + len, sizeof(buf) - len, " %s", id->id);
 
-       pnp_dbg(&dev->dev, "%s device, IDs%s (%s)\n",
-               dev->protocol->name, buf, dev->active ? "active" : "disabled");
+       dev_printk(KERN_DEBUG, &dev->dev, "%s device, IDs%s (%s)\n",
+                  dev->protocol->name, buf,
+                  dev->active ? "active" : "disabled");
        return 0;
 }
 
index cd11b11..d1dbb9d 100644 (file)
@@ -236,7 +236,7 @@ void pnp_unregister_driver(struct pnp_driver *drv)
  * @dev: pointer to the desired device
  * @id: pointer to an EISA id string
  */
-struct pnp_id *pnp_add_id(struct pnp_dev *dev, char *id)
+struct pnp_id *pnp_add_id(struct pnp_dev *dev, const char *id)
 {
        struct pnp_id *dev_id, *ptr;
 
index dc4e32e..2d73dfc 100644 (file)
@@ -28,7 +28,7 @@
 #include "../base.h"
 #include "pnpacpi.h"
 
-static int num = 0;
+static int num;
 
 /* We need only to blacklist devices that have already an acpi driver that
  * can't use pnp layer. We don't need to blacklist device that are directly
@@ -59,7 +59,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev)
 #define TEST_ALPHA(c) \
        if (!('@' <= (c) || (c) <= 'Z')) \
                return 0
-static int __init ispnpidacpi(char *id)
+static int __init ispnpidacpi(const char *id)
 {
        TEST_ALPHA(id[0]);
        TEST_ALPHA(id[1]);
@@ -180,11 +180,24 @@ struct pnp_protocol pnpacpi_protocol = {
 };
 EXPORT_SYMBOL(pnpacpi_protocol);
 
+static char *pnpacpi_get_id(struct acpi_device *device)
+{
+       struct acpi_hardware_id *id;
+
+       list_for_each_entry(id, &device->pnp.ids, list) {
+               if (ispnpidacpi(id->id))
+                       return id->id;
+       }
+
+       return NULL;
+}
+
 static int __init pnpacpi_add_device(struct acpi_device *device)
 {
        acpi_handle temp = NULL;
        acpi_status status;
        struct pnp_dev *dev;
+       char *pnpid;
        struct acpi_hardware_id *id;
 
        /*
@@ -192,11 +205,17 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
         * driver should not be loaded.
         */
        status = acpi_get_handle(device->handle, "_CRS", &temp);
-       if (ACPI_FAILURE(status) || !ispnpidacpi(acpi_device_hid(device)) ||
-           is_exclusive_device(device) || (!device->status.present))
+       if (ACPI_FAILURE(status))
+               return 0;
+
+       pnpid = pnpacpi_get_id(device);
+       if (!pnpid)
+               return 0;
+
+       if (is_exclusive_device(device) || !device->status.present)
                return 0;
 
-       dev = pnp_alloc_dev(&pnpacpi_protocol, num, acpi_device_hid(device));
+       dev = pnp_alloc_dev(&pnpacpi_protocol, num, pnpid);
        if (!dev)
                return -ENOMEM;
 
@@ -227,7 +246,7 @@ static int __init pnpacpi_add_device(struct acpi_device *device)
                pnpacpi_parse_resource_option_data(dev);
 
        list_for_each_entry(id, &device->pnp.ids, list) {
-               if (!strcmp(id->id, acpi_device_hid(device)))
+               if (!strcmp(id->id, pnpid))
                        continue;
                if (!ispnpidacpi(id->id))
                        continue;
index e3446ab..a925e6b 100644 (file)
@@ -523,7 +523,7 @@ struct pnp_resource *pnp_add_irq_resource(struct pnp_dev *dev, int irq,
        res->start = irq;
        res->end = irq;
 
-       pnp_dbg(&dev->dev, "  add %pr\n", res);
+       dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
        return pnp_res;
 }
 
@@ -544,7 +544,7 @@ struct pnp_resource *pnp_add_dma_resource(struct pnp_dev *dev, int dma,
        res->start = dma;
        res->end = dma;
 
-       pnp_dbg(&dev->dev, "  add %pr\n", res);
+       dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
        return pnp_res;
 }
 
@@ -568,7 +568,7 @@ struct pnp_resource *pnp_add_io_resource(struct pnp_dev *dev,
        res->start = start;
        res->end = end;
 
-       pnp_dbg(&dev->dev, "  add %pr\n", res);
+       dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
        return pnp_res;
 }
 
@@ -592,7 +592,7 @@ struct pnp_resource *pnp_add_mem_resource(struct pnp_dev *dev,
        res->start = start;
        res->end = end;
 
-       pnp_dbg(&dev->dev, "  add %pr\n", res);
+       dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
        return pnp_res;
 }
 
@@ -616,7 +616,7 @@ struct pnp_resource *pnp_add_bus_resource(struct pnp_dev *dev,
        res->start = start;
        res->end = end;
 
-       pnp_dbg(&dev->dev, "  add %pr\n", res);
+       dev_printk(KERN_DEBUG, &dev->dev, "%pR\n", res);
        return pnp_res;
 }
 
index 0734356..60d83d9 100644 (file)
@@ -64,8 +64,7 @@ config TEST_POWER
 
 config BATTERY_DS2760
        tristate "DS2760 battery driver (HP iPAQ & others)"
-       select W1
-       select W1_SLAVE_DS2760
+       depends on W1 && W1_SLAVE_DS2760
        help
          Say Y here to enable support for batteries with ds2760 chip.
 
@@ -109,6 +108,13 @@ config BATTERY_WM97XX
        help
          Say Y to enable support for battery measured by WM97xx aux port.
 
+config BATTERY_BQ20Z75
+        tristate "TI BQ20z75 gas gauge"
+        depends on I2C
+        help
+         Say Y to include support for TI BQ20z75 SBS-compliant
+         gas gauge and protection IC.
+
 config BATTERY_BQ27x00
        tristate "BQ27x00 battery driver"
        depends on I2C
@@ -166,4 +172,17 @@ config BATTERY_INTEL_MID
          Say Y here to enable the battery driver on Intel MID
          platforms.
 
+config CHARGER_ISP1704
+       tristate "ISP1704 USB Charger Detection"
+       depends on USB_OTG_UTILS
+       help
+         Say Y to enable support for USB Charger Detection with
+         ISP1707/ISP1704 USB transceivers.
+
+config CHARGER_TWL4030
+       tristate "OMAP TWL4030 BCI charger driver"
+       depends on TWL4030_CORE
+       help
+         Say Y here to enable support for TWL4030 Battery Charge Interface.
+
 endif # POWER_SUPPLY
index 10143aa..c75772e 100644 (file)
@@ -1,16 +1,8 @@
-power_supply-objs := power_supply_core.o
+ccflags-$(CONFIG_POWER_SUPPLY_DEBUG) := -DDEBUG
 
-ifeq ($(CONFIG_SYSFS),y)
-power_supply-objs += power_supply_sysfs.o
-endif
-
-ifeq ($(CONFIG_LEDS_TRIGGERS),y)
-power_supply-objs += power_supply_leds.o
-endif
-
-ifeq ($(CONFIG_POWER_SUPPLY_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+power_supply-y                         := power_supply_core.o
+power_supply-$(CONFIG_SYSFS)           += power_supply_sysfs.o
+power_supply-$(CONFIG_LEDS_TRIGGERS)   += power_supply_leds.o
 
 obj-$(CONFIG_POWER_SUPPLY)     += power_supply.o
 
@@ -29,6 +21,7 @@ obj-$(CONFIG_BATTERY_OLPC)    += olpc_battery.o
 obj-$(CONFIG_BATTERY_TOSA)     += tosa_battery.o
 obj-$(CONFIG_BATTERY_COLLIE)   += collie_battery.o
 obj-$(CONFIG_BATTERY_WM97XX)   += wm97xx_battery.o
+obj-$(CONFIG_BATTERY_BQ20Z75)  += bq20z75.o
 obj-$(CONFIG_BATTERY_BQ27x00)  += bq27x00_battery.o
 obj-$(CONFIG_BATTERY_DA9030)   += da9030_battery.o
 obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
@@ -37,3 +30,5 @@ obj-$(CONFIG_BATTERY_S3C_ADC) += s3c_adc_battery.o
 obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
 obj-$(CONFIG_BATTERY_JZ4740)   += jz4740-battery.o
 obj-$(CONFIG_BATTERY_INTEL_MID)        += intel_mid_battery.o
+obj-$(CONFIG_CHARGER_ISP1704)  += isp1704_charger.o
+obj-$(CONFIG_CHARGER_TWL4030)  += twl4030_charger.o
diff --git a/drivers/power/bq20z75.c b/drivers/power/bq20z75.c
new file mode 100644 (file)
index 0000000..492da27
--- /dev/null
@@ -0,0 +1,493 @@
+/*
+ * Gas Gauge driver for TI's BQ20Z75
+ *
+ * Copyright (c) 2010, 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.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+
+enum {
+       REG_MANUFACTURER_DATA,
+       REG_TEMPERATURE,
+       REG_VOLTAGE,
+       REG_CURRENT,
+       REG_CAPACITY,
+       REG_TIME_TO_EMPTY,
+       REG_TIME_TO_FULL,
+       REG_STATUS,
+       REG_CYCLE_COUNT,
+       REG_SERIAL_NUMBER,
+       REG_REMAINING_CAPACITY,
+       REG_FULL_CHARGE_CAPACITY,
+       REG_DESIGN_CAPACITY,
+       REG_DESIGN_VOLTAGE,
+};
+
+/* manufacturer access defines */
+#define MANUFACTURER_ACCESS_STATUS     0x0006
+#define MANUFACTURER_ACCESS_SLEEP      0x0011
+
+/* battery status value bits */
+#define BATTERY_DISCHARGING            0x40
+#define BATTERY_FULL_CHARGED           0x20
+#define BATTERY_FULL_DISCHARGED                0x10
+
+#define BQ20Z75_DATA(_psp, _addr, _min_value, _max_value) { \
+       .psp = _psp, \
+       .addr = _addr, \
+       .min_value = _min_value, \
+       .max_value = _max_value, \
+}
+
+static const struct bq20z75_device_data {
+       enum power_supply_property psp;
+       u8 addr;
+       int min_value;
+       int max_value;
+} bq20z75_data[] = {
+       [REG_MANUFACTURER_DATA] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
+       [REG_TEMPERATURE] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
+       [REG_VOLTAGE] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
+       [REG_CURRENT] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768,
+                       32767),
+       [REG_CAPACITY] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
+       [REG_REMAINING_CAPACITY] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
+       [REG_FULL_CHARGE_CAPACITY] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
+       [REG_TIME_TO_EMPTY] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0,
+                       65535),
+       [REG_TIME_TO_FULL] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0,
+                       65535),
+       [REG_STATUS] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
+       [REG_CYCLE_COUNT] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
+       [REG_DESIGN_CAPACITY] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0,
+                       65535),
+       [REG_DESIGN_VOLTAGE] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0,
+                       65535),
+       [REG_SERIAL_NUMBER] =
+               BQ20Z75_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
+};
+
+static enum power_supply_property bq20z75_properties[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_TECHNOLOGY,
+       POWER_SUPPLY_PROP_CYCLE_COUNT,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+       POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
+       POWER_SUPPLY_PROP_SERIAL_NUMBER,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+       POWER_SUPPLY_PROP_ENERGY_NOW,
+       POWER_SUPPLY_PROP_ENERGY_FULL,
+       POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+};
+
+struct bq20z75_info {
+       struct i2c_client       *client;
+       struct power_supply     power_supply;
+};
+
+static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
+{
+       s32 ret;
+
+       ret = i2c_smbus_read_word_data(client, address);
+       if (ret < 0) {
+               dev_err(&client->dev,
+                       "%s: i2c read at address 0x%x failed\n",
+                       __func__, address);
+               return ret;
+       }
+       return le16_to_cpu(ret);
+}
+
+static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
+       u16 value)
+{
+       s32 ret;
+
+       ret = i2c_smbus_write_word_data(client, address, le16_to_cpu(value));
+       if (ret < 0) {
+               dev_err(&client->dev,
+                       "%s: i2c write to address 0x%x failed\n",
+                       __func__, address);
+               return ret;
+       }
+       return 0;
+}
+
+static int bq20z75_get_battery_presence_and_health(
+       struct i2c_client *client, enum power_supply_property psp,
+       union power_supply_propval *val)
+{
+       s32 ret;
+
+       /* Write to ManufacturerAccess with
+        * ManufacturerAccess command and then
+        * read the status */
+       ret = bq20z75_write_word_data(client,
+               bq20z75_data[REG_MANUFACTURER_DATA].addr,
+               MANUFACTURER_ACCESS_STATUS);
+       if (ret < 0)
+               return ret;
+
+
+       ret = bq20z75_read_word_data(client,
+               bq20z75_data[REG_MANUFACTURER_DATA].addr);
+       if (ret < 0)
+               return ret;
+
+       if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
+           ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
+               val->intval = 0;
+               return 0;
+       }
+
+       /* Mask the upper nibble of 2nd byte and
+        * lower byte of response then
+        * shift the result by 8 to get status*/
+       ret &= 0x0F00;
+       ret >>= 8;
+       if (psp == POWER_SUPPLY_PROP_PRESENT) {
+               if (ret == 0x0F)
+                       /* battery removed */
+                       val->intval = 0;
+               else
+                       val->intval = 1;
+       } else if (psp == POWER_SUPPLY_PROP_HEALTH) {
+               if (ret == 0x09)
+                       val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+               else if (ret == 0x0B)
+                       val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+               else if (ret == 0x0C)
+                       val->intval = POWER_SUPPLY_HEALTH_DEAD;
+               else
+                       val->intval = POWER_SUPPLY_HEALTH_GOOD;
+       }
+
+       return 0;
+}
+
+static int bq20z75_get_battery_property(struct i2c_client *client,
+       int reg_offset, enum power_supply_property psp,
+       union power_supply_propval *val)
+{
+       s32 ret;
+
+       ret = bq20z75_read_word_data(client,
+               bq20z75_data[reg_offset].addr);
+       if (ret < 0)
+               return ret;
+
+       /* returned values are 16 bit */
+       if (bq20z75_data[reg_offset].min_value < 0)
+               ret = (s16)ret;
+
+       if (ret >= bq20z75_data[reg_offset].min_value &&
+           ret <= bq20z75_data[reg_offset].max_value) {
+               val->intval = ret;
+               if (psp == POWER_SUPPLY_PROP_STATUS) {
+                       if (ret & BATTERY_FULL_CHARGED)
+                               val->intval = POWER_SUPPLY_STATUS_FULL;
+                       else if (ret & BATTERY_FULL_DISCHARGED)
+                               val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+                       else if (ret & BATTERY_DISCHARGING)
+                               val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+                       else
+                               val->intval = POWER_SUPPLY_STATUS_CHARGING;
+               }
+       } else {
+               if (psp == POWER_SUPPLY_PROP_STATUS)
+                       val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+               else
+                       val->intval = 0;
+       }
+
+       return 0;
+}
+
+static void  bq20z75_unit_adjustment(struct i2c_client *client,
+       enum power_supply_property psp, union power_supply_propval *val)
+{
+#define BASE_UNIT_CONVERSION           1000
+#define BATTERY_MODE_CAP_MULT_WATT     (10 * BASE_UNIT_CONVERSION)
+#define TIME_UNIT_CONVERSION           600
+#define TEMP_KELVIN_TO_CELCIUS         2731
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ENERGY_NOW:
+       case POWER_SUPPLY_PROP_ENERGY_FULL:
+       case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+               val->intval *= BATTERY_MODE_CAP_MULT_WATT;
+               break;
+
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               val->intval *= BASE_UNIT_CONVERSION;
+               break;
+
+       case POWER_SUPPLY_PROP_TEMP:
+               /* bq20z75 provides battery tempreture in 0.1°K
+                * so convert it to 0.1°C */
+               val->intval -= TEMP_KELVIN_TO_CELCIUS;
+               val->intval *= 10;
+               break;
+
+       case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+       case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
+               val->intval *= TIME_UNIT_CONVERSION;
+               break;
+
+       default:
+               dev_dbg(&client->dev,
+                       "%s: no need for unit conversion %d\n", __func__, psp);
+       }
+}
+
+static int bq20z75_get_battery_capacity(struct i2c_client *client,
+       int reg_offset, enum power_supply_property psp,
+       union power_supply_propval *val)
+{
+       s32 ret;
+
+       ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
+       if (ret < 0)
+               return ret;
+
+       if (psp == POWER_SUPPLY_PROP_CAPACITY) {
+               /* bq20z75 spec says that this can be >100 %
+               * even if max value is 100 % */
+               val->intval = min(ret, 100);
+       } else
+               val->intval = ret;
+
+       return 0;
+}
+
+static char bq20z75_serial[5];
+static int bq20z75_get_battery_serial_number(struct i2c_client *client,
+       union power_supply_propval *val)
+{
+       int ret;
+
+       ret = bq20z75_read_word_data(client,
+               bq20z75_data[REG_SERIAL_NUMBER].addr);
+       if (ret < 0)
+               return ret;
+
+       ret = sprintf(bq20z75_serial, "%04x", ret);
+       val->strval = bq20z75_serial;
+
+       return 0;
+}
+
+static int bq20z75_get_property(struct power_supply *psy,
+       enum power_supply_property psp,
+       union power_supply_propval *val)
+{
+       int count;
+       int ret;
+       struct bq20z75_info *bq20z75_device = container_of(psy,
+                               struct bq20z75_info, power_supply);
+       struct i2c_client *client = bq20z75_device->client;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_PRESENT:
+       case POWER_SUPPLY_PROP_HEALTH:
+               ret = bq20z75_get_battery_presence_and_health(client, psp, val);
+               if (ret)
+                       return ret;
+               break;
+
+       case POWER_SUPPLY_PROP_TECHNOLOGY:
+               val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+               break;
+
+       case POWER_SUPPLY_PROP_ENERGY_NOW:
+       case POWER_SUPPLY_PROP_ENERGY_FULL:
+       case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+       case POWER_SUPPLY_PROP_CAPACITY:
+               for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) {
+                       if (psp == bq20z75_data[count].psp)
+                               break;
+               }
+
+               ret = bq20z75_get_battery_capacity(client, count, psp, val);
+               if (ret)
+                       return ret;
+
+               break;
+
+       case POWER_SUPPLY_PROP_SERIAL_NUMBER:
+               ret = bq20z75_get_battery_serial_number(client, val);
+               if (ret)
+                       return ret;
+               break;
+
+       case POWER_SUPPLY_PROP_STATUS:
+       case POWER_SUPPLY_PROP_CYCLE_COUNT:
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+       case POWER_SUPPLY_PROP_TEMP:
+       case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+       case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) {
+                       if (psp == bq20z75_data[count].psp)
+                               break;
+               }
+
+               ret = bq20z75_get_battery_property(client, count, psp, val);
+               if (ret)
+                       return ret;
+
+               break;
+
+       default:
+               dev_err(&client->dev,
+                       "%s: INVALID property\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Convert units to match requirements for power supply class */
+       bq20z75_unit_adjustment(client, psp, val);
+
+       dev_dbg(&client->dev,
+               "%s: property = %d, value = %d\n", __func__, psp, val->intval);
+
+       return 0;
+}
+
+static int bq20z75_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
+{
+       struct bq20z75_info *bq20z75_device;
+       int rc;
+
+       bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL);
+       if (!bq20z75_device)
+               return -ENOMEM;
+
+       bq20z75_device->client = client;
+       bq20z75_device->power_supply.name = "battery";
+       bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
+       bq20z75_device->power_supply.properties = bq20z75_properties;
+       bq20z75_device->power_supply.num_properties =
+               ARRAY_SIZE(bq20z75_properties);
+       bq20z75_device->power_supply.get_property = bq20z75_get_property;
+
+       i2c_set_clientdata(client, bq20z75_device);
+
+       rc = power_supply_register(&client->dev, &bq20z75_device->power_supply);
+       if (rc) {
+               dev_err(&client->dev,
+                       "%s: Failed to register power supply\n", __func__);
+               kfree(bq20z75_device);
+               return rc;
+       }
+
+       dev_info(&client->dev,
+               "%s: battery gas gauge device registered\n", client->name);
+
+       return 0;
+}
+
+static int bq20z75_remove(struct i2c_client *client)
+{
+       struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+
+       power_supply_unregister(&bq20z75_device->power_supply);
+       kfree(bq20z75_device);
+       bq20z75_device = NULL;
+
+       return 0;
+}
+
+#if defined CONFIG_PM
+static int bq20z75_suspend(struct i2c_client *client,
+       pm_message_t state)
+{
+       s32 ret;
+
+       /* write to manufacturer access with sleep command */
+       ret = bq20z75_write_word_data(client,
+               bq20z75_data[REG_MANUFACTURER_DATA].addr,
+               MANUFACTURER_ACCESS_SLEEP);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+#else
+#define bq20z75_suspend                NULL
+#endif
+/* any smbus transaction will wake up bq20z75 */
+#define bq20z75_resume         NULL
+
+static const struct i2c_device_id bq20z75_id[] = {
+       { "bq20z75", 0 },
+       {}
+};
+
+static struct i2c_driver bq20z75_battery_driver = {
+       .probe          = bq20z75_probe,
+       .remove         = bq20z75_remove,
+       .suspend        = bq20z75_suspend,
+       .resume         = bq20z75_resume,
+       .id_table       = bq20z75_id,
+       .driver = {
+               .name   = "bq20z75-battery",
+       },
+};
+
+static int __init bq20z75_battery_init(void)
+{
+       return i2c_add_driver(&bq20z75_battery_driver);
+}
+module_init(bq20z75_battery_init);
+
+static void __exit bq20z75_battery_exit(void)
+{
+       i2c_del_driver(&bq20z75_battery_driver);
+}
+module_exit(bq20z75_battery_exit);
+
+MODULE_DESCRIPTION("BQ20z75 battery monitor driver");
+MODULE_LICENSE("GPL");
index 3ec9c6a..eff0273 100644 (file)
@@ -418,6 +418,7 @@ static int bq27x00_battery_remove(struct i2c_client *client)
 
        power_supply_unregister(&di->bat);
 
+       kfree(di->bus);
        kfree(di->bat.name);
 
        mutex_lock(&battery_mutex);
index 4d3b272..b3c01c1 100644 (file)
@@ -586,6 +586,7 @@ static int ds2760_battery_remove(struct platform_device *pdev)
                                          &di->set_charged_work);
        destroy_workqueue(di->monitor_wqueue);
        power_supply_unregister(&di->bat);
+       kfree(di);
 
        return 0;
 }
index 84d3c43..6957e8a 100644 (file)
@@ -44,8 +44,8 @@ struct ds278x_info;
 
 struct ds278x_battery_ops {
        int (*get_battery_current)(struct ds278x_info *info, int *current_uA);
-       int (*get_battery_voltage)(struct ds278x_info *info, int *voltage_uA);
-       int (*get_battery_capacity)(struct ds278x_info *info, int *capacity_uA);
+       int (*get_battery_voltage)(struct ds278x_info *info, int *voltage_uV);
+       int (*get_battery_capacity)(struct ds278x_info *info, int *capacity);
 };
 
 #define to_ds278x_info(x) container_of(x, struct ds278x_info, battery)
@@ -137,7 +137,7 @@ static int ds2782_get_current(struct ds278x_info *info, int *current_uA)
        return 0;
 }
 
-static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uA)
+static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uV)
 {
        s16 raw;
        int err;
@@ -149,7 +149,7 @@ static int ds2782_get_voltage(struct ds278x_info *info, int *voltage_uA)
        err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
        if (err)
                return err;
-       *voltage_uA = (raw / 32) * 4800;
+       *voltage_uV = (raw / 32) * 4800;
        return 0;
 }
 
@@ -177,7 +177,7 @@ static int ds2786_get_current(struct ds278x_info *info, int *current_uA)
        return 0;
 }
 
-static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uA)
+static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uV)
 {
        s16 raw;
        int err;
@@ -189,7 +189,7 @@ static int ds2786_get_voltage(struct ds278x_info *info, int *voltage_uA)
        err = ds278x_read_reg16(info, DS278x_REG_VOLT_MSB, &raw);
        if (err)
                return err;
-       *voltage_uA = (raw / 8) * 1220;
+       *voltage_uV = (raw / 8) * 1220;
        return 0;
 }
 
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
new file mode 100644 (file)
index 0000000..7251218
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * ISP1704 USB Charger Detection driver
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/delay.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+/* Vendor specific Power Control register */
+#define ISP1704_PWR_CTRL               0x3d
+#define ISP1704_PWR_CTRL_SWCTRL                (1 << 0)
+#define ISP1704_PWR_CTRL_DET_COMP      (1 << 1)
+#define ISP1704_PWR_CTRL_BVALID_RISE   (1 << 2)
+#define ISP1704_PWR_CTRL_BVALID_FALL   (1 << 3)
+#define ISP1704_PWR_CTRL_DP_WKPU_EN    (1 << 4)
+#define ISP1704_PWR_CTRL_VDAT_DET      (1 << 5)
+#define ISP1704_PWR_CTRL_DPVSRC_EN     (1 << 6)
+#define ISP1704_PWR_CTRL_HWDETECT      (1 << 7)
+
+#define NXP_VENDOR_ID                  0x04cc
+
+static u16 isp170x_id[] = {
+       0x1704,
+       0x1707,
+};
+
+struct isp1704_charger {
+       struct device           *dev;
+       struct power_supply     psy;
+       struct otg_transceiver  *otg;
+       struct notifier_block   nb;
+       struct work_struct      work;
+
+       char                    model[7];
+       unsigned                present:1;
+};
+
+/*
+ * ISP1704 detects PS/2 adapters as charger. To make sure the detected charger
+ * is actually a dedicated charger, the following steps need to be taken.
+ */
+static inline int isp1704_charger_verify(struct isp1704_charger *isp)
+{
+       int     ret = 0;
+       u8      r;
+
+       /* Reset the transceiver */
+       r = otg_io_read(isp->otg, ULPI_FUNC_CTRL);
+       r |= ULPI_FUNC_CTRL_RESET;
+       otg_io_write(isp->otg, ULPI_FUNC_CTRL, r);
+       usleep_range(1000, 2000);
+
+       /* Set normal mode */
+       r &= ~(ULPI_FUNC_CTRL_RESET | ULPI_FUNC_CTRL_OPMODE_MASK);
+       otg_io_write(isp->otg, ULPI_FUNC_CTRL, r);
+
+       /* Clear the DP and DM pull-down bits */
+       r = ULPI_OTG_CTRL_DP_PULLDOWN | ULPI_OTG_CTRL_DM_PULLDOWN;
+       otg_io_write(isp->otg, ULPI_CLR(ULPI_OTG_CTRL), r);
+
+       /* Enable strong pull-up on DP (1.5K) and reset */
+       r = ULPI_FUNC_CTRL_TERMSELECT | ULPI_FUNC_CTRL_RESET;
+       otg_io_write(isp->otg, ULPI_SET(ULPI_FUNC_CTRL), r);
+       usleep_range(1000, 2000);
+
+       /* Read the line state */
+       if (!otg_io_read(isp->otg, ULPI_DEBUG)) {
+               /* Disable strong pull-up on DP (1.5K) */
+               otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL),
+                               ULPI_FUNC_CTRL_TERMSELECT);
+               return 1;
+       }
+
+       /* Is it a charger or PS/2 connection */
+
+       /* Enable weak pull-up resistor on DP */
+       otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL),
+                       ISP1704_PWR_CTRL_DP_WKPU_EN);
+
+       /* Disable strong pull-up on DP (1.5K) */
+       otg_io_write(isp->otg, ULPI_CLR(ULPI_FUNC_CTRL),
+                       ULPI_FUNC_CTRL_TERMSELECT);
+
+       /* Enable weak pull-down resistor on DM */
+       otg_io_write(isp->otg, ULPI_SET(ULPI_OTG_CTRL),
+                       ULPI_OTG_CTRL_DM_PULLDOWN);
+
+       /* It's a charger if the line states are clear */
+       if (!(otg_io_read(isp->otg, ULPI_DEBUG)))
+               ret = 1;
+
+       /* Disable weak pull-up resistor on DP */
+       otg_io_write(isp->otg, ULPI_CLR(ISP1704_PWR_CTRL),
+                       ISP1704_PWR_CTRL_DP_WKPU_EN);
+
+       return ret;
+}
+
+static inline int isp1704_charger_detect(struct isp1704_charger *isp)
+{
+       unsigned long   timeout;
+       u8              r;
+       int             ret = 0;
+
+       /* set SW control bit in PWR_CTRL register */
+       otg_io_write(isp->otg, ISP1704_PWR_CTRL,
+                       ISP1704_PWR_CTRL_SWCTRL);
+
+       /* enable manual charger detection */
+       r = (ISP1704_PWR_CTRL_SWCTRL | ISP1704_PWR_CTRL_DPVSRC_EN);
+       otg_io_write(isp->otg, ULPI_SET(ISP1704_PWR_CTRL), r);
+       usleep_range(1000, 2000);
+
+       timeout = jiffies + msecs_to_jiffies(300);
+       do {
+               /* Check if there is a charger */
+               if (otg_io_read(isp->otg, ISP1704_PWR_CTRL)
+                               & ISP1704_PWR_CTRL_VDAT_DET) {
+                       ret = isp1704_charger_verify(isp);
+                       break;
+               }
+       } while (!time_after(jiffies, timeout));
+
+       return ret;
+}
+
+static void isp1704_charger_work(struct work_struct *data)
+{
+       int                     detect;
+       struct isp1704_charger  *isp =
+               container_of(data, struct isp1704_charger, work);
+
+       /*
+        * FIXME Only supporting dedicated chargers even though isp1704 can
+        * detect HUB and HOST chargers. If the device has already been
+        * enumerated, the detection will break the connection.
+        */
+       if (isp->otg->state != OTG_STATE_B_IDLE)
+               return;
+
+       /* disable data pullups */
+       if (isp->otg->gadget)
+               usb_gadget_disconnect(isp->otg->gadget);
+
+       /* detect charger */
+       detect = isp1704_charger_detect(isp);
+       if (detect) {
+               isp->present = detect;
+               power_supply_changed(&isp->psy);
+       }
+
+       /* enable data pullups */
+       if (isp->otg->gadget)
+               usb_gadget_connect(isp->otg->gadget);
+}
+
+static int isp1704_notifier_call(struct notifier_block *nb,
+               unsigned long event, void *unused)
+{
+       struct isp1704_charger *isp =
+               container_of(nb, struct isp1704_charger, nb);
+
+       switch (event) {
+       case USB_EVENT_VBUS:
+               schedule_work(&isp->work);
+               break;
+       case USB_EVENT_NONE:
+               if (isp->present) {
+                       isp->present = 0;
+                       power_supply_changed(&isp->psy);
+               }
+               break;
+       default:
+               return NOTIFY_DONE;
+       }
+
+       return NOTIFY_OK;
+}
+
+static int isp1704_charger_get_property(struct power_supply *psy,
+                               enum power_supply_property psp,
+                               union power_supply_propval *val)
+{
+       struct isp1704_charger *isp =
+               container_of(psy, struct isp1704_charger, psy);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = isp->present;
+               break;
+       case POWER_SUPPLY_PROP_MODEL_NAME:
+               val->strval = isp->model;
+               break;
+       case POWER_SUPPLY_PROP_MANUFACTURER:
+               val->strval = "NXP";
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static enum power_supply_property power_props[] = {
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_MODEL_NAME,
+       POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+static inline int isp1704_test_ulpi(struct isp1704_charger *isp)
+{
+       int vendor;
+       int product;
+       int i;
+       int ret = -ENODEV;
+
+       /* Test ULPI interface */
+       ret = otg_io_write(isp->otg, ULPI_SCRATCH, 0xaa);
+       if (ret < 0)
+               return ret;
+
+       ret = otg_io_read(isp->otg, ULPI_SCRATCH);
+       if (ret < 0)
+               return ret;
+
+       if (ret != 0xaa)
+               return -ENODEV;
+
+       /* Verify the product and vendor id matches */
+       vendor = otg_io_read(isp->otg, ULPI_VENDOR_ID_LOW);
+       vendor |= otg_io_read(isp->otg, ULPI_VENDOR_ID_HIGH) << 8;
+       if (vendor != NXP_VENDOR_ID)
+               return -ENODEV;
+
+       product = otg_io_read(isp->otg, ULPI_PRODUCT_ID_LOW);
+       product |= otg_io_read(isp->otg, ULPI_PRODUCT_ID_HIGH) << 8;
+
+       for (i = 0; i < ARRAY_SIZE(isp170x_id); i++) {
+               if (product == isp170x_id[i]) {
+                       sprintf(isp->model, "isp%x", product);
+                       return product;
+               }
+       }
+
+       dev_err(isp->dev, "product id %x not matching known ids", product);
+
+       return -ENODEV;
+}
+
+static int __devinit isp1704_charger_probe(struct platform_device *pdev)
+{
+       struct isp1704_charger  *isp;
+       int                     ret = -ENODEV;
+
+       isp = kzalloc(sizeof *isp, GFP_KERNEL);
+       if (!isp)
+               return -ENOMEM;
+
+       isp->otg = otg_get_transceiver();
+       if (!isp->otg)
+               goto fail0;
+
+       ret = isp1704_test_ulpi(isp);
+       if (ret < 0)
+               goto fail1;
+
+       isp->dev = &pdev->dev;
+       platform_set_drvdata(pdev, isp);
+
+       isp->psy.name           = "isp1704";
+       isp->psy.type           = POWER_SUPPLY_TYPE_USB;
+       isp->psy.properties     = power_props;
+       isp->psy.num_properties = ARRAY_SIZE(power_props);
+       isp->psy.get_property   = isp1704_charger_get_property;
+
+       ret = power_supply_register(isp->dev, &isp->psy);
+       if (ret)
+               goto fail1;
+
+       /*
+        * REVISIT: using work in order to allow the otg notifications to be
+        * made atomically in the future.
+        */
+       INIT_WORK(&isp->work, isp1704_charger_work);
+
+       isp->nb.notifier_call = isp1704_notifier_call;
+
+       ret = otg_register_notifier(isp->otg, &isp->nb);
+       if (ret)
+               goto fail2;
+
+       dev_info(isp->dev, "registered with product id %s\n", isp->model);
+
+       return 0;
+fail2:
+       power_supply_unregister(&isp->psy);
+fail1:
+       otg_put_transceiver(isp->otg);
+fail0:
+       kfree(isp);
+
+       dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);
+
+       return ret;
+}
+
+static int __devexit isp1704_charger_remove(struct platform_device *pdev)
+{
+       struct isp1704_charger *isp = platform_get_drvdata(pdev);
+
+       otg_unregister_notifier(isp->otg, &isp->nb);
+       power_supply_unregister(&isp->psy);
+       otg_put_transceiver(isp->otg);
+       kfree(isp);
+
+       return 0;
+}
+
+static struct platform_driver isp1704_charger_driver = {
+       .driver = {
+               .name = "isp1704_charger",
+       },
+       .probe = isp1704_charger_probe,
+       .remove = __devexit_p(isp1704_charger_remove),
+};
+
+static int __init isp1704_charger_init(void)
+{
+       return platform_driver_register(&isp1704_charger_driver);
+}
+module_init(isp1704_charger_init);
+
+static void __exit isp1704_charger_exit(void)
+{
+       platform_driver_unregister(&isp1704_charger_driver);
+}
+module_exit(isp1704_charger_exit);
+
+MODULE_ALIAS("platform:isp1704_charger");
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("ISP170x USB Charger driver");
+MODULE_LICENSE("GPL");
index 20c4b95..a8108a7 100644 (file)
@@ -383,6 +383,7 @@ static int __devexit jz_battery_remove(struct platform_device *pdev)
 
        iounmap(jz_battery->base);
        release_mem_region(jz_battery->mem->start, resource_size(jz_battery->mem));
+       kfree(jz_battery);
 
        return 0;
 }
index aafc1c5..5bc1dcf 100644 (file)
@@ -271,14 +271,14 @@ static int olpc_bat_get_property(struct power_supply *psy,
                if (ret)
                        return ret;
 
-               val->intval = (int)be16_to_cpu(ec_word) * 9760L / 32;
+               val->intval = (s16)be16_to_cpu(ec_word) * 9760L / 32;
                break;
        case POWER_SUPPLY_PROP_CURRENT_AVG:
                ret = olpc_ec_cmd(EC_BAT_CURRENT, NULL, 0, (void *)&ec_word, 2);
                if (ret)
                        return ret;
 
-               val->intval = (int)be16_to_cpu(ec_word) * 15625L / 120;
+               val->intval = (s16)be16_to_cpu(ec_word) * 15625L / 120;
                break;
        case POWER_SUPPLY_PROP_CAPACITY:
                ret = olpc_ec_cmd(EC_BAT_SOC, NULL, 0, &ec_byte, 1);
@@ -299,7 +299,7 @@ static int olpc_bat_get_property(struct power_supply *psy,
                if (ret)
                        return ret;
 
-               val->intval = (int)be16_to_cpu(ec_word) * 100 / 256;
+               val->intval = (s16)be16_to_cpu(ec_word) * 100 / 256;
                break;
        case POWER_SUPPLY_PROP_TEMP_AMBIENT:
                ret = olpc_ec_cmd(EC_AMB_TEMP, NULL, 0, (void *)&ec_word, 2);
@@ -313,7 +313,7 @@ static int olpc_bat_get_property(struct power_supply *psy,
                if (ret)
                        return ret;
 
-               val->intval = (int)be16_to_cpu(ec_word) * 6250 / 15;
+               val->intval = (s16)be16_to_cpu(ec_word) * 6250 / 15;
                break;
        case POWER_SUPPLY_PROP_SERIAL_NUMBER:
                ret = olpc_ec_cmd(EC_BAT_SERIAL, NULL, 0, (void *)&ser_buf, 8);
index 066f994..4fa52e1 100644 (file)
@@ -456,6 +456,7 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
        for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
                pcf50633_free_irq(mbc->pcf, mbc_irq_handlers[i]);
 
+       sysfs_remove_group(&pdev->dev.kobj, &mbc_attr_group);
        power_supply_unregister(&mbc->usb);
        power_supply_unregister(&mbc->adapter);
        power_supply_unregister(&mbc->ac);
index 9d30eeb..cd1f907 100644 (file)
@@ -42,7 +42,8 @@ static ssize_t power_supply_show_property(struct device *dev,
                                          struct device_attribute *attr,
                                          char *buf) {
        static char *type_text[] = {
-               "Battery", "UPS", "Mains", "USB"
+               "Battery", "UPS", "Mains", "USB",
+               "USB_DCP", "USB_CDP", "USB_ACA"
        };
        static char *status_text[] = {
                "Unknown", "Charging", "Discharging", "Not charging", "Full"
@@ -138,6 +139,7 @@ static struct device_attribute power_supply_attrs[] = {
        POWER_SUPPLY_ATTR(voltage_min_design),
        POWER_SUPPLY_ATTR(voltage_now),
        POWER_SUPPLY_ATTR(voltage_avg),
+       POWER_SUPPLY_ATTR(current_max),
        POWER_SUPPLY_ATTR(current_now),
        POWER_SUPPLY_ATTR(current_avg),
        POWER_SUPPLY_ATTR(power_now),
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
new file mode 100644 (file)
index 0000000..ff1f423
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ * TWL4030/TPS65950 BCI (Battery Charger Interface) driver
+ *
+ * Copyright (C) 2010 Gražvydas Ignotas <notasas@gmail.com>
+ *
+ * based on twl4030_bci_battery.c by TI
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/i2c/twl.h>
+#include <linux/power_supply.h>
+#include <linux/notifier.h>
+#include <linux/usb/otg.h>
+
+#define TWL4030_BCIMSTATEC     0x02
+#define TWL4030_BCIICHG                0x08
+#define TWL4030_BCIVAC         0x0a
+#define TWL4030_BCIVBUS                0x0c
+#define TWL4030_BCIMFSTS4      0x10
+#define TWL4030_BCICTL1                0x23
+
+#define TWL4030_BCIAUTOWEN     BIT(5)
+#define TWL4030_CONFIG_DONE    BIT(4)
+#define TWL4030_BCIAUTOUSB     BIT(1)
+#define TWL4030_BCIAUTOAC      BIT(0)
+#define TWL4030_CGAIN          BIT(5)
+#define TWL4030_USBFASTMCHG    BIT(2)
+#define TWL4030_STS_VBUS       BIT(7)
+#define TWL4030_STS_USB_ID     BIT(2)
+
+/* BCI interrupts */
+#define TWL4030_WOVF           BIT(0) /* Watchdog overflow */
+#define TWL4030_TMOVF          BIT(1) /* Timer overflow */
+#define TWL4030_ICHGHIGH       BIT(2) /* Battery charge current high */
+#define TWL4030_ICHGLOW                BIT(3) /* Battery cc. low / FSM state change */
+#define TWL4030_ICHGEOC                BIT(4) /* Battery current end-of-charge */
+#define TWL4030_TBATOR2                BIT(5) /* Battery temperature out of range 2 */
+#define TWL4030_TBATOR1                BIT(6) /* Battery temperature out of range 1 */
+#define TWL4030_BATSTS         BIT(7) /* Battery status */
+
+#define TWL4030_VBATLVL                BIT(0) /* VBAT level */
+#define TWL4030_VBATOV         BIT(1) /* VBAT overvoltage */
+#define TWL4030_VBUSOV         BIT(2) /* VBUS overvoltage */
+#define TWL4030_ACCHGOV                BIT(3) /* Ac charger overvoltage */
+
+#define TWL4030_MSTATEC_USB            BIT(4)
+#define TWL4030_MSTATEC_AC             BIT(5)
+#define TWL4030_MSTATEC_MASK           0x0f
+#define TWL4030_MSTATEC_QUICK1         0x02
+#define TWL4030_MSTATEC_QUICK7         0x07
+#define TWL4030_MSTATEC_COMPLETE1      0x0b
+#define TWL4030_MSTATEC_COMPLETE4      0x0e
+
+static bool allow_usb;
+module_param(allow_usb, bool, 1);
+MODULE_PARM_DESC(allow_usb, "Allow USB charge drawing default current");
+
+struct twl4030_bci {
+       struct device           *dev;
+       struct power_supply     ac;
+       struct power_supply     usb;
+       struct otg_transceiver  *transceiver;
+       struct notifier_block   otg_nb;
+       int                     irq_chg;
+       int                     irq_bci;
+};
+
+/*
+ * clear and set bits on an given register on a given module
+ */
+static int twl4030_clear_set(u8 mod_no, u8 clear, u8 set, u8 reg)
+{
+       u8 val = 0;
+       int ret;
+
+       ret = twl_i2c_read_u8(mod_no, &val, reg);
+       if (ret)
+               return ret;
+
+       val &= ~clear;
+       val |= set;
+
+       return twl_i2c_write_u8(mod_no, val, reg);
+}
+
+static int twl4030_bci_read(u8 reg, u8 *val)
+{
+       return twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, val, reg);
+}
+
+static int twl4030_clear_set_boot_bci(u8 clear, u8 set)
+{
+       return twl4030_clear_set(TWL4030_MODULE_PM_MASTER, 0,
+                       TWL4030_CONFIG_DONE | TWL4030_BCIAUTOWEN | set,
+                       TWL4030_PM_MASTER_BOOT_BCI);
+}
+
+static int twl4030bci_read_adc_val(u8 reg)
+{
+       int ret, temp;
+       u8 val;
+
+       /* read MSB */
+       ret = twl4030_bci_read(reg + 1, &val);
+       if (ret)
+               return ret;
+
+       temp = (int)(val & 0x03) << 8;
+
+       /* read LSB */
+       ret = twl4030_bci_read(reg, &val);
+       if (ret)
+               return ret;
+
+       return temp | val;
+}
+
+/*
+ * Check if VBUS power is present
+ */
+static int twl4030_bci_have_vbus(struct twl4030_bci *bci)
+{
+       int ret;
+       u8 hwsts;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &hwsts,
+                             TWL4030_PM_MASTER_STS_HW_CONDITIONS);
+       if (ret < 0)
+               return 0;
+
+       dev_dbg(bci->dev, "check_vbus: HW_CONDITIONS %02x\n", hwsts);
+
+       /* in case we also have STS_USB_ID, VBUS is driven by TWL itself */
+       if ((hwsts & TWL4030_STS_VBUS) && !(hwsts & TWL4030_STS_USB_ID))
+               return 1;
+
+       return 0;
+}
+
+/*
+ * Enable/Disable USB Charge funtionality.
+ */
+static int twl4030_charger_enable_usb(struct twl4030_bci *bci, bool enable)
+{
+       int ret;
+
+       if (enable) {
+               /* Check for USB charger conneted */
+               if (!twl4030_bci_have_vbus(bci))
+                       return -ENODEV;
+
+               /*
+                * Until we can find out what current the device can provide,
+                * require a module param to enable USB charging.
+                */
+               if (!allow_usb) {
+                       dev_warn(bci->dev, "USB charging is disabled.\n");
+                       return -EACCES;
+               }
+
+               /* forcing the field BCIAUTOUSB (BOOT_BCI[1]) to 1 */
+               ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOUSB);
+               if (ret < 0)
+                       return ret;
+
+               /* forcing USBFASTMCHG(BCIMFSTS4[2]) to 1 */
+               ret = twl4030_clear_set(TWL4030_MODULE_MAIN_CHARGE, 0,
+                       TWL4030_USBFASTMCHG, TWL4030_BCIMFSTS4);
+       } else {
+               ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOUSB, 0);
+       }
+
+       return ret;
+}
+
+/*
+ * Enable/Disable AC Charge funtionality.
+ */
+static int twl4030_charger_enable_ac(bool enable)
+{
+       int ret;
+
+       if (enable)
+               ret = twl4030_clear_set_boot_bci(0, TWL4030_BCIAUTOAC);
+       else
+               ret = twl4030_clear_set_boot_bci(TWL4030_BCIAUTOAC, 0);
+
+       return ret;
+}
+
+/*
+ * TWL4030 CHG_PRES (AC charger presence) events
+ */
+static irqreturn_t twl4030_charger_interrupt(int irq, void *arg)
+{
+       struct twl4030_bci *bci = arg;
+
+       dev_dbg(bci->dev, "CHG_PRES irq\n");
+       power_supply_changed(&bci->ac);
+       power_supply_changed(&bci->usb);
+
+       return IRQ_HANDLED;
+}
+
+/*
+ * TWL4030 BCI monitoring events
+ */
+static irqreturn_t twl4030_bci_interrupt(int irq, void *arg)
+{
+       struct twl4030_bci *bci = arg;
+       u8 irqs1, irqs2;
+       int ret;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &irqs1,
+                             TWL4030_INTERRUPTS_BCIISR1A);
+       if (ret < 0)
+               return IRQ_HANDLED;
+
+       ret = twl_i2c_read_u8(TWL4030_MODULE_INTERRUPTS, &irqs2,
+                             TWL4030_INTERRUPTS_BCIISR2A);
+       if (ret < 0)
+               return IRQ_HANDLED;
+
+       dev_dbg(bci->dev, "BCI irq %02x %02x\n", irqs2, irqs1);
+
+       if (irqs1 & (TWL4030_ICHGLOW | TWL4030_ICHGEOC)) {
+               /* charger state change, inform the core */
+               power_supply_changed(&bci->ac);
+               power_supply_changed(&bci->usb);
+       }
+
+       /* various monitoring events, for now we just log them here */
+       if (irqs1 & (TWL4030_TBATOR2 | TWL4030_TBATOR1))
+               dev_warn(bci->dev, "battery temperature out of range\n");
+
+       if (irqs1 & TWL4030_BATSTS)
+               dev_crit(bci->dev, "battery disconnected\n");
+
+       if (irqs2 & TWL4030_VBATOV)
+               dev_crit(bci->dev, "VBAT overvoltage\n");
+
+       if (irqs2 & TWL4030_VBUSOV)
+               dev_crit(bci->dev, "VBUS overvoltage\n");
+
+       if (irqs2 & TWL4030_ACCHGOV)
+               dev_crit(bci->dev, "Ac charger overvoltage\n");
+
+       return IRQ_HANDLED;
+}
+
+static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
+                              void *priv)
+{
+       struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb);
+
+       dev_dbg(bci->dev, "OTG notify %lu\n", val);
+
+       switch (val) {
+       case USB_EVENT_VBUS:
+       case USB_EVENT_CHARGER:
+               twl4030_charger_enable_usb(bci, true);
+               break;
+       case USB_EVENT_NONE:
+               twl4030_charger_enable_usb(bci, false);
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+/*
+ * TI provided formulas:
+ * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
+ * CGAIN == 1: ICHG = (BCIICHG * 3.4) / (2^10 - 1) - 1.7
+ * Here we use integer approximation of:
+ * CGAIN == 0: val * 1.6618 - 0.85
+ * CGAIN == 1: (val * 1.6618 - 0.85) * 2
+ */
+static int twl4030_charger_get_current(void)
+{
+       int curr;
+       int ret;
+       u8 bcictl1;
+
+       curr = twl4030bci_read_adc_val(TWL4030_BCIICHG);
+       if (curr < 0)
+               return curr;
+
+       ret = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+       if (ret)
+               return ret;
+
+       ret = (curr * 16618 - 850 * 10000) / 10;
+       if (bcictl1 & TWL4030_CGAIN)
+               ret *= 2;
+
+       return ret;
+}
+
+/*
+ * Returns the main charge FSM state
+ * Or < 0 on failure.
+ */
+static int twl4030bci_state(struct twl4030_bci *bci)
+{
+       int ret;
+       u8 state;
+
+       ret = twl4030_bci_read(TWL4030_BCIMSTATEC, &state);
+       if (ret) {
+               pr_err("twl4030_bci: error reading BCIMSTATEC\n");
+               return ret;
+       }
+
+       dev_dbg(bci->dev, "state: %02x\n", state);
+
+       return state;
+}
+
+static int twl4030_bci_state_to_status(int state)
+{
+       state &= TWL4030_MSTATEC_MASK;
+       if (TWL4030_MSTATEC_QUICK1 <= state && state <= TWL4030_MSTATEC_QUICK7)
+               return POWER_SUPPLY_STATUS_CHARGING;
+       else if (TWL4030_MSTATEC_COMPLETE1 <= state &&
+                                       state <= TWL4030_MSTATEC_COMPLETE4)
+               return POWER_SUPPLY_STATUS_FULL;
+       else
+               return POWER_SUPPLY_STATUS_NOT_CHARGING;
+}
+
+static int twl4030_bci_get_property(struct power_supply *psy,
+                                   enum power_supply_property psp,
+                                   union power_supply_propval *val)
+{
+       struct twl4030_bci *bci = dev_get_drvdata(psy->dev->parent);
+       int is_charging;
+       int state;
+       int ret;
+
+       state = twl4030bci_state(bci);
+       if (state < 0)
+               return state;
+
+       if (psy->type == POWER_SUPPLY_TYPE_USB)
+               is_charging = state & TWL4030_MSTATEC_USB;
+       else
+               is_charging = state & TWL4030_MSTATEC_AC;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               if (is_charging)
+                       val->intval = twl4030_bci_state_to_status(state);
+               else
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               /* charging must be active for meaningful result */
+               if (!is_charging)
+                       return -ENODATA;
+               if (psy->type == POWER_SUPPLY_TYPE_USB) {
+                       ret = twl4030bci_read_adc_val(TWL4030_BCIVBUS);
+                       if (ret < 0)
+                               return ret;
+                       /* BCIVBUS uses ADCIN8, 7/1023 V/step */
+                       val->intval = ret * 6843;
+               } else {
+                       ret = twl4030bci_read_adc_val(TWL4030_BCIVAC);
+                       if (ret < 0)
+                               return ret;
+                       /* BCIVAC uses ADCIN11, 10/1023 V/step */
+                       val->intval = ret * 9775;
+               }
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               if (!is_charging)
+                       return -ENODATA;
+               /* current measurement is shared between AC and USB */
+               ret = twl4030_charger_get_current();
+               if (ret < 0)
+                       return ret;
+               val->intval = ret;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = is_charging &&
+                       twl4030_bci_state_to_status(state) !=
+                               POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static enum power_supply_property twl4030_charger_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+};
+
+static int __init twl4030_bci_probe(struct platform_device *pdev)
+{
+       struct twl4030_bci *bci;
+       int ret;
+       int reg;
+
+       bci = kzalloc(sizeof(*bci), GFP_KERNEL);
+       if (bci == NULL)
+               return -ENOMEM;
+
+       bci->dev = &pdev->dev;
+       bci->irq_chg = platform_get_irq(pdev, 0);
+       bci->irq_bci = platform_get_irq(pdev, 1);
+
+       platform_set_drvdata(pdev, bci);
+
+       bci->ac.name = "twl4030_ac";
+       bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
+       bci->ac.properties = twl4030_charger_props;
+       bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
+       bci->ac.get_property = twl4030_bci_get_property;
+
+       ret = power_supply_register(&pdev->dev, &bci->ac);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
+               goto fail_register_ac;
+       }
+
+       bci->usb.name = "twl4030_usb";
+       bci->usb.type = POWER_SUPPLY_TYPE_USB;
+       bci->usb.properties = twl4030_charger_props;
+       bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props);
+       bci->usb.get_property = twl4030_bci_get_property;
+
+       ret = power_supply_register(&pdev->dev, &bci->usb);
+       if (ret) {
+               dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
+               goto fail_register_usb;
+       }
+
+       ret = request_threaded_irq(bci->irq_chg, NULL,
+                       twl4030_charger_interrupt, 0, pdev->name, bci);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "could not request irq %d, status %d\n",
+                       bci->irq_chg, ret);
+               goto fail_chg_irq;
+       }
+
+       ret = request_threaded_irq(bci->irq_bci, NULL,
+                       twl4030_bci_interrupt, 0, pdev->name, bci);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "could not request irq %d, status %d\n",
+                       bci->irq_bci, ret);
+               goto fail_bci_irq;
+       }
+
+       bci->transceiver = otg_get_transceiver();
+       if (bci->transceiver != NULL) {
+               bci->otg_nb.notifier_call = twl4030_bci_usb_ncb;
+               otg_register_notifier(bci->transceiver, &bci->otg_nb);
+       }
+
+       /* Enable interrupts now. */
+       reg = ~(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
+               TWL4030_TBATOR1 | TWL4030_BATSTS);
+       ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
+                              TWL4030_INTERRUPTS_BCIIMR1A);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
+               goto fail_unmask_interrupts;
+       }
+
+       reg = ~(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
+       ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
+                              TWL4030_INTERRUPTS_BCIIMR2A);
+       if (ret < 0)
+               dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
+
+       twl4030_charger_enable_ac(true);
+       twl4030_charger_enable_usb(bci, true);
+
+       return 0;
+
+fail_unmask_interrupts:
+       if (bci->transceiver != NULL) {
+               otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
+               otg_put_transceiver(bci->transceiver);
+       }
+       free_irq(bci->irq_bci, bci);
+fail_bci_irq:
+       free_irq(bci->irq_chg, bci);
+fail_chg_irq:
+       power_supply_unregister(&bci->usb);
+fail_register_usb:
+       power_supply_unregister(&bci->ac);
+fail_register_ac:
+       platform_set_drvdata(pdev, NULL);
+       kfree(bci);
+
+       return ret;
+}
+
+static int __exit twl4030_bci_remove(struct platform_device *pdev)
+{
+       struct twl4030_bci *bci = platform_get_drvdata(pdev);
+
+       twl4030_charger_enable_ac(false);
+       twl4030_charger_enable_usb(bci, false);
+
+       /* mask interrupts */
+       twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
+                        TWL4030_INTERRUPTS_BCIIMR1A);
+       twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
+                        TWL4030_INTERRUPTS_BCIIMR2A);
+
+       if (bci->transceiver != NULL) {
+               otg_unregister_notifier(bci->transceiver, &bci->otg_nb);
+               otg_put_transceiver(bci->transceiver);
+       }
+       free_irq(bci->irq_bci, bci);
+       free_irq(bci->irq_chg, bci);
+       power_supply_unregister(&bci->usb);
+       power_supply_unregister(&bci->ac);
+       platform_set_drvdata(pdev, NULL);
+       kfree(bci);
+
+       return 0;
+}
+
+static struct platform_driver twl4030_bci_driver = {
+       .driver = {
+               .name   = "twl4030_bci",
+               .owner  = THIS_MODULE,
+       },
+       .remove = __exit_p(twl4030_bci_remove),
+};
+
+static int __init twl4030_bci_init(void)
+{
+       return platform_driver_probe(&twl4030_bci_driver, twl4030_bci_probe);
+}
+module_init(twl4030_bci_init);
+
+static void __exit twl4030_bci_exit(void)
+{
+       platform_driver_unregister(&twl4030_bci_driver);
+}
+module_exit(twl4030_bci_exit);
+
+MODULE_AUTHOR("Gražydas Ignotas");
+MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:twl4030_bci");
index fbcc36d..ddf8cf5 100644 (file)
@@ -267,7 +267,6 @@ static void wm831x_config_battery(struct wm831x *wm831x)
        ret = wm831x_set_bits(wm831x, WM831X_CHARGER_CONTROL_1,
                              WM831X_CHG_ENA_MASK |
                              WM831X_CHG_FAST_MASK |
-                             WM831X_CHG_ITERM_MASK |
                              WM831X_CHG_ITERM_MASK,
                              reg1);
        if (ret != 0)
@@ -612,6 +611,7 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
        power_supply_unregister(&wm831x_power->battery);
        power_supply_unregister(&wm831x_power->wall);
        power_supply_unregister(&wm831x_power->usb);
+       kfree(wm831x_power);
        return 0;
 }
 
index 48ca713..2785a0f 100644 (file)
@@ -765,15 +765,15 @@ config RTC_DRV_AT32AP700X
          AT32AP700x family processors.
 
 config RTC_DRV_AT91RM9200
-       tristate "AT91RM9200 or AT91SAM9RL"
-       depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL
+       tristate "AT91RM9200 or some AT91SAM9 RTC"
+       depends on ARCH_AT91RM9200 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45
        help
          Driver for the internal RTC (Realtime Clock) module found on
-         Atmel AT91RM9200's and AT91SAM9RL chips. On SAM9RL chips
+         Atmel AT91RM9200's and some  AT91SAM9 chips. On AT91SAM9 chips
          this is powered by the backup power supply.
 
 config RTC_DRV_AT91SAM9
-       tristate "AT91SAM9x/AT91CAP9"
+       tristate "AT91SAM9x/AT91CAP9 RTT as RTC"
        depends on ARCH_AT91 && !(ARCH_AT91RM9200 || ARCH_AT91X40)
        help
          RTC driver for the Atmel AT91SAM9x and AT91CAP9 internal RTT
@@ -781,8 +781,8 @@ config RTC_DRV_AT91SAM9
          supply (such as a small coin cell battery), but do not need to
          be used as RTCs.
 
-         (On AT91SAM9rl chips you probably want to use the dedicated RTC
-         module and leave the RTT available for other uses.)
+         (On AT91SAM9rl and AT91SAM9G45 chips you probably want to use the
+         dedicated RTC module and leave the RTT available for other uses.)
 
 config RTC_DRV_AT91SAM9_RTT
        int
index 9278164..aff9dcd 100644 (file)
@@ -1410,6 +1410,33 @@ config SERIAL_OF_PLATFORM
          Currently, only 8250 compatible ports are supported, but
          others can easily be added.
 
+config SERIAL_OMAP
+       tristate "OMAP serial port support"
+       depends on ARCH_OMAP2 || ARCH_OMAP3 || ARCH_OMAP4
+       select SERIAL_CORE
+       help
+         If you have a machine based on an Texas Instruments OMAP CPU you
+         can enable its onboard serial ports by enabling this option.
+
+         By enabling this option you take advantage of dma feature available
+         with the omap-serial driver. DMA support can be enabled from platform
+         data.
+
+config SERIAL_OMAP_CONSOLE
+       bool "Console on OMAP serial port"
+       depends on SERIAL_OMAP
+       select SERIAL_CORE_CONSOLE
+       help
+         Select this option if you would like to use omap serial port as
+         console.
+
+         Even if you say Y here, the currently visible virtual console
+         (/dev/tty0) will still be used as the system console by default, but
+         you can alter that using a kernel command line option such as
+         "console=ttyOx". (Try "man bootparam" or see the documentation of
+         your boot loader about how to pass options to the kernel at
+         boot time.)
+
 config SERIAL_OF_PLATFORM_NWPSERIAL
        tristate "NWP serial port driver"
        depends on PPC_OF && PPC_DCR
index 1ca4fd5..c570576 100644 (file)
@@ -88,3 +88,4 @@ obj-$(CONFIG_SERIAL_ALTERA_JTAGUART) += altera_jtaguart.o
 obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o
 obj-$(CONFIG_SERIAL_MRST_MAX3110)      += mrst_max3110.o
 obj-$(CONFIG_SERIAL_MFD_HSU)   += mfd.o
+obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
diff --git a/drivers/serial/omap-serial.c b/drivers/serial/omap-serial.c
new file mode 100644 (file)
index 0000000..14365f7
--- /dev/null
@@ -0,0 +1,1333 @@
+/*
+ * Driver for OMAP-UART controller.
+ * Based on drivers/serial/8250.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Authors:
+ *     Govindraj R     <govindraj.raja@ti.com>
+ *     Thara Gopinath  <thara@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Note: This driver is made seperate from 8250 driver as we cannot
+ * over load 8250 driver with omap platform specific configuration for
+ * features like DMA, it makes easier to implement features like DMA and
+ * hardware flow control and software flow control configuration with
+ * this driver as required for the omap-platform.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/serial_reg.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/serial_core.h>
+#include <linux/irq.h>
+
+#include <plat/dma.h>
+#include <plat/dmtimer.h>
+#include <plat/omap-serial.h>
+
+static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS];
+
+/* Forward declaration of functions */
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data);
+static void serial_omap_rx_timeout(unsigned long uart_no);
+static int serial_omap_start_rxdma(struct uart_omap_port *up);
+
+static inline unsigned int serial_in(struct uart_omap_port *up, int offset)
+{
+       offset <<= up->port.regshift;
+       return readw(up->port.membase + offset);
+}
+
+static inline void serial_out(struct uart_omap_port *up, int offset, int value)
+{
+       offset <<= up->port.regshift;
+       writew(value, up->port.membase + offset);
+}
+
+static inline void serial_omap_clear_fifos(struct uart_omap_port *up)
+{
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+       serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+                      UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+       serial_out(up, UART_FCR, 0);
+}
+
+/*
+ * serial_omap_get_divisor - calculate divisor value
+ * @port: uart port info
+ * @baud: baudrate for which divisor needs to be calculated.
+ *
+ * We have written our own function to get the divisor so as to support
+ * 13x mode. 3Mbps Baudrate as an different divisor.
+ * Reference OMAP TRM Chapter 17:
+ * Table 17-1. UART Mode Baud Rates, Divisor Values, and Error Rates
+ * referring to oversampling - divisor value
+ * baudrate 460,800 to 3,686,400 all have divisor 13
+ * except 3,000,000 which has divisor value 16
+ */
+static unsigned int
+serial_omap_get_divisor(struct uart_port *port, unsigned int baud)
+{
+       unsigned int divisor;
+
+       if (baud > OMAP_MODE13X_SPEED && baud != 3000000)
+               divisor = 13;
+       else
+               divisor = 16;
+       return port->uartclk/(baud * divisor);
+}
+
+static void serial_omap_stop_rxdma(struct uart_omap_port *up)
+{
+       if (up->uart_dma.rx_dma_used) {
+               del_timer(&up->uart_dma.rx_timer);
+               omap_stop_dma(up->uart_dma.rx_dma_channel);
+               omap_free_dma(up->uart_dma.rx_dma_channel);
+               up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
+               up->uart_dma.rx_dma_used = false;
+       }
+}
+
+static void serial_omap_enable_ms(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       dev_dbg(up->port.dev, "serial_omap_enable_ms+%d\n", up->pdev->id);
+       up->ier |= UART_IER_MSI;
+       serial_out(up, UART_IER, up->ier);
+}
+
+static void serial_omap_stop_tx(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       if (up->use_dma &&
+               up->uart_dma.tx_dma_channel != OMAP_UART_DMA_CH_FREE) {
+               /*
+                * Check if dma is still active. If yes do nothing,
+                * return. Else stop dma
+                */
+               if (omap_get_dma_active_status(up->uart_dma.tx_dma_channel))
+                       return;
+               omap_stop_dma(up->uart_dma.tx_dma_channel);
+               omap_free_dma(up->uart_dma.tx_dma_channel);
+               up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+       }
+
+       if (up->ier & UART_IER_THRI) {
+               up->ier &= ~UART_IER_THRI;
+               serial_out(up, UART_IER, up->ier);
+       }
+}
+
+static void serial_omap_stop_rx(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       if (up->use_dma)
+               serial_omap_stop_rxdma(up);
+       up->ier &= ~UART_IER_RLSI;
+       up->port.read_status_mask &= ~UART_LSR_DR;
+       serial_out(up, UART_IER, up->ier);
+}
+
+static inline void receive_chars(struct uart_omap_port *up, int *status)
+{
+       struct tty_struct *tty = up->port.state->port.tty;
+       unsigned int flag;
+       unsigned char ch, lsr = *status;
+       int max_count = 256;
+
+       do {
+               if (likely(lsr & UART_LSR_DR))
+                       ch = serial_in(up, UART_RX);
+               flag = TTY_NORMAL;
+               up->port.icount.rx++;
+
+               if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
+                       /*
+                        * For statistics only
+                        */
+                       if (lsr & UART_LSR_BI) {
+                               lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+                               up->port.icount.brk++;
+                               /*
+                                * We do the SysRQ and SAK checking
+                                * here because otherwise the break
+                                * may get masked by ignore_status_mask
+                                * or read_status_mask.
+                                */
+                               if (uart_handle_break(&up->port))
+                                       goto ignore_char;
+                       } else if (lsr & UART_LSR_PE) {
+                               up->port.icount.parity++;
+                       } else if (lsr & UART_LSR_FE) {
+                               up->port.icount.frame++;
+                       }
+
+                       if (lsr & UART_LSR_OE)
+                               up->port.icount.overrun++;
+
+                       /*
+                        * Mask off conditions which should be ignored.
+                        */
+                       lsr &= up->port.read_status_mask;
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+                       if (up->port.line == up->port.cons->index) {
+                               /* Recover the break flag from console xmit */
+                               lsr |= up->lsr_break_flag;
+                               up->lsr_break_flag = 0;
+                       }
+#endif
+                       if (lsr & UART_LSR_BI)
+                               flag = TTY_BREAK;
+                       else if (lsr & UART_LSR_PE)
+                               flag = TTY_PARITY;
+                       else if (lsr & UART_LSR_FE)
+                               flag = TTY_FRAME;
+               }
+
+               if (uart_handle_sysrq_char(&up->port, ch))
+                       goto ignore_char;
+               uart_insert_char(&up->port, lsr, UART_LSR_OE, ch, flag);
+ignore_char:
+               lsr = serial_in(up, UART_LSR);
+       } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (max_count-- > 0));
+       spin_unlock(&up->port.lock);
+       tty_flip_buffer_push(tty);
+       spin_lock(&up->port.lock);
+}
+
+static void transmit_chars(struct uart_omap_port *up)
+{
+       struct circ_buf *xmit = &up->port.state->xmit;
+       int count;
+
+       if (up->port.x_char) {
+               serial_out(up, UART_TX, up->port.x_char);
+               up->port.icount.tx++;
+               up->port.x_char = 0;
+               return;
+       }
+       if (uart_circ_empty(xmit) || uart_tx_stopped(&up->port)) {
+               serial_omap_stop_tx(&up->port);
+               return;
+       }
+       count = up->port.fifosize / 4;
+       do {
+               serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+               xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+               up->port.icount.tx++;
+               if (uart_circ_empty(xmit))
+                       break;
+       } while (--count > 0);
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&up->port);
+
+       if (uart_circ_empty(xmit))
+               serial_omap_stop_tx(&up->port);
+}
+
+static inline void serial_omap_enable_ier_thri(struct uart_omap_port *up)
+{
+       if (!(up->ier & UART_IER_THRI)) {
+               up->ier |= UART_IER_THRI;
+               serial_out(up, UART_IER, up->ier);
+       }
+}
+
+static void serial_omap_start_tx(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       struct circ_buf *xmit;
+       unsigned int start;
+       int ret = 0;
+
+       if (!up->use_dma) {
+               serial_omap_enable_ier_thri(up);
+               return;
+       }
+
+       if (up->uart_dma.tx_dma_used)
+               return;
+
+       xmit = &up->port.state->xmit;
+
+       if (up->uart_dma.tx_dma_channel == OMAP_UART_DMA_CH_FREE) {
+               ret = omap_request_dma(up->uart_dma.uart_dma_tx,
+                               "UART Tx DMA",
+                               (void *)uart_tx_dma_callback, up,
+                               &(up->uart_dma.tx_dma_channel));
+
+               if (ret < 0) {
+                       serial_omap_enable_ier_thri(up);
+                       return;
+               }
+       }
+       spin_lock(&(up->uart_dma.tx_lock));
+       up->uart_dma.tx_dma_used = true;
+       spin_unlock(&(up->uart_dma.tx_lock));
+
+       start = up->uart_dma.tx_buf_dma_phys +
+                               (xmit->tail & (UART_XMIT_SIZE - 1));
+
+       up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+       /*
+        * It is a circular buffer. See if the buffer has wounded back.
+        * If yes it will have to be transferred in two separate dma
+        * transfers
+        */
+       if (start + up->uart_dma.tx_buf_size >=
+                       up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+               up->uart_dma.tx_buf_size =
+                       (up->uart_dma.tx_buf_dma_phys +
+                       UART_XMIT_SIZE) - start;
+
+       omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               up->uart_dma.uart_base, 0, 0);
+       omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+       omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+                               OMAP_DMA_DATA_TYPE_S8,
+                               up->uart_dma.tx_buf_size, 1,
+                               OMAP_DMA_SYNC_ELEMENT,
+                               up->uart_dma.uart_dma_tx, 0);
+       /* FIXME: Cache maintenance needed here? */
+       omap_start_dma(up->uart_dma.tx_dma_channel);
+}
+
+static unsigned int check_modem_status(struct uart_omap_port *up)
+{
+       unsigned int status;
+
+       status = serial_in(up, UART_MSR);
+       status |= up->msr_saved_flags;
+       up->msr_saved_flags = 0;
+       if ((status & UART_MSR_ANY_DELTA) == 0)
+               return status;
+
+       if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+           up->port.state != NULL) {
+               if (status & UART_MSR_TERI)
+                       up->port.icount.rng++;
+               if (status & UART_MSR_DDSR)
+                       up->port.icount.dsr++;
+               if (status & UART_MSR_DDCD)
+                       uart_handle_dcd_change
+                               (&up->port, status & UART_MSR_DCD);
+               if (status & UART_MSR_DCTS)
+                       uart_handle_cts_change
+                               (&up->port, status & UART_MSR_CTS);
+               wake_up_interruptible(&up->port.state->port.delta_msr_wait);
+       }
+
+       return status;
+}
+
+/**
+ * serial_omap_irq() - This handles the interrupt from one port
+ * @irq: uart port irq number
+ * @dev_id: uart port info
+ */
+static inline irqreturn_t serial_omap_irq(int irq, void *dev_id)
+{
+       struct uart_omap_port *up = dev_id;
+       unsigned int iir, lsr;
+       unsigned long flags;
+
+       iir = serial_in(up, UART_IIR);
+       if (iir & UART_IIR_NO_INT)
+               return IRQ_NONE;
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       lsr = serial_in(up, UART_LSR);
+       if (iir & UART_IIR_RLSI) {
+               if (!up->use_dma) {
+                       if (lsr & UART_LSR_DR)
+                               receive_chars(up, &lsr);
+               } else {
+                       up->ier &= ~(UART_IER_RDI | UART_IER_RLSI);
+                       serial_out(up, UART_IER, up->ier);
+                       if ((serial_omap_start_rxdma(up) != 0) &&
+                                       (lsr & UART_LSR_DR))
+                               receive_chars(up, &lsr);
+               }
+       }
+
+       check_modem_status(up);
+       if ((lsr & UART_LSR_THRE) && (iir & UART_IIR_THRI))
+               transmit_chars(up);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       up->port_activity = jiffies;
+       return IRQ_HANDLED;
+}
+
+static unsigned int serial_omap_tx_empty(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+       unsigned int ret = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_tx_empty+%d\n", up->pdev->id);
+       spin_lock_irqsave(&up->port.lock, flags);
+       ret = serial_in(up, UART_LSR) & UART_LSR_TEMT ? TIOCSER_TEMT : 0;
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       return ret;
+}
+
+static unsigned int serial_omap_get_mctrl(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char status;
+       unsigned int ret = 0;
+
+       status = check_modem_status(up);
+       dev_dbg(up->port.dev, "serial_omap_get_mctrl+%d\n", up->pdev->id);
+
+       if (status & UART_MSR_DCD)
+               ret |= TIOCM_CAR;
+       if (status & UART_MSR_RI)
+               ret |= TIOCM_RNG;
+       if (status & UART_MSR_DSR)
+               ret |= TIOCM_DSR;
+       if (status & UART_MSR_CTS)
+               ret |= TIOCM_CTS;
+       return ret;
+}
+
+static void serial_omap_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char mcr = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_set_mctrl+%d\n", up->pdev->id);
+       if (mctrl & TIOCM_RTS)
+               mcr |= UART_MCR_RTS;
+       if (mctrl & TIOCM_DTR)
+               mcr |= UART_MCR_DTR;
+       if (mctrl & TIOCM_OUT1)
+               mcr |= UART_MCR_OUT1;
+       if (mctrl & TIOCM_OUT2)
+               mcr |= UART_MCR_OUT2;
+       if (mctrl & TIOCM_LOOP)
+               mcr |= UART_MCR_LOOP;
+
+       mcr |= up->mcr;
+       serial_out(up, UART_MCR, mcr);
+}
+
+static void serial_omap_break_ctl(struct uart_port *port, int break_state)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_break_ctl+%d\n", up->pdev->id);
+       spin_lock_irqsave(&up->port.lock, flags);
+       if (break_state == -1)
+               up->lcr |= UART_LCR_SBC;
+       else
+               up->lcr &= ~UART_LCR_SBC;
+       serial_out(up, UART_LCR, up->lcr);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+}
+
+static int serial_omap_startup(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+       int retval;
+
+       /*
+        * Allocate the IRQ
+        */
+       retval = request_irq(up->port.irq, serial_omap_irq, up->port.irqflags,
+                               up->name, up);
+       if (retval)
+               return retval;
+
+       dev_dbg(up->port.dev, "serial_omap_startup+%d\n", up->pdev->id);
+
+       /*
+        * Clear the FIFO buffers and disable them.
+        * (they will be reenabled in set_termios())
+        */
+       serial_omap_clear_fifos(up);
+       /* For Hardware flow control */
+       serial_out(up, UART_MCR, UART_MCR_RTS);
+
+       /*
+        * Clear the interrupt registers.
+        */
+       (void) serial_in(up, UART_LSR);
+       if (serial_in(up, UART_LSR) & UART_LSR_DR)
+               (void) serial_in(up, UART_RX);
+       (void) serial_in(up, UART_IIR);
+       (void) serial_in(up, UART_MSR);
+
+       /*
+        * Now, initialize the UART
+        */
+       serial_out(up, UART_LCR, UART_LCR_WLEN8);
+       spin_lock_irqsave(&up->port.lock, flags);
+       /*
+        * Most PC uarts need OUT2 raised to enable interrupts.
+        */
+       up->port.mctrl |= TIOCM_OUT2;
+       serial_omap_set_mctrl(&up->port, up->port.mctrl);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       up->msr_saved_flags = 0;
+       if (up->use_dma) {
+               free_page((unsigned long)up->port.state->xmit.buf);
+               up->port.state->xmit.buf = dma_alloc_coherent(NULL,
+                       UART_XMIT_SIZE,
+                       (dma_addr_t *)&(up->uart_dma.tx_buf_dma_phys),
+                       0);
+               init_timer(&(up->uart_dma.rx_timer));
+               up->uart_dma.rx_timer.function = serial_omap_rx_timeout;
+               up->uart_dma.rx_timer.data = up->pdev->id;
+               /* Currently the buffer size is 4KB. Can increase it */
+               up->uart_dma.rx_buf = dma_alloc_coherent(NULL,
+                       up->uart_dma.rx_buf_size,
+                       (dma_addr_t *)&(up->uart_dma.rx_buf_dma_phys), 0);
+       }
+       /*
+        * Finally, enable interrupts. Note: Modem status interrupts
+        * are set via set_termios(), which will be occurring imminently
+        * anyway, so we don't enable them here.
+        */
+       up->ier = UART_IER_RLSI | UART_IER_RDI;
+       serial_out(up, UART_IER, up->ier);
+
+       up->port_activity = jiffies;
+       return 0;
+}
+
+static void serial_omap_shutdown(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned long flags = 0;
+
+       dev_dbg(up->port.dev, "serial_omap_shutdown+%d\n", up->pdev->id);
+       /*
+        * Disable interrupts from this port
+        */
+       up->ier = 0;
+       serial_out(up, UART_IER, 0);
+
+       spin_lock_irqsave(&up->port.lock, flags);
+       up->port.mctrl &= ~TIOCM_OUT2;
+       serial_omap_set_mctrl(&up->port, up->port.mctrl);
+       spin_unlock_irqrestore(&up->port.lock, flags);
+
+       /*
+        * Disable break condition and FIFOs
+        */
+       serial_out(up, UART_LCR, serial_in(up, UART_LCR) & ~UART_LCR_SBC);
+       serial_omap_clear_fifos(up);
+
+       /*
+        * Read data port to reset things, and then free the irq
+        */
+       if (serial_in(up, UART_LSR) & UART_LSR_DR)
+               (void) serial_in(up, UART_RX);
+       if (up->use_dma) {
+               dma_free_coherent(up->port.dev,
+                       UART_XMIT_SIZE, up->port.state->xmit.buf,
+                       up->uart_dma.tx_buf_dma_phys);
+               up->port.state->xmit.buf = NULL;
+               serial_omap_stop_rx(port);
+               dma_free_coherent(up->port.dev,
+                       up->uart_dma.rx_buf_size, up->uart_dma.rx_buf,
+                       up->uart_dma.rx_buf_dma_phys);
+               up->uart_dma.rx_buf = NULL;
+       }
+       free_irq(up->port.irq, up);
+}
+
+static inline void
+serial_omap_configure_xonxoff
+               (struct uart_omap_port *up, struct ktermios *termios)
+{
+       unsigned char efr = 0;
+
+       up->lcr = serial_in(up, UART_LCR);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       up->efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, up->efr & ~UART_EFR_ECB);
+
+       serial_out(up, UART_XON1, termios->c_cc[VSTART]);
+       serial_out(up, UART_XOFF1, termios->c_cc[VSTOP]);
+
+       /* clear SW control mode bits */
+       efr = up->efr;
+       efr &= OMAP_UART_SW_CLR;
+
+       /*
+        * IXON Flag:
+        * Enable XON/XOFF flow control on output.
+        * Transmit XON1, XOFF1
+        */
+       if (termios->c_iflag & IXON)
+               efr |= OMAP_UART_SW_TX;
+
+       /*
+        * IXOFF Flag:
+        * Enable XON/XOFF flow control on input.
+        * Receiver compares XON1, XOFF1.
+        */
+       if (termios->c_iflag & IXOFF)
+               efr |= OMAP_UART_SW_RX;
+
+       serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+       up->mcr = serial_in(up, UART_MCR);
+
+       /*
+        * IXANY Flag:
+        * Enable any character to restart output.
+        * Operation resumes after receiving any
+        * character after recognition of the XOFF character
+        */
+       if (termios->c_iflag & IXANY)
+               up->mcr |= UART_MCR_XONANY;
+
+       serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
+       /* Enable special char function UARTi.EFR_REG[5] and
+        * load the new software flow control mode IXON or IXOFF
+        * and restore the UARTi.EFR_REG[4] ENHANCED_EN value.
+        */
+       serial_out(up, UART_EFR, efr | UART_EFR_SCD);
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+       serial_out(up, UART_MCR, up->mcr & ~UART_MCR_TCRTLR);
+       serial_out(up, UART_LCR, up->lcr);
+}
+
+static void
+serial_omap_set_termios(struct uart_port *port, struct ktermios *termios,
+                       struct ktermios *old)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char cval = 0;
+       unsigned char efr = 0;
+       unsigned long flags = 0;
+       unsigned int baud, quot;
+
+       switch (termios->c_cflag & CSIZE) {
+       case CS5:
+               cval = UART_LCR_WLEN5;
+               break;
+       case CS6:
+               cval = UART_LCR_WLEN6;
+               break;
+       case CS7:
+               cval = UART_LCR_WLEN7;
+               break;
+       default:
+       case CS8:
+               cval = UART_LCR_WLEN8;
+               break;
+       }
+
+       if (termios->c_cflag & CSTOPB)
+               cval |= UART_LCR_STOP;
+       if (termios->c_cflag & PARENB)
+               cval |= UART_LCR_PARITY;
+       if (!(termios->c_cflag & PARODD))
+               cval |= UART_LCR_EPAR;
+
+       /*
+        * Ask the core to calculate the divisor for us.
+        */
+
+       baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/13);
+       quot = serial_omap_get_divisor(port, baud);
+
+       up->fcr = UART_FCR_R_TRIG_01 | UART_FCR_T_TRIG_01 |
+                       UART_FCR_ENABLE_FIFO;
+       if (up->use_dma)
+               up->fcr |= UART_FCR_DMA_SELECT;
+
+       /*
+        * Ok, we're now changing the port state. Do it with
+        * interrupts disabled.
+        */
+       spin_lock_irqsave(&up->port.lock, flags);
+
+       /*
+        * Update the per-port timeout.
+        */
+       uart_update_timeout(port, termios->c_cflag, baud);
+
+       up->port.read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+       if (termios->c_iflag & INPCK)
+               up->port.read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+       if (termios->c_iflag & (BRKINT | PARMRK))
+               up->port.read_status_mask |= UART_LSR_BI;
+
+       /*
+        * Characters to ignore
+        */
+       up->port.ignore_status_mask = 0;
+       if (termios->c_iflag & IGNPAR)
+               up->port.ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+       if (termios->c_iflag & IGNBRK) {
+               up->port.ignore_status_mask |= UART_LSR_BI;
+               /*
+                * If we're ignoring parity and break indicators,
+                * ignore overruns too (for real raw support).
+                */
+               if (termios->c_iflag & IGNPAR)
+                       up->port.ignore_status_mask |= UART_LSR_OE;
+       }
+
+       /*
+        * ignore all characters if CREAD is not set
+        */
+       if ((termios->c_cflag & CREAD) == 0)
+               up->port.ignore_status_mask |= UART_LSR_DR;
+
+       /*
+        * Modem status interrupts
+        */
+       up->ier &= ~UART_IER_MSI;
+       if (UART_ENABLE_MS(&up->port, termios->c_cflag))
+               up->ier |= UART_IER_MSI;
+       serial_out(up, UART_IER, up->ier);
+       serial_out(up, UART_LCR, cval);         /* reset DLAB */
+
+       /* FIFOs and DMA Settings */
+
+       /* FCR can be changed only when the
+        * baud clock is not running
+        * DLL_REG and DLH_REG set to 0.
+        */
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+       serial_out(up, UART_DLL, 0);
+       serial_out(up, UART_DLM, 0);
+       serial_out(up, UART_LCR, 0);
+
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       up->efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+       up->mcr = serial_in(up, UART_MCR);
+       serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+       /* FIFO ENABLE, DMA MODE */
+       serial_out(up, UART_FCR, up->fcr);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       if (up->use_dma) {
+               serial_out(up, UART_TI752_TLR, 0);
+               serial_out(up, UART_OMAP_SCR,
+                       (UART_FCR_TRIGGER_4 | UART_FCR_TRIGGER_8));
+       }
+
+       serial_out(up, UART_EFR, up->efr);
+       serial_out(up, UART_LCR, UART_LCR_DLAB);
+       serial_out(up, UART_MCR, up->mcr);
+
+       /* Protocol, Baud Rate, and Interrupt Settings */
+
+       serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_DISABLE);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       up->efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+       serial_out(up, UART_LCR, 0);
+       serial_out(up, UART_IER, 0);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       serial_out(up, UART_DLL, quot & 0xff);          /* LS of divisor */
+       serial_out(up, UART_DLM, quot >> 8);            /* MS of divisor */
+
+       serial_out(up, UART_LCR, 0);
+       serial_out(up, UART_IER, up->ier);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+
+       serial_out(up, UART_EFR, up->efr);
+       serial_out(up, UART_LCR, cval);
+
+       if (baud > 230400 && baud != 3000000)
+               serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE13X);
+       else
+               serial_out(up, UART_OMAP_MDR1, OMAP_MDR1_MODE16X);
+
+       /* Hardware Flow Control Configuration */
+
+       if (termios->c_cflag & CRTSCTS) {
+               efr |= (UART_EFR_CTS | UART_EFR_RTS);
+               serial_out(up, UART_LCR, UART_LCR_DLAB);
+
+               up->mcr = serial_in(up, UART_MCR);
+               serial_out(up, UART_MCR, up->mcr | UART_MCR_TCRTLR);
+
+               serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+               up->efr = serial_in(up, UART_EFR);
+               serial_out(up, UART_EFR, up->efr | UART_EFR_ECB);
+
+               serial_out(up, UART_TI752_TCR, OMAP_UART_TCR_TRIG);
+               serial_out(up, UART_EFR, efr); /* Enable AUTORTS and AUTOCTS */
+               serial_out(up, UART_LCR, UART_LCR_DLAB);
+               serial_out(up, UART_MCR, up->mcr | UART_MCR_RTS);
+               serial_out(up, UART_LCR, cval);
+       }
+
+       serial_omap_set_mctrl(&up->port, up->port.mctrl);
+       /* Software Flow Control Configuration */
+       if (termios->c_iflag & (IXON | IXOFF))
+               serial_omap_configure_xonxoff(up, termios);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
+       dev_dbg(up->port.dev, "serial_omap_set_termios+%d\n", up->pdev->id);
+}
+
+static void
+serial_omap_pm(struct uart_port *port, unsigned int state,
+              unsigned int oldstate)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+       unsigned char efr;
+
+       dev_dbg(up->port.dev, "serial_omap_pm+%d\n", up->pdev->id);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       efr = serial_in(up, UART_EFR);
+       serial_out(up, UART_EFR, efr | UART_EFR_ECB);
+       serial_out(up, UART_LCR, 0);
+
+       serial_out(up, UART_IER, (state != 0) ? UART_IERX_SLEEP : 0);
+       serial_out(up, UART_LCR, OMAP_UART_LCR_CONF_MDB);
+       serial_out(up, UART_EFR, efr);
+       serial_out(up, UART_LCR, 0);
+       /* Enable module level wake up */
+       serial_out(up, UART_OMAP_WER,
+               (state != 0) ? OMAP_UART_WER_MOD_WKUP : 0);
+}
+
+static void serial_omap_release_port(struct uart_port *port)
+{
+       dev_dbg(port->dev, "serial_omap_release_port+\n");
+}
+
+static int serial_omap_request_port(struct uart_port *port)
+{
+       dev_dbg(port->dev, "serial_omap_request_port+\n");
+       return 0;
+}
+
+static void serial_omap_config_port(struct uart_port *port, int flags)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       dev_dbg(up->port.dev, "serial_omap_config_port+%d\n",
+                                                       up->pdev->id);
+       up->port.type = PORT_OMAP;
+}
+
+static int
+serial_omap_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+       /* we don't want the core code to modify any port params */
+       dev_dbg(port->dev, "serial_omap_verify_port+\n");
+       return -EINVAL;
+}
+
+static const char *
+serial_omap_type(struct uart_port *port)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       dev_dbg(up->port.dev, "serial_omap_type+%d\n", up->pdev->id);
+       return up->name;
+}
+
+#ifdef CONFIG_SERIAL_OMAP_CONSOLE
+
+static struct uart_omap_port *serial_omap_console_ports[4];
+
+static struct uart_driver serial_omap_reg;
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+static inline void wait_for_xmitr(struct uart_omap_port *up)
+{
+       unsigned int status, tmout = 10000;
+
+       /* Wait up to 10ms for the character(s) to be sent. */
+       do {
+               status = serial_in(up, UART_LSR);
+
+               if (status & UART_LSR_BI)
+                       up->lsr_break_flag = UART_LSR_BI;
+
+               if (--tmout == 0)
+                       break;
+               udelay(1);
+       } while ((status & BOTH_EMPTY) != BOTH_EMPTY);
+
+       /* Wait up to 1s for flow control if necessary */
+       if (up->port.flags & UPF_CONS_FLOW) {
+               tmout = 1000000;
+               for (tmout = 1000000; tmout; tmout--) {
+                       unsigned int msr = serial_in(up, UART_MSR);
+
+                       up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+                       if (msr & UART_MSR_CTS)
+                               break;
+
+                       udelay(1);
+               }
+       }
+}
+
+static void serial_omap_console_putchar(struct uart_port *port, int ch)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)port;
+
+       wait_for_xmitr(up);
+       serial_out(up, UART_TX, ch);
+}
+
+static void
+serial_omap_console_write(struct console *co, const char *s,
+               unsigned int count)
+{
+       struct uart_omap_port *up = serial_omap_console_ports[co->index];
+       unsigned long flags;
+       unsigned int ier;
+       int locked = 1;
+
+       local_irq_save(flags);
+       if (up->port.sysrq)
+               locked = 0;
+       else if (oops_in_progress)
+               locked = spin_trylock(&up->port.lock);
+       else
+               spin_lock(&up->port.lock);
+
+       /*
+        * First save the IER then disable the interrupts
+        */
+       ier = serial_in(up, UART_IER);
+       serial_out(up, UART_IER, 0);
+
+       uart_console_write(&up->port, s, count, serial_omap_console_putchar);
+
+       /*
+        * Finally, wait for transmitter to become empty
+        * and restore the IER
+        */
+       wait_for_xmitr(up);
+       serial_out(up, UART_IER, ier);
+       /*
+        * The receive handling will happen properly because the
+        * receive ready bit will still be set; it is not cleared
+        * on read.  However, modem control will not, we must
+        * call it if we have saved something in the saved flags
+        * while processing with interrupts off.
+        */
+       if (up->msr_saved_flags)
+               check_modem_status(up);
+
+       if (locked)
+               spin_unlock(&up->port.lock);
+       local_irq_restore(flags);
+}
+
+static int __init
+serial_omap_console_setup(struct console *co, char *options)
+{
+       struct uart_omap_port *up;
+       int baud = 115200;
+       int bits = 8;
+       int parity = 'n';
+       int flow = 'n';
+
+       if (serial_omap_console_ports[co->index] == NULL)
+               return -ENODEV;
+       up = serial_omap_console_ports[co->index];
+
+       if (options)
+               uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+       return uart_set_options(&up->port, co, baud, parity, bits, flow);
+}
+
+static struct console serial_omap_console = {
+       .name           = OMAP_SERIAL_NAME,
+       .write          = serial_omap_console_write,
+       .device         = uart_console_device,
+       .setup          = serial_omap_console_setup,
+       .flags          = CON_PRINTBUFFER,
+       .index          = -1,
+       .data           = &serial_omap_reg,
+};
+
+static void serial_omap_add_console_port(struct uart_omap_port *up)
+{
+       serial_omap_console_ports[up->pdev->id] = up;
+}
+
+#define OMAP_CONSOLE   (&serial_omap_console)
+
+#else
+
+#define OMAP_CONSOLE   NULL
+
+static inline void serial_omap_add_console_port(struct uart_omap_port *up)
+{}
+
+#endif
+
+static struct uart_ops serial_omap_pops = {
+       .tx_empty       = serial_omap_tx_empty,
+       .set_mctrl      = serial_omap_set_mctrl,
+       .get_mctrl      = serial_omap_get_mctrl,
+       .stop_tx        = serial_omap_stop_tx,
+       .start_tx       = serial_omap_start_tx,
+       .stop_rx        = serial_omap_stop_rx,
+       .enable_ms      = serial_omap_enable_ms,
+       .break_ctl      = serial_omap_break_ctl,
+       .startup        = serial_omap_startup,
+       .shutdown       = serial_omap_shutdown,
+       .set_termios    = serial_omap_set_termios,
+       .pm             = serial_omap_pm,
+       .type           = serial_omap_type,
+       .release_port   = serial_omap_release_port,
+       .request_port   = serial_omap_request_port,
+       .config_port    = serial_omap_config_port,
+       .verify_port    = serial_omap_verify_port,
+};
+
+static struct uart_driver serial_omap_reg = {
+       .owner          = THIS_MODULE,
+       .driver_name    = "OMAP-SERIAL",
+       .dev_name       = OMAP_SERIAL_NAME,
+       .nr             = OMAP_MAX_HSUART_PORTS,
+       .cons           = OMAP_CONSOLE,
+};
+
+static int
+serial_omap_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct uart_omap_port *up = platform_get_drvdata(pdev);
+
+       if (up)
+               uart_suspend_port(&serial_omap_reg, &up->port);
+       return 0;
+}
+
+static int serial_omap_resume(struct platform_device *dev)
+{
+       struct uart_omap_port *up = platform_get_drvdata(dev);
+
+       if (up)
+               uart_resume_port(&serial_omap_reg, &up->port);
+       return 0;
+}
+
+static void serial_omap_rx_timeout(unsigned long uart_no)
+{
+       struct uart_omap_port *up = ui[uart_no];
+       unsigned int curr_dma_pos, curr_transmitted_size;
+       int ret = 0;
+
+       curr_dma_pos = omap_get_dma_dst_pos(up->uart_dma.rx_dma_channel);
+       if ((curr_dma_pos == up->uart_dma.prev_rx_dma_pos) ||
+                            (curr_dma_pos == 0)) {
+               if (jiffies_to_msecs(jiffies - up->port_activity) <
+                                                       RX_TIMEOUT) {
+                       mod_timer(&up->uart_dma.rx_timer, jiffies +
+                               usecs_to_jiffies(up->uart_dma.rx_timeout));
+               } else {
+                       serial_omap_stop_rxdma(up);
+                       up->ier |= (UART_IER_RDI | UART_IER_RLSI);
+                       serial_out(up, UART_IER, up->ier);
+               }
+               return;
+       }
+
+       curr_transmitted_size = curr_dma_pos -
+                                       up->uart_dma.prev_rx_dma_pos;
+       up->port.icount.rx += curr_transmitted_size;
+       tty_insert_flip_string(up->port.state->port.tty,
+                       up->uart_dma.rx_buf +
+                       (up->uart_dma.prev_rx_dma_pos -
+                       up->uart_dma.rx_buf_dma_phys),
+                       curr_transmitted_size);
+       tty_flip_buffer_push(up->port.state->port.tty);
+       up->uart_dma.prev_rx_dma_pos = curr_dma_pos;
+       if (up->uart_dma.rx_buf_size +
+                       up->uart_dma.rx_buf_dma_phys == curr_dma_pos) {
+               ret = serial_omap_start_rxdma(up);
+               if (ret < 0) {
+                       serial_omap_stop_rxdma(up);
+                       up->ier |= (UART_IER_RDI | UART_IER_RLSI);
+                       serial_out(up, UART_IER, up->ier);
+               }
+       } else  {
+               mod_timer(&up->uart_dma.rx_timer, jiffies +
+                       usecs_to_jiffies(up->uart_dma.rx_timeout));
+       }
+       up->port_activity = jiffies;
+}
+
+static void uart_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       return;
+}
+
+static int serial_omap_start_rxdma(struct uart_omap_port *up)
+{
+       int ret = 0;
+
+       if (up->uart_dma.rx_dma_channel == -1) {
+               ret = omap_request_dma(up->uart_dma.uart_dma_rx,
+                               "UART Rx DMA",
+                               (void *)uart_rx_dma_callback, up,
+                               &(up->uart_dma.rx_dma_channel));
+               if (ret < 0)
+                       return ret;
+
+               omap_set_dma_src_params(up->uart_dma.rx_dma_channel, 0,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               up->uart_dma.uart_base, 0, 0);
+               omap_set_dma_dest_params(up->uart_dma.rx_dma_channel, 0,
+                               OMAP_DMA_AMODE_POST_INC,
+                               up->uart_dma.rx_buf_dma_phys, 0, 0);
+               omap_set_dma_transfer_params(up->uart_dma.rx_dma_channel,
+                               OMAP_DMA_DATA_TYPE_S8,
+                               up->uart_dma.rx_buf_size, 1,
+                               OMAP_DMA_SYNC_ELEMENT,
+                               up->uart_dma.uart_dma_rx, 0);
+       }
+       up->uart_dma.prev_rx_dma_pos = up->uart_dma.rx_buf_dma_phys;
+       /* FIXME: Cache maintenance needed here? */
+       omap_start_dma(up->uart_dma.rx_dma_channel);
+       mod_timer(&up->uart_dma.rx_timer, jiffies +
+                               usecs_to_jiffies(up->uart_dma.rx_timeout));
+       up->uart_dma.rx_dma_used = true;
+       return ret;
+}
+
+static void serial_omap_continue_tx(struct uart_omap_port *up)
+{
+       struct circ_buf *xmit = &up->port.state->xmit;
+       unsigned int start = up->uart_dma.tx_buf_dma_phys
+                       + (xmit->tail & (UART_XMIT_SIZE - 1));
+
+       if (uart_circ_empty(xmit))
+               return;
+
+       up->uart_dma.tx_buf_size = uart_circ_chars_pending(xmit);
+       /*
+        * It is a circular buffer. See if the buffer has wounded back.
+        * If yes it will have to be transferred in two separate dma
+        * transfers
+        */
+       if (start + up->uart_dma.tx_buf_size >=
+                       up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE)
+               up->uart_dma.tx_buf_size =
+                       (up->uart_dma.tx_buf_dma_phys + UART_XMIT_SIZE) - start;
+       omap_set_dma_dest_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_CONSTANT,
+                               up->uart_dma.uart_base, 0, 0);
+       omap_set_dma_src_params(up->uart_dma.tx_dma_channel, 0,
+                               OMAP_DMA_AMODE_POST_INC, start, 0, 0);
+       omap_set_dma_transfer_params(up->uart_dma.tx_dma_channel,
+                               OMAP_DMA_DATA_TYPE_S8,
+                               up->uart_dma.tx_buf_size, 1,
+                               OMAP_DMA_SYNC_ELEMENT,
+                               up->uart_dma.uart_dma_tx, 0);
+       /* FIXME: Cache maintenance needed here? */
+       omap_start_dma(up->uart_dma.tx_dma_channel);
+}
+
+static void uart_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+       struct uart_omap_port *up = (struct uart_omap_port *)data;
+       struct circ_buf *xmit = &up->port.state->xmit;
+
+       xmit->tail = (xmit->tail + up->uart_dma.tx_buf_size) & \
+                       (UART_XMIT_SIZE - 1);
+       up->port.icount.tx += up->uart_dma.tx_buf_size;
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&up->port);
+
+       if (uart_circ_empty(xmit)) {
+               spin_lock(&(up->uart_dma.tx_lock));
+               serial_omap_stop_tx(&up->port);
+               up->uart_dma.tx_dma_used = false;
+               spin_unlock(&(up->uart_dma.tx_lock));
+       } else {
+               omap_stop_dma(up->uart_dma.tx_dma_channel);
+               serial_omap_continue_tx(up);
+       }
+       up->port_activity = jiffies;
+       return;
+}
+
+static int serial_omap_probe(struct platform_device *pdev)
+{
+       struct uart_omap_port   *up;
+       struct resource         *mem, *irq, *dma_tx, *dma_rx;
+       struct omap_uart_port_info *omap_up_info = pdev->dev.platform_data;
+       int ret = -ENOSPC;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "no mem resource?\n");
+               return -ENODEV;
+       }
+
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "no irq resource?\n");
+               return -ENODEV;
+       }
+
+       if (!request_mem_region(mem->start, (mem->end - mem->start) + 1,
+                                    pdev->dev.driver->name)) {
+               dev_err(&pdev->dev, "memory region already claimed\n");
+               return -EBUSY;
+       }
+
+       dma_rx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+       if (!dma_rx) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       dma_tx = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+       if (!dma_tx) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       up = kzalloc(sizeof(*up), GFP_KERNEL);
+       if (up == NULL) {
+               ret = -ENOMEM;
+               goto do_release_region;
+       }
+       sprintf(up->name, "OMAP UART%d", pdev->id);
+       up->pdev = pdev;
+       up->port.dev = &pdev->dev;
+       up->port.type = PORT_OMAP;
+       up->port.iotype = UPIO_MEM;
+       up->port.irq = irq->start;
+
+       up->port.regshift = 2;
+       up->port.fifosize = 64;
+       up->port.ops = &serial_omap_pops;
+       up->port.line = pdev->id;
+
+       up->port.membase = omap_up_info->membase;
+       up->port.mapbase = omap_up_info->mapbase;
+       up->port.flags = omap_up_info->flags;
+       up->port.irqflags = omap_up_info->irqflags;
+       up->port.uartclk = omap_up_info->uartclk;
+       up->uart_dma.uart_base = mem->start;
+
+       if (omap_up_info->dma_enabled) {
+               up->uart_dma.uart_dma_tx = dma_tx->start;
+               up->uart_dma.uart_dma_rx = dma_rx->start;
+               up->use_dma = 1;
+               up->uart_dma.rx_buf_size = 4096;
+               up->uart_dma.rx_timeout = 2;
+               spin_lock_init(&(up->uart_dma.tx_lock));
+               spin_lock_init(&(up->uart_dma.rx_lock));
+               up->uart_dma.tx_dma_channel = OMAP_UART_DMA_CH_FREE;
+               up->uart_dma.rx_dma_channel = OMAP_UART_DMA_CH_FREE;
+       }
+
+       ui[pdev->id] = up;
+       serial_omap_add_console_port(up);
+
+       ret = uart_add_one_port(&serial_omap_reg, &up->port);
+       if (ret != 0)
+               goto do_release_region;
+
+       platform_set_drvdata(pdev, up);
+       return 0;
+err:
+       dev_err(&pdev->dev, "[UART%d]: failure [%s]: %d\n",
+                               pdev->id, __func__, ret);
+do_release_region:
+       release_mem_region(mem->start, (mem->end - mem->start) + 1);
+       return ret;
+}
+
+static int serial_omap_remove(struct platform_device *dev)
+{
+       struct uart_omap_port *up = platform_get_drvdata(dev);
+
+       platform_set_drvdata(dev, NULL);
+       if (up) {
+               uart_remove_one_port(&serial_omap_reg, &up->port);
+               kfree(up);
+       }
+       return 0;
+}
+
+static struct platform_driver serial_omap_driver = {
+       .probe          = serial_omap_probe,
+       .remove         = serial_omap_remove,
+
+       .suspend        = serial_omap_suspend,
+       .resume         = serial_omap_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+       },
+};
+
+static int __init serial_omap_init(void)
+{
+       int ret;
+
+       ret = uart_register_driver(&serial_omap_reg);
+       if (ret != 0)
+               return ret;
+       ret = platform_driver_register(&serial_omap_driver);
+       if (ret != 0)
+               uart_unregister_driver(&serial_omap_reg);
+       return ret;
+}
+
+static void __exit serial_omap_exit(void)
+{
+       platform_driver_unregister(&serial_omap_driver);
+       uart_unregister_driver(&serial_omap_reg);
+}
+
+module_init(serial_omap_init);
+module_exit(serial_omap_exit);
+
+MODULE_DESCRIPTION("OMAP High Speed UART driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Texas Instruments Inc");
index 4b9eec6..78f9fd0 100644 (file)
@@ -329,6 +329,13 @@ config SPI_STMP3XXX
        help
          SPI driver for Freescale STMP37xx/378x SoC SSP interface
 
+config SPI_TEGRA
+       tristate "Nvidia Tegra SPI controller"
+       depends on ARCH_TEGRA
+       select TEGRA_SYSTEM_DMA
+       help
+         SPI driver for NVidia Tegra SoCs
+
 config SPI_TOPCLIFF_PCH
        tristate "Topcliff PCH SPI Controller"
        depends on PCI
index 557aaad..8bc1a5a 100644 (file)
@@ -39,6 +39,7 @@ obj-$(CONFIG_SPI_PPC4xx)              += spi_ppc4xx.o
 obj-$(CONFIG_SPI_S3C24XX_GPIO)         += spi_s3c24xx_gpio.o
 obj-$(CONFIG_SPI_S3C24XX)              += spi_s3c24xx_hw.o
 obj-$(CONFIG_SPI_S3C64XX)              += spi_s3c64xx.o
+obj-$(CONFIG_SPI_TEGRA)                        += spi_tegra.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)         += spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)                 += spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)               += xilinx_spi.o
diff --git a/drivers/spi/spi_tegra.c b/drivers/spi/spi_tegra.c
new file mode 100644 (file)
index 0000000..bb7df02
--- /dev/null
@@ -0,0 +1,618 @@
+/*
+ * Driver for Nvidia TEGRA spi controller.
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *     Erik Gilling <konkers@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <linux/spi/spi.h>
+
+#include <mach/dma.h>
+
+#define SLINK_COMMAND          0x000
+#define   SLINK_BIT_LENGTH(x)          (((x) & 0x1f) << 0)
+#define   SLINK_WORD_SIZE(x)           (((x) & 0x1f) << 5)
+#define   SLINK_BOTH_EN                        (1 << 10)
+#define   SLINK_CS_SW                  (1 << 11)
+#define   SLINK_CS_VALUE               (1 << 12)
+#define   SLINK_CS_POLARITY            (1 << 13)
+#define   SLINK_IDLE_SDA_DRIVE_LOW     (0 << 16)
+#define   SLINK_IDLE_SDA_DRIVE_HIGH    (1 << 16)
+#define   SLINK_IDLE_SDA_PULL_LOW      (2 << 16)
+#define   SLINK_IDLE_SDA_PULL_HIGH     (3 << 16)
+#define   SLINK_IDLE_SDA_MASK          (3 << 16)
+#define   SLINK_CS_POLARITY1           (1 << 20)
+#define   SLINK_CK_SDA                 (1 << 21)
+#define   SLINK_CS_POLARITY2           (1 << 22)
+#define   SLINK_CS_POLARITY3           (1 << 23)
+#define   SLINK_IDLE_SCLK_DRIVE_LOW    (0 << 24)
+#define   SLINK_IDLE_SCLK_DRIVE_HIGH   (1 << 24)
+#define   SLINK_IDLE_SCLK_PULL_LOW     (2 << 24)
+#define   SLINK_IDLE_SCLK_PULL_HIGH    (3 << 24)
+#define   SLINK_IDLE_SCLK_MASK         (3 << 24)
+#define   SLINK_M_S                    (1 << 28)
+#define   SLINK_WAIT                   (1 << 29)
+#define   SLINK_GO                     (1 << 30)
+#define   SLINK_ENB                    (1 << 31)
+
+#define SLINK_COMMAND2         0x004
+#define   SLINK_LSBFE                  (1 << 0)
+#define   SLINK_SSOE                   (1 << 1)
+#define   SLINK_SPIE                   (1 << 4)
+#define   SLINK_BIDIROE                        (1 << 6)
+#define   SLINK_MODFEN                 (1 << 7)
+#define   SLINK_INT_SIZE(x)            (((x) & 0x1f) << 8)
+#define   SLINK_CS_ACTIVE_BETWEEN      (1 << 17)
+#define   SLINK_SS_EN_CS(x)            (((x) & 0x3) << 18)
+#define   SLINK_SS_SETUP(x)            (((x) & 0x3) << 20)
+#define   SLINK_FIFO_REFILLS_0         (0 << 22)
+#define   SLINK_FIFO_REFILLS_1         (1 << 22)
+#define   SLINK_FIFO_REFILLS_2         (2 << 22)
+#define   SLINK_FIFO_REFILLS_3         (3 << 22)
+#define   SLINK_FIFO_REFILLS_MASK      (3 << 22)
+#define   SLINK_WAIT_PACK_INT(x)       (((x) & 0x7) << 26)
+#define   SLINK_SPC0                   (1 << 29)
+#define   SLINK_TXEN                   (1 << 30)
+#define   SLINK_RXEN                   (1 << 31)
+
+#define SLINK_STATUS           0x008
+#define   SLINK_COUNT(val)             (((val) >> 0) & 0x1f)
+#define   SLINK_WORD(val)              (((val) >> 5) & 0x1f)
+#define   SLINK_BLK_CNT(val)           (((val) >> 0) & 0xffff)
+#define   SLINK_MODF                   (1 << 16)
+#define   SLINK_RX_UNF                 (1 << 18)
+#define   SLINK_TX_OVF                 (1 << 19)
+#define   SLINK_TX_FULL                        (1 << 20)
+#define   SLINK_TX_EMPTY               (1 << 21)
+#define   SLINK_RX_FULL                        (1 << 22)
+#define   SLINK_RX_EMPTY               (1 << 23)
+#define   SLINK_TX_UNF                 (1 << 24)
+#define   SLINK_RX_OVF                 (1 << 25)
+#define   SLINK_TX_FLUSH               (1 << 26)
+#define   SLINK_RX_FLUSH               (1 << 27)
+#define   SLINK_SCLK                   (1 << 28)
+#define   SLINK_ERR                    (1 << 29)
+#define   SLINK_RDY                    (1 << 30)
+#define   SLINK_BSY                    (1 << 31)
+
+#define SLINK_MAS_DATA         0x010
+#define SLINK_SLAVE_DATA       0x014
+
+#define SLINK_DMA_CTL          0x018
+#define   SLINK_DMA_BLOCK_SIZE(x)      (((x) & 0xffff) << 0)
+#define   SLINK_TX_TRIG_1              (0 << 16)
+#define   SLINK_TX_TRIG_4              (1 << 16)
+#define   SLINK_TX_TRIG_8              (2 << 16)
+#define   SLINK_TX_TRIG_16             (3 << 16)
+#define   SLINK_TX_TRIG_MASK           (3 << 16)
+#define   SLINK_RX_TRIG_1              (0 << 18)
+#define   SLINK_RX_TRIG_4              (1 << 18)
+#define   SLINK_RX_TRIG_8              (2 << 18)
+#define   SLINK_RX_TRIG_16             (3 << 18)
+#define   SLINK_RX_TRIG_MASK           (3 << 18)
+#define   SLINK_PACKED                 (1 << 20)
+#define   SLINK_PACK_SIZE_4            (0 << 21)
+#define   SLINK_PACK_SIZE_8            (1 << 21)
+#define   SLINK_PACK_SIZE_16           (2 << 21)
+#define   SLINK_PACK_SIZE_32           (3 << 21)
+#define   SLINK_PACK_SIZE_MASK         (3 << 21)
+#define   SLINK_IE_TXC                 (1 << 26)
+#define   SLINK_IE_RXC                 (1 << 27)
+#define   SLINK_DMA_EN                 (1 << 31)
+
+#define SLINK_STATUS2          0x01c
+#define   SLINK_TX_FIFO_EMPTY_COUNT(val)       (((val) & 0x3f) >> 0)
+#define   SLINK_RX_FIFO_FULL_COUNT(val)                (((val) & 0x3f) >> 16)
+
+#define SLINK_TX_FIFO          0x100
+#define SLINK_RX_FIFO          0x180
+
+static const unsigned long spi_tegra_req_sels[] = {
+       TEGRA_DMA_REQ_SEL_SL2B1,
+       TEGRA_DMA_REQ_SEL_SL2B2,
+       TEGRA_DMA_REQ_SEL_SL2B3,
+       TEGRA_DMA_REQ_SEL_SL2B4,
+};
+
+#define BB_LEN                 32
+
+struct spi_tegra_data {
+       struct spi_master       *master;
+       struct platform_device  *pdev;
+       spinlock_t              lock;
+
+       struct clk              *clk;
+       void __iomem            *base;
+       unsigned long           phys;
+
+       u32                     cur_speed;
+
+       struct list_head        queue;
+       struct spi_transfer     *cur;
+       unsigned                cur_pos;
+       unsigned                cur_len;
+       unsigned                cur_bytes_per_word;
+
+       /* The tegra spi controller has a bug which causes the first word
+        * in PIO transactions to be garbage.  Since packed DMA transactions
+        * require transfers to be 4 byte aligned we need a bounce buffer
+        * for the generic case.
+        */
+       struct tegra_dma_req    rx_dma_req;
+       struct tegra_dma_channel *rx_dma;
+       u32                     *rx_bb;
+       dma_addr_t              rx_bb_phys;
+};
+
+
+static inline unsigned long spi_tegra_readl(struct spi_tegra_data *tspi,
+                                           unsigned long reg)
+{
+       return readl(tspi->base + reg);
+}
+
+static inline void spi_tegra_writel(struct spi_tegra_data *tspi,
+                                   unsigned long val,
+                                   unsigned long reg)
+{
+       writel(val, tspi->base + reg);
+}
+
+static void spi_tegra_go(struct spi_tegra_data *tspi)
+{
+       unsigned long val;
+
+       wmb();
+
+       val = spi_tegra_readl(tspi, SLINK_DMA_CTL);
+       val &= ~SLINK_DMA_BLOCK_SIZE(~0) & ~SLINK_DMA_EN;
+       val |= SLINK_DMA_BLOCK_SIZE(tspi->rx_dma_req.size / 4 - 1);
+       spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+
+       tegra_dma_enqueue_req(tspi->rx_dma, &tspi->rx_dma_req);
+
+       val |= SLINK_DMA_EN;
+       spi_tegra_writel(tspi, val, SLINK_DMA_CTL);
+}
+
+static unsigned spi_tegra_fill_tx_fifo(struct spi_tegra_data *tspi,
+                                 struct spi_transfer *t)
+{
+       unsigned len = min(t->len - tspi->cur_pos, BB_LEN *
+                          tspi->cur_bytes_per_word);
+       u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_pos;
+       int i, j;
+       unsigned long val;
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND);
+       val &= ~SLINK_WORD_SIZE(~0);
+       val |= SLINK_WORD_SIZE(len / tspi->cur_bytes_per_word - 1);
+       spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+       for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+               val = 0;
+               for (j = 0; j < tspi->cur_bytes_per_word; j++)
+                       val |= tx_buf[i + j] << j * 8;
+
+               spi_tegra_writel(tspi, val, SLINK_TX_FIFO);
+       }
+
+       tspi->rx_dma_req.size = len / tspi->cur_bytes_per_word * 4;
+
+       return len;
+}
+
+static unsigned spi_tegra_drain_rx_fifo(struct spi_tegra_data *tspi,
+                                 struct spi_transfer *t)
+{
+       unsigned len = tspi->cur_len;
+       u8 *rx_buf = (u8 *)t->rx_buf + tspi->cur_pos;
+       int i, j;
+       unsigned long val;
+
+       for (i = 0; i < len; i += tspi->cur_bytes_per_word) {
+               val = tspi->rx_bb[i / tspi->cur_bytes_per_word];
+               for (j = 0; j < tspi->cur_bytes_per_word; j++)
+                       rx_buf[i + j] = (val >> (j * 8)) & 0xff;
+       }
+
+       return len;
+}
+
+static void spi_tegra_start_transfer(struct spi_device *spi,
+                                   struct spi_transfer *t)
+{
+       struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+       u32 speed;
+       u8 bits_per_word;
+       unsigned long val;
+
+       speed = t->speed_hz ? t->speed_hz : spi->max_speed_hz;
+       bits_per_word = t->bits_per_word ? t->bits_per_word  :
+               spi->bits_per_word;
+
+       tspi->cur_bytes_per_word = (bits_per_word - 1) / 8 + 1;
+
+       if (speed != tspi->cur_speed)
+               clk_set_rate(tspi->clk, speed);
+
+       if (tspi->cur_speed == 0)
+               clk_enable(tspi->clk);
+
+       tspi->cur_speed = speed;
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND2);
+       val &= ~SLINK_SS_EN_CS(~0) | SLINK_RXEN | SLINK_TXEN;
+       if (t->rx_buf)
+               val |= SLINK_RXEN;
+       if (t->tx_buf)
+               val |= SLINK_TXEN;
+       val |= SLINK_SS_EN_CS(spi->chip_select);
+       val |= SLINK_SPIE;
+       spi_tegra_writel(tspi, val, SLINK_COMMAND2);
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND);
+       val &= ~SLINK_BIT_LENGTH(~0);
+       val |= SLINK_BIT_LENGTH(bits_per_word - 1);
+
+       /* FIXME: should probably control CS manually so that we can be sure
+        * it does not go low between transfer and to support delay_usecs
+        * correctly.
+        */
+       val &= ~SLINK_IDLE_SCLK_MASK & ~SLINK_CK_SDA & ~SLINK_CS_SW;
+
+       if (spi->mode & SPI_CPHA)
+               val |= SLINK_CK_SDA;
+
+       if (spi->mode & SPI_CPOL)
+               val |= SLINK_IDLE_SCLK_DRIVE_HIGH;
+       else
+               val |= SLINK_IDLE_SCLK_DRIVE_LOW;
+
+       val |= SLINK_M_S;
+
+       spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+       spi_tegra_writel(tspi, SLINK_RX_FLUSH | SLINK_TX_FLUSH, SLINK_STATUS);
+
+       tspi->cur = t;
+       tspi->cur_pos = 0;
+       tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, t);
+
+       spi_tegra_go(tspi);
+}
+
+static void spi_tegra_start_message(struct spi_device *spi,
+                                   struct spi_message *m)
+{
+       struct spi_transfer *t;
+
+       m->actual_length = 0;
+       m->status = 0;
+
+       t = list_first_entry(&m->transfers, struct spi_transfer, transfer_list);
+       spi_tegra_start_transfer(spi, t);
+}
+
+static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
+{
+       struct spi_tegra_data *tspi = req->dev;
+       unsigned long flags;
+       struct spi_message *m;
+       struct spi_device *spi;
+       int timeout = 0;
+       unsigned long val;
+
+       /* the SPI controller may come back with both the BSY and RDY bits
+        * set.  In this case we need to wait for the BSY bit to clear so
+        * that we are sure the DMA is finished.  1000 reads was empirically
+        * determined to be long enough.
+        */
+       while (timeout++ < 1000) {
+               if (!(spi_tegra_readl(tspi, SLINK_STATUS) & SLINK_BSY))
+                       break;
+       }
+
+       spin_lock_irqsave(&tspi->lock, flags);
+
+       val = spi_tegra_readl(tspi, SLINK_STATUS);
+       val |= SLINK_RDY;
+       spi_tegra_writel(tspi, val, SLINK_STATUS);
+
+       m = list_first_entry(&tspi->queue, struct spi_message, queue);
+
+       if (timeout >= 1000)
+               m->status = -EIO;
+
+       spi = m->state;
+
+       tspi->cur_pos += spi_tegra_drain_rx_fifo(tspi, tspi->cur);
+       m->actual_length += tspi->cur_pos;
+
+       if (tspi->cur_pos < tspi->cur->len) {
+               tspi->cur_len = spi_tegra_fill_tx_fifo(tspi, tspi->cur);
+               spi_tegra_go(tspi);
+       } else if (!list_is_last(&tspi->cur->transfer_list,
+                                &m->transfers)) {
+               tspi->cur =  list_first_entry(&tspi->cur->transfer_list,
+                                             struct spi_transfer,
+                                             transfer_list);
+               spi_tegra_start_transfer(spi, tspi->cur);
+       } else {
+               list_del(&m->queue);
+
+               m->complete(m->context);
+
+               if (!list_empty(&tspi->queue)) {
+                       m = list_first_entry(&tspi->queue, struct spi_message,
+                                            queue);
+                       spi = m->state;
+                       spi_tegra_start_message(spi, m);
+               } else {
+                       clk_disable(tspi->clk);
+                       tspi->cur_speed = 0;
+               }
+       }
+
+       spin_unlock_irqrestore(&tspi->lock, flags);
+}
+
+static int spi_tegra_setup(struct spi_device *spi)
+{
+       struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+       unsigned long cs_bit;
+       unsigned long val;
+       unsigned long flags;
+
+       dev_dbg(&spi->dev, "setup %d bpw, %scpol, %scpha, %dHz\n",
+               spi->bits_per_word,
+               spi->mode & SPI_CPOL ? "" : "~",
+               spi->mode & SPI_CPHA ? "" : "~",
+               spi->max_speed_hz);
+
+
+       switch (spi->chip_select) {
+       case 0:
+               cs_bit = SLINK_CS_POLARITY;
+               break;
+
+       case 1:
+               cs_bit = SLINK_CS_POLARITY1;
+               break;
+
+       case 2:
+               cs_bit = SLINK_CS_POLARITY2;
+               break;
+
+       case 4:
+               cs_bit = SLINK_CS_POLARITY3;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       spin_lock_irqsave(&tspi->lock, flags);
+
+       val = spi_tegra_readl(tspi, SLINK_COMMAND);
+       if (spi->mode & SPI_CS_HIGH)
+               val |= cs_bit;
+       else
+               val &= ~cs_bit;
+       spi_tegra_writel(tspi, val, SLINK_COMMAND);
+
+       spin_unlock_irqrestore(&tspi->lock, flags);
+
+       return 0;
+}
+
+static int spi_tegra_transfer(struct spi_device *spi, struct spi_message *m)
+{
+       struct spi_tegra_data *tspi = spi_master_get_devdata(spi->master);
+       struct spi_transfer *t;
+       unsigned long flags;
+       int was_empty;
+
+       if (list_empty(&m->transfers) || !m->complete)
+               return -EINVAL;
+
+       list_for_each_entry(t, &m->transfers, transfer_list) {
+               if (t->bits_per_word < 0 || t->bits_per_word > 32)
+                       return -EINVAL;
+
+               if (t->len == 0)
+                       return -EINVAL;
+
+               if (!t->rx_buf && !t->tx_buf)
+                       return -EINVAL;
+       }
+
+       m->state = spi;
+
+       spin_lock_irqsave(&tspi->lock, flags);
+       was_empty = list_empty(&tspi->queue);
+       list_add_tail(&m->queue, &tspi->queue);
+
+       if (was_empty)
+               spi_tegra_start_message(spi, m);
+
+       spin_unlock_irqrestore(&tspi->lock, flags);
+
+       return 0;
+}
+
+static int __init spi_tegra_probe(struct platform_device *pdev)
+{
+       struct spi_master       *master;
+       struct spi_tegra_data   *tspi;
+       struct resource         *r;
+       int ret;
+
+       master = spi_alloc_master(&pdev->dev, sizeof *tspi);
+       if (master == NULL) {
+               dev_err(&pdev->dev, "master allocation failed\n");
+               return -ENOMEM;
+       }
+
+       /* the spi->mode bits understood by this driver: */
+       master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+       master->bus_num = pdev->id;
+
+       master->setup = spi_tegra_setup;
+       master->transfer = spi_tegra_transfer;
+       master->num_chipselect = 4;
+
+       dev_set_drvdata(&pdev->dev, master);
+       tspi = spi_master_get_devdata(master);
+       tspi->master = master;
+       tspi->pdev = pdev;
+       spin_lock_init(&tspi->lock);
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (r == NULL) {
+               ret = -ENODEV;
+               goto err0;
+       }
+
+       if (!request_mem_region(r->start, (r->end - r->start) + 1,
+                               dev_name(&pdev->dev))) {
+               ret = -EBUSY;
+               goto err0;
+       }
+
+       tspi->phys = r->start;
+       tspi->base = ioremap(r->start, r->end - r->start + 1);
+       if (!tspi->base) {
+               dev_err(&pdev->dev, "can't ioremap iomem\n");
+               ret = -ENOMEM;
+               goto err1;
+       }
+
+       tspi->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR_OR_NULL(tspi->clk)) {
+               dev_err(&pdev->dev, "can not get clock\n");
+               ret = PTR_ERR(tspi->clk);
+               goto err2;
+       }
+
+       INIT_LIST_HEAD(&tspi->queue);
+
+       tspi->rx_dma = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
+       if (!tspi->rx_dma) {
+               dev_err(&pdev->dev, "can not allocate rx dma channel\n");
+               ret = -ENODEV;
+               goto err3;
+       }
+
+       tspi->rx_bb = dma_alloc_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+                                        &tspi->rx_bb_phys, GFP_KERNEL);
+       if (!tspi->rx_bb) {
+               dev_err(&pdev->dev, "can not allocate rx bounce buffer\n");
+               ret = -ENOMEM;
+               goto err4;
+       }
+
+       tspi->rx_dma_req.complete = tegra_spi_rx_dma_complete;
+       tspi->rx_dma_req.to_memory = 1;
+       tspi->rx_dma_req.dest_addr = tspi->rx_bb_phys;
+       tspi->rx_dma_req.dest_bus_width = 32;
+       tspi->rx_dma_req.source_addr = tspi->phys + SLINK_RX_FIFO;
+       tspi->rx_dma_req.source_bus_width = 32;
+       tspi->rx_dma_req.source_wrap = 4;
+       tspi->rx_dma_req.req_sel = spi_tegra_req_sels[pdev->id];
+       tspi->rx_dma_req.dev = tspi;
+
+       ret = spi_register_master(master);
+
+       if (ret < 0)
+               goto err5;
+
+       return ret;
+
+err5:
+       dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+                         tspi->rx_bb, tspi->rx_bb_phys);
+err4:
+       tegra_dma_free_channel(tspi->rx_dma);
+err3:
+       clk_put(tspi->clk);
+err2:
+       iounmap(tspi->base);
+err1:
+       release_mem_region(r->start, (r->end - r->start) + 1);
+err0:
+       spi_master_put(master);
+       return ret;
+}
+
+static int __devexit spi_tegra_remove(struct platform_device *pdev)
+{
+       struct spi_master       *master;
+       struct spi_tegra_data   *tspi;
+       struct resource         *r;
+
+       master = dev_get_drvdata(&pdev->dev);
+       tspi = spi_master_get_devdata(master);
+
+       tegra_dma_free_channel(tspi->rx_dma);
+
+       dma_free_coherent(&pdev->dev, sizeof(u32) * BB_LEN,
+                         tspi->rx_bb, tspi->rx_bb_phys);
+
+       clk_put(tspi->clk);
+       iounmap(tspi->base);
+
+       spi_master_put(master);
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(r->start, (r->end - r->start) + 1);
+
+       return 0;
+}
+
+MODULE_ALIAS("platform:spi_tegra");
+
+static struct platform_driver spi_tegra_driver = {
+       .driver = {
+               .name =         "spi_tegra",
+               .owner =        THIS_MODULE,
+       },
+       .remove =       __devexit_p(spi_tegra_remove),
+};
+
+static int __init spi_tegra_init(void)
+{
+       return platform_driver_probe(&spi_tegra_driver, spi_tegra_probe);
+}
+module_init(spi_tegra_init);
+
+static void __exit spi_tegra_exit(void)
+{
+       platform_driver_unregister(&spi_tegra_driver);
+}
+module_exit(spi_tegra_exit);
+
+MODULE_LICENSE("GPL");
index 61d3ca6..cb5cd42 100644 (file)
@@ -54,7 +54,6 @@
 
 #include <plat/dma.h>
 #include <plat/usb.h>
-#include <plat/control.h>
 
 #include "omap_udc.h"
 
@@ -2309,21 +2308,12 @@ static char *trx_mode(unsigned m, int enabled)
 static int proc_otg_show(struct seq_file *s)
 {
        u32             tmp;
-       u32             trans;
-       char            *ctrl_name;
+       u32             trans = 0;
+       char            *ctrl_name = "(UNKNOWN)";
 
+       /* XXX This needs major revision for OMAP2+ */
        tmp = omap_readl(OTG_REV);
-       if (cpu_is_omap24xx()) {
-               /*
-                * REVISIT: Not clear how this works on OMAP2.  trans
-                * is ANDed to produce bits 7 and 8, which might make
-                * sense for USB_TRANSCEIVER_CTRL on OMAP1,
-                * but with CONTROL_DEVCONF, these bits have something to
-                * do with the frame adjustment counter and McBSP2.
-                */
-               ctrl_name = "control_devconf";
-               trans = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-       } else {
+       if (cpu_class_is_omap1()) {
                ctrl_name = "tranceiver_ctrl";
                trans = omap_readw(USB_TRANSCEIVER_CTRL);
        }
index e77e8e4..4ea187d 100644 (file)
@@ -1079,7 +1079,7 @@ static int au1200fb_fb_check_var(struct fb_var_screeninfo *var,
         * clock can only be obtain by dividing this value by an even integer.
         * Fallback to a slower pixel clock if necessary. */
        pixclock = max((u32)(PICOS2KHZ(var->pixclock) * 1000), fbi->monspecs.dclkmin);
-       pixclock = min(pixclock, min(fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2));
+       pixclock = min3(pixclock, fbi->monspecs.dclkmax, (u32)AU1200_LCD_MAX_CLK/2);
 
        if (AU1200_LCD_MAX_CLK % pixclock) {
                int diff = AU1200_LCD_MAX_CLK % pixclock;
index ca75cc2..d7c6c3e 100644 (file)
@@ -25,8 +25,6 @@
 #include <linux/gpio.h>
 #include <linux/i2c/twl.h>
 
-#include <plat/mux.h>
-#include <plat/mux.h>
 #include <asm/mach-types.h>
 
 #include "omapfb.h"
index 881c9f7..12327bb 100644 (file)
@@ -40,7 +40,7 @@ config PANEL_TPO_TD043MTEA1
 
 config PANEL_ACX565AKM
        tristate "ACX565AKM Panel"
-       depends on OMAP2_DSS_SDI
+       depends on OMAP2_DSS_SDI && SPI
        select BACKLIGHT_CLASS_DEVICE
        help
          This is the LCD panel used on Nokia N900
index 07fbb8a..e773106 100644 (file)
@@ -587,6 +587,9 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev)
 
        dev_dbg(&dssdev->dev, "%s\n", __func__);
 
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
        mutex_lock(&md->mutex);
 
        r = omapdss_sdi_display_enable(dssdev);
@@ -644,6 +647,9 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev)
 
        dev_dbg(&dssdev->dev, "%s\n", __func__);
 
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
        mutex_lock(&md->mutex);
 
        if (!md->enabled) {
index 300eff5..395a68d 100644 (file)
@@ -39,6 +39,9 @@ static int generic_panel_power_on(struct omap_dss_device *dssdev)
 {
        int r;
 
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -58,6 +61,9 @@ err0:
 
 static void generic_panel_power_off(struct omap_dss_device *dssdev)
 {
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
index 1026746..0c6896c 100644 (file)
@@ -43,6 +43,9 @@ static int sharp_lq_panel_power_on(struct omap_dss_device *dssdev)
 {
        int r;
 
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -65,6 +68,9 @@ err0:
 
 static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev)
 {
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
index 7d9eb2b..9a138f6 100644 (file)
@@ -135,6 +135,9 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev)
 {
        int r = 0;
 
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -157,6 +160,9 @@ err0:
 
 static void sharp_ls_power_off(struct omap_dss_device *dssdev)
 {
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
index e320e67..526e906 100644 (file)
@@ -46,6 +46,9 @@ static int toppoly_tdo_panel_power_on(struct omap_dss_device *dssdev)
 {
        int r;
 
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -65,6 +68,9 @@ err0:
 
 static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
 {
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
        if (dssdev->platform_disable)
                dssdev->platform_disable(dssdev);
 
index e866e76..dbe9d43 100644 (file)
@@ -269,6 +269,9 @@ static int tpo_td043_power_on(struct omap_dss_device *dssdev)
        int nreset_gpio = dssdev->reset_gpio;
        int r;
 
+       if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+               return 0;
+
        r = omapdss_dpi_display_enable(dssdev);
        if (r)
                goto err0;
@@ -308,6 +311,9 @@ static void tpo_td043_power_off(struct omap_dss_device *dssdev)
        struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
        int nreset_gpio = dssdev->reset_gpio;
 
+       if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+               return;
+
        tpo_td043_write(tpo_td043->spi, 3,
                        TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
 
index d71b5d9..7db17b5 100644 (file)
@@ -1,5 +1,5 @@
 obj-$(CONFIG_OMAP2_DSS) += omapdss.o
-omapdss-y := core.o dss.o dispc.o display.o manager.o overlay.o
+omapdss-y := core.o dss.o dss_features.o dispc.o display.o manager.o overlay.o
 omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o
 omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
 omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
index b3a498f..8e89f60 100644 (file)
@@ -37,6 +37,7 @@
 #include <plat/clock.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static struct {
        struct platform_device *pdev;
@@ -502,6 +503,8 @@ static int omap_dss_probe(struct platform_device *pdev)
 
        core.pdev = pdev;
 
+       dss_features_init();
+
        dss_init_overlay_managers(pdev);
        dss_init_overlays(pdev);
 
index 5ecdc00..fa40fa5 100644 (file)
@@ -39,6 +39,7 @@
 #include <plat/display.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 /* DISPC */
 #define DISPC_BASE                     0x48050400
@@ -139,6 +140,22 @@ struct omap_dispc_isr_data {
        u32                     mask;
 };
 
+struct dispc_h_coef {
+       s8 hc4;
+       s8 hc3;
+       u8 hc2;
+       s8 hc1;
+       s8 hc0;
+};
+
+struct dispc_v_coef {
+       s8 vc22;
+       s8 vc2;
+       u8 vc1;
+       s8 vc0;
+       s8 vc00;
+};
+
 #define REG_GET(idx, start, end) \
        FLD_GET(dispc_read_reg(idx), start, end)
 
@@ -564,106 +581,77 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
                int vscaleup, int five_taps)
 {
        /* Coefficients for horizontal up-sampling */
-       static const u32 coef_hup[8] = {
-               0x00800000,
-               0x0D7CF800,
-               0x1E70F5FF,
-               0x335FF5FE,
-               0xF74949F7,
-               0xF55F33FB,
-               0xF5701EFE,
-               0xF87C0DFF,
+       static const struct dispc_h_coef coef_hup[8] = {
+               {  0,   0, 128,   0,  0 },
+               { -1,  13, 124,  -8,  0 },
+               { -2,  30, 112, -11, -1 },
+               { -5,  51,  95, -11, -2 },
+               {  0,  -9,  73,  73, -9 },
+               { -2, -11,  95,  51, -5 },
+               { -1, -11, 112,  30, -2 },
+               {  0,  -8, 124,  13, -1 },
        };
 
-       /* Coefficients for horizontal down-sampling */
-       static const u32 coef_hdown[8] = {
-               0x24382400,
-               0x28371FFE,
-               0x2C361BFB,
-               0x303516F9,
-               0x11343311,
-               0x1635300C,
-               0x1B362C08,
-               0x1F372804,
+       /* Coefficients for vertical up-sampling */
+       static const struct dispc_v_coef coef_vup_3tap[8] = {
+               { 0,  0, 128,  0, 0 },
+               { 0,  3, 123,  2, 0 },
+               { 0, 12, 111,  5, 0 },
+               { 0, 32,  89,  7, 0 },
+               { 0,  0,  64, 64, 0 },
+               { 0,  7,  89, 32, 0 },
+               { 0,  5, 111, 12, 0 },
+               { 0,  2, 123,  3, 0 },
        };
 
-       /* Coefficients for horizontal and vertical up-sampling */
-       static const u32 coef_hvup[2][8] = {
-               {
-               0x00800000,
-               0x037B02FF,
-               0x0C6F05FE,
-               0x205907FB,
-               0x00404000,
-               0x075920FE,
-               0x056F0CFF,
-               0x027B0300,
-               },
-               {
-               0x00800000,
-               0x0D7CF8FF,
-               0x1E70F5FE,
-               0x335FF5FB,
-               0xF7404000,
-               0xF55F33FE,
-               0xF5701EFF,
-               0xF87C0D00,
-               },
+       static const struct dispc_v_coef coef_vup_5tap[8] = {
+               {  0,   0, 128,   0,  0 },
+               { -1,  13, 124,  -8,  0 },
+               { -2,  30, 112, -11, -1 },
+               { -5,  51,  95, -11, -2 },
+               {  0,  -9,  73,  73, -9 },
+               { -2, -11,  95,  51, -5 },
+               { -1, -11, 112,  30, -2 },
+               {  0,  -8, 124,  13, -1 },
        };
 
-       /* Coefficients for horizontal and vertical down-sampling */
-       static const u32 coef_hvdown[2][8] = {
-               {
-               0x24382400,
-               0x28391F04,
-               0x2D381B08,
-               0x3237170C,
-               0x123737F7,
-               0x173732F9,
-               0x1B382DFB,
-               0x1F3928FE,
-               },
-               {
-               0x24382400,
-               0x28371F04,
-               0x2C361B08,
-               0x3035160C,
-               0x113433F7,
-               0x163530F9,
-               0x1B362CFB,
-               0x1F3728FE,
-               },
+       /* Coefficients for horizontal down-sampling */
+       static const struct dispc_h_coef coef_hdown[8] = {
+               {   0, 36, 56, 36,  0 },
+               {   4, 40, 55, 31, -2 },
+               {   8, 44, 54, 27, -5 },
+               {  12, 48, 53, 22, -7 },
+               {  -9, 17, 52, 51, 17 },
+               {  -7, 22, 53, 48, 12 },
+               {  -5, 27, 54, 44,  8 },
+               {  -2, 31, 55, 40,  4 },
        };
 
-       /* Coefficients for vertical up-sampling */
-       static const u32 coef_vup[8] = {
-               0x00000000,
-               0x0000FF00,
-               0x0000FEFF,
-               0x0000FBFE,
-               0x000000F7,
-               0x0000FEFB,
-               0x0000FFFE,
-               0x000000FF,
+       /* Coefficients for vertical down-sampling */
+       static const struct dispc_v_coef coef_vdown_3tap[8] = {
+               { 0, 36, 56, 36, 0 },
+               { 0, 40, 57, 31, 0 },
+               { 0, 45, 56, 27, 0 },
+               { 0, 50, 55, 23, 0 },
+               { 0, 18, 55, 55, 0 },
+               { 0, 23, 55, 50, 0 },
+               { 0, 27, 56, 45, 0 },
+               { 0, 31, 57, 40, 0 },
        };
 
-
-       /* Coefficients for vertical down-sampling */
-       static const u32 coef_vdown[8] = {
-               0x00000000,
-               0x000004FE,
-               0x000008FB,
-               0x00000CF9,
-               0x0000F711,
-               0x0000F90C,
-               0x0000FB08,
-               0x0000FE04,
+       static const struct dispc_v_coef coef_vdown_5tap[8] = {
+               {   0, 36, 56, 36,  0 },
+               {   4, 40, 55, 31, -2 },
+               {   8, 44, 54, 27, -5 },
+               {  12, 48, 53, 22, -7 },
+               {  -9, 17, 52, 51, 17 },
+               {  -7, 22, 53, 48, 12 },
+               {  -5, 27, 54, 44,  8 },
+               {  -2, 31, 55, 40,  4 },
        };
 
-       const u32 *h_coef;
-       const u32 *hv_coef;
-       const u32 *hv_coef_mod;
-       const u32 *v_coef;
+       const struct dispc_h_coef *h_coef;
+       const struct dispc_v_coef *v_coef;
        int i;
 
        if (hscaleup)
@@ -671,47 +659,34 @@ static void _dispc_set_scale_coef(enum omap_plane plane, int hscaleup,
        else
                h_coef = coef_hdown;
 
-       if (vscaleup) {
-               hv_coef = coef_hvup[five_taps];
-               v_coef = coef_vup;
-
-               if (hscaleup)
-                       hv_coef_mod = NULL;
-               else
-                       hv_coef_mod = coef_hvdown[five_taps];
-       } else {
-               hv_coef = coef_hvdown[five_taps];
-               v_coef = coef_vdown;
-
-               if (hscaleup)
-                       hv_coef_mod = coef_hvup[five_taps];
-               else
-                       hv_coef_mod = NULL;
-       }
+       if (vscaleup)
+               v_coef = five_taps ? coef_vup_5tap : coef_vup_3tap;
+       else
+               v_coef = five_taps ? coef_vdown_5tap : coef_vdown_3tap;
 
        for (i = 0; i < 8; i++) {
                u32 h, hv;
 
-               h = h_coef[i];
-
-               hv = hv_coef[i];
-
-               if (hv_coef_mod) {
-                       hv &= 0xffffff00;
-                       hv |= (hv_coef_mod[i] & 0xff);
-               }
+               h = FLD_VAL(h_coef[i].hc0, 7, 0)
+                       | FLD_VAL(h_coef[i].hc1, 15, 8)
+                       | FLD_VAL(h_coef[i].hc2, 23, 16)
+                       | FLD_VAL(h_coef[i].hc3, 31, 24);
+               hv = FLD_VAL(h_coef[i].hc4, 7, 0)
+                       | FLD_VAL(v_coef[i].vc0, 15, 8)
+                       | FLD_VAL(v_coef[i].vc1, 23, 16)
+                       | FLD_VAL(v_coef[i].vc2, 31, 24);
 
                _dispc_write_firh_reg(plane, i, h);
                _dispc_write_firhv_reg(plane, i, hv);
        }
 
-       if (!five_taps)
-               return;
-
-       for (i = 0; i < 8; i++) {
-               u32 v;
-               v = v_coef[i];
-               _dispc_write_firv_reg(plane, i, v);
+       if (five_taps) {
+               for (i = 0; i < 8; i++) {
+                       u32 v;
+                       v = FLD_VAL(v_coef[i].vc00, 7, 0)
+                               | FLD_VAL(v_coef[i].vc22, 15, 8);
+                       _dispc_write_firv_reg(plane, i, v);
+               }
        }
 }
 
@@ -800,12 +775,12 @@ static void _dispc_set_vid_size(enum omap_plane plane, int width, int height)
 
 static void _dispc_setup_global_alpha(enum omap_plane plane, u8 global_alpha)
 {
-
-       BUG_ON(plane == OMAP_DSS_VIDEO1);
-
-       if (cpu_is_omap24xx())
+       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                return;
 
+       BUG_ON(!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
+                       plane == OMAP_DSS_VIDEO1);
+
        if (plane == OMAP_DSS_GFX)
                REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, 7, 0);
        else if (plane == OMAP_DSS_VIDEO2)
@@ -975,17 +950,14 @@ static void dispc_read_plane_fifo_sizes(void)
                                      DISPC_VID_FIFO_SIZE_STATUS(1) };
        u32 size;
        int plane;
+       u8 start, end;
 
        enable_clocks(1);
 
-       for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
-               if (cpu_is_omap24xx())
-                       size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 8, 0);
-               else if (cpu_is_omap34xx())
-                       size = FLD_GET(dispc_read_reg(fsz_reg[plane]), 10, 0);
-               else
-                       BUG();
+       dss_feat_get_reg_field(FEAT_REG_FIFOSIZE, &start, &end);
 
+       for (plane = 0; plane < ARRAY_SIZE(dispc.fifo_size); ++plane) {
+               size = FLD_GET(dispc_read_reg(fsz_reg[plane]), start, end);
                dispc.fifo_size[plane] = size;
        }
 
@@ -1002,6 +974,8 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
        const struct dispc_reg ftrs_reg[] = { DISPC_GFX_FIFO_THRESHOLD,
                                       DISPC_VID_FIFO_THRESHOLD(0),
                                       DISPC_VID_FIFO_THRESHOLD(1) };
+       u8 hi_start, hi_end, lo_start, lo_end;
+
        enable_clocks(1);
 
        DSSDBG("fifo(%d) low/high old %u/%u, new %u/%u\n",
@@ -1010,12 +984,12 @@ void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high)
                        REG_GET(ftrs_reg[plane], 27, 16),
                        low, high);
 
-       if (cpu_is_omap24xx())
-               dispc_write_reg(ftrs_reg[plane],
-                               FLD_VAL(high, 24, 16) | FLD_VAL(low, 8, 0));
-       else
-               dispc_write_reg(ftrs_reg[plane],
-                               FLD_VAL(high, 27, 16) | FLD_VAL(low, 11, 0));
+       dss_feat_get_reg_field(FEAT_REG_FIFOHIGHTHRESHOLD, &hi_start, &hi_end);
+       dss_feat_get_reg_field(FEAT_REG_FIFOLOWTHRESHOLD, &lo_start, &lo_end);
+
+       dispc_write_reg(ftrs_reg[plane],
+                       FLD_VAL(high, hi_start, hi_end) |
+                       FLD_VAL(low, lo_start, lo_end));
 
        enable_clocks(0);
 }
@@ -1035,13 +1009,16 @@ static void _dispc_set_fir(enum omap_plane plane, int hinc, int vinc)
        u32 val;
        const struct dispc_reg fir_reg[] = { DISPC_VID_FIR(0),
                                      DISPC_VID_FIR(1) };
+       u8 hinc_start, hinc_end, vinc_start, vinc_end;
 
        BUG_ON(plane == OMAP_DSS_GFX);
 
-       if (cpu_is_omap24xx())
-               val = FLD_VAL(vinc, 27, 16) | FLD_VAL(hinc, 11, 0);
-       else
-               val = FLD_VAL(vinc, 28, 16) | FLD_VAL(hinc, 12, 0);
+       dss_feat_get_reg_field(FEAT_REG_FIRHINC, &hinc_start, &hinc_end);
+       dss_feat_get_reg_field(FEAT_REG_FIRVINC, &vinc_start, &vinc_end);
+
+       val = FLD_VAL(vinc, vinc_start, vinc_end) |
+                       FLD_VAL(hinc, hinc_start, hinc_end);
+
        dispc_write_reg(fir_reg[plane-1], val);
 }
 
@@ -1567,6 +1544,8 @@ static int _dispc_setup_plane(enum omap_plane plane,
                case OMAP_DSS_COLOR_ARGB16:
                case OMAP_DSS_COLOR_ARGB32:
                case OMAP_DSS_COLOR_RGBA32:
+                       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
+                               return -EINVAL;
                case OMAP_DSS_COLOR_RGBX32:
                        if (cpu_is_omap24xx())
                                return -EINVAL;
@@ -1607,9 +1586,10 @@ static int _dispc_setup_plane(enum omap_plane plane,
                case OMAP_DSS_COLOR_ARGB16:
                case OMAP_DSS_COLOR_ARGB32:
                case OMAP_DSS_COLOR_RGBA32:
-                       if (cpu_is_omap24xx())
+                       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                                return -EINVAL;
-                       if (plane == OMAP_DSS_VIDEO1)
+                       if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
+                                       plane == OMAP_DSS_VIDEO1)
                                return -EINVAL;
                        break;
 
@@ -2002,7 +1982,7 @@ void dispc_enable_trans_key(enum omap_channel ch, bool enable)
 }
 void dispc_enable_alpha_blending(enum omap_channel ch, bool enable)
 {
-       if (cpu_is_omap24xx())
+       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                return;
 
        enable_clocks(1);
@@ -2016,7 +1996,7 @@ bool dispc_alpha_blending_enabled(enum omap_channel ch)
 {
        bool enabled;
 
-       if (cpu_is_omap24xx())
+       if (!dss_has_feature(FEAT_GLOBAL_ALPHA))
                return false;
 
        enable_clocks(1);
index b3fa3a7..aa4f7a5 100644 (file)
@@ -3274,7 +3274,6 @@ int dsi_init(struct platform_device *pdev)
 
        dsi.vdds_dsi_reg = dss_get_vdds_dsi();
        if (IS_ERR(dsi.vdds_dsi_reg)) {
-               iounmap(dsi.base);
                DSSERR("can't get VDDS_DSI regulator\n");
                r = PTR_ERR(dsi.vdds_dsi_reg);
                goto err2;
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
new file mode 100644 (file)
index 0000000..867f68d
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * linux/drivers/video/omap2/dss/dss_features.c
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <plat/display.h>
+#include <plat/cpu.h>
+
+#include "dss_features.h"
+
+/* Defines a generic omap register field */
+struct dss_reg_field {
+       enum dss_feat_reg_field id;
+       u8 start, end;
+};
+
+struct omap_dss_features {
+       const struct dss_reg_field *reg_fields;
+       const int num_reg_fields;
+
+       const u32 has_feature;
+
+       const int num_mgrs;
+       const int num_ovls;
+       const enum omap_display_type *supported_displays;
+       const enum omap_color_mode *supported_color_modes;
+};
+
+/* This struct is assigned to one of the below during initialization */
+static struct omap_dss_features *omap_current_dss_features;
+
+static const struct dss_reg_field omap2_dss_reg_fields[] = {
+       { FEAT_REG_FIRHINC, 11, 0 },
+       { FEAT_REG_FIRVINC, 27, 16 },
+       { FEAT_REG_FIFOLOWTHRESHOLD, 8, 0 },
+       { FEAT_REG_FIFOHIGHTHRESHOLD, 24, 16 },
+       { FEAT_REG_FIFOSIZE, 8, 0 },
+};
+
+static const struct dss_reg_field omap3_dss_reg_fields[] = {
+       { FEAT_REG_FIRHINC, 12, 0 },
+       { FEAT_REG_FIRVINC, 28, 16 },
+       { FEAT_REG_FIFOLOWTHRESHOLD, 11, 0 },
+       { FEAT_REG_FIFOHIGHTHRESHOLD, 27, 16 },
+       { FEAT_REG_FIFOSIZE, 10, 0 },
+};
+
+static const enum omap_display_type omap2_dss_supported_displays[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+       OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_display_type omap3_dss_supported_displays[] = {
+       /* OMAP_DSS_CHANNEL_LCD */
+       OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
+       OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI,
+
+       /* OMAP_DSS_CHANNEL_DIGIT */
+       OMAP_DISPLAY_TYPE_VENC,
+};
+
+static const enum omap_color_mode omap2_dss_supported_color_modes[] = {
+       /* OMAP_DSS_GFX */
+       OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+       OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+       OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
+       OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
+
+       /* OMAP_DSS_VIDEO1 */
+       OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+       OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+       OMAP_DSS_COLOR_UYVY,
+
+       /* OMAP_DSS_VIDEO2 */
+       OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+       OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+       OMAP_DSS_COLOR_UYVY,
+};
+
+static const enum omap_color_mode omap3_dss_supported_color_modes[] = {
+       /* OMAP_DSS_GFX */
+       OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
+       OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
+       OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+       OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+       OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
+       OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+
+       /* OMAP_DSS_VIDEO1 */
+       OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
+       OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
+       OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
+
+       /* OMAP_DSS_VIDEO2 */
+       OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
+       OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
+       OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
+       OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
+       OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
+};
+
+/* OMAP2 DSS Features */
+static struct omap_dss_features omap2_dss_features = {
+       .reg_fields = omap2_dss_reg_fields,
+       .num_reg_fields = ARRAY_SIZE(omap2_dss_reg_fields),
+
+       .num_mgrs = 2,
+       .num_ovls = 3,
+       .supported_displays = omap2_dss_supported_displays,
+       .supported_color_modes = omap2_dss_supported_color_modes,
+};
+
+/* OMAP3 DSS Features */
+static struct omap_dss_features omap3_dss_features = {
+       .reg_fields = omap3_dss_reg_fields,
+       .num_reg_fields = ARRAY_SIZE(omap3_dss_reg_fields),
+
+       .has_feature    = FEAT_GLOBAL_ALPHA,
+
+       .num_mgrs = 2,
+       .num_ovls = 3,
+       .supported_displays = omap3_dss_supported_displays,
+       .supported_color_modes = omap3_dss_supported_color_modes,
+};
+
+/* Functions returning values related to a DSS feature */
+int dss_feat_get_num_mgrs(void)
+{
+       return omap_current_dss_features->num_mgrs;
+}
+
+int dss_feat_get_num_ovls(void)
+{
+       return omap_current_dss_features->num_ovls;
+}
+
+enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel)
+{
+       return omap_current_dss_features->supported_displays[channel];
+}
+
+enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane)
+{
+       return omap_current_dss_features->supported_color_modes[plane];
+}
+
+/* DSS has_feature check */
+bool dss_has_feature(enum dss_feat_id id)
+{
+       return omap_current_dss_features->has_feature & id;
+}
+
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
+{
+       if (id >= omap_current_dss_features->num_reg_fields)
+               BUG();
+
+       *start = omap_current_dss_features->reg_fields[id].start;
+       *end = omap_current_dss_features->reg_fields[id].end;
+}
+
+void dss_features_init(void)
+{
+       if (cpu_is_omap24xx())
+               omap_current_dss_features = &omap2_dss_features;
+       else
+               omap_current_dss_features = &omap3_dss_features;
+}
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
new file mode 100644 (file)
index 0000000..cb231ea
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * linux/drivers/video/omap2/dss/dss_features.h
+ *
+ * Copyright (C) 2010 Texas Instruments
+ * Author: Archit Taneja <archit@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __OMAP2_DSS_FEATURES_H
+#define __OMAP2_DSS_FEATURES_H
+
+#define MAX_DSS_MANAGERS       2
+#define MAX_DSS_OVERLAYS       3
+
+/* DSS has feature id */
+enum dss_feat_id {
+       FEAT_GLOBAL_ALPHA       = 1 << 0,
+       FEAT_GLOBAL_ALPHA_VID1  = 1 << 1,
+};
+
+/* DSS register field id */
+enum dss_feat_reg_field {
+       FEAT_REG_FIRHINC,
+       FEAT_REG_FIRVINC,
+       FEAT_REG_FIFOHIGHTHRESHOLD,
+       FEAT_REG_FIFOLOWTHRESHOLD,
+       FEAT_REG_FIFOSIZE,
+};
+
+/* DSS Feature Functions */
+int dss_feat_get_num_mgrs(void);
+int dss_feat_get_num_ovls(void);
+enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel);
+enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane);
+
+bool dss_has_feature(enum dss_feat_id id);
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
+void dss_features_init(void);
+#endif
index 6a649ab..545e9b9 100644 (file)
@@ -33,6 +33,7 @@
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static int num_managers;
 static struct list_head manager_list;
@@ -448,8 +449,8 @@ struct manager_cache_data {
 
 static struct {
        spinlock_t lock;
-       struct overlay_cache_data overlay_cache[3];
-       struct manager_cache_data manager_cache[2];
+       struct overlay_cache_data overlay_cache[MAX_DSS_OVERLAYS];
+       struct manager_cache_data manager_cache[MAX_DSS_MANAGERS];
 
        bool irq_enabled;
 } dss_cache;
@@ -882,12 +883,12 @@ static int configure_dispc(void)
 {
        struct overlay_cache_data *oc;
        struct manager_cache_data *mc;
-       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
-       const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+       const int num_ovls = dss_feat_get_num_ovls();
+       const int num_mgrs = dss_feat_get_num_mgrs();
        int i;
        int r;
-       bool mgr_busy[2];
-       bool mgr_go[2];
+       bool mgr_busy[MAX_DSS_MANAGERS];
+       bool mgr_go[MAX_DSS_MANAGERS];
        bool busy;
 
        r = 0;
@@ -989,7 +990,7 @@ void dss_setup_partial_planes(struct omap_dss_device *dssdev,
 {
        struct overlay_cache_data *oc;
        struct manager_cache_data *mc;
-       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
+       const int num_ovls = dss_feat_get_num_ovls();
        struct omap_overlay_manager *mgr;
        int i;
        u16 x, y, w, h;
@@ -1121,8 +1122,8 @@ void dss_start_update(struct omap_dss_device *dssdev)
 {
        struct manager_cache_data *mc;
        struct overlay_cache_data *oc;
-       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
-       const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+       const int num_ovls = dss_feat_get_num_ovls();
+       const int num_mgrs = dss_feat_get_num_mgrs();
        struct omap_overlay_manager *mgr;
        int i;
 
@@ -1151,10 +1152,10 @@ static void dss_apply_irq_handler(void *data, u32 mask)
 {
        struct manager_cache_data *mc;
        struct overlay_cache_data *oc;
-       const int num_ovls = ARRAY_SIZE(dss_cache.overlay_cache);
-       const int num_mgrs = ARRAY_SIZE(dss_cache.manager_cache);
+       const int num_ovls = dss_feat_get_num_ovls();
+       const int num_mgrs = dss_feat_get_num_mgrs();
        int i, r;
-       bool mgr_busy[2];
+       bool mgr_busy[MAX_DSS_MANAGERS];
 
        mgr_busy[0] = dispc_go_busy(0);
        mgr_busy[1] = dispc_go_busy(1);
@@ -1461,7 +1462,7 @@ int dss_init_overlay_managers(struct platform_device *pdev)
 
        num_managers = 0;
 
-       for (i = 0; i < 2; ++i) {
+       for (i = 0; i < dss_feat_get_num_mgrs(); ++i) {
                struct omap_overlay_manager *mgr;
                mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
 
@@ -1471,14 +1472,10 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                case 0:
                        mgr->name = "lcd";
                        mgr->id = OMAP_DSS_CHANNEL_LCD;
-                       mgr->supported_displays =
-                               OMAP_DISPLAY_TYPE_DPI | OMAP_DISPLAY_TYPE_DBI |
-                               OMAP_DISPLAY_TYPE_SDI | OMAP_DISPLAY_TYPE_DSI;
                        break;
                case 1:
                        mgr->name = "tv";
                        mgr->id = OMAP_DSS_CHANNEL_DIGIT;
-                       mgr->supported_displays = OMAP_DISPLAY_TYPE_VENC;
                        break;
                }
 
@@ -1494,6 +1491,8 @@ int dss_init_overlay_managers(struct platform_device *pdev)
                mgr->disable = &dss_mgr_disable;
 
                mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
+               mgr->supported_displays =
+                       dss_feat_get_supported_displays(mgr->id);
 
                dss_overlay_setup_dispc_manager(mgr);
 
index 244dca8..75642c2 100644 (file)
@@ -35,6 +35,7 @@
 #include <plat/cpu.h>
 
 #include "dss.h"
+#include "dss_features.h"
 
 static int num_overlays;
 static struct list_head overlay_list;
@@ -237,7 +238,8 @@ static ssize_t overlay_global_alpha_store(struct omap_overlay *ovl,
        /* Video1 plane does not support global alpha
         * to always make it 255 completely opaque
         */
-       if (ovl->id == OMAP_DSS_VIDEO1)
+       if (!dss_has_feature(FEAT_GLOBAL_ALPHA_VID1) &&
+                       ovl->id == OMAP_DSS_VIDEO1)
                info.global_alpha = 255;
        else
                info.global_alpha = simple_strtoul(buf, NULL, 10);
@@ -510,11 +512,11 @@ static void omap_dss_add_overlay(struct omap_overlay *overlay)
        list_add_tail(&overlay->list, &overlay_list);
 }
 
-static struct omap_overlay *dispc_overlays[3];
+static struct omap_overlay *dispc_overlays[MAX_DSS_OVERLAYS];
 
 void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr)
 {
-       mgr->num_overlays = 3;
+       mgr->num_overlays = dss_feat_get_num_ovls();
        mgr->overlays = dispc_overlays;
 }
 
@@ -535,7 +537,7 @@ void dss_init_overlays(struct platform_device *pdev)
 
        num_overlays = 0;
 
-       for (i = 0; i < 3; ++i) {
+       for (i = 0; i < dss_feat_get_num_ovls(); ++i) {
                struct omap_overlay *ovl;
                ovl = kzalloc(sizeof(*ovl), GFP_KERNEL);
 
@@ -545,18 +547,12 @@ void dss_init_overlays(struct platform_device *pdev)
                case 0:
                        ovl->name = "gfx";
                        ovl->id = OMAP_DSS_GFX;
-                       ovl->supported_modes = cpu_is_omap34xx() ?
-                               OMAP_DSS_COLOR_GFX_OMAP3 :
-                               OMAP_DSS_COLOR_GFX_OMAP2;
                        ovl->caps = OMAP_DSS_OVL_CAP_DISPC;
                        ovl->info.global_alpha = 255;
                        break;
                case 1:
                        ovl->name = "vid1";
                        ovl->id = OMAP_DSS_VIDEO1;
-                       ovl->supported_modes = cpu_is_omap34xx() ?
-                               OMAP_DSS_COLOR_VID1_OMAP3 :
-                               OMAP_DSS_COLOR_VID_OMAP2;
                        ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
                                OMAP_DSS_OVL_CAP_DISPC;
                        ovl->info.global_alpha = 255;
@@ -564,9 +560,6 @@ void dss_init_overlays(struct platform_device *pdev)
                case 2:
                        ovl->name = "vid2";
                        ovl->id = OMAP_DSS_VIDEO2;
-                       ovl->supported_modes = cpu_is_omap34xx() ?
-                               OMAP_DSS_COLOR_VID2_OMAP3 :
-                               OMAP_DSS_COLOR_VID_OMAP2;
                        ovl->caps = OMAP_DSS_OVL_CAP_SCALE |
                                OMAP_DSS_OVL_CAP_DISPC;
                        ovl->info.global_alpha = 255;
@@ -579,6 +572,9 @@ void dss_init_overlays(struct platform_device *pdev)
                ovl->get_overlay_info = &dss_ovl_get_overlay_info;
                ovl->wait_for_go = &dss_ovl_wait_for_go;
 
+               ovl->supported_modes =
+                       dss_feat_get_supported_color_modes(ovl->id);
+
                omap_dss_add_overlay(ovl);
 
                r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
@@ -651,7 +647,7 @@ void dss_recheck_connections(struct omap_dss_device *dssdev, bool force)
        }
 
        if (mgr) {
-               for (i = 0; i < 3; i++) {
+               for (i = 0; i < dss_feat_get_num_ovls(); i++) {
                        struct omap_overlay *ovl;
                        ovl = omap_dss_get_overlay(i);
                        if (!ovl->manager || force) {
index 43496d6..65149b2 100644 (file)
@@ -3,7 +3,7 @@ menuconfig FB_OMAP2
         depends on FB && OMAP2_DSS
 
        select OMAP2_VRAM
-       select OMAP2_VRFB
+       select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
         select FB_CFB_FILLRECT
         select FB_CFB_COPYAREA
         select FB_CFB_IMAGEBLIT
index 04034d4..6a704f1 100644 (file)
@@ -714,10 +714,10 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
                var->pixclock = timings.pixel_clock != 0 ?
                        KHZ2PICOS(timings.pixel_clock) :
                        0;
-               var->left_margin = timings.hfp;
-               var->right_margin = timings.hbp;
-               var->upper_margin = timings.vfp;
-               var->lower_margin = timings.vbp;
+               var->left_margin = timings.hbp;
+               var->right_margin = timings.hfp;
+               var->upper_margin = timings.vbp;
+               var->lower_margin = timings.vfp;
                var->hsync_len = timings.hsw;
                var->vsync_len = timings.vsw;
        } else {
@@ -2059,10 +2059,10 @@ static int omapfb_mode_to_timings(const char *mode_str,
 
        if (r != 0) {
                timings->pixel_clock = PICOS2KHZ(var.pixclock);
-               timings->hfp = var.left_margin;
-               timings->hbp = var.right_margin;
-               timings->vfp = var.upper_margin;
-               timings->vbp = var.lower_margin;
+               timings->hbp = var.left_margin;
+               timings->hfp = var.right_margin;
+               timings->vbp = var.upper_margin;
+               timings->vfp = var.lower_margin;
                timings->hsw = var.hsync_len;
                timings->vsw = var.vsync_len;
                timings->x_res = var.xres;
@@ -2198,6 +2198,16 @@ static int omapfb_probe(struct platform_device *pdev)
                goto err0;
        }
 
+       /* TODO : Replace cpu check with omap_has_vrfb once HAS_FEATURE
+       *        available for OMAP2 and OMAP3
+       */
+       if (def_vrfb && !cpu_is_omap24xx() && !cpu_is_omap34xx()) {
+               def_vrfb = 0;
+               dev_warn(&pdev->dev, "VRFB is not supported on this hardware, "
+                               "ignoring the module parameter vrfb=y\n");
+       }
+
+
        mutex_init(&fbdev->mtx);
 
        fbdev->dev = &pdev->dev;
index 0c9ce88..68bd234 100644 (file)
 #include <linux/dma-mapping.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
 #include <linux/io.h>
 #include <linux/xilinxfb.h>
 #include <linux/slab.h>
+
+#ifdef CONFIG_PPC_DCR
 #include <asm/dcr.h>
+#endif
 
 #define DRIVER_NAME            "xilinxfb"
 
@@ -123,10 +127,10 @@ struct xilinxfb_drvdata {
                                                registers */
        void __iomem    *regs;          /* virt. address of the control
                                                registers */
-
+#ifdef CONFIG_PPC_DCR
        dcr_host_t      dcr_host;
        unsigned int    dcr_len;
-
+#endif
        void            *fb_virt;       /* virt. address of the frame buffer */
        dma_addr_t      fb_phys;        /* phys. address of the frame buffer */
        int             fb_alloced;     /* Flag, was the fb memory alloced? */
@@ -152,9 +156,10 @@ static void xilinx_fb_out_be32(struct xilinxfb_drvdata *drvdata, u32 offset,
 {
        if (drvdata->flags & PLB_ACCESS_FLAG)
                out_be32(drvdata->regs + (offset << 2), val);
+#ifdef CONFIG_PPC_DCR
        else
                dcr_write(drvdata->dcr_host, offset, val);
-
+#endif
 }
 
 static int
@@ -383,8 +388,11 @@ static int xilinxfb_release(struct device *dev)
        if (drvdata->flags & PLB_ACCESS_FLAG) {
                iounmap(drvdata->regs);
                release_mem_region(drvdata->regs_phys, 8);
-       } else
+       }
+#ifdef CONFIG_PPC_DCR
+       else
                dcr_unmap(drvdata->dcr_host, drvdata->dcr_len);
+#endif
 
        kfree(drvdata);
        dev_set_drvdata(dev, NULL);
@@ -404,7 +412,7 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
        u32 tft_access;
        struct xilinxfb_platform_data pdata;
        struct resource res;
-       int size, rc, start;
+       int size, rc;
        struct xilinxfb_drvdata *drvdata;
 
        /* Copy with the default pdata (not a ptr reference!) */
@@ -437,7 +445,10 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
                        dev_err(&op->dev, "invalid address\n");
                        goto err;
                }
-       } else {
+       }
+#ifdef CONFIG_PPC_DCR
+       else {
+               int start;
                res.start = 0;
                start = dcr_resource_start(op->dev.of_node, 0);
                drvdata->dcr_len = dcr_resource_len(op->dev.of_node, 0);
@@ -447,6 +458,7 @@ xilinxfb_of_probe(struct platform_device *op, const struct of_device_id *match)
                        goto err;
                }
        }
+#endif
 
        prop = of_get_property(op->dev.of_node, "phys-size", &size);
        if ((prop) && (size >= sizeof(u32)*2)) {
index 81e3d61..3dd4971 100644 (file)
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
-#include <linux/clk.h>
 #include <linux/bitops.h>
 #include <linux/io.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <mach/hardware.h>
 #include <plat/prcm.h>
 
@@ -61,8 +61,6 @@ struct omap_wdt_dev {
        void __iomem    *base;          /* physical */
        struct device   *dev;
        int             omap_wdt_users;
-       struct clk      *ick;
-       struct clk      *fck;
        struct resource *mem;
        struct miscdevice omap_wdt_miscdev;
 };
@@ -146,8 +144,7 @@ static int omap_wdt_open(struct inode *inode, struct file *file)
        if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users)))
                return -EBUSY;
 
-       clk_enable(wdev->ick);    /* Enable the interface clock */
-       clk_enable(wdev->fck);    /* Enable the functional clock */
+       pm_runtime_get_sync(wdev->dev);
 
        /* initialize prescaler */
        while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01)
@@ -177,8 +174,7 @@ static int omap_wdt_release(struct inode *inode, struct file *file)
 
        omap_wdt_disable(wdev);
 
-       clk_disable(wdev->ick);
-       clk_disable(wdev->fck);
+       pm_runtime_put_sync(wdev->dev);
 #else
        printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n");
 #endif
@@ -293,19 +289,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
 
        wdev->omap_wdt_users = 0;
        wdev->mem = mem;
-
-       wdev->ick = clk_get(&pdev->dev, "ick");
-       if (IS_ERR(wdev->ick)) {
-               ret = PTR_ERR(wdev->ick);
-               wdev->ick = NULL;
-               goto err_clk;
-       }
-       wdev->fck = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(wdev->fck)) {
-               ret = PTR_ERR(wdev->fck);
-               wdev->fck = NULL;
-               goto err_clk;
-       }
+       wdev->dev = &pdev->dev;
 
        wdev->base = ioremap(res->start, resource_size(res));
        if (!wdev->base) {
@@ -315,8 +299,8 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, wdev);
 
-       clk_enable(wdev->ick);
-       clk_enable(wdev->fck);
+       pm_runtime_enable(wdev->dev);
+       pm_runtime_get_sync(wdev->dev);
 
        omap_wdt_disable(wdev);
        omap_wdt_adjust_timeout(timer_margin);
@@ -334,11 +318,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev)
                __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF,
                timer_margin);
 
-       /* autogate OCP interface clock */
-       __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG);
-
-       clk_disable(wdev->ick);
-       clk_disable(wdev->fck);
+       pm_runtime_put_sync(wdev->dev);
 
        omap_wdt_dev = pdev;
 
@@ -350,12 +330,6 @@ err_misc:
 
 err_ioremap:
        wdev->base = NULL;
-
-err_clk:
-       if (wdev->ick)
-               clk_put(wdev->ick);
-       if (wdev->fck)
-               clk_put(wdev->fck);
        kfree(wdev);
 
 err_kzalloc:
@@ -387,8 +361,6 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev)
        release_mem_region(res->start, resource_size(res));
        platform_set_drvdata(pdev, NULL);
 
-       clk_put(wdev->ick);
-       clk_put(wdev->fck);
        iounmap(wdev->base);
 
        kfree(wdev);
index 5a03ba8..ba0cf0b 100644 (file)
@@ -55,6 +55,7 @@ static int output_records(int outfd);
 
 static int sort_records = 0;
 static int wide_records = 0;
+static int include_jump = 0;
 
 static int usage(void)
 {
@@ -63,6 +64,7 @@ static int usage(void)
        fprintf(stderr, "usage: ihex2fw [<options>] <src.HEX> <dst.fw>\n");
        fprintf(stderr, "       -w: wide records (16-bit length)\n");
        fprintf(stderr, "       -s: sort records by address\n");
+       fprintf(stderr, "       -j: include records for CS:IP/EIP address\n");
        return 1;
 }
 
@@ -73,7 +75,7 @@ int main(int argc, char **argv)
        uint8_t *data;
        int opt;
 
-       while ((opt = getopt(argc, argv, "ws")) != -1) {
+       while ((opt = getopt(argc, argv, "wsj")) != -1) {
                switch (opt) {
                case 'w':
                        wide_records = 1;
@@ -81,7 +83,9 @@ int main(int argc, char **argv)
                case 's':
                        sort_records = 1;
                        break;
-               default:
+               case 'j':
+                       include_jump = 1;
+                       break;
                        return usage();
                }
        }
@@ -128,6 +132,7 @@ static int process_ihex(uint8_t *data, ssize_t size)
 {
        struct ihex_binrec *record;
        uint32_t offset = 0;
+       uint32_t data32;
        uint8_t type, crc = 0, crcbyte = 0;
        int i, j;
        int line = 1;
@@ -223,8 +228,14 @@ next_record:
                        return -EINVAL;
                }
 
+               memcpy(&data32, &record->data[0], sizeof(data32));
+               data32 = htonl(data32);
+               memcpy(&record->data[0], &data32, sizeof(data32));
+
                /* These records contain the CS/IP or EIP where execution
-                * starts. Don't really know what to do with them. */
+                * starts. If requested output this as a record. */
+               if (include_jump)
+                       file_record(record);
                goto next_record;
 
        default:
index e6ec1d3..26956fc 100644 (file)
@@ -29,10 +29,7 @@ obj-$(CONFIG_EVENTFD)                += eventfd.o
 obj-$(CONFIG_AIO)               += aio.o
 obj-$(CONFIG_FILE_LOCKING)      += locks.o
 obj-$(CONFIG_COMPAT)           += compat.o compat_ioctl.o
-
-nfsd-$(CONFIG_NFSD)            := nfsctl.o
-obj-y                          += $(nfsd-y) $(nfsd-m)
-
+obj-$(CONFIG_NFSD_DEPRECATED)  += nfsctl.o
 obj-$(CONFIG_BINFMT_AOUT)      += binfmt_aout.o
 obj-$(CONFIG_BINFMT_EM86)      += binfmt_em86.o
 obj-$(CONFIG_BINFMT_MISC)      += binfmt_misc.o
index 722743b..15690bb 100644 (file)
@@ -438,7 +438,6 @@ no_more:
  */
 int afs_writepage(struct page *page, struct writeback_control *wbc)
 {
-       struct backing_dev_info *bdi = page->mapping->backing_dev_info;
        struct afs_writeback *wb;
        int ret;
 
@@ -455,8 +454,6 @@ int afs_writepage(struct page *page, struct writeback_control *wbc)
        }
 
        wbc->nr_to_write -= ret;
-       if (wbc->nonblocking && bdi_write_congested(bdi))
-               wbc->encountered_congestion = 1;
 
        _leave(" = 0");
        return 0;
@@ -469,7 +466,6 @@ static int afs_writepages_region(struct address_space *mapping,
                                 struct writeback_control *wbc,
                                 pgoff_t index, pgoff_t end, pgoff_t *_next)
 {
-       struct backing_dev_info *bdi = mapping->backing_dev_info;
        struct afs_writeback *wb;
        struct page *page;
        int ret, n;
@@ -529,11 +525,6 @@ static int afs_writepages_region(struct address_space *mapping,
 
                wbc->nr_to_write -= ret;
 
-               if (wbc->nonblocking && bdi_write_congested(bdi)) {
-                       wbc->encountered_congestion = 1;
-                       break;
-               }
-
                cond_resched();
        } while (index < end && wbc->nr_to_write > 0);
 
@@ -548,24 +539,16 @@ static int afs_writepages_region(struct address_space *mapping,
 int afs_writepages(struct address_space *mapping,
                   struct writeback_control *wbc)
 {
-       struct backing_dev_info *bdi = mapping->backing_dev_info;
        pgoff_t start, end, next;
        int ret;
 
        _enter("");
 
-       if (wbc->nonblocking && bdi_write_congested(bdi)) {
-               wbc->encountered_congestion = 1;
-               _leave(" = 0 [congest]");
-               return 0;
-       }
-
        if (wbc->range_cyclic) {
                start = mapping->writeback_index;
                end = -1;
                ret = afs_writepages_region(mapping, wbc, start, end, &next);
-               if (start > 0 && wbc->nr_to_write > 0 && ret == 0 &&
-                   !(wbc->nonblocking && wbc->encountered_congestion))
+               if (start > 0 && wbc->nr_to_write > 0 && ret == 0)
                        ret = afs_writepages_region(mapping, wbc, 0, start,
                                                    &next);
                mapping->writeback_index = next;
index d895d9f..5930e38 100644 (file)
@@ -1705,7 +1705,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page,
                 * and kswapd activity, but those code paths have their own
                 * higher-level throttling.
                 */
-               if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
+               if (wbc->sync_mode != WB_SYNC_NONE) {
                        lock_buffer(bh);
                } else if (!trylock_buffer(bh)) {
                        redirty_page_for_writepage(wbc, page);
index 51bcc5c..e9c874a 100644 (file)
@@ -591,7 +591,6 @@ static int ceph_writepages_start(struct address_space *mapping,
                                 struct writeback_control *wbc)
 {
        struct inode *inode = mapping->host;
-       struct backing_dev_info *bdi = mapping->backing_dev_info;
        struct ceph_inode_info *ci = ceph_inode(inode);
        struct ceph_fs_client *fsc;
        pgoff_t index, start, end;
@@ -633,13 +632,6 @@ static int ceph_writepages_start(struct address_space *mapping,
 
        pagevec_init(&pvec, 0);
 
-       /* ?? */
-       if (wbc->nonblocking && bdi_write_congested(bdi)) {
-               dout(" writepages congested\n");
-               wbc->encountered_congestion = 1;
-               goto out_final;
-       }
-
        /* where to start/end? */
        if (wbc->range_cyclic) {
                start = mapping->writeback_index; /* Start from prev offset */
@@ -885,7 +877,6 @@ out:
                rc = 0;  /* vfs expects us to return 0 */
        ceph_put_snap_context(snapc);
        dout("writepages done, rc = %d\n", rc);
-out_final:
        return rc;
 }
 
index 8c81e7b..45af003 100644 (file)
@@ -1303,7 +1303,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
 static int cifs_writepages(struct address_space *mapping,
                           struct writeback_control *wbc)
 {
-       struct backing_dev_info *bdi = mapping->backing_dev_info;
        unsigned int bytes_to_write;
        unsigned int bytes_written;
        struct cifs_sb_info *cifs_sb;
@@ -1326,15 +1325,6 @@ static int cifs_writepages(struct address_space *mapping,
        int scanned = 0;
        int xid, long_op;
 
-       /*
-        * BB: Is this meaningful for a non-block-device file system?
-        * If it is, we should test it again after we do I/O
-        */
-       if (wbc->nonblocking && bdi_write_congested(bdi)) {
-               wbc->encountered_congestion = 1;
-               return 0;
-       }
-
        cifs_sb = CIFS_SB(mapping->host->i_sb);
 
        /*
index 0644a15..f03abda 100644 (file)
@@ -1963,7 +1963,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 }
 #endif /* HAVE_SET_RESTORE_SIGMASK */
 
-#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
+#if (defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)) && !defined(CONFIG_NFSD_DEPRECATED)
 /* Stuff for NFS server syscalls... */
 struct compat_nfsctl_svc {
        u16                     svc32_port;
index 48d74c7..85882f6 100644 (file)
@@ -218,7 +218,7 @@ static struct page *dio_get_page(struct dio *dio)
  * filesystems can use it to hold additional state between get_block calls and
  * dio_complete.
  */
-static int dio_complete(struct dio *dio, loff_t offset, int ret, bool is_async)
+static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is_async)
 {
        ssize_t transferred = 0;
 
index 6d2b6f9..3aa75b8 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -54,6 +54,7 @@
 #include <linux/fsnotify.h>
 #include <linux/fs_struct.h>
 #include <linux/pipe_fs_i.h>
+#include <linux/oom.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -759,6 +760,10 @@ static int exec_mmap(struct mm_struct *mm)
        tsk->mm = mm;
        tsk->active_mm = mm;
        activate_mm(active_mm, mm);
+       if (old_mm && tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+               atomic_dec(&old_mm->oom_disable_count);
+               atomic_inc(&tsk->mm->oom_disable_count);
+       }
        task_unlock(tsk);
        arch_pick_mmap_layout(mm);
        if (old_mm) {
index f6af81a..aed881a 100644 (file)
@@ -586,7 +586,7 @@ static inline bool over_bground_thresh(void)
        global_dirty_limits(&background_thresh, &dirty_thresh);
 
        return (global_page_state(NR_FILE_DIRTY) +
-               global_page_state(NR_UNSTABLE_NFS) >= background_thresh);
+               global_page_state(NR_UNSTABLE_NFS) > background_thresh);
 }
 
 /*
@@ -724,6 +724,10 @@ static long wb_check_old_data_flush(struct bdi_writeback *wb)
                return 0;
 
        wb->last_old_flush = jiffies;
+       /*
+        * Add in the number of potentially dirty inodes, because each inode
+        * write can dirty pagecache in the underlying blockdev.
+        */
        nr_pages = global_page_state(NR_FILE_DIRTY) +
                        global_page_state(NR_UNSTABLE_NFS) +
                        get_nr_dirty_inodes();
@@ -793,7 +797,7 @@ int bdi_writeback_thread(void *data)
        struct backing_dev_info *bdi = wb->bdi;
        long pages_written;
 
-       current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+       current->flags |= PF_SWAPWRITE;
        set_freezable();
        wb->last_active = jiffies;
 
index cde755c..b986642 100644 (file)
@@ -809,11 +809,9 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
        int err;
        struct page *page = *pagep;
 
-       if (page && zeroing && count < PAGE_SIZE) {
-               void *mapaddr = kmap_atomic(page, KM_USER1);
-               memset(mapaddr, 0, PAGE_SIZE);
-               kunmap_atomic(mapaddr, KM_USER1);
-       }
+       if (page && zeroing && count < PAGE_SIZE)
+               clear_highpage(page);
+
        while (count) {
                if (cs->write && cs->pipebufs && page) {
                        return fuse_ref_page(cs, page, offset, count);
@@ -830,10 +828,10 @@ static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
                        }
                }
                if (page) {
-                       void *mapaddr = kmap_atomic(page, KM_USER1);
+                       void *mapaddr = kmap_atomic(page, KM_USER0);
                        void *buf = mapaddr + offset;
                        offset += fuse_copy_do(cs, &buf, &count);
-                       kunmap_atomic(mapaddr, KM_USER1);
+                       kunmap_atomic(mapaddr, KM_USER0);
                } else
                        offset += fuse_copy_do(cs, NULL, &count);
        }
index f3b071f..939739c 100644 (file)
@@ -55,7 +55,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb
                 * activity, but those code paths have their own higher-level
                 * throttling.
                 */
-               if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
+               if (wbc->sync_mode != WB_SYNC_NONE) {
                        lock_buffer(bh);
                } else if (!trylock_buffer(bh)) {
                        redirty_page_for_writepage(wbc, page);
index 8d02683..d51a983 100644 (file)
@@ -94,8 +94,7 @@ void *open_dir(char *path, int *err_out)
 
        dir = opendir(path);
        *err_out = errno;
-       if (dir == NULL)
-               return NULL;
+
        return dir;
 }
 
@@ -205,7 +204,7 @@ int set_attr(const char *file, struct hostfs_iattr *attrs, int fd)
        if (attrs->ia_valid & HOSTFS_ATTR_MODE) {
                if (fd >= 0) {
                        if (fchmod(fd, attrs->ia_mode) != 0)
-                               return (-errno);
+                               return -errno;
                } else if (chmod(file, attrs->ia_mode) != 0) {
                        return -errno;
                }
index 8d0607b..b14be3f 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/statfs.h>
 #include <linux/security.h>
 #include <linux/magic.h>
+#include <linux/migrate.h>
 
 #include <asm/uaccess.h>
 
@@ -574,6 +575,19 @@ static int hugetlbfs_set_page_dirty(struct page *page)
        return 0;
 }
 
+static int hugetlbfs_migrate_page(struct address_space *mapping,
+                               struct page *newpage, struct page *page)
+{
+       int rc;
+
+       rc = migrate_huge_page_move_mapping(mapping, newpage, page);
+       if (rc)
+               return rc;
+       migrate_page_copy(newpage, page);
+
+       return 0;
+}
+
 static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb);
@@ -660,6 +674,7 @@ static const struct address_space_operations hugetlbfs_aops = {
        .write_begin    = hugetlbfs_write_begin,
        .write_end      = hugetlbfs_write_end,
        .set_page_dirty = hugetlbfs_set_page_dirty,
+       .migratepage    = hugetlbfs_migrate_page,
 };
 
 
index a6d6068..ae2727a 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/mount.h>
 #include <linux/async.h>
 #include <linux/posix_acl.h>
+#include <linux/ima.h>
 
 /*
  * This is needed for the following functions:
index 64fd427..d5bb868 100644 (file)
@@ -42,6 +42,7 @@ struct nlm_wait {
 };
 
 static LIST_HEAD(nlm_blocked);
+static DEFINE_SPINLOCK(nlm_blocked_lock);
 
 /**
  * nlmclnt_init - Set up per-NFS mount point lockd data structures
@@ -97,7 +98,10 @@ struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *
                block->b_lock = fl;
                init_waitqueue_head(&block->b_wait);
                block->b_status = nlm_lck_blocked;
+
+               spin_lock(&nlm_blocked_lock);
                list_add(&block->b_list, &nlm_blocked);
+               spin_unlock(&nlm_blocked_lock);
        }
        return block;
 }
@@ -106,7 +110,9 @@ void nlmclnt_finish_block(struct nlm_wait *block)
 {
        if (block == NULL)
                return;
+       spin_lock(&nlm_blocked_lock);
        list_del(&block->b_list);
+       spin_unlock(&nlm_blocked_lock);
        kfree(block);
 }
 
@@ -154,6 +160,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
         * Look up blocked request based on arguments. 
         * Warning: must not use cookie to match it!
         */
+       spin_lock(&nlm_blocked_lock);
        list_for_each_entry(block, &nlm_blocked, b_list) {
                struct file_lock *fl_blocked = block->b_lock;
 
@@ -178,6 +185,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
                wake_up(&block->b_wait);
                res = nlm_granted;
        }
+       spin_unlock(&nlm_blocked_lock);
        return res;
 }
 
@@ -216,10 +224,6 @@ reclaimer(void *ptr)
        allow_signal(SIGKILL);
 
        down_write(&host->h_rwsem);
-
-       /* This one ensures that our parent doesn't terminate while the
-        * reclaim is in progress */
-       lock_kernel();
        lockd_up();     /* note: this cannot fail as lockd is already running */
 
        dprintk("lockd: reclaiming locks for host %s\n", host->h_name);
@@ -260,16 +264,17 @@ restart:
        dprintk("NLM: done reclaiming locks for host %s\n", host->h_name);
 
        /* Now, wake up all processes that sleep on a blocked lock */
+       spin_lock(&nlm_blocked_lock);
        list_for_each_entry(block, &nlm_blocked, b_list) {
                if (block->b_host == host) {
                        block->b_status = nlm_lck_denied_grace_period;
                        wake_up(&block->b_wait);
                }
        }
+       spin_unlock(&nlm_blocked_lock);
 
        /* Release host handle after use */
        nlm_release_host(host);
        lockd_down();
-       unlock_kernel();
        return 0;
 }
index 7932c39..47ea1e1 100644 (file)
@@ -166,7 +166,6 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
        /* Set up the argument struct */
        nlmclnt_setlockargs(call, fl);
 
-       lock_kernel();
        if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
                if (fl->fl_type != F_UNLCK) {
                        call->a_args.block = IS_SETLKW(cmd) ? 1 : 0;
@@ -177,10 +176,8 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
                status = nlmclnt_test(call, fl);
        else
                status = -EINVAL;
-
        fl->fl_ops->fl_release_private(fl);
        fl->fl_ops = NULL;
-       unlock_kernel();
 
        dprintk("lockd: clnt proc returns %d\n", status);
        return status;
@@ -226,9 +223,7 @@ void nlm_release_call(struct nlm_rqst *call)
 
 static void nlmclnt_rpc_release(void *data)
 {
-       lock_kernel();
        nlm_release_call(data);
-       unlock_kernel();
 }
 
 static int nlm_wait_on_grace(wait_queue_head_t *queue)
@@ -448,14 +443,18 @@ out:
 
 static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl)
 {
+       spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock);
        new->fl_u.nfs_fl.state = fl->fl_u.nfs_fl.state;
        new->fl_u.nfs_fl.owner = nlm_get_lockowner(fl->fl_u.nfs_fl.owner);
        list_add_tail(&new->fl_u.nfs_fl.list, &fl->fl_u.nfs_fl.owner->host->h_granted);
+       spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock);
 }
 
 static void nlmclnt_locks_release_private(struct file_lock *fl)
 {
+       spin_lock(&fl->fl_u.nfs_fl.owner->host->h_lock);
        list_del(&fl->fl_u.nfs_fl.list);
+       spin_unlock(&fl->fl_u.nfs_fl.owner->host->h_lock);
        nlm_put_lockowner(fl->fl_u.nfs_fl.owner);
 }
 
@@ -721,9 +720,7 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
 die:
        return;
  retry_rebind:
-       lock_kernel();
        nlm_rebind_host(req->a_host);
-       unlock_kernel();
  retry_unlock:
        rpc_restart_call(task);
 }
@@ -801,9 +798,7 @@ retry_cancel:
        /* Don't ever retry more than 3 times */
        if (req->a_retries++ >= NLMCLNT_MAX_RETRIES)
                goto die;
-       lock_kernel();
        nlm_rebind_host(req->a_host);
-       unlock_kernel();
        rpc_restart_call(task);
        rpc_delay(task, 30 * HZ);
 }
index bb464d1..25e21e4 100644 (file)
@@ -353,6 +353,7 @@ nlm_bind_host(struct nlm_host *host)
                        .to_retries     = 5U,
                };
                struct rpc_create_args args = {
+                       .net            = &init_net,
                        .protocol       = host->h_proto,
                        .address        = nlm_addr(host),
                        .addrsize       = host->h_addrlen,
index e301546..e0c9189 100644 (file)
@@ -69,6 +69,7 @@ static struct rpc_clnt *nsm_create(void)
                .sin_addr.s_addr        = htonl(INADDR_LOOPBACK),
        };
        struct rpc_create_args args = {
+               .net                    = &init_net,
                .protocol               = XPRT_TRANSPORT_UDP,
                .address                = (struct sockaddr *)&sin,
                .addrsize               = sizeof(sin),
index f1bacf1..b13aabc 100644 (file)
@@ -206,7 +206,7 @@ static int create_lockd_listener(struct svc_serv *serv, const char *name,
 
        xprt = svc_find_xprt(serv, name, family, 0);
        if (xprt == NULL)
-               return svc_create_xprt(serv, name, family, port,
+               return svc_create_xprt(serv, name, &init_net, family, port,
                                                SVC_SOCK_DEFAULTS);
        svc_xprt_put(xprt);
        return 0;
index 031c656..a336e83 100644 (file)
@@ -230,9 +230,7 @@ static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
 
 static void nlm4svc_callback_release(void *data)
 {
-       lock_kernel();
        nlm_release_call(data);
-       unlock_kernel();
 }
 
 static const struct rpc_call_ops nlm4svc_callback_ops = {
index 84055d3..6f1ef00 100644 (file)
@@ -52,12 +52,13 @@ static const struct rpc_call_ops nlmsvc_grant_ops;
  * The list of blocked locks to retry
  */
 static LIST_HEAD(nlm_blocked);
+static DEFINE_SPINLOCK(nlm_blocked_lock);
 
 /*
  * Insert a blocked lock into the global list
  */
 static void
-nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
+nlmsvc_insert_block_locked(struct nlm_block *block, unsigned long when)
 {
        struct nlm_block *b;
        struct list_head *pos;
@@ -87,6 +88,13 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
        block->b_when = when;
 }
 
+static void nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
+{
+       spin_lock(&nlm_blocked_lock);
+       nlmsvc_insert_block_locked(block, when);
+       spin_unlock(&nlm_blocked_lock);
+}
+
 /*
  * Remove a block from the global list
  */
@@ -94,7 +102,9 @@ static inline void
 nlmsvc_remove_block(struct nlm_block *block)
 {
        if (!list_empty(&block->b_list)) {
+               spin_lock(&nlm_blocked_lock);
                list_del_init(&block->b_list);
+               spin_unlock(&nlm_blocked_lock);
                nlmsvc_release_block(block);
        }
 }
@@ -651,7 +661,7 @@ static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf,
        struct nlm_block *block;
        int rc = -ENOENT;
 
-       lock_kernel();
+       spin_lock(&nlm_blocked_lock);
        list_for_each_entry(block, &nlm_blocked, b_list) {
                if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) {
                        dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n",
@@ -665,13 +675,13 @@ static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf,
                        } else if (result == 0)
                                block->b_granted = 1;
 
-                       nlmsvc_insert_block(block, 0);
+                       nlmsvc_insert_block_locked(block, 0);
                        svc_wake_up(block->b_daemon);
                        rc = 0;
                        break;
                }
        }
-       unlock_kernel();
+       spin_unlock(&nlm_blocked_lock);
        if (rc == -ENOENT)
                printk(KERN_WARNING "lockd: grant for unknown block\n");
        return rc;
@@ -803,7 +813,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
 
        dprintk("lockd: GRANT_MSG RPC callback\n");
 
-       lock_kernel();
+       spin_lock(&nlm_blocked_lock);
        /* if the block is not on a list at this point then it has
         * been invalidated. Don't try to requeue it.
         *
@@ -825,19 +835,20 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data)
                /* Call was successful, now wait for client callback */
                timeout = 60 * HZ;
        }
-       nlmsvc_insert_block(block, timeout);
+       nlmsvc_insert_block_locked(block, timeout);
        svc_wake_up(block->b_daemon);
 out:
-       unlock_kernel();
+       spin_unlock(&nlm_blocked_lock);
 }
 
+/*
+ * FIXME: nlmsvc_release_block() grabs a mutex.  This is not allowed for an
+ * .rpc_release rpc_call_op
+ */
 static void nlmsvc_grant_release(void *data)
 {
        struct nlm_rqst         *call = data;
-
-       lock_kernel();
        nlmsvc_release_block(call->a_block);
-       unlock_kernel();
 }
 
 static const struct rpc_call_ops nlmsvc_grant_ops = {
index 0f2ab74..c3069f3 100644 (file)
@@ -260,9 +260,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
 
 static void nlmsvc_callback_release(void *data)
 {
-       lock_kernel();
        nlm_release_call(data);
-       unlock_kernel();
 }
 
 static const struct rpc_call_ops nlmsvc_callback_ops = {
index 8b2b6ad..4de3a26 100644 (file)
@@ -2109,7 +2109,7 @@ EXPORT_SYMBOL_GPL(vfs_cancel_lock);
 #include <linux/seq_file.h>
 
 static void lock_get_status(struct seq_file *f, struct file_lock *fl,
-                                                       int id, char *pfx)
+                           loff_t id, char *pfx)
 {
        struct inode *inode = NULL;
        unsigned int fl_pid;
@@ -2122,7 +2122,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
        if (fl->fl_file != NULL)
                inode = fl->fl_file->f_path.dentry->d_inode;
 
-       seq_printf(f, "%d:%s ", id, pfx);
+       seq_printf(f, "%lld:%s ", id, pfx);
        if (IS_POSIX(fl)) {
                seq_printf(f, "%6s %s ",
                             (fl->fl_flags & FL_ACCESS) ? "ACCESS" : "POSIX ",
@@ -2185,24 +2185,27 @@ static int locks_show(struct seq_file *f, void *v)
 
        fl = list_entry(v, struct file_lock, fl_link);
 
-       lock_get_status(f, fl, (long)f->private, "");
+       lock_get_status(f, fl, *((loff_t *)f->private), "");
 
        list_for_each_entry(bfl, &fl->fl_block, fl_block)
-               lock_get_status(f, bfl, (long)f->private, " ->");
+               lock_get_status(f, bfl, *((loff_t *)f->private), " ->");
 
-       f->private++;
        return 0;
 }
 
 static void *locks_start(struct seq_file *f, loff_t *pos)
 {
+       loff_t *p = f->private;
+
        lock_flocks();
-       f->private = (void *)1;
+       *p = (*pos + 1);
        return seq_list_start(&file_lock_list, *pos);
 }
 
 static void *locks_next(struct seq_file *f, void *v, loff_t *pos)
 {
+       loff_t *p = f->private;
+       ++*p;
        return seq_list_next(v, &file_lock_list, pos);
 }
 
@@ -2220,14 +2223,14 @@ static const struct seq_operations locks_seq_operations = {
 
 static int locks_open(struct inode *inode, struct file *filp)
 {
-       return seq_open(filp, &locks_seq_operations);
+       return seq_open_private(filp, &locks_seq_operations, sizeof(loff_t));
 }
 
 static const struct file_operations proc_locks_operations = {
        .open           = locks_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
-       .release        = seq_release,
+       .release        = seq_release_private,
 };
 
 static int __init proc_locks_init(void)
index b950415..fd66765 100644 (file)
@@ -77,13 +77,17 @@ config NFS_V4
 
 config NFS_V4_1
        bool "NFS client support for NFSv4.1 (EXPERIMENTAL)"
-       depends on NFS_V4 && EXPERIMENTAL
+       depends on NFS_FS && NFS_V4 && EXPERIMENTAL
+       select PNFS_FILE_LAYOUT
        help
          This option enables support for minor version 1 of the NFSv4 protocol
-         (draft-ietf-nfsv4-minorversion1) in the kernel's NFS client.
+         (RFC 5661) in the kernel's NFS client.
 
          If unsure, say N.
 
+config PNFS_FILE_LAYOUT
+       tristate
+
 config ROOT_NFS
        bool "Root file system on NFS"
        depends on NFS_FS=y && IP_PNP
@@ -118,3 +122,14 @@ config NFS_USE_KERNEL_DNS
        select DNS_RESOLVER
        select KEYS
        default y
+
+config NFS_USE_NEW_IDMAPPER
+       bool "Use the new idmapper upcall routine"
+       depends on NFS_V4 && KEYS
+       help
+         Say Y here if you want NFS to use the new idmapper upcall functions.
+         You will need /sbin/request-key (usually provided by the keyutils
+         package).  For details, read
+         <file:Documentation/filesystems/nfs/idmapper.txt>.
+
+         If you are unsure, say N.
index da7fda6..4776ff9 100644 (file)
@@ -15,5 +15,9 @@ nfs-$(CONFIG_NFS_V4)  += nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o \
                           delegation.o idmap.o \
                           callback.o callback_xdr.o callback_proc.o \
                           nfs4namespace.o
+nfs-$(CONFIG_NFS_V4_1) += pnfs.o
 nfs-$(CONFIG_SYSCTL) += sysctl.o
 nfs-$(CONFIG_NFS_FSCACHE) += fscache.o fscache-index.o
+
+obj-$(CONFIG_PNFS_FILE_LAYOUT) += nfs_layout_nfsv41_files.o
+nfs_layout_nfsv41_files-y := nfs4filelayout.o nfs4filelayoutdev.o
index e17b49e..aeec017 100644 (file)
@@ -109,7 +109,7 @@ nfs4_callback_up(struct svc_serv *serv)
 {
        int ret;
 
-       ret = svc_create_xprt(serv, "tcp", PF_INET,
+       ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET,
                                nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
        if (ret <= 0)
                goto out_err;
@@ -117,7 +117,7 @@ nfs4_callback_up(struct svc_serv *serv)
        dprintk("NFS: Callback listener port = %u (af %u)\n",
                        nfs_callback_tcpport, PF_INET);
 
-       ret = svc_create_xprt(serv, "tcp", PF_INET6,
+       ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6,
                                nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS);
        if (ret > 0) {
                nfs_callback_tcpport6 = ret;
index 930d10f..2950fca 100644 (file)
@@ -118,11 +118,11 @@ int nfs41_validate_delegation_stateid(struct nfs_delegation *delegation, const n
        if (delegation == NULL)
                return 0;
 
-       /* seqid is 4-bytes long */
-       if (((u32 *) &stateid->data)[0] != 0)
+       if (stateid->stateid.seqid != 0)
                return 0;
-       if (memcmp(&delegation->stateid.data[4], &stateid->data[4],
-                  sizeof(stateid->data)-4))
+       if (memcmp(&delegation->stateid.stateid.other,
+                  &stateid->stateid.other,
+                  NFS4_STATEID_OTHER_SIZE))
                return 0;
 
        return 1;
index e734072..0870d0d 100644 (file)
@@ -48,6 +48,7 @@
 #include "iostat.h"
 #include "internal.h"
 #include "fscache.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_CLIENT
 
@@ -155,7 +156,9 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
        cred = rpc_lookup_machine_cred();
        if (!IS_ERR(cred))
                clp->cl_machine_cred = cred;
-
+#if defined(CONFIG_NFS_V4_1)
+       INIT_LIST_HEAD(&clp->cl_layouts);
+#endif
        nfs_fscache_get_client_cookie(clp);
 
        return clp;
@@ -252,6 +255,7 @@ void nfs_put_client(struct nfs_client *clp)
                nfs_free_client(clp);
        }
 }
+EXPORT_SYMBOL_GPL(nfs_put_client);
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 /*
@@ -601,6 +605,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
 {
        struct rpc_clnt         *clnt = NULL;
        struct rpc_create_args args = {
+               .net            = &init_net,
                .protocol       = clp->cl_proto,
                .address        = (struct sockaddr *)&clp->cl_addr,
                .addrsize       = clp->cl_addrlen,
@@ -635,7 +640,8 @@ static int nfs_create_rpc_client(struct nfs_client *clp,
  */
 static void nfs_destroy_server(struct nfs_server *server)
 {
-       if (!(server->flags & NFS_MOUNT_NONLM))
+       if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) ||
+                       !(server->flags & NFS_MOUNT_LOCAL_FCNTL))
                nlmclnt_done(server->nlm_host);
 }
 
@@ -657,7 +663,8 @@ static int nfs_start_lockd(struct nfs_server *server)
 
        if (nlm_init.nfs_version > 3)
                return 0;
-       if (server->flags & NFS_MOUNT_NONLM)
+       if ((server->flags & NFS_MOUNT_LOCAL_FLOCK) &&
+                       (server->flags & NFS_MOUNT_LOCAL_FCNTL))
                return 0;
 
        switch (clp->cl_proto) {
@@ -898,11 +905,13 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
        if (server->wsize > NFS_MAX_FILE_IO_SIZE)
                server->wsize = NFS_MAX_FILE_IO_SIZE;
        server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+       set_pnfs_layoutdriver(server, fsinfo->layouttype);
+
        server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
 
        server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
-       if (server->dtsize > PAGE_CACHE_SIZE)
-               server->dtsize = PAGE_CACHE_SIZE;
+       if (server->dtsize > PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES)
+               server->dtsize = PAGE_CACHE_SIZE * NFS_MAX_READDIR_PAGES;
        if (server->dtsize > server->rsize)
                server->dtsize = server->rsize;
 
@@ -913,6 +922,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
 
        server->maxfilesize = fsinfo->maxfilesize;
 
+       server->time_delta = fsinfo->time_delta;
+
        /* We're airborne Set socket buffersize */
        rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
 }
@@ -935,6 +946,7 @@ static int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, str
        }
 
        fsinfo.fattr = fattr;
+       fsinfo.layouttype = 0;
        error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
        if (error < 0)
                goto out_error;
@@ -1017,6 +1029,7 @@ void nfs_free_server(struct nfs_server *server)
 {
        dprintk("--> nfs_free_server()\n");
 
+       unset_pnfs_layoutdriver(server);
        spin_lock(&nfs_client_lock);
        list_del(&server->client_link);
        list_del(&server->master_link);
@@ -1356,8 +1369,9 @@ static int nfs4_init_server(struct nfs_server *server,
 
        /* Initialise the client representation from the mount data */
        server->flags = data->flags;
-       server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|
-               NFS_CAP_POSIX_LOCK;
+       server->caps |= NFS_CAP_ATOMIC_OPEN|NFS_CAP_CHANGE_ATTR|NFS_CAP_POSIX_LOCK;
+       if (!(data->flags & NFS_MOUNT_NORDIRPLUS))
+                       server->caps |= NFS_CAP_READDIRPLUS;
        server->options = data->options;
 
        /* Get a client record */
index 0fac7fe..07ac384 100644 (file)
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
-#include "nfs4_fs.h"
 #include "delegation.h"
 #include "iostat.h"
 #include "internal.h"
+#include "fscache.h"
 
 /* #define NFS_DEBUG_VERBOSE 1 */
 
@@ -55,6 +56,7 @@ static int nfs_rename(struct inode *, struct dentry *,
                      struct inode *, struct dentry *);
 static int nfs_fsync_dir(struct file *, int);
 static loff_t nfs_llseek_dir(struct file *, loff_t, int);
+static int nfs_readdir_clear_array(struct page*, gfp_t);
 
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
@@ -80,6 +82,10 @@ const struct inode_operations nfs_dir_inode_operations = {
        .setattr        = nfs_setattr,
 };
 
+const struct address_space_operations nfs_dir_addr_space_ops = {
+       .releasepage = nfs_readdir_clear_array,
+};
+
 #ifdef CONFIG_NFS_V3
 const struct inode_operations nfs3_dir_inode_operations = {
        .create         = nfs_create,
@@ -104,8 +110,9 @@ const struct inode_operations nfs3_dir_inode_operations = {
 #ifdef CONFIG_NFS_V4
 
 static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd);
 const struct inode_operations nfs4_dir_inode_operations = {
-       .create         = nfs_create,
+       .create         = nfs_open_create,
        .lookup         = nfs_atomic_lookup,
        .link           = nfs_link,
        .unlink         = nfs_unlink,
@@ -150,51 +157,197 @@ nfs_opendir(struct inode *inode, struct file *filp)
        return res;
 }
 
-typedef __be32 * (*decode_dirent_t)(__be32 *, struct nfs_entry *, int);
+struct nfs_cache_array_entry {
+       u64 cookie;
+       u64 ino;
+       struct qstr string;
+};
+
+struct nfs_cache_array {
+       unsigned int size;
+       int eof_index;
+       u64 last_cookie;
+       struct nfs_cache_array_entry array[0];
+};
+
+#define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry))
+
+typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 typedef struct {
        struct file     *file;
        struct page     *page;
        unsigned long   page_index;
-       __be32          *ptr;
        u64             *dir_cookie;
        loff_t          current_index;
-       struct nfs_entry *entry;
        decode_dirent_t decode;
-       int             plus;
+
        unsigned long   timestamp;
        unsigned long   gencount;
-       int             timestamp_valid;
+       unsigned int    cache_entry_index;
+       unsigned int    plus:1;
+       unsigned int    eof:1;
 } nfs_readdir_descriptor_t;
 
-/* Now we cache directories properly, by stuffing the dirent
- * data directly in the page cache.
- *
- * Inode invalidation due to refresh etc. takes care of
- * _everything_, no sloppy entry flushing logic, no extraneous
- * copying, network direct to page cache, the way it was meant
- * to be.
- *
- * NOTE: Dirent information verification is done always by the
- *      page-in of the RPC reply, nowhere else, this simplies
- *      things substantially.
+/*
+ * The caller is responsible for calling nfs_readdir_release_array(page)
  */
 static
-int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
+{
+       if (page == NULL)
+               return ERR_PTR(-EIO);
+       return (struct nfs_cache_array *)kmap(page);
+}
+
+static
+void nfs_readdir_release_array(struct page *page)
+{
+       kunmap(page);
+}
+
+/*
+ * we are freeing strings created by nfs_add_to_readdir_array()
+ */
+static
+int nfs_readdir_clear_array(struct page *page, gfp_t mask)
+{
+       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       int i;
+       for (i = 0; i < array->size; i++)
+               kfree(array->array[i].string.name);
+       nfs_readdir_release_array(page);
+       return 0;
+}
+
+/*
+ * the caller is responsible for freeing qstr.name
+ * when called by nfs_readdir_add_to_array, the strings will be freed in
+ * nfs_clear_readdir_array()
+ */
+static
+int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len)
+{
+       string->len = len;
+       string->name = kmemdup(name, len, GFP_KERNEL);
+       if (string->name == NULL)
+               return -ENOMEM;
+       string->hash = full_name_hash(name, len);
+       return 0;
+}
+
+static
+int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
+{
+       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       struct nfs_cache_array_entry *cache_entry;
+       int ret;
+
+       if (IS_ERR(array))
+               return PTR_ERR(array);
+       ret = -EIO;
+       if (array->size >= MAX_READDIR_ARRAY)
+               goto out;
+
+       cache_entry = &array->array[array->size];
+       cache_entry->cookie = entry->prev_cookie;
+       cache_entry->ino = entry->ino;
+       ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
+       if (ret)
+               goto out;
+       array->last_cookie = entry->cookie;
+       if (entry->eof == 1)
+               array->eof_index = array->size;
+       array->size++;
+out:
+       nfs_readdir_release_array(page);
+       return ret;
+}
+
+static
+int nfs_readdir_search_for_pos(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
+{
+       loff_t diff = desc->file->f_pos - desc->current_index;
+       unsigned int index;
+
+       if (diff < 0)
+               goto out_eof;
+       if (diff >= array->size) {
+               if (array->eof_index > 0)
+                       goto out_eof;
+               desc->current_index += array->size;
+               return -EAGAIN;
+       }
+
+       index = (unsigned int)diff;
+       *desc->dir_cookie = array->array[index].cookie;
+       desc->cache_entry_index = index;
+       if (index == array->eof_index)
+               desc->eof = 1;
+       return 0;
+out_eof:
+       desc->eof = 1;
+       return -EBADCOOKIE;
+}
+
+static
+int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, nfs_readdir_descriptor_t *desc)
+{
+       int i;
+       int status = -EAGAIN;
+
+       for (i = 0; i < array->size; i++) {
+               if (i == array->eof_index) {
+                       desc->eof = 1;
+                       status = -EBADCOOKIE;
+               }
+               if (array->array[i].cookie == *desc->dir_cookie) {
+                       desc->cache_entry_index = i;
+                       status = 0;
+                       break;
+               }
+       }
+
+       return status;
+}
+
+static
+int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
+{
+       struct nfs_cache_array *array;
+       int status = -EBADCOOKIE;
+
+       if (desc->dir_cookie == NULL)
+               goto out;
+
+       array = nfs_readdir_get_array(desc->page);
+       if (IS_ERR(array)) {
+               status = PTR_ERR(array);
+               goto out;
+       }
+
+       if (*desc->dir_cookie == 0)
+               status = nfs_readdir_search_for_pos(array, desc);
+       else
+               status = nfs_readdir_search_for_cookie(array, desc);
+
+       nfs_readdir_release_array(desc->page);
+out:
+       return status;
+}
+
+/* Fill a page with xdr information before transferring to the cache page */
+static
+int nfs_readdir_xdr_filler(struct page **pages, nfs_readdir_descriptor_t *desc,
+                       struct nfs_entry *entry, struct file *file, struct inode *inode)
 {
-       struct file     *file = desc->file;
-       struct inode    *inode = file->f_path.dentry->d_inode;
        struct rpc_cred *cred = nfs_file_cred(file);
        unsigned long   timestamp, gencount;
        int             error;
 
-       dfprintk(DIRCACHE, "NFS: %s: reading cookie %Lu into page %lu\n",
-                       __func__, (long long)desc->entry->cookie,
-                       page->index);
-
  again:
        timestamp = jiffies;
        gencount = nfs_inc_attr_generation_counter();
-       error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, desc->entry->cookie, page,
+       error = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred, entry->cookie, pages,
                                          NFS_SERVER(inode)->dtsize, desc->plus);
        if (error < 0) {
                /* We requested READDIRPLUS, but the server doesn't grok it */
@@ -208,190 +361,292 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
        }
        desc->timestamp = timestamp;
        desc->gencount = gencount;
-       desc->timestamp_valid = 1;
-       SetPageUptodate(page);
-       /* Ensure consistent page alignment of the data.
-        * Note: assumes we have exclusive access to this mapping either
-        *       through inode->i_mutex or some other mechanism.
-        */
-       if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
-               /* Should never happen */
-               nfs_zap_mapping(inode, inode->i_mapping);
-       }
-       unlock_page(page);
-       return 0;
- error:
-       unlock_page(page);
-       return -EIO;
+error:
+       return error;
 }
 
-static inline
-int dir_decode(nfs_readdir_descriptor_t *desc)
+/* Fill in an entry based on the xdr code stored in desc->page */
+static
+int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct xdr_stream *stream)
 {
-       __be32  *p = desc->ptr;
-       p = desc->decode(p, desc->entry, desc->plus);
+       __be32 *p = desc->decode(stream, entry, NFS_SERVER(desc->file->f_path.dentry->d_inode), desc->plus);
        if (IS_ERR(p))
                return PTR_ERR(p);
-       desc->ptr = p;
-       if (desc->timestamp_valid) {
-               desc->entry->fattr->time_start = desc->timestamp;
-               desc->entry->fattr->gencount = desc->gencount;
-       } else
-               desc->entry->fattr->valid &= ~NFS_ATTR_FATTR;
+
+       entry->fattr->time_start = desc->timestamp;
+       entry->fattr->gencount = desc->gencount;
        return 0;
 }
 
-static inline
-void dir_page_release(nfs_readdir_descriptor_t *desc)
+static
+int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
 {
-       kunmap(desc->page);
-       page_cache_release(desc->page);
-       desc->page = NULL;
-       desc->ptr = NULL;
+       struct nfs_inode *node;
+       if (dentry->d_inode == NULL)
+               goto different;
+       node = NFS_I(dentry->d_inode);
+       if (node->fh.size != entry->fh->size)
+               goto different;
+       if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0)
+               goto different;
+       return 1;
+different:
+       return 0;
 }
 
-/*
- * Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the next entry with cookie '*desc->dir_cookie'.
- *
- * If the end of the buffer has been reached, return -EAGAIN, if not,
- * return the offset within the buffer of the next entry to be
- * read.
- */
-static inline
-int find_dirent(nfs_readdir_descriptor_t *desc)
+static
+void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry)
 {
-       struct nfs_entry *entry = desc->entry;
-       int             loop_count = 0,
-                       status;
+       struct qstr filename = {
+               .len = entry->len,
+               .name = entry->name,
+       };
+       struct dentry *dentry;
+       struct dentry *alias;
+       struct inode *dir = parent->d_inode;
+       struct inode *inode;
 
-       while((status = dir_decode(desc)) == 0) {
-               dfprintk(DIRCACHE, "NFS: %s: examining cookie %Lu\n",
-                               __func__, (unsigned long long)entry->cookie);
-               if (entry->prev_cookie == *desc->dir_cookie)
-                       break;
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
+       if (filename.name[0] == '.') {
+               if (filename.len == 1)
+                       return;
+               if (filename.len == 2 && filename.name[1] == '.')
+                       return;
+       }
+       filename.hash = full_name_hash(filename.name, filename.len);
+
+       dentry = d_lookup(parent, &filename);
+       if (dentry != NULL) {
+               if (nfs_same_file(dentry, entry)) {
+                       nfs_refresh_inode(dentry->d_inode, entry->fattr);
+                       goto out;
+               } else {
+                       d_drop(dentry);
+                       dput(dentry);
                }
        }
-       return status;
+
+       dentry = d_alloc(parent, &filename);
+       if (dentry == NULL)
+               return;
+
+       dentry->d_op = NFS_PROTO(dir)->dentry_ops;
+       inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
+       if (IS_ERR(inode))
+               goto out;
+
+       alias = d_materialise_unique(dentry, inode);
+       if (IS_ERR(alias))
+               goto out;
+       else if (alias) {
+               nfs_set_verifier(alias, nfs_save_change_attribute(dir));
+               dput(alias);
+       } else
+               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+
+out:
+       dput(dentry);
+}
+
+/* Perform conversion from xdr to cache array */
+static
+void nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry,
+                               void *xdr_page, struct page *page, unsigned int buflen)
+{
+       struct xdr_stream stream;
+       struct xdr_buf buf;
+       __be32 *ptr = xdr_page;
+       int status;
+       struct nfs_cache_array *array;
+
+       buf.head->iov_base = xdr_page;
+       buf.head->iov_len = buflen;
+       buf.tail->iov_len = 0;
+       buf.page_base = 0;
+       buf.page_len = 0;
+       buf.buflen = buf.head->iov_len;
+       buf.len = buf.head->iov_len;
+
+       xdr_init_decode(&stream, &buf, ptr);
+
+
+       do {
+               status = xdr_decode(desc, entry, &stream);
+               if (status != 0)
+                       break;
+
+               if (nfs_readdir_add_to_array(entry, page) == -1)
+                       break;
+               if (desc->plus == 1)
+                       nfs_prime_dcache(desc->file->f_path.dentry, entry);
+       } while (!entry->eof);
+
+       if (status == -EBADCOOKIE && entry->eof) {
+               array = nfs_readdir_get_array(page);
+               array->eof_index = array->size - 1;
+               status = 0;
+               nfs_readdir_release_array(page);
+       }
+}
+
+static
+void nfs_readdir_free_pagearray(struct page **pages, unsigned int npages)
+{
+       unsigned int i;
+       for (i = 0; i < npages; i++)
+               put_page(pages[i]);
+}
+
+static
+void nfs_readdir_free_large_page(void *ptr, struct page **pages,
+               unsigned int npages)
+{
+       vm_unmap_ram(ptr, npages);
+       nfs_readdir_free_pagearray(pages, npages);
 }
 
 /*
- * Given a pointer to a buffer that has already been filled by a call
- * to readdir, find the entry at offset 'desc->file->f_pos'.
- *
- * If the end of the buffer has been reached, return -EAGAIN, if not,
- * return the offset within the buffer of the next entry to be
- * read.
+ * nfs_readdir_large_page will allocate pages that must be freed with a call
+ * to nfs_readdir_free_large_page
  */
-static inline
-int find_dirent_index(nfs_readdir_descriptor_t *desc)
+static
+void *nfs_readdir_large_page(struct page **pages, unsigned int npages)
 {
-       struct nfs_entry *entry = desc->entry;
-       int             loop_count = 0,
-                       status;
+       void *ptr;
+       unsigned int i;
+
+       for (i = 0; i < npages; i++) {
+               struct page *page = alloc_page(GFP_KERNEL);
+               if (page == NULL)
+                       goto out_freepages;
+               pages[i] = page;
+       }
 
-       for(;;) {
-               status = dir_decode(desc);
-               if (status)
-                       break;
+       ptr = vm_map_ram(pages, npages, 0, PAGE_KERNEL);
+       if (!IS_ERR_OR_NULL(ptr))
+               return ptr;
+out_freepages:
+       nfs_readdir_free_pagearray(pages, i);
+       return NULL;
+}
+
+static
+int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode)
+{
+       struct page *pages[NFS_MAX_READDIR_PAGES];
+       void *pages_ptr = NULL;
+       struct nfs_entry entry;
+       struct file     *file = desc->file;
+       struct nfs_cache_array *array;
+       int status = 0;
+       unsigned int array_size = ARRAY_SIZE(pages);
+
+       entry.prev_cookie = 0;
+       entry.cookie = *desc->dir_cookie;
+       entry.eof = 0;
+       entry.fh = nfs_alloc_fhandle();
+       entry.fattr = nfs_alloc_fattr();
+       if (entry.fh == NULL || entry.fattr == NULL)
+               goto out;
 
-               dfprintk(DIRCACHE, "NFS: found cookie %Lu at index %Ld\n",
-                               (unsigned long long)entry->cookie, desc->current_index);
+       array = nfs_readdir_get_array(page);
+       memset(array, 0, sizeof(struct nfs_cache_array));
+       array->eof_index = -1;
 
-               if (desc->file->f_pos == desc->current_index) {
-                       *desc->dir_cookie = entry->cookie;
+       pages_ptr = nfs_readdir_large_page(pages, array_size);
+       if (!pages_ptr)
+               goto out_release_array;
+       do {
+               status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode);
+
+               if (status < 0)
                        break;
-               }
-               desc->current_index++;
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
-               }
-       }
+               nfs_readdir_page_filler(desc, &entry, pages_ptr, page, array_size * PAGE_SIZE);
+       } while (array->eof_index < 0 && array->size < MAX_READDIR_ARRAY);
+
+       nfs_readdir_free_large_page(pages_ptr, pages, array_size);
+out_release_array:
+       nfs_readdir_release_array(page);
+out:
+       nfs_free_fattr(entry.fattr);
+       nfs_free_fhandle(entry.fh);
        return status;
 }
 
 /*
- * Find the given page, and call find_dirent() or find_dirent_index in
- * order to try to return the next entry.
+ * Now we cache directories properly, by converting xdr information
+ * to an array that can be used for lookups later.  This results in
+ * fewer cache pages, since we can store more information on each page.
+ * We only need to convert from xdr once so future lookups are much simpler
  */
-static inline
-int find_dirent_page(nfs_readdir_descriptor_t *desc)
+static
+int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 {
        struct inode    *inode = desc->file->f_path.dentry->d_inode;
-       struct page     *page;
-       int             status;
 
-       dfprintk(DIRCACHE, "NFS: %s: searching page %ld for target %Lu\n",
-                       __func__, desc->page_index,
-                       (long long) *desc->dir_cookie);
+       if (nfs_readdir_xdr_to_array(desc, page, inode) < 0)
+               goto error;
+       SetPageUptodate(page);
 
-       /* If we find the page in the page_cache, we cannot be sure
-        * how fresh the data is, so we will ignore readdir_plus attributes.
-        */
-       desc->timestamp_valid = 0;
-       page = read_cache_page(inode->i_mapping, desc->page_index,
-                              (filler_t *)nfs_readdir_filler, desc);
-       if (IS_ERR(page)) {
-               status = PTR_ERR(page);
-               goto out;
+       if (invalidate_inode_pages2_range(inode->i_mapping, page->index + 1, -1) < 0) {
+               /* Should never happen */
+               nfs_zap_mapping(inode, inode->i_mapping);
        }
+       unlock_page(page);
+       return 0;
+ error:
+       unlock_page(page);
+       return -EIO;
+}
 
-       /* NOTE: Someone else may have changed the READDIRPLUS flag */
-       desc->page = page;
-       desc->ptr = kmap(page);         /* matching kunmap in nfs_do_filldir */
-       if (*desc->dir_cookie != 0)
-               status = find_dirent(desc);
-       else
-               status = find_dirent_index(desc);
-       if (status < 0)
-               dir_page_release(desc);
- out:
-       dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status);
-       return status;
+static
+void cache_page_release(nfs_readdir_descriptor_t *desc)
+{
+       page_cache_release(desc->page);
+       desc->page = NULL;
+}
+
+static
+struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
+{
+       struct page *page;
+       page = read_cache_page(desc->file->f_path.dentry->d_inode->i_mapping,
+                       desc->page_index, (filler_t *)nfs_readdir_filler, desc);
+       if (IS_ERR(page))
+               desc->eof = 1;
+       return page;
 }
 
 /*
- * Recurse through the page cache pages, and return a
- * filled nfs_entry structure of the next directory entry if possible.
- *
- * The target for the search is '*desc->dir_cookie' if non-0,
- * 'desc->file->f_pos' otherwise
+ * Returns 0 if desc->dir_cookie was found on page desc->page_index
  */
+static
+int find_cache_page(nfs_readdir_descriptor_t *desc)
+{
+       int res;
+
+       desc->page = get_cache_page(desc);
+       if (IS_ERR(desc->page))
+               return PTR_ERR(desc->page);
+
+       res = nfs_readdir_search_array(desc);
+       if (res == 0)
+               return 0;
+       cache_page_release(desc);
+       return res;
+}
+
+/* Search for desc->dir_cookie from the beginning of the page cache */
 static inline
 int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
-       int             loop_count = 0;
-       int             res;
-
-       /* Always search-by-index from the beginning of the cache */
-       if (*desc->dir_cookie == 0) {
-               dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for offset %Ld\n",
-                               (long long)desc->file->f_pos);
-               desc->page_index = 0;
-               desc->entry->cookie = desc->entry->prev_cookie = 0;
-               desc->entry->eof = 0;
-               desc->current_index = 0;
-       } else
-               dfprintk(DIRCACHE, "NFS: readdir_search_pagecache() searching for cookie %Lu\n",
-                               (unsigned long long)*desc->dir_cookie);
+       int res = -EAGAIN;
 
-       for (;;) {
-               res = find_dirent_page(desc);
+       while (1) {
+               res = find_cache_page(desc);
                if (res != -EAGAIN)
                        break;
-               /* Align to beginning of next page */
-               desc->page_index ++;
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
-               }
+               desc->page_index++;
        }
-
-       dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, res);
        return res;
 }
 
@@ -400,8 +655,6 @@ static inline unsigned int dt_type(struct inode *inode)
        return (inode->i_mode >> 12) & 15;
 }
 
-static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc);
-
 /*
  * Once we've found the start of the dirent within a page: fill 'er up...
  */
@@ -410,49 +663,36 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
                   filldir_t filldir)
 {
        struct file     *file = desc->file;
-       struct nfs_entry *entry = desc->entry;
-       struct dentry   *dentry = NULL;
-       u64             fileid;
-       int             loop_count = 0,
-                       res;
-
-       dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n",
-                       (unsigned long long)entry->cookie);
-
-       for(;;) {
-               unsigned d_type = DT_UNKNOWN;
-               /* Note: entry->prev_cookie contains the cookie for
-                *       retrieving the current dirent on the server */
-               fileid = entry->ino;
-
-               /* Get a dentry if we have one */
-               if (dentry != NULL)
-                       dput(dentry);
-               dentry = nfs_readdir_lookup(desc);
+       int i = 0;
+       int res = 0;
+       struct nfs_cache_array *array = NULL;
+       unsigned int d_type = DT_UNKNOWN;
+       struct dentry *dentry = NULL;
 
-               /* Use readdirplus info */
-               if (dentry != NULL && dentry->d_inode != NULL) {
-                       d_type = dt_type(dentry->d_inode);
-                       fileid = NFS_FILEID(dentry->d_inode);
-               }
+       array = nfs_readdir_get_array(desc->page);
 
-               res = filldir(dirent, entry->name, entry->len, 
-                             file->f_pos, nfs_compat_user_ino64(fileid),
-                             d_type);
+       for (i = desc->cache_entry_index; i < array->size; i++) {
+               d_type = DT_UNKNOWN;
+
+               res = filldir(dirent, array->array[i].string.name,
+                       array->array[i].string.len, file->f_pos,
+                       nfs_compat_user_ino64(array->array[i].ino), d_type);
                if (res < 0)
                        break;
                file->f_pos++;
-               *desc->dir_cookie = entry->cookie;
-               if (dir_decode(desc) != 0) {
-                       desc->page_index ++;
+               desc->cache_entry_index = i;
+               if (i < (array->size-1))
+                       *desc->dir_cookie = array->array[i+1].cookie;
+               else
+                       *desc->dir_cookie = array->last_cookie;
+               if (i == array->eof_index) {
+                       desc->eof = 1;
                        break;
                }
-               if (loop_count++ > 200) {
-                       loop_count = 0;
-                       schedule();
-               }
        }
-       dir_page_release(desc);
+
+       nfs_readdir_release_array(desc->page);
+       cache_page_release(desc);
        if (dentry != NULL)
                dput(dentry);
        dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
@@ -476,12 +716,9 @@ static inline
 int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                     filldir_t filldir)
 {
-       struct file     *file = desc->file;
-       struct inode    *inode = file->f_path.dentry->d_inode;
-       struct rpc_cred *cred = nfs_file_cred(file);
        struct page     *page = NULL;
        int             status;
-       unsigned long   timestamp, gencount;
+       struct inode *inode = desc->file->f_path.dentry->d_inode;
 
        dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
                        (unsigned long long)*desc->dir_cookie);
@@ -491,38 +728,22 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
                status = -ENOMEM;
                goto out;
        }
-       timestamp = jiffies;
-       gencount = nfs_inc_attr_generation_counter();
-       status = NFS_PROTO(inode)->readdir(file->f_path.dentry, cred,
-                                               *desc->dir_cookie, page,
-                                               NFS_SERVER(inode)->dtsize,
-                                               desc->plus);
-       desc->page = page;
-       desc->ptr = kmap(page);         /* matching kunmap in nfs_do_filldir */
-       if (status >= 0) {
-               desc->timestamp = timestamp;
-               desc->gencount = gencount;
-               desc->timestamp_valid = 1;
-               if ((status = dir_decode(desc)) == 0)
-                       desc->entry->prev_cookie = *desc->dir_cookie;
-       } else
+
+       if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) {
                status = -EIO;
-       if (status < 0)
                goto out_release;
+       }
 
+       desc->page_index = 0;
+       desc->page = page;
        status = nfs_do_filldir(desc, dirent, filldir);
 
-       /* Reset read descriptor so it searches the page cache from
-        * the start upon the next call to readdir_search_pagecache() */
-       desc->page_index = 0;
-       desc->entry->cookie = desc->entry->prev_cookie = 0;
-       desc->entry->eof = 0;
  out:
        dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
                        __func__, status);
        return status;
  out_release:
-       dir_page_release(desc);
+       cache_page_release(desc);
        goto out;
 }
 
@@ -536,7 +757,6 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        struct inode    *inode = dentry->d_inode;
        nfs_readdir_descriptor_t my_desc,
                        *desc = &my_desc;
-       struct nfs_entry my_entry;
        int res = -ENOMEM;
 
        dfprintk(FILE, "NFS: readdir(%s/%s) starting at cookie %llu\n",
@@ -557,26 +777,17 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
        desc->decode = NFS_PROTO(inode)->decode_dirent;
        desc->plus = NFS_USE_READDIRPLUS(inode);
 
-       my_entry.cookie = my_entry.prev_cookie = 0;
-       my_entry.eof = 0;
-       my_entry.fh = nfs_alloc_fhandle();
-       my_entry.fattr = nfs_alloc_fattr();
-       if (my_entry.fh == NULL || my_entry.fattr == NULL)
-               goto out_alloc_failed;
-
-       desc->entry = &my_entry;
-
        nfs_block_sillyrename(dentry);
        res = nfs_revalidate_mapping(inode, filp->f_mapping);
        if (res < 0)
                goto out;
 
-       while(!desc->entry->eof) {
+       while (desc->eof != 1) {
                res = readdir_search_pagecache(desc);
 
                if (res == -EBADCOOKIE) {
                        /* This means either end of directory */
-                       if (*desc->dir_cookie && desc->entry->cookie != *desc->dir_cookie) {
+                       if (*desc->dir_cookie && desc->eof == 0) {
                                /* Or that the server has 'lost' a cookie */
                                res = uncached_readdir(desc, dirent, filldir);
                                if (res >= 0)
@@ -588,8 +799,9 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
                if (res == -ETOOSMALL && desc->plus) {
                        clear_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        nfs_zap_caches(inode);
+                       desc->page_index = 0;
                        desc->plus = 0;
-                       desc->entry->eof = 0;
+                       desc->eof = 0;
                        continue;
                }
                if (res < 0)
@@ -605,9 +817,6 @@ out:
        nfs_unblock_sillyrename(dentry);
        if (res > 0)
                res = 0;
-out_alloc_failed:
-       nfs_free_fattr(my_entry.fattr);
-       nfs_free_fhandle(my_entry.fh);
        dfprintk(FILE, "NFS: readdir(%s/%s) returns %d\n",
                        dentry->d_parent->d_name.name, dentry->d_name.name,
                        res);
@@ -1029,10 +1238,63 @@ static int is_atomic_open(struct nameidata *nd)
        return 1;
 }
 
+static struct nfs_open_context *nameidata_to_nfs_open_context(struct dentry *dentry, struct nameidata *nd)
+{
+       struct path path = {
+               .mnt = nd->path.mnt,
+               .dentry = dentry,
+       };
+       struct nfs_open_context *ctx;
+       struct rpc_cred *cred;
+       fmode_t fmode = nd->intent.open.flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
+
+       cred = rpc_lookup_cred();
+       if (IS_ERR(cred))
+               return ERR_CAST(cred);
+       ctx = alloc_nfs_open_context(&path, cred, fmode);
+       put_rpccred(cred);
+       if (ctx == NULL)
+               return ERR_PTR(-ENOMEM);
+       return ctx;
+}
+
+static int do_open(struct inode *inode, struct file *filp)
+{
+       nfs_fscache_set_inode_cookie(inode, filp);
+       return 0;
+}
+
+static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
+{
+       struct file *filp;
+       int ret = 0;
+
+       /* If the open_intent is for execute, we have an extra check to make */
+       if (ctx->mode & FMODE_EXEC) {
+               ret = nfs_may_open(ctx->path.dentry->d_inode,
+                               ctx->cred,
+                               nd->intent.open.flags);
+               if (ret < 0)
+                       goto out;
+       }
+       filp = lookup_instantiate_filp(nd, ctx->path.dentry, do_open);
+       if (IS_ERR(filp))
+               ret = PTR_ERR(filp);
+       else
+               nfs_file_set_open_context(filp, ctx);
+out:
+       put_nfs_open_context(ctx);
+       return ret;
+}
+
 static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
 {
+       struct nfs_open_context *ctx;
+       struct iattr attr;
        struct dentry *res = NULL;
-       int error;
+       struct inode *inode;
+       int open_flags;
+       int err;
 
        dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1054,13 +1316,32 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                goto out;
        }
 
+       ctx = nameidata_to_nfs_open_context(dentry, nd);
+       res = ERR_CAST(ctx);
+       if (IS_ERR(ctx))
+               goto out;
+
+       open_flags = nd->intent.open.flags;
+       if (nd->flags & LOOKUP_CREATE) {
+               attr.ia_mode = nd->intent.open.create_mode;
+               attr.ia_valid = ATTR_MODE;
+               if (!IS_POSIXACL(dir))
+                       attr.ia_mode &= ~current_umask();
+       } else {
+               open_flags &= ~(O_EXCL | O_CREAT);
+               attr.ia_valid = 0;
+       }
+
        /* Open the file on the server */
-       res = nfs4_atomic_open(dir, dentry, nd);
-       if (IS_ERR(res)) {
-               error = PTR_ERR(res);
-               switch (error) {
+       nfs_block_sillyrename(dentry->d_parent);
+       inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
+       if (IS_ERR(inode)) {
+               nfs_unblock_sillyrename(dentry->d_parent);
+               put_nfs_open_context(ctx);
+               switch (PTR_ERR(inode)) {
                        /* Make a negative dentry */
                        case -ENOENT:
+                               d_add(dentry, NULL);
                                res = NULL;
                                goto out;
                        /* This turned out not to be a regular file */
@@ -1072,11 +1353,25 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                                        goto no_open;
                        /* case -EINVAL: */
                        default:
+                               res = ERR_CAST(inode);
                                goto out;
                }
-       } else if (res != NULL)
+       }
+       res = d_add_unique(dentry, inode);
+       nfs_unblock_sillyrename(dentry->d_parent);
+       if (res != NULL) {
+               dput(ctx->path.dentry);
+               ctx->path.dentry = dget(res);
                dentry = res;
+       }
+       err = nfs_intent_set_file(nd, ctx);
+       if (err < 0) {
+               if (res != NULL)
+                       dput(res);
+               return ERR_PTR(err);
+       }
 out:
+       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
        return res;
 no_open:
        return nfs_lookup(dir, dentry, nd);
@@ -1087,12 +1382,15 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct dentry *parent = NULL;
        struct inode *inode = dentry->d_inode;
        struct inode *dir;
+       struct nfs_open_context *ctx;
        int openflags, ret = 0;
 
        if (!is_atomic_open(nd) || d_mountpoint(dentry))
                goto no_open;
+
        parent = dget_parent(dentry);
        dir = parent->d_inode;
+
        /* We can't create new files in nfs_open_revalidate(), so we
         * optimize away revalidation of negative dentries.
         */
@@ -1112,99 +1410,96 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
        /* We can't create new files, or truncate existing ones here */
        openflags &= ~(O_CREAT|O_EXCL|O_TRUNC);
 
+       ctx = nameidata_to_nfs_open_context(dentry, nd);
+       ret = PTR_ERR(ctx);
+       if (IS_ERR(ctx))
+               goto out;
        /*
         * Note: we're not holding inode->i_mutex and so may be racing with
         * operations that change the directory. We therefore save the
         * change attribute *before* we do the RPC call.
         */
-       ret = nfs4_open_revalidate(dir, dentry, openflags, nd);
+       inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, NULL);
+       if (IS_ERR(inode)) {
+               ret = PTR_ERR(inode);
+               switch (ret) {
+               case -EPERM:
+               case -EACCES:
+               case -EDQUOT:
+               case -ENOSPC:
+               case -EROFS:
+                       goto out_put_ctx;
+               default:
+                       goto out_drop;
+               }
+       }
+       iput(inode);
+       if (inode != dentry->d_inode)
+               goto out_drop;
+
+       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+       ret = nfs_intent_set_file(nd, ctx);
+       if (ret >= 0)
+               ret = 1;
 out:
        dput(parent);
-       if (!ret)
-               d_drop(dentry);
        return ret;
+out_drop:
+       d_drop(dentry);
+       ret = 0;
+out_put_ctx:
+       put_nfs_open_context(ctx);
+       goto out;
+
 no_open_dput:
        dput(parent);
 no_open:
        return nfs_lookup_revalidate(dentry, nd);
 }
-#endif /* CONFIG_NFSV4 */
 
-static struct dentry *nfs_readdir_lookup(nfs_readdir_descriptor_t *desc)
+static int nfs_open_create(struct inode *dir, struct dentry *dentry, int mode,
+               struct nameidata *nd)
 {
-       struct dentry *parent = desc->file->f_path.dentry;
-       struct inode *dir = parent->d_inode;
-       struct nfs_entry *entry = desc->entry;
-       struct dentry *dentry, *alias;
-       struct qstr name = {
-               .name = entry->name,
-               .len = entry->len,
-       };
-       struct inode *inode;
-       unsigned long verf = nfs_save_change_attribute(dir);
+       struct nfs_open_context *ctx = NULL;
+       struct iattr attr;
+       int error;
+       int open_flags = 0;
 
-       switch (name.len) {
-               case 2:
-                       if (name.name[0] == '.' && name.name[1] == '.')
-                               return dget_parent(parent);
-                       break;
-               case 1:
-                       if (name.name[0] == '.')
-                               return dget(parent);
-       }
+       dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
+                       dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
-       spin_lock(&dir->i_lock);
-       if (NFS_I(dir)->cache_validity & NFS_INO_INVALID_DATA) {
-               spin_unlock(&dir->i_lock);
-               return NULL;
-       }
-       spin_unlock(&dir->i_lock);
+       attr.ia_mode = mode;
+       attr.ia_valid = ATTR_MODE;
 
-       name.hash = full_name_hash(name.name, name.len);
-       dentry = d_lookup(parent, &name);
-       if (dentry != NULL) {
-               /* Is this a positive dentry that matches the readdir info? */
-               if (dentry->d_inode != NULL &&
-                               (NFS_FILEID(dentry->d_inode) == entry->ino ||
-                               d_mountpoint(dentry))) {
-                       if (!desc->plus || entry->fh->size == 0)
-                               return dentry;
-                       if (nfs_compare_fh(NFS_FH(dentry->d_inode),
-                                               entry->fh) == 0)
-                               goto out_renew;
-               }
-               /* No, so d_drop to allow one to be created */
-               d_drop(dentry);
-               dput(dentry);
-       }
-       if (!desc->plus || !(entry->fattr->valid & NFS_ATTR_FATTR))
-               return NULL;
-       if (name.len > NFS_SERVER(dir)->namelen)
-               return NULL;
-       /* Note: caller is already holding the dir->i_mutex! */
-       dentry = d_alloc(parent, &name);
-       if (dentry == NULL)
-               return NULL;
-       dentry->d_op = NFS_PROTO(dir)->dentry_ops;
-       inode = nfs_fhget(dentry->d_sb, entry->fh, entry->fattr);
-       if (IS_ERR(inode)) {
-               dput(dentry);
-               return NULL;
-       }
+       if ((nd->flags & LOOKUP_CREATE) != 0) {
+               open_flags = nd->intent.open.flags;
 
-       alias = d_materialise_unique(dentry, inode);
-       if (alias != NULL) {
-               dput(dentry);
-               if (IS_ERR(alias))
-                       return NULL;
-               dentry = alias;
+               ctx = nameidata_to_nfs_open_context(dentry, nd);
+               error = PTR_ERR(ctx);
+               if (IS_ERR(ctx))
+                       goto out_err_drop;
        }
 
-out_renew:
-       nfs_set_verifier(dentry, verf);
-       return dentry;
+       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
+       if (error != 0)
+               goto out_put_ctx;
+       if (ctx != NULL) {
+               error = nfs_intent_set_file(nd, ctx);
+               if (error < 0)
+                       goto out_err;
+       }
+       return 0;
+out_put_ctx:
+       if (ctx != NULL)
+               put_nfs_open_context(ctx);
+out_err_drop:
+       d_drop(dentry);
+out_err:
+       return error;
 }
 
+#endif /* CONFIG_NFSV4 */
+
 /*
  * Code common to create, mkdir, and mknod.
  */
@@ -1258,7 +1553,6 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
 {
        struct iattr attr;
        int error;
-       int open_flags = 0;
 
        dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1266,10 +1560,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry, int mode,
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       if ((nd->flags & LOOKUP_CREATE) != 0)
-               open_flags = nd->intent.open.flags;
-
-       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, nd);
+       error = NFS_PROTO(dir)->create(dir, dentry, &attr, 0, NULL);
        if (error != 0)
                goto out_err;
        return 0;
@@ -1351,76 +1642,6 @@ static int nfs_rmdir(struct inode *dir, struct dentry *dentry)
        return error;
 }
 
-static int nfs_sillyrename(struct inode *dir, struct dentry *dentry)
-{
-       static unsigned int sillycounter;
-       const int      fileidsize  = sizeof(NFS_FILEID(dentry->d_inode))*2;
-       const int      countersize = sizeof(sillycounter)*2;
-       const int      slen        = sizeof(".nfs")+fileidsize+countersize-1;
-       char           silly[slen+1];
-       struct qstr    qsilly;
-       struct dentry *sdentry;
-       int            error = -EIO;
-
-       dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
-               dentry->d_parent->d_name.name, dentry->d_name.name, 
-               atomic_read(&dentry->d_count));
-       nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
-
-       /*
-        * We don't allow a dentry to be silly-renamed twice.
-        */
-       error = -EBUSY;
-       if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
-               goto out;
-
-       sprintf(silly, ".nfs%*.*Lx",
-               fileidsize, fileidsize,
-               (unsigned long long)NFS_FILEID(dentry->d_inode));
-
-       /* Return delegation in anticipation of the rename */
-       nfs_inode_return_delegation(dentry->d_inode);
-
-       sdentry = NULL;
-       do {
-               char *suffix = silly + slen - countersize;
-
-               dput(sdentry);
-               sillycounter++;
-               sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
-
-               dfprintk(VFS, "NFS: trying to rename %s to %s\n",
-                               dentry->d_name.name, silly);
-               
-               sdentry = lookup_one_len(silly, dentry->d_parent, slen);
-               /*
-                * N.B. Better to return EBUSY here ... it could be
-                * dangerous to delete the file while it's in use.
-                */
-               if (IS_ERR(sdentry))
-                       goto out;
-       } while(sdentry->d_inode != NULL); /* need negative lookup */
-
-       qsilly.name = silly;
-       qsilly.len  = strlen(silly);
-       if (dentry->d_inode) {
-               error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-                               dir, &qsilly);
-               nfs_mark_for_revalidate(dentry->d_inode);
-       } else
-               error = NFS_PROTO(dir)->rename(dir, &dentry->d_name,
-                               dir, &qsilly);
-       if (!error) {
-               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-               d_move(dentry, sdentry);
-               error = nfs_async_unlink(dir, dentry);
-               /* If we return 0 we don't unlink */
-       }
-       dput(sdentry);
-out:
-       return error;
-}
-
 /*
  * Remove a file after making sure there are no pending writes,
  * and after checking that the file has only one user. 
@@ -1711,14 +1932,14 @@ static void nfs_access_free_list(struct list_head *head)
 int nfs_access_cache_shrinker(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask)
 {
        LIST_HEAD(head);
-       struct nfs_inode *nfsi;
+       struct nfs_inode *nfsi, *next;
        struct nfs_access_entry *cache;
 
        if ((gfp_mask & GFP_KERNEL) != GFP_KERNEL)
                return (nr_to_scan == 0) ? 0 : -1;
 
        spin_lock(&nfs_access_lru_lock);
-       list_for_each_entry(nfsi, &nfs_access_lru_list, access_cache_inode_lru) {
+       list_for_each_entry_safe(nfsi, next, &nfs_access_lru_list, access_cache_inode_lru) {
                struct inode *inode;
 
                if (nr_to_scan-- == 0)
index dba50a5..a6e711a 100644 (file)
@@ -167,7 +167,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
                return 0;
        }
        item = container_of(h, struct nfs_dns_ent, h);
-       ttl = (long)item->h.expiry_time - (long)get_seconds();
+       ttl = item->h.expiry_time - seconds_since_boot();
        if (ttl < 0)
                ttl = 0;
 
@@ -239,7 +239,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)
        ttl = get_expiry(&buf);
        if (ttl == 0)
                goto out;
-       key.h.expiry_time = ttl + get_seconds();
+       key.h.expiry_time = ttl + seconds_since_boot();
 
        ret = -ENOMEM;
        item = nfs_dns_lookup(cd, &key);
@@ -301,7 +301,7 @@ static int do_cache_lookup_nowait(struct cache_detail *cd,
                goto out_err;
        ret = -ETIMEDOUT;
        if (!test_bit(CACHE_VALID, &(*item)->h.flags)
-                       || (*item)->h.expiry_time < get_seconds()
+                       || (*item)->h.expiry_time < seconds_since_boot()
                        || cd->flush_time > (*item)->h.last_refresh)
                goto out_put;
        ret = -ENOENT;
index 05bf3c0..e756075 100644 (file)
@@ -36,6 +36,7 @@
 #include "internal.h"
 #include "iostat.h"
 #include "fscache.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_FILE
 
@@ -386,6 +387,10 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping,
                file->f_path.dentry->d_name.name,
                mapping->host->i_ino, len, (long long) pos);
 
+       pnfs_update_layout(mapping->host,
+                          nfs_file_open_context(file),
+                          IOMODE_RW);
+
 start:
        /*
         * Prevent starvation issues if someone is doing a consistency
@@ -551,7 +556,7 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        struct file *filp = vma->vm_file;
        struct dentry *dentry = filp->f_path.dentry;
        unsigned pagelen;
-       int ret = -EINVAL;
+       int ret = VM_FAULT_NOPAGE;
        struct address_space *mapping;
 
        dfprintk(PAGECACHE, "NFS: vm_page_mkwrite(%s/%s(%ld), offset %lld)\n",
@@ -567,21 +572,20 @@ static int nfs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (mapping != dentry->d_inode->i_mapping)
                goto out_unlock;
 
-       ret = 0;
        pagelen = nfs_page_length(page);
        if (pagelen == 0)
                goto out_unlock;
 
-       ret = nfs_flush_incompatible(filp, page);
-       if (ret != 0)
-               goto out_unlock;
+       ret = VM_FAULT_LOCKED;
+       if (nfs_flush_incompatible(filp, page) == 0 &&
+           nfs_updatepage(filp, page, 0, pagelen) == 0)
+               goto out;
 
-       ret = nfs_updatepage(filp, page, 0, pagelen);
+       ret = VM_FAULT_SIGBUS;
 out_unlock:
-       if (!ret)
-               return VM_FAULT_LOCKED;
        unlock_page(page);
-       return VM_FAULT_SIGBUS;
+out:
+       return ret;
 }
 
 static const struct vm_operations_struct nfs_file_vm_ops = {
@@ -684,7 +688,8 @@ static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
        return ret;
 }
 
-static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+do_getlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status = 0;
@@ -699,7 +704,7 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
        if (nfs_have_delegation(inode, FMODE_READ))
                goto out_noconflict;
 
-       if (NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM)
+       if (is_local)
                goto out_noconflict;
 
        status = NFS_PROTO(inode)->lock(filp, cmd, fl);
@@ -726,7 +731,8 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl)
        return res;
 }
 
-static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status;
@@ -741,15 +747,24 @@ static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
         *      If we're signalled while cleaning up locks on process exit, we
         *      still need to complete the unlock.
         */
-       /* Use local locking if mounted with "-onolock" */
-       if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+       /*
+        * Use local locking if mounted with "-onolock" or with appropriate
+        * "-olocal_lock="
+        */
+       if (!is_local)
                status = NFS_PROTO(inode)->lock(filp, cmd, fl);
        else
                status = do_vfs_lock(filp, fl);
        return status;
 }
 
-static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
+static int
+is_time_granular(struct timespec *ts) {
+       return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000));
+}
+
+static int
+do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
 {
        struct inode *inode = filp->f_mapping->host;
        int status;
@@ -762,20 +777,31 @@ static int do_setlk(struct file *filp, int cmd, struct file_lock *fl)
        if (status != 0)
                goto out;
 
-       /* Use local locking if mounted with "-onolock" */
-       if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
+       /*
+        * Use local locking if mounted with "-onolock" or with appropriate
+        * "-olocal_lock="
+        */
+       if (!is_local)
                status = NFS_PROTO(inode)->lock(filp, cmd, fl);
        else
                status = do_vfs_lock(filp, fl);
        if (status < 0)
                goto out;
+
        /*
-        * Make sure we clear the cache whenever we try to get the lock.
+        * Revalidate the cache if the server has time stamps granular
+        * enough to detect subsecond changes.  Otherwise, clear the
+        * cache to prevent missing any changes.
+        *
         * This makes locking act as a cache coherency point.
         */
        nfs_sync_mapping(filp->f_mapping);
-       if (!nfs_have_delegation(inode, FMODE_READ))
-               nfs_zap_caches(inode);
+       if (!nfs_have_delegation(inode, FMODE_READ)) {
+               if (is_time_granular(&NFS_SERVER(inode)->time_delta))
+                       __nfs_revalidate_inode(NFS_SERVER(inode), inode);
+               else
+                       nfs_zap_caches(inode);
+       }
 out:
        return status;
 }
@@ -787,6 +813,7 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
        struct inode *inode = filp->f_mapping->host;
        int ret = -ENOLCK;
+       int is_local = 0;
 
        dprintk("NFS: lock(%s/%s, t=%x, fl=%x, r=%lld:%lld)\n",
                        filp->f_path.dentry->d_parent->d_name.name,
@@ -800,6 +827,9 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
        if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK)
                goto out_err;
 
+       if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FCNTL)
+               is_local = 1;
+
        if (NFS_PROTO(inode)->lock_check_bounds != NULL) {
                ret = NFS_PROTO(inode)->lock_check_bounds(fl);
                if (ret < 0)
@@ -807,11 +837,11 @@ static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
        }
 
        if (IS_GETLK(cmd))
-               ret = do_getlk(filp, cmd, fl);
+               ret = do_getlk(filp, cmd, fl, is_local);
        else if (fl->fl_type == F_UNLCK)
-               ret = do_unlk(filp, cmd, fl);
+               ret = do_unlk(filp, cmd, fl, is_local);
        else
-               ret = do_setlk(filp, cmd, fl);
+               ret = do_setlk(filp, cmd, fl, is_local);
 out_err:
        return ret;
 }
@@ -821,6 +851,9 @@ out_err:
  */
 static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
 {
+       struct inode *inode = filp->f_mapping->host;
+       int is_local = 0;
+
        dprintk("NFS: flock(%s/%s, t=%x, fl=%x)\n",
                        filp->f_path.dentry->d_parent->d_name.name,
                        filp->f_path.dentry->d_name.name,
@@ -829,14 +862,17 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
        if (!(fl->fl_flags & FL_FLOCK))
                return -ENOLCK;
 
+       if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK)
+               is_local = 1;
+
        /* We're simulating flock() locks using posix locks on the server */
        fl->fl_owner = (fl_owner_t)filp;
        fl->fl_start = 0;
        fl->fl_end = OFFSET_MAX;
 
        if (fl->fl_type == F_UNLCK)
-               return do_unlk(filp, cmd, fl);
-       return do_setlk(filp, cmd, fl);
+               return do_unlk(filp, cmd, fl, is_local);
+       return do_setlk(filp, cmd, fl, is_local);
 }
 
 /*
index 21a84d4..dec47ed 100644 (file)
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifdef CONFIG_NFS_USE_NEW_IDMAPPER
+
+#include <linux/slab.h>
+#include <linux/cred.h>
+#include <linux/nfs_idmap.h>
+#include <linux/keyctl.h>
+#include <linux/key-type.h>
+#include <linux/rcupdate.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+
+#include <keys/user-type.h>
+
+#define NFS_UINT_MAXLEN 11
+
+const struct cred *id_resolver_cache;
+
+struct key_type key_type_id_resolver = {
+       .name           = "id_resolver",
+       .instantiate    = user_instantiate,
+       .match          = user_match,
+       .revoke         = user_revoke,
+       .destroy        = user_destroy,
+       .describe       = user_describe,
+       .read           = user_read,
+};
+
+int nfs_idmap_init(void)
+{
+       struct cred *cred;
+       struct key *keyring;
+       int ret = 0;
+
+       printk(KERN_NOTICE "Registering the %s key type\n", key_type_id_resolver.name);
+
+       cred = prepare_kernel_cred(NULL);
+       if (!cred)
+               return -ENOMEM;
+
+       keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred,
+                            (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+                            KEY_USR_VIEW | KEY_USR_READ,
+                            KEY_ALLOC_NOT_IN_QUOTA);
+       if (IS_ERR(keyring)) {
+               ret = PTR_ERR(keyring);
+               goto failed_put_cred;
+       }
+
+       ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL);
+       if (ret < 0)
+               goto failed_put_key;
+
+       ret = register_key_type(&key_type_id_resolver);
+       if (ret < 0)
+               goto failed_put_key;
+
+       cred->thread_keyring = keyring;
+       cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+       id_resolver_cache = cred;
+       return 0;
+
+failed_put_key:
+       key_put(keyring);
+failed_put_cred:
+       put_cred(cred);
+       return ret;
+}
+
+void nfs_idmap_quit(void)
+{
+       key_revoke(id_resolver_cache->thread_keyring);
+       unregister_key_type(&key_type_id_resolver);
+       put_cred(id_resolver_cache);
+}
+
+/*
+ * Assemble the description to pass to request_key()
+ * This function will allocate a new string and update dest to point
+ * at it.  The caller is responsible for freeing dest.
+ *
+ * On error 0 is returned.  Otherwise, the length of dest is returned.
+ */
+static ssize_t nfs_idmap_get_desc(const char *name, size_t namelen,
+                               const char *type, size_t typelen, char **desc)
+{
+       char *cp;
+       size_t desclen = typelen + namelen + 2;
+
+       *desc = kmalloc(desclen, GFP_KERNEL);
+       if (!desc)
+               return -ENOMEM;
+
+       cp = *desc;
+       memcpy(cp, type, typelen);
+       cp += typelen;
+       *cp++ = ':';
+
+       memcpy(cp, name, namelen);
+       cp += namelen;
+       *cp = '\0';
+       return desclen;
+}
+
+static ssize_t nfs_idmap_request_key(const char *name, size_t namelen,
+               const char *type, void *data, size_t data_size)
+{
+       const struct cred *saved_cred;
+       struct key *rkey;
+       char *desc;
+       struct user_key_payload *payload;
+       ssize_t ret;
+
+       ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc);
+       if (ret <= 0)
+               goto out;
+
+       saved_cred = override_creds(id_resolver_cache);
+       rkey = request_key(&key_type_id_resolver, desc, "");
+       revert_creds(saved_cred);
+       kfree(desc);
+       if (IS_ERR(rkey)) {
+               ret = PTR_ERR(rkey);
+               goto out;
+       }
+
+       rcu_read_lock();
+       rkey->perm |= KEY_USR_VIEW;
+
+       ret = key_validate(rkey);
+       if (ret < 0)
+               goto out_up;
+
+       payload = rcu_dereference(rkey->payload.data);
+       if (IS_ERR_OR_NULL(payload)) {
+               ret = PTR_ERR(payload);
+               goto out_up;
+       }
+
+       ret = payload->datalen;
+       if (ret > 0 && ret <= data_size)
+               memcpy(data, payload->data, ret);
+       else
+               ret = -EINVAL;
+
+out_up:
+       rcu_read_unlock();
+       key_put(rkey);
+out:
+       return ret;
+}
+
+
+/* ID -> Name */
+static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf, size_t buflen)
+{
+       char id_str[NFS_UINT_MAXLEN];
+       int id_len;
+       ssize_t ret;
+
+       id_len = snprintf(id_str, sizeof(id_str), "%u", id);
+       ret = nfs_idmap_request_key(id_str, id_len, type, buf, buflen);
+       if (ret < 0)
+               return -EINVAL;
+       return ret;
+}
+
+/* Name -> ID */
+static int nfs_idmap_lookup_id(const char *name, size_t namelen,
+                               const char *type, __u32 *id)
+{
+       char id_str[NFS_UINT_MAXLEN];
+       long id_long;
+       ssize_t data_size;
+       int ret = 0;
+
+       data_size = nfs_idmap_request_key(name, namelen, type, id_str, NFS_UINT_MAXLEN);
+       if (data_size <= 0) {
+               ret = -EINVAL;
+       } else {
+               ret = strict_strtol(id_str, 10, &id_long);
+               *id = (__u32)id_long;
+       }
+       return ret;
+}
+
+int nfs_map_name_to_uid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *uid)
+{
+       return nfs_idmap_lookup_id(name, namelen, "uid", uid);
+}
+
+int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namelen, __u32 *gid)
+{
+       return nfs_idmap_lookup_id(name, namelen, "gid", gid);
+}
+
+int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
+{
+       return nfs_idmap_lookup_name(uid, "user", buf, buflen);
+}
+int nfs_map_gid_to_group(struct nfs_client *clp, __u32 gid, char *buf, size_t buflen)
+{
+       return nfs_idmap_lookup_name(gid, "group", buf, buflen);
+}
+
+#else  /* CONFIG_NFS_USE_IDMAPPER not defined */
+
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/init.h>
@@ -503,16 +709,17 @@ int nfs_map_group_to_gid(struct nfs_client *clp, const char *name, size_t namele
        return nfs_idmap_id(idmap, &idmap->idmap_group_hash, name, namelen, uid);
 }
 
-int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf)
+int nfs_map_uid_to_name(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
 {
        struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_name(idmap, &idmap->idmap_user_hash, uid, buf);
 }
-int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf)
+int nfs_map_gid_to_group(struct nfs_client *clp, __u32 uid, char *buf, size_t buflen)
 {
        struct idmap *idmap = clp->cl_idmap;
 
        return nfs_idmap_name(idmap, &idmap->idmap_group_hash, uid, buf);
 }
 
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
index 7d2d6c7..314f571 100644 (file)
@@ -48,6 +48,7 @@
 #include "internal.h"
 #include "fscache.h"
 #include "dns_resolve.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
@@ -234,9 +235,6 @@ nfs_init_locked(struct inode *inode, void *opaque)
        return 0;
 }
 
-/* Don't use READDIRPLUS on directories that we believe are too large */
-#define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE)
-
 /*
  * This is our front-end to iget that looks up inodes by file handle
  * instead of inode number.
@@ -291,8 +289,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                } else if (S_ISDIR(inode->i_mode)) {
                        inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops;
                        inode->i_fop = &nfs_dir_operations;
-                       if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS)
-                           && fattr->size <= NFS_LIMIT_READDIRPLUS)
+                       if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS))
                                set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_I(inode)->flags);
                        /* Deal with crossing mountpoints */
                        if ((fattr->valid & NFS_ATTR_FATTR_FSID)
@@ -623,7 +620,7 @@ void nfs_close_context(struct nfs_open_context *ctx, int is_sync)
        nfs_revalidate_inode(server, inode);
 }
 
-static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred)
+struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode)
 {
        struct nfs_open_context *ctx;
 
@@ -633,11 +630,13 @@ static struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct
                path_get(&ctx->path);
                ctx->cred = get_rpccred(cred);
                ctx->state = NULL;
+               ctx->mode = f_mode;
                ctx->flags = 0;
                ctx->error = 0;
                ctx->dir_cookie = 0;
                nfs_init_lock_context(&ctx->lock_context);
                ctx->lock_context.open_context = ctx;
+               INIT_LIST_HEAD(&ctx->list);
        }
        return ctx;
 }
@@ -653,11 +652,15 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)
 {
        struct inode *inode = ctx->path.dentry->d_inode;
 
-       if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+       if (!list_empty(&ctx->list)) {
+               if (!atomic_dec_and_lock(&ctx->lock_context.count, &inode->i_lock))
+                       return;
+               list_del(&ctx->list);
+               spin_unlock(&inode->i_lock);
+       } else if (!atomic_dec_and_test(&ctx->lock_context.count))
                return;
-       list_del(&ctx->list);
-       spin_unlock(&inode->i_lock);
-       NFS_PROTO(inode)->close_context(ctx, is_sync);
+       if (inode != NULL)
+               NFS_PROTO(inode)->close_context(ctx, is_sync);
        if (ctx->cred != NULL)
                put_rpccred(ctx->cred);
        path_put(&ctx->path);
@@ -673,7 +676,7 @@ void put_nfs_open_context(struct nfs_open_context *ctx)
  * Ensure that mmap has a recent RPC credential for use when writing out
  * shared pages
  */
-static void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
+void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx)
 {
        struct inode *inode = filp->f_path.dentry->d_inode;
        struct nfs_inode *nfsi = NFS_I(inode);
@@ -730,11 +733,10 @@ int nfs_open(struct inode *inode, struct file *filp)
        cred = rpc_lookup_cred();
        if (IS_ERR(cred))
                return PTR_ERR(cred);
-       ctx = alloc_nfs_open_context(&filp->f_path, cred);
+       ctx = alloc_nfs_open_context(&filp->f_path, cred, filp->f_mode);
        put_rpccred(cred);
        if (ctx == NULL)
                return -ENOMEM;
-       ctx->mode = filp->f_mode;
        nfs_file_set_open_context(filp, ctx);
        put_nfs_open_context(ctx);
        nfs_fscache_set_inode_cookie(inode, filp);
@@ -1409,6 +1411,7 @@ void nfs4_evict_inode(struct inode *inode)
 {
        truncate_inode_pages(&inode->i_data, 0);
        end_writeback(inode);
+       pnfs_destroy_layout(NFS_I(inode));
        /* If we are holding a delegation, return it! */
        nfs_inode_return_delegation_noreclaim(inode);
        /* First call standard NFS clear_inode() code */
@@ -1446,6 +1449,7 @@ static inline void nfs4_init_once(struct nfs_inode *nfsi)
        nfsi->delegation = NULL;
        nfsi->delegation_state = 0;
        init_rwsem(&nfsi->rwsem);
+       nfsi->layout = NULL;
 #endif
 }
 
@@ -1493,7 +1497,7 @@ static int nfsiod_start(void)
 {
        struct workqueue_struct *wq;
        dprintk("RPC:       creating workqueue nfsiod\n");
-       wq = create_singlethread_workqueue("nfsiod");
+       wq = alloc_workqueue("nfsiod", WQ_RESCUER, 0);
        if (wq == NULL)
                return -ENOMEM;
        nfsiod_workqueue = wq;
@@ -1521,6 +1525,10 @@ static int __init init_nfs_fs(void)
 {
        int err;
 
+       err = nfs_idmap_init();
+       if (err < 0)
+               goto out9;
+
        err = nfs_dns_resolver_init();
        if (err < 0)
                goto out8;
@@ -1585,6 +1593,8 @@ out6:
 out7:
        nfs_dns_resolver_destroy();
 out8:
+       nfs_idmap_quit();
+out9:
        return err;
 }
 
@@ -1597,6 +1607,7 @@ static void __exit exit_nfs_fs(void)
        nfs_destroy_nfspagecache();
        nfs_fscache_unregister();
        nfs_dns_resolver_destroy();
+       nfs_idmap_quit();
 #ifdef CONFIG_PROC_FS
        rpc_proc_unregister("nfs");
 #endif
index c961bc9..db08ff3 100644 (file)
@@ -63,6 +63,12 @@ struct nfs_clone_mount {
 #define NFS_UNSPEC_PORT                (-1)
 
 /*
+ * Maximum number of pages that readdir can use for creating
+ * a vmapped array of pages.
+ */
+#define NFS_MAX_READDIR_PAGES 8
+
+/*
  * In-kernel mount arguments
  */
 struct nfs_parsed_mount_data {
@@ -181,15 +187,15 @@ extern void nfs_destroy_directcache(void);
 /* nfs2xdr.c */
 extern int nfs_stat_to_errno(int);
 extern struct rpc_procinfo nfs_procedures[];
-extern __be32 * nfs_decode_dirent(__be32 *, struct nfs_entry *, int);
+extern __be32 *nfs_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 
 /* nfs3xdr.c */
 extern struct rpc_procinfo nfs3_procedures[];
-extern __be32 *nfs3_decode_dirent(__be32 *, struct nfs_entry *, int);
+extern __be32 *nfs3_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 
 /* nfs4xdr.c */
 #ifdef CONFIG_NFS_V4
-extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 #endif
 #ifdef CONFIG_NFS_V4_1
 extern const u32 nfs41_maxread_overhead;
index 59047f8..eceafe7 100644 (file)
@@ -153,6 +153,7 @@ int nfs_mount(struct nfs_mount_request *info)
                .rpc_resp       = &result,
        };
        struct rpc_create_args args = {
+               .net            = &init_net,
                .protocol       = info->protocol,
                .address        = info->sap,
                .addrsize       = info->salen,
@@ -224,6 +225,7 @@ void nfs_umount(const struct nfs_mount_request *info)
                .to_retries = 2,
        };
        struct rpc_create_args args = {
+               .net            = &init_net,
                .protocol       = IPPROTO_UDP,
                .address        = info->sap,
                .addrsize       = info->salen,
@@ -436,7 +438,7 @@ static int decode_auth_flavors(struct xdr_stream *xdr, struct mountres *res)
 
        for (i = 0; i < entries; i++) {
                flavors[i] = ntohl(*p++);
-               dprintk("NFS:\tflavor %u: %d\n", i, flavors[i]);
+               dprintk("NFS:   auth flavor[%u]: %d\n", i, flavors[i]);
        }
        *count = i;
 
index db8846a..e6bf457 100644 (file)
@@ -337,10 +337,10 @@ nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
 static int
 nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 {
-       p = xdr_encode_fhandle(p, args->fromfh);
-       p = xdr_encode_array(p, args->fromname, args->fromlen);
-       p = xdr_encode_fhandle(p, args->tofh);
-       p = xdr_encode_array(p, args->toname, args->tolen);
+       p = xdr_encode_fhandle(p, args->old_dir);
+       p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
+       p = xdr_encode_fhandle(p, args->new_dir);
+       p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
        return 0;
 }
@@ -423,9 +423,7 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
        struct page **page;
        size_t hdrlen;
        unsigned int pglen, recvd;
-       u32 len;
        int status, nr = 0;
-       __be32 *end, *entry, *kaddr;
 
        if ((status = ntohl(*p++)))
                return nfs_stat_to_errno(status);
@@ -445,80 +443,59 @@ nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
        if (pglen > recvd)
                pglen = recvd;
        page = rcvbuf->pages;
-       kaddr = p = kmap_atomic(*page, KM_USER0);
-       end = (__be32 *)((char *)p + pglen);
-       entry = p;
-
-       /* Make sure the packet actually has a value_follows and EOF entry */
-       if ((entry + 1) > end)
-               goto short_pkt;
-
-       for (; *p++; nr++) {
-               if (p + 2 > end)
-                       goto short_pkt;
-               p++; /* fileid */
-               len = ntohl(*p++);
-               p += XDR_QUADLEN(len) + 1;      /* name plus cookie */
-               if (len > NFS2_MAXNAMLEN) {
-                       dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
-                                               len);
-                       goto err_unmap;
-               }
-               if (p + 2 > end)
-                       goto short_pkt;
-               entry = p;
-       }
-
-       /*
-        * Apparently some server sends responses that are a valid size, but
-        * contain no entries, and have value_follows==0 and EOF==0. For
-        * those, just set the EOF marker.
-        */
-       if (!nr && entry[1] == 0) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
- out:
-       kunmap_atomic(kaddr, KM_USER0);
        return nr;
- short_pkt:
-       /*
-        * When we get a short packet there are 2 possibilities. We can
-        * return an error, or fix up the response to look like a valid
-        * response and return what we have so far. If there are no
-        * entries and the packet was short, then return -EIO. If there
-        * are valid entries in the response, return them and pretend that
-        * the call was successful, but incomplete. The caller can retry the
-        * readdir starting at the last cookie.
-        */
-       entry[0] = entry[1] = 0;
-       if (!nr)
-               nr = -errno_NFSERR_IO;
-       goto out;
-err_unmap:
-       nr = -errno_NFSERR_IO;
-       goto out;
+}
+
+static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+{
+       dprintk("nfs: %s: prematurely hit end of receive buffer. "
+               "Remaining buffer length is %tu words.\n",
+               func, xdr->end - xdr->p);
 }
 
 __be32 *
-nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
 {
-       if (!*p++) {
-               if (!*p)
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (!ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (!ntohl(*p++))
                        return ERR_PTR(-EAGAIN);
                entry->eof = 1;
                return ERR_PTR(-EBADCOOKIE);
        }
 
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+               goto out_overflow;
+
        entry->ino        = ntohl(*p++);
        entry->len        = ntohl(*p++);
+
+       p = xdr_inline_decode(xdr, entry->len + 4);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->name       = (const char *) p;
        p                += XDR_QUADLEN(entry->len);
        entry->prev_cookie        = entry->cookie;
        entry->cookie     = ntohl(*p++);
-       entry->eof        = !p[0] && p[1];
+
+       p = xdr_inline_peek(xdr, 8);
+       if (p != NULL)
+               entry->eof = !p[0] && p[1];
+       else
+               entry->eof = 0;
 
        return p;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
 }
 
 /*
@@ -596,7 +573,6 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
        struct kvec *iov = rcvbuf->head;
        size_t hdrlen;
        u32 len, recvd;
-       char    *kaddr;
        int     status;
 
        if ((status = ntohl(*p++)))
@@ -623,10 +599,7 @@ nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
                return -EIO;
        }
 
-       /* NULL terminate the string we got */
-       kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-       kaddr[len+rcvbuf->page_base] = '\0';
-       kunmap_atomic(kaddr, KM_USER0);
+       xdr_terminate_string(rcvbuf, len);
        return 0;
 }
 
index fabb4f2..ce939c0 100644 (file)
@@ -313,7 +313,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                int flags, struct nameidata *nd)
+                int flags, struct nfs_open_context *ctx)
 {
        struct nfs3_createdata *data;
        mode_t mode = sattr->ia_mode;
@@ -438,19 +438,38 @@ nfs3_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        return 1;
 }
 
+static void
+nfs3_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+       msg->rpc_proc = &nfs3_procedures[NFS3PROC_RENAME];
+}
+
+static int
+nfs3_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+                     struct inode *new_dir)
+{
+       struct nfs_renameres *res;
+
+       if (nfs3_async_handle_jukebox(task, old_dir))
+               return 0;
+       res = task->tk_msg.rpc_resp;
+
+       nfs_post_op_update_inode(old_dir, res->old_fattr);
+       nfs_post_op_update_inode(new_dir, res->new_fattr);
+       return 1;
+}
+
 static int
 nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
                 struct inode *new_dir, struct qstr *new_name)
 {
-       struct nfs3_renameargs  arg = {
-               .fromfh         = NFS_FH(old_dir),
-               .fromname       = old_name->name,
-               .fromlen        = old_name->len,
-               .tofh           = NFS_FH(new_dir),
-               .toname         = new_name->name,
-               .tolen          = new_name->len
+       struct nfs_renameargs   arg = {
+               .old_dir        = NFS_FH(old_dir),
+               .old_name       = old_name,
+               .new_dir        = NFS_FH(new_dir),
+               .new_name       = new_name,
        };
-       struct nfs3_renameres res;
+       struct nfs_renameres res;
        struct rpc_message msg = {
                .rpc_proc       = &nfs3_procedures[NFS3PROC_RENAME],
                .rpc_argp       = &arg,
@@ -460,17 +479,17 @@ nfs3_proc_rename(struct inode *old_dir, struct qstr *old_name,
 
        dprintk("NFS call  rename %s -> %s\n", old_name->name, new_name->name);
 
-       res.fromattr = nfs_alloc_fattr();
-       res.toattr = nfs_alloc_fattr();
-       if (res.fromattr == NULL || res.toattr == NULL)
+       res.old_fattr = nfs_alloc_fattr();
+       res.new_fattr = nfs_alloc_fattr();
+       if (res.old_fattr == NULL || res.new_fattr == NULL)
                goto out;
 
        status = rpc_call_sync(NFS_CLIENT(old_dir), &msg, 0);
-       nfs_post_op_update_inode(old_dir, res.fromattr);
-       nfs_post_op_update_inode(new_dir, res.toattr);
+       nfs_post_op_update_inode(old_dir, res.old_fattr);
+       nfs_post_op_update_inode(new_dir, res.new_fattr);
 out:
-       nfs_free_fattr(res.toattr);
-       nfs_free_fattr(res.fromattr);
+       nfs_free_fattr(res.old_fattr);
+       nfs_free_fattr(res.new_fattr);
        dprintk("NFS reply rename: %d\n", status);
        return status;
 }
@@ -611,7 +630,7 @@ out:
  */
 static int
 nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                 u64 cookie, struct page *page, unsigned int count, int plus)
+                 u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
        __be32                  *verf = NFS_COOKIEVERF(dir);
@@ -621,7 +640,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                .verf           = {verf[0], verf[1]},
                .plus           = plus,
                .count          = count,
-               .pages          = &page
+               .pages          = pages
        };
        struct nfs3_readdirres  res = {
                .verf           = verf,
@@ -652,7 +671,8 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 
        nfs_free_fattr(res.dir_attr);
 out:
-       dprintk("NFS reply readdir: %d\n", status);
+       dprintk("NFS reply readdir%s: %d\n",
+                       plus? "plus" : "", status);
        return status;
 }
 
@@ -722,7 +742,7 @@ nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
        dprintk("NFS call  fsstat\n");
        nfs_fattr_init(stat->fattr);
        status = rpc_call_sync(server->client, &msg, 0);
-       dprintk("NFS reply statfs: %d\n", status);
+       dprintk("NFS reply fsstat: %d\n", status);
        return status;
 }
 
@@ -844,6 +864,8 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .unlink_setup   = nfs3_proc_unlink_setup,
        .unlink_done    = nfs3_proc_unlink_done,
        .rename         = nfs3_proc_rename,
+       .rename_setup   = nfs3_proc_rename_setup,
+       .rename_done    = nfs3_proc_rename_done,
        .link           = nfs3_proc_link,
        .symlink        = nfs3_proc_symlink,
        .mkdir          = nfs3_proc_mkdir,
index 9769704..d9a5e83 100644 (file)
@@ -100,6 +100,13 @@ static const umode_t nfs_type2fmt[] = {
        [NF3FIFO] = S_IFIFO,
 };
 
+static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
+{
+       dprintk("nfs: %s: prematurely hit end of receive buffer. "
+               "Remaining buffer length is %tu words.\n",
+               func, xdr->end - xdr->p);
+}
+
 /*
  * Common NFS XDR functions as inlines
  */
@@ -119,6 +126,29 @@ xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
        return NULL;
 }
 
+static inline __be32 *
+xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
+{
+       __be32 *p;
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       fh->size = ntohl(*p++);
+
+       if (fh->size <= NFS3_FHSIZE) {
+               p = xdr_inline_decode(xdr, fh->size);
+               if (unlikely(!p))
+                       goto out_overflow;
+               memcpy(fh->data, p, fh->size);
+               return p + XDR_QUADLEN(fh->size);
+       }
+       return NULL;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
+}
+
 /*
  * Encode/decode time.
  */
@@ -241,6 +271,26 @@ xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
 }
 
 static inline __be32 *
+xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
+{
+       __be32 *p;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 84);
+               if (unlikely(!p))
+                       goto out_overflow;
+               p = xdr_decode_fattr(p, fattr);
+       }
+       return p;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
+}
+
+static inline __be32 *
 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
 {
        if (*p++)
@@ -442,12 +492,12 @@ nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
  * Encode RENAME arguments
  */
 static int
-nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
+nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
 {
-       p = xdr_encode_fhandle(p, args->fromfh);
-       p = xdr_encode_array(p, args->fromname, args->fromlen);
-       p = xdr_encode_fhandle(p, args->tofh);
-       p = xdr_encode_array(p, args->toname, args->tolen);
+       p = xdr_encode_fhandle(p, args->old_dir);
+       p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
+       p = xdr_encode_fhandle(p, args->new_dir);
+       p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
        req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
        return 0;
 }
@@ -504,9 +554,8 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
        struct kvec *iov = rcvbuf->head;
        struct page **page;
        size_t hdrlen;
-       u32 len, recvd, pglen;
+       u32 recvd, pglen;
        int status, nr = 0;
-       __be32 *entry, *end, *kaddr;
 
        status = ntohl(*p++);
        /* Decode post_op_attrs */
@@ -536,99 +585,38 @@ nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res
        if (pglen > recvd)
                pglen = recvd;
        page = rcvbuf->pages;
-       kaddr = p = kmap_atomic(*page, KM_USER0);
-       end = (__be32 *)((char *)p + pglen);
-       entry = p;
-
-       /* Make sure the packet actually has a value_follows and EOF entry */
-       if ((entry + 1) > end)
-               goto short_pkt;
-
-       for (; *p++; nr++) {
-               if (p + 3 > end)
-                       goto short_pkt;
-               p += 2;                         /* inode # */
-               len = ntohl(*p++);              /* string length */
-               p += XDR_QUADLEN(len) + 2;      /* name + cookie */
-               if (len > NFS3_MAXNAMLEN) {
-                       dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
-                                               len);
-                       goto err_unmap;
-               }
 
-               if (res->plus) {
-                       /* post_op_attr */
-                       if (p + 2 > end)
-                               goto short_pkt;
-                       if (*p++) {
-                               p += 21;
-                               if (p + 1 > end)
-                                       goto short_pkt;
-                       }
-                       /* post_op_fh3 */
-                       if (*p++) {
-                               if (p + 1 > end)
-                                       goto short_pkt;
-                               len = ntohl(*p++);
-                               if (len > NFS3_FHSIZE) {
-                                       dprintk("NFS: giant filehandle in "
-                                               "readdir (len 0x%x)!\n", len);
-                                       goto err_unmap;
-                               }
-                               p += XDR_QUADLEN(len);
-                       }
-               }
-
-               if (p + 2 > end)
-                       goto short_pkt;
-               entry = p;
-       }
-
-       /*
-        * Apparently some server sends responses that are a valid size, but
-        * contain no entries, and have value_follows==0 and EOF==0. For
-        * those, just set the EOF marker.
-        */
-       if (!nr && entry[1] == 0) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
- out:
-       kunmap_atomic(kaddr, KM_USER0);
        return nr;
- short_pkt:
-       /*
-        * When we get a short packet there are 2 possibilities. We can
-        * return an error, or fix up the response to look like a valid
-        * response and return what we have so far. If there are no
-        * entries and the packet was short, then return -EIO. If there
-        * are valid entries in the response, return them and pretend that
-        * the call was successful, but incomplete. The caller can retry the
-        * readdir starting at the last cookie.
-        */
-       entry[0] = entry[1] = 0;
-       if (!nr)
-               nr = -errno_NFSERR_IO;
-       goto out;
-err_unmap:
-       nr = -errno_NFSERR_IO;
-       goto out;
 }
 
 __be32 *
-nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
 {
+       __be32 *p;
        struct nfs_entry old = *entry;
 
-       if (!*p++) {
-               if (!*p)
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (!ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (!ntohl(*p++))
                        return ERR_PTR(-EAGAIN);
                entry->eof = 1;
                return ERR_PTR(-EBADCOOKIE);
        }
 
+       p = xdr_inline_decode(xdr, 12);
+       if (unlikely(!p))
+               goto out_overflow;
        p = xdr_decode_hyper(p, &entry->ino);
        entry->len  = ntohl(*p++);
+
+       p = xdr_inline_decode(xdr, entry->len + 8);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->name = (const char *) p;
        p += XDR_QUADLEN(entry->len);
        entry->prev_cookie = entry->cookie;
@@ -636,10 +624,17 @@ nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
 
        if (plus) {
                entry->fattr->valid = 0;
-               p = xdr_decode_post_op_attr(p, entry->fattr);
+               p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
+               if (IS_ERR(p))
+                       goto out_overflow_exit;
                /* In fact, a post_op_fh3: */
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
                if (*p++) {
-                       p = xdr_decode_fhandle(p, entry->fh);
+                       p = xdr_decode_fhandle_stream(xdr, entry->fh);
+                       if (IS_ERR(p))
+                               goto out_overflow_exit;
                        /* Ugh -- server reply was truncated */
                        if (p == NULL) {
                                dprintk("NFS: FH truncated\n");
@@ -650,8 +645,18 @@ nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
                        memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
        }
 
-       entry->eof = !p[0] && p[1];
+       p = xdr_inline_peek(xdr, 8);
+       if (p != NULL)
+               entry->eof = !p[0] && p[1];
+       else
+               entry->eof = 0;
+
        return p;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+out_overflow_exit:
+       return ERR_PTR(-EIO);
 }
 
 /*
@@ -824,7 +829,6 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
        struct kvec *iov = rcvbuf->head;
        size_t hdrlen;
        u32 len, recvd;
-       char    *kaddr;
        int     status;
 
        status = ntohl(*p++);
@@ -857,10 +861,7 @@ nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
                return -EIO;
        }
 
-       /* NULL terminate the string we got */
-       kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-       kaddr[len+rcvbuf->page_base] = '\0';
-       kunmap_atomic(kaddr, KM_USER0);
+       xdr_terminate_string(rcvbuf, len);
        return 0;
 }
 
@@ -970,14 +971,14 @@ nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
  * Decode RENAME reply
  */
 static int
-nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
+nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
 {
        int     status;
 
        if ((status = ntohl(*p++)) != 0)
                status = nfs_stat_to_errno(status);
-       p = xdr_decode_wcc_data(p, res->fromattr);
-       p = xdr_decode_wcc_data(p, res->toattr);
+       p = xdr_decode_wcc_data(p, res->old_fattr);
+       p = xdr_decode_wcc_data(p, res->new_fattr);
        return status;
 }
 
@@ -1043,8 +1044,9 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
        res->wtmult = ntohl(*p++);
        res->dtpref = ntohl(*p++);
        p = xdr_decode_hyper(p, &res->maxfilesize);
+       p = xdr_decode_time3(p, &res->time_delta);
 
-       /* ignore time_delta and properties */
+       /* ignore properties */
        res->lease_time = 0;
        return 0;
 }
index 311e15c..9fa4963 100644 (file)
@@ -242,8 +242,6 @@ extern int nfs4_proc_renew(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs41_init_clientid(struct nfs_client *, struct rpc_cred *);
 extern int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, int wait);
-extern struct dentry *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
-extern int nfs4_open_revalidate(struct inode *, struct dentry *, int, struct nameidata *);
 extern int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle);
 extern int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
                struct nfs4_fs_locations *fs_locations, struct page *page);
@@ -333,7 +331,7 @@ extern void nfs_free_seqid(struct nfs_seqid *seqid);
 extern const nfs4_stateid zero_stateid;
 
 /* nfs4xdr.c */
-extern __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus);
+extern __be32 *nfs4_decode_dirent(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int);
 extern struct rpc_procinfo nfs4_procedures[];
 
 struct nfs4_mount_data;
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
new file mode 100644 (file)
index 0000000..2e92f0d
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ *  Module for the pnfs nfs4 file layout driver.
+ *  Defines all I/O and Policy interface operations, plus code
+ *  to register itself with the pNFS client.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#include <linux/nfs_fs.h>
+
+#include "internal.h"
+#include "nfs4filelayout.h"
+
+#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Dean Hildebrand <dhildebz@umich.edu>");
+MODULE_DESCRIPTION("The NFSv4 file layout driver");
+
+static int
+filelayout_set_layoutdriver(struct nfs_server *nfss)
+{
+       int status = pnfs_alloc_init_deviceid_cache(nfss->nfs_client,
+                                               nfs4_fl_free_deviceid_callback);
+       if (status) {
+               printk(KERN_WARNING "%s: deviceid cache could not be "
+                       "initialized\n", __func__);
+               return status;
+       }
+       dprintk("%s: deviceid cache has been initialized successfully\n",
+               __func__);
+       return 0;
+}
+
+/* Clear out the layout by destroying its device list */
+static int
+filelayout_clear_layoutdriver(struct nfs_server *nfss)
+{
+       dprintk("--> %s\n", __func__);
+
+       if (nfss->nfs_client->cl_devid_cache)
+               pnfs_put_deviceid_cache(nfss->nfs_client);
+       return 0;
+}
+
+/*
+ * filelayout_check_layout()
+ *
+ * Make sure layout segment parameters are sane WRT the device.
+ * At this point no generic layer initialization of the lseg has occurred,
+ * and nothing has been added to the layout_hdr cache.
+ *
+ */
+static int
+filelayout_check_layout(struct pnfs_layout_hdr *lo,
+                       struct nfs4_filelayout_segment *fl,
+                       struct nfs4_layoutget_res *lgr,
+                       struct nfs4_deviceid *id)
+{
+       struct nfs4_file_layout_dsaddr *dsaddr;
+       int status = -EINVAL;
+       struct nfs_server *nfss = NFS_SERVER(lo->inode);
+
+       dprintk("--> %s\n", __func__);
+
+       if (fl->pattern_offset > lgr->range.offset) {
+               dprintk("%s pattern_offset %lld to large\n",
+                               __func__, fl->pattern_offset);
+               goto out;
+       }
+
+       if (fl->stripe_unit % PAGE_SIZE) {
+               dprintk("%s Stripe unit (%u) not page aligned\n",
+                       __func__, fl->stripe_unit);
+               goto out;
+       }
+
+       /* find and reference the deviceid */
+       dsaddr = nfs4_fl_find_get_deviceid(nfss->nfs_client, id);
+       if (dsaddr == NULL) {
+               dsaddr = get_device_info(lo->inode, id);
+               if (dsaddr == NULL)
+                       goto out;
+       }
+       fl->dsaddr = dsaddr;
+
+       if (fl->first_stripe_index < 0 ||
+           fl->first_stripe_index >= dsaddr->stripe_count) {
+               dprintk("%s Bad first_stripe_index %d\n",
+                               __func__, fl->first_stripe_index);
+               goto out_put;
+       }
+
+       if ((fl->stripe_type == STRIPE_SPARSE &&
+           fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) ||
+           (fl->stripe_type == STRIPE_DENSE &&
+           fl->num_fh != dsaddr->stripe_count)) {
+               dprintk("%s num_fh %u not valid for given packing\n",
+                       __func__, fl->num_fh);
+               goto out_put;
+       }
+
+       if (fl->stripe_unit % nfss->rsize || fl->stripe_unit % nfss->wsize) {
+               dprintk("%s Stripe unit (%u) not aligned with rsize %u "
+                       "wsize %u\n", __func__, fl->stripe_unit, nfss->rsize,
+                       nfss->wsize);
+       }
+
+       status = 0;
+out:
+       dprintk("--> %s returns %d\n", __func__, status);
+       return status;
+out_put:
+       pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache, &dsaddr->deviceid);
+       goto out;
+}
+
+static void filelayout_free_fh_array(struct nfs4_filelayout_segment *fl)
+{
+       int i;
+
+       for (i = 0; i < fl->num_fh; i++) {
+               if (!fl->fh_array[i])
+                       break;
+               kfree(fl->fh_array[i]);
+       }
+       kfree(fl->fh_array);
+       fl->fh_array = NULL;
+}
+
+static void
+_filelayout_free_lseg(struct nfs4_filelayout_segment *fl)
+{
+       filelayout_free_fh_array(fl);
+       kfree(fl);
+}
+
+static int
+filelayout_decode_layout(struct pnfs_layout_hdr *flo,
+                        struct nfs4_filelayout_segment *fl,
+                        struct nfs4_layoutget_res *lgr,
+                        struct nfs4_deviceid *id)
+{
+       uint32_t *p = (uint32_t *)lgr->layout.buf;
+       uint32_t nfl_util;
+       int i;
+
+       dprintk("%s: set_layout_map Begin\n", __func__);
+
+       memcpy(id, p, sizeof(*id));
+       p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE);
+       print_deviceid(id);
+
+       nfl_util = be32_to_cpup(p++);
+       if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS)
+               fl->commit_through_mds = 1;
+       if (nfl_util & NFL4_UFLG_DENSE)
+               fl->stripe_type = STRIPE_DENSE;
+       else
+               fl->stripe_type = STRIPE_SPARSE;
+       fl->stripe_unit = nfl_util & ~NFL4_UFLG_MASK;
+
+       fl->first_stripe_index = be32_to_cpup(p++);
+       p = xdr_decode_hyper(p, &fl->pattern_offset);
+       fl->num_fh = be32_to_cpup(p++);
+
+       dprintk("%s: nfl_util 0x%X num_fh %u fsi %u po %llu\n",
+               __func__, nfl_util, fl->num_fh, fl->first_stripe_index,
+               fl->pattern_offset);
+
+       fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+                              GFP_KERNEL);
+       if (!fl->fh_array)
+               return -ENOMEM;
+
+       for (i = 0; i < fl->num_fh; i++) {
+               /* Do we want to use a mempool here? */
+               fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL);
+               if (!fl->fh_array[i]) {
+                       filelayout_free_fh_array(fl);
+                       return -ENOMEM;
+               }
+               fl->fh_array[i]->size = be32_to_cpup(p++);
+               if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) {
+                       printk(KERN_ERR "Too big fh %d received %d\n",
+                              i, fl->fh_array[i]->size);
+                       filelayout_free_fh_array(fl);
+                       return -EIO;
+               }
+               memcpy(fl->fh_array[i]->data, p, fl->fh_array[i]->size);
+               p += XDR_QUADLEN(fl->fh_array[i]->size);
+               dprintk("DEBUG: %s: fh len %d\n", __func__,
+                       fl->fh_array[i]->size);
+       }
+
+       return 0;
+}
+
+static struct pnfs_layout_segment *
+filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid,
+                     struct nfs4_layoutget_res *lgr)
+{
+       struct nfs4_filelayout_segment *fl;
+       int rc;
+       struct nfs4_deviceid id;
+
+       dprintk("--> %s\n", __func__);
+       fl = kzalloc(sizeof(*fl), GFP_KERNEL);
+       if (!fl)
+               return NULL;
+
+       rc = filelayout_decode_layout(layoutid, fl, lgr, &id);
+       if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id)) {
+               _filelayout_free_lseg(fl);
+               return NULL;
+       }
+       return &fl->generic_hdr;
+}
+
+static void
+filelayout_free_lseg(struct pnfs_layout_segment *lseg)
+{
+       struct nfs_server *nfss = NFS_SERVER(lseg->layout->inode);
+       struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg);
+
+       dprintk("--> %s\n", __func__);
+       pnfs_put_deviceid(nfss->nfs_client->cl_devid_cache,
+                         &fl->dsaddr->deviceid);
+       _filelayout_free_lseg(fl);
+}
+
+static struct pnfs_layoutdriver_type filelayout_type = {
+       .id = LAYOUT_NFSV4_1_FILES,
+       .name = "LAYOUT_NFSV4_1_FILES",
+       .owner = THIS_MODULE,
+       .set_layoutdriver = filelayout_set_layoutdriver,
+       .clear_layoutdriver = filelayout_clear_layoutdriver,
+       .alloc_lseg              = filelayout_alloc_lseg,
+       .free_lseg               = filelayout_free_lseg,
+};
+
+static int __init nfs4filelayout_init(void)
+{
+       printk(KERN_INFO "%s: NFSv4 File Layout Driver Registering...\n",
+              __func__);
+       return pnfs_register_layoutdriver(&filelayout_type);
+}
+
+static void __exit nfs4filelayout_exit(void)
+{
+       printk(KERN_INFO "%s: NFSv4 File Layout Driver Unregistering...\n",
+              __func__);
+       pnfs_unregister_layoutdriver(&filelayout_type);
+}
+
+module_init(nfs4filelayout_init);
+module_exit(nfs4filelayout_exit);
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
new file mode 100644 (file)
index 0000000..bbf60dd
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ *  NFSv4 file layout driver data structures.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#ifndef FS_NFS_NFS4FILELAYOUT_H
+#define FS_NFS_NFS4FILELAYOUT_H
+
+#include "pnfs.h"
+
+/*
+ * Field testing shows we need to support upto 4096 stripe indices.
+ * We store each index as a u8 (u32 on the wire) to keep the memory footprint
+ * reasonable. This in turn means we support a maximum of 256
+ * RFC 5661 multipath_list4 structures.
+ */
+#define NFS4_PNFS_MAX_STRIPE_CNT 4096
+#define NFS4_PNFS_MAX_MULTI_CNT  256 /* 256 fit into a u8 stripe_index */
+
+enum stripetype4 {
+       STRIPE_SPARSE = 1,
+       STRIPE_DENSE = 2
+};
+
+/* Individual ip address */
+struct nfs4_pnfs_ds {
+       struct list_head        ds_node;  /* nfs4_pnfs_dev_hlist dev_dslist */
+       u32                     ds_ip_addr;
+       u32                     ds_port;
+       struct nfs_client       *ds_clp;
+       atomic_t                ds_count;
+};
+
+struct nfs4_file_layout_dsaddr {
+       struct pnfs_deviceid_node       deviceid;
+       u32                             stripe_count;
+       u8                              *stripe_indices;
+       u32                             ds_num;
+       struct nfs4_pnfs_ds             *ds_list[1];
+};
+
+struct nfs4_filelayout_segment {
+       struct pnfs_layout_segment generic_hdr;
+       u32 stripe_type;
+       u32 commit_through_mds;
+       u32 stripe_unit;
+       u32 first_stripe_index;
+       u64 pattern_offset;
+       struct nfs4_file_layout_dsaddr *dsaddr; /* Point to GETDEVINFO data */
+       unsigned int num_fh;
+       struct nfs_fh **fh_array;
+};
+
+static inline struct nfs4_filelayout_segment *
+FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
+{
+       return container_of(lseg,
+                           struct nfs4_filelayout_segment,
+                           generic_hdr);
+}
+
+extern void nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *);
+extern void print_ds(struct nfs4_pnfs_ds *ds);
+extern void print_deviceid(struct nfs4_deviceid *dev_id);
+extern struct nfs4_file_layout_dsaddr *
+nfs4_fl_find_get_deviceid(struct nfs_client *, struct nfs4_deviceid *dev_id);
+struct nfs4_file_layout_dsaddr *
+get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id);
+
+#endif /* FS_NFS_NFS4FILELAYOUT_H */
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
new file mode 100644 (file)
index 0000000..51fe64a
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ *  Device operations for the pnfs nfs4 file layout driver.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *  Garth Goodson   <Garth.Goodson@netapp.com>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#include <linux/nfs_fs.h>
+#include <linux/vmalloc.h>
+
+#include "internal.h"
+#include "nfs4filelayout.h"
+
+#define NFSDBG_FACILITY                NFSDBG_PNFS_LD
+
+/*
+ * Data server cache
+ *
+ * Data servers can be mapped to different device ids.
+ * nfs4_pnfs_ds reference counting
+ *   - set to 1 on allocation
+ *   - incremented when a device id maps a data server already in the cache.
+ *   - decremented when deviceid is removed from the cache.
+ */
+DEFINE_SPINLOCK(nfs4_ds_cache_lock);
+static LIST_HEAD(nfs4_data_server_cache);
+
+/* Debug routines */
+void
+print_ds(struct nfs4_pnfs_ds *ds)
+{
+       if (ds == NULL) {
+               printk("%s NULL device\n", __func__);
+               return;
+       }
+       printk("        ip_addr %x port %hu\n"
+               "        ref count %d\n"
+               "        client %p\n"
+               "        cl_exchange_flags %x\n",
+               ntohl(ds->ds_ip_addr), ntohs(ds->ds_port),
+               atomic_read(&ds->ds_count), ds->ds_clp,
+               ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0);
+}
+
+void
+print_ds_list(struct nfs4_file_layout_dsaddr *dsaddr)
+{
+       int i;
+
+       ifdebug(FACILITY) {
+               printk("%s dsaddr->ds_num %d\n", __func__,
+                      dsaddr->ds_num);
+               for (i = 0; i < dsaddr->ds_num; i++)
+                       print_ds(dsaddr->ds_list[i]);
+       }
+}
+
+void print_deviceid(struct nfs4_deviceid *id)
+{
+       u32 *p = (u32 *)id;
+
+       dprintk("%s: device id= [%x%x%x%x]\n", __func__,
+               p[0], p[1], p[2], p[3]);
+}
+
+/* nfs4_ds_cache_lock is held */
+static struct nfs4_pnfs_ds *
+_data_server_lookup_locked(u32 ip_addr, u32 port)
+{
+       struct nfs4_pnfs_ds *ds;
+
+       dprintk("_data_server_lookup: ip_addr=%x port=%hu\n",
+                       ntohl(ip_addr), ntohs(port));
+
+       list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) {
+               if (ds->ds_ip_addr == ip_addr &&
+                   ds->ds_port == port) {
+                       return ds;
+               }
+       }
+       return NULL;
+}
+
+static void
+destroy_ds(struct nfs4_pnfs_ds *ds)
+{
+       dprintk("--> %s\n", __func__);
+       ifdebug(FACILITY)
+               print_ds(ds);
+
+       if (ds->ds_clp)
+               nfs_put_client(ds->ds_clp);
+       kfree(ds);
+}
+
+static void
+nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)
+{
+       struct nfs4_pnfs_ds *ds;
+       int i;
+
+       print_deviceid(&dsaddr->deviceid.de_id);
+
+       for (i = 0; i < dsaddr->ds_num; i++) {
+               ds = dsaddr->ds_list[i];
+               if (ds != NULL) {
+                       if (atomic_dec_and_lock(&ds->ds_count,
+                                               &nfs4_ds_cache_lock)) {
+                               list_del_init(&ds->ds_node);
+                               spin_unlock(&nfs4_ds_cache_lock);
+                               destroy_ds(ds);
+                       }
+               }
+       }
+       kfree(dsaddr->stripe_indices);
+       kfree(dsaddr);
+}
+
+void
+nfs4_fl_free_deviceid_callback(struct pnfs_deviceid_node *device)
+{
+       struct nfs4_file_layout_dsaddr *dsaddr =
+               container_of(device, struct nfs4_file_layout_dsaddr, deviceid);
+
+       nfs4_fl_free_deviceid(dsaddr);
+}
+
+static struct nfs4_pnfs_ds *
+nfs4_pnfs_ds_add(struct inode *inode, u32 ip_addr, u32 port)
+{
+       struct nfs4_pnfs_ds *tmp_ds, *ds;
+
+       ds = kzalloc(sizeof(*tmp_ds), GFP_KERNEL);
+       if (!ds)
+               goto out;
+
+       spin_lock(&nfs4_ds_cache_lock);
+       tmp_ds = _data_server_lookup_locked(ip_addr, port);
+       if (tmp_ds == NULL) {
+               ds->ds_ip_addr = ip_addr;
+               ds->ds_port = port;
+               atomic_set(&ds->ds_count, 1);
+               INIT_LIST_HEAD(&ds->ds_node);
+               ds->ds_clp = NULL;
+               list_add(&ds->ds_node, &nfs4_data_server_cache);
+               dprintk("%s add new data server ip 0x%x\n", __func__,
+                       ds->ds_ip_addr);
+       } else {
+               kfree(ds);
+               atomic_inc(&tmp_ds->ds_count);
+               dprintk("%s data server found ip 0x%x, inc'ed ds_count to %d\n",
+                       __func__, tmp_ds->ds_ip_addr,
+                       atomic_read(&tmp_ds->ds_count));
+               ds = tmp_ds;
+       }
+       spin_unlock(&nfs4_ds_cache_lock);
+out:
+       return ds;
+}
+
+/*
+ * Currently only support ipv4, and one multi-path address.
+ */
+static struct nfs4_pnfs_ds *
+decode_and_add_ds(__be32 **pp, struct inode *inode)
+{
+       struct nfs4_pnfs_ds *ds = NULL;
+       char *buf;
+       const char *ipend, *pstr;
+       u32 ip_addr, port;
+       int nlen, rlen, i;
+       int tmp[2];
+       __be32 *r_netid, *r_addr, *p = *pp;
+
+       /* r_netid */
+       nlen = be32_to_cpup(p++);
+       r_netid = p;
+       p += XDR_QUADLEN(nlen);
+
+       /* r_addr */
+       rlen = be32_to_cpup(p++);
+       r_addr = p;
+       p += XDR_QUADLEN(rlen);
+       *pp = p;
+
+       /* Check that netid is "tcp" */
+       if (nlen != 3 ||  memcmp((char *)r_netid, "tcp", 3)) {
+               dprintk("%s: ERROR: non ipv4 TCP r_netid\n", __func__);
+               goto out_err;
+       }
+
+       /* ipv6 length plus port is legal */
+       if (rlen > INET6_ADDRSTRLEN + 8) {
+               dprintk("%s Invalid address, length %d\n", __func__,
+                       rlen);
+               goto out_err;
+       }
+       buf = kmalloc(rlen + 1, GFP_KERNEL);
+       buf[rlen] = '\0';
+       memcpy(buf, r_addr, rlen);
+
+       /* replace the port dots with dashes for the in4_pton() delimiter*/
+       for (i = 0; i < 2; i++) {
+               char *res = strrchr(buf, '.');
+               *res = '-';
+       }
+
+       /* Currently only support ipv4 address */
+       if (in4_pton(buf, rlen, (u8 *)&ip_addr, '-', &ipend) == 0) {
+               dprintk("%s: Only ipv4 addresses supported\n", __func__);
+               goto out_free;
+       }
+
+       /* port */
+       pstr = ipend;
+       sscanf(pstr, "-%d-%d", &tmp[0], &tmp[1]);
+       port = htons((tmp[0] << 8) | (tmp[1]));
+
+       ds = nfs4_pnfs_ds_add(inode, ip_addr, port);
+       dprintk("%s Decoded address and port %s\n", __func__, buf);
+out_free:
+       kfree(buf);
+out_err:
+       return ds;
+}
+
+/* Decode opaque device data and return the result */
+static struct nfs4_file_layout_dsaddr*
+decode_device(struct inode *ino, struct pnfs_device *pdev)
+{
+       int i, dummy;
+       u32 cnt, num;
+       u8 *indexp;
+       __be32 *p = (__be32 *)pdev->area, *indicesp;
+       struct nfs4_file_layout_dsaddr *dsaddr;
+
+       /* Get the stripe count (number of stripe index) */
+       cnt = be32_to_cpup(p++);
+       dprintk("%s stripe count  %d\n", __func__, cnt);
+       if (cnt > NFS4_PNFS_MAX_STRIPE_CNT) {
+               printk(KERN_WARNING "%s: stripe count %d greater than "
+                      "supported maximum %d\n", __func__,
+                       cnt, NFS4_PNFS_MAX_STRIPE_CNT);
+               goto out_err;
+       }
+
+       /* Check the multipath list count */
+       indicesp = p;
+       p += XDR_QUADLEN(cnt << 2);
+       num = be32_to_cpup(p++);
+       dprintk("%s ds_num %u\n", __func__, num);
+       if (num > NFS4_PNFS_MAX_MULTI_CNT) {
+               printk(KERN_WARNING "%s: multipath count %d greater than "
+                       "supported maximum %d\n", __func__,
+                       num, NFS4_PNFS_MAX_MULTI_CNT);
+               goto out_err;
+       }
+       dsaddr = kzalloc(sizeof(*dsaddr) +
+                       (sizeof(struct nfs4_pnfs_ds *) * (num - 1)),
+                       GFP_KERNEL);
+       if (!dsaddr)
+               goto out_err;
+
+       dsaddr->stripe_indices = kzalloc(sizeof(u8) * cnt, GFP_KERNEL);
+       if (!dsaddr->stripe_indices)
+               goto out_err_free;
+
+       dsaddr->stripe_count = cnt;
+       dsaddr->ds_num = num;
+
+       memcpy(&dsaddr->deviceid.de_id, &pdev->dev_id, sizeof(pdev->dev_id));
+
+       /* Go back an read stripe indices */
+       p = indicesp;
+       indexp = &dsaddr->stripe_indices[0];
+       for (i = 0; i < dsaddr->stripe_count; i++) {
+               *indexp = be32_to_cpup(p++);
+               if (*indexp >= num)
+                       goto out_err_free;
+               indexp++;
+       }
+       /* Skip already read multipath list count */
+       p++;
+
+       for (i = 0; i < dsaddr->ds_num; i++) {
+               int j;
+
+               dummy = be32_to_cpup(p++); /* multipath count */
+               if (dummy > 1) {
+                       printk(KERN_WARNING
+                              "%s: Multipath count %d not supported, "
+                              "skipping all greater than 1\n", __func__,
+                               dummy);
+               }
+               for (j = 0; j < dummy; j++) {
+                       if (j == 0) {
+                               dsaddr->ds_list[i] = decode_and_add_ds(&p, ino);
+                               if (dsaddr->ds_list[i] == NULL)
+                                       goto out_err_free;
+                       } else {
+                               u32 len;
+                               /* skip extra multipath */
+                               len = be32_to_cpup(p++);
+                               p += XDR_QUADLEN(len);
+                               len = be32_to_cpup(p++);
+                               p += XDR_QUADLEN(len);
+                               continue;
+                       }
+               }
+       }
+       return dsaddr;
+
+out_err_free:
+       nfs4_fl_free_deviceid(dsaddr);
+out_err:
+       dprintk("%s ERROR: returning NULL\n", __func__);
+       return NULL;
+}
+
+/*
+ * Decode the opaque device specified in 'dev'
+ * and add it to the list of available devices.
+ * If the deviceid is already cached, nfs4_add_deviceid will return
+ * a pointer to the cached struct and throw away the new.
+ */
+static struct nfs4_file_layout_dsaddr*
+decode_and_add_device(struct inode *inode, struct pnfs_device *dev)
+{
+       struct nfs4_file_layout_dsaddr *dsaddr;
+       struct pnfs_deviceid_node *d;
+
+       dsaddr = decode_device(inode, dev);
+       if (!dsaddr) {
+               printk(KERN_WARNING "%s: Could not decode or add device\n",
+                       __func__);
+               return NULL;
+       }
+
+       d = pnfs_add_deviceid(NFS_SERVER(inode)->nfs_client->cl_devid_cache,
+                             &dsaddr->deviceid);
+
+       return container_of(d, struct nfs4_file_layout_dsaddr, deviceid);
+}
+
+/*
+ * Retrieve the information for dev_id, add it to the list
+ * of available devices, and return it.
+ */
+struct nfs4_file_layout_dsaddr *
+get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id)
+{
+       struct pnfs_device *pdev = NULL;
+       u32 max_resp_sz;
+       int max_pages;
+       struct page **pages = NULL;
+       struct nfs4_file_layout_dsaddr *dsaddr = NULL;
+       int rc, i;
+       struct nfs_server *server = NFS_SERVER(inode);
+
+       /*
+        * Use the session max response size as the basis for setting
+        * GETDEVICEINFO's maxcount
+        */
+       max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
+       max_pages = max_resp_sz >> PAGE_SHIFT;
+       dprintk("%s inode %p max_resp_sz %u max_pages %d\n",
+               __func__, inode, max_resp_sz, max_pages);
+
+       pdev = kzalloc(sizeof(struct pnfs_device), GFP_KERNEL);
+       if (pdev == NULL)
+               return NULL;
+
+       pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL);
+       if (pages == NULL) {
+               kfree(pdev);
+               return NULL;
+       }
+       for (i = 0; i < max_pages; i++) {
+               pages[i] = alloc_page(GFP_KERNEL);
+               if (!pages[i])
+                       goto out_free;
+       }
+
+       /* set pdev->area */
+       pdev->area = vmap(pages, max_pages, VM_MAP, PAGE_KERNEL);
+       if (!pdev->area)
+               goto out_free;
+
+       memcpy(&pdev->dev_id, dev_id, sizeof(*dev_id));
+       pdev->layout_type = LAYOUT_NFSV4_1_FILES;
+       pdev->pages = pages;
+       pdev->pgbase = 0;
+       pdev->pglen = PAGE_SIZE * max_pages;
+       pdev->mincount = 0;
+
+       rc = nfs4_proc_getdeviceinfo(server, pdev);
+       dprintk("%s getdevice info returns %d\n", __func__, rc);
+       if (rc)
+               goto out_free;
+
+       /*
+        * Found new device, need to decode it and then add it to the
+        * list of known devices for this mountpoint.
+        */
+       dsaddr = decode_and_add_device(inode, pdev);
+out_free:
+       if (pdev->area != NULL)
+               vunmap(pdev->area);
+       for (i = 0; i < max_pages; i++)
+               __free_page(pages[i]);
+       kfree(pages);
+       kfree(pdev);
+       dprintk("<-- %s dsaddr %p\n", __func__, dsaddr);
+       return dsaddr;
+}
+
+struct nfs4_file_layout_dsaddr *
+nfs4_fl_find_get_deviceid(struct nfs_client *clp, struct nfs4_deviceid *id)
+{
+       struct pnfs_deviceid_node *d;
+
+       d = pnfs_find_get_deviceid(clp->cl_devid_cache, id);
+       return (d == NULL) ? NULL :
+               container_of(d, struct nfs4_file_layout_dsaddr, deviceid);
+}
index 089da5b..32c8758 100644 (file)
@@ -55,6 +55,7 @@
 #include "internal.h"
 #include "iostat.h"
 #include "callback.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PROC
 
@@ -129,7 +130,8 @@ const u32 nfs4_fsinfo_bitmap[2] = { FATTR4_WORD0_MAXFILESIZE
                        | FATTR4_WORD0_MAXREAD
                        | FATTR4_WORD0_MAXWRITE
                        | FATTR4_WORD0_LEASE_TIME,
-                       0
+                       FATTR4_WORD1_TIME_DELTA
+                       | FATTR4_WORD1_FS_LAYOUT_TYPES
 };
 
 const u32 nfs4_fs_locations_bitmap[2] = {
@@ -255,9 +257,6 @@ static int nfs4_handle_exception(const struct nfs_server *server, int errorcode,
                        nfs4_state_mark_reclaim_nograce(clp, state);
                        goto do_state_recovery;
                case -NFS4ERR_STALE_STATEID:
-                       if (state == NULL)
-                               break;
-                       nfs4_state_mark_reclaim_reboot(clp, state);
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_EXPIRED:
                        goto do_state_recovery;
@@ -334,10 +333,12 @@ static void renew_lease(const struct nfs_server *server, unsigned long timestamp
  * Must be called while holding tbl->slot_tbl_lock
  */
 static void
-nfs4_free_slot(struct nfs4_slot_table *tbl, u8 free_slotid)
+nfs4_free_slot(struct nfs4_slot_table *tbl, struct nfs4_slot *free_slot)
 {
+       int free_slotid = free_slot - tbl->slots;
        int slotid = free_slotid;
 
+       BUG_ON(slotid < 0 || slotid >= NFS4_MAX_SLOT_TABLE);
        /* clear used bit in bitmap */
        __clear_bit(slotid, tbl->used_slots);
 
@@ -379,7 +380,7 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
        struct nfs4_slot_table *tbl;
 
        tbl = &res->sr_session->fc_slot_table;
-       if (res->sr_slotid == NFS4_MAX_SLOT_TABLE) {
+       if (!res->sr_slot) {
                /* just wake up the next guy waiting since
                 * we may have not consumed a slot after all */
                dprintk("%s: No slot\n", __func__);
@@ -387,17 +388,15 @@ static void nfs41_sequence_free_slot(struct nfs4_sequence_res *res)
        }
 
        spin_lock(&tbl->slot_tbl_lock);
-       nfs4_free_slot(tbl, res->sr_slotid);
+       nfs4_free_slot(tbl, res->sr_slot);
        nfs41_check_drain_session_complete(res->sr_session);
        spin_unlock(&tbl->slot_tbl_lock);
-       res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+       res->sr_slot = NULL;
 }
 
 static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
 {
        unsigned long timestamp;
-       struct nfs4_slot_table *tbl;
-       struct nfs4_slot *slot;
        struct nfs_client *clp;
 
        /*
@@ -410,17 +409,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
                res->sr_status = NFS_OK;
 
        /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
-       if (res->sr_slotid == NFS4_MAX_SLOT_TABLE)
+       if (!res->sr_slot)
                goto out;
 
-       tbl = &res->sr_session->fc_slot_table;
-       slot = tbl->slots + res->sr_slotid;
-
        /* Check the SEQUENCE operation status */
        switch (res->sr_status) {
        case 0:
                /* Update the slot's sequence and clientid lease timer */
-               ++slot->seq_nr;
+               ++res->sr_slot->seq_nr;
                timestamp = res->sr_renewal_time;
                clp = res->sr_session->clp;
                do_renew_lease(clp, timestamp);
@@ -433,12 +429,14 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
                 * returned NFS4ERR_DELAY as per Section 2.10.6.2
                 * of RFC5661.
                 */
-               dprintk("%s: slot=%d seq=%d: Operation in progress\n",
-                               __func__, res->sr_slotid, slot->seq_nr);
+               dprintk("%s: slot=%ld seq=%d: Operation in progress\n",
+                       __func__,
+                       res->sr_slot - res->sr_session->fc_slot_table.slots,
+                       res->sr_slot->seq_nr);
                goto out_retry;
        default:
                /* Just update the slot sequence no. */
-               ++slot->seq_nr;
+               ++res->sr_slot->seq_nr;
        }
 out:
        /* The session may be reset by one of the error handlers. */
@@ -505,10 +503,9 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
 
        dprintk("--> %s\n", __func__);
        /* slot already allocated? */
-       if (res->sr_slotid != NFS4_MAX_SLOT_TABLE)
+       if (res->sr_slot != NULL)
                return 0;
 
-       res->sr_slotid = NFS4_MAX_SLOT_TABLE;
        tbl = &session->fc_slot_table;
 
        spin_lock(&tbl->slot_tbl_lock);
@@ -550,7 +547,7 @@ static int nfs41_setup_sequence(struct nfs4_session *session,
        dprintk("<-- %s slotid=%d seqid=%d\n", __func__, slotid, slot->seq_nr);
 
        res->sr_session = session;
-       res->sr_slotid = slotid;
+       res->sr_slot = slot;
        res->sr_renewal_time = jiffies;
        res->sr_status_flags = 0;
        /*
@@ -576,8 +573,9 @@ int nfs4_setup_sequence(const struct nfs_server *server,
                goto out;
        }
 
-       dprintk("--> %s clp %p session %p sr_slotid %d\n",
-               __func__, session->clp, session, res->sr_slotid);
+       dprintk("--> %s clp %p session %p sr_slot %ld\n",
+               __func__, session->clp, session, res->sr_slot ?
+                       res->sr_slot - session->fc_slot_table.slots : -1);
 
        ret = nfs41_setup_sequence(session, args, res, cache_reply,
                                   task);
@@ -650,7 +648,7 @@ static int nfs4_call_sync_sequence(struct nfs_server *server,
                .callback_data = &data
        };
 
-       res->sr_slotid = NFS4_MAX_SLOT_TABLE;
+       res->sr_slot = NULL;
        if (privileged)
                task_setup.callback_ops = &nfs41_call_priv_sync_ops;
        task = rpc_run_task(&task_setup);
@@ -735,7 +733,6 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p)
        p->o_res.server = p->o_arg.server;
        nfs_fattr_init(&p->f_attr);
        nfs_fattr_init(&p->dir_attr);
-       p->o_res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 }
 
 static struct nfs4_opendata *nfs4_opendata_alloc(struct path *path,
@@ -1120,6 +1117,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
        clear_bit(NFS_DELEGATED_STATE, &state->flags);
        smp_rmb();
        if (state->n_rdwr != 0) {
+               clear_bit(NFS_O_RDWR_STATE, &state->flags);
                ret = nfs4_open_recover_helper(opendata, FMODE_READ|FMODE_WRITE, &newstate);
                if (ret != 0)
                        return ret;
@@ -1127,6 +1125,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
                        return -ESTALE;
        }
        if (state->n_wronly != 0) {
+               clear_bit(NFS_O_WRONLY_STATE, &state->flags);
                ret = nfs4_open_recover_helper(opendata, FMODE_WRITE, &newstate);
                if (ret != 0)
                        return ret;
@@ -1134,6 +1133,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
                        return -ESTALE;
        }
        if (state->n_rdonly != 0) {
+               clear_bit(NFS_O_RDONLY_STATE, &state->flags);
                ret = nfs4_open_recover_helper(opendata, FMODE_READ, &newstate);
                if (ret != 0)
                        return ret;
@@ -1188,7 +1188,7 @@ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state
        int err;
        do {
                err = _nfs4_do_open_reclaim(ctx, state);
-               if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
+               if (err != -NFS4ERR_DELAY)
                        break;
                nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
@@ -1258,6 +1258,13 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state
                        case -NFS4ERR_ADMIN_REVOKED:
                        case -NFS4ERR_BAD_STATEID:
                                nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
+                       case -EKEYEXPIRED:
+                               /*
+                                * User RPCSEC_GSS context has expired.
+                                * We cannot recover this stateid now, so
+                                * skip it and allow recovery thread to
+                                * proceed.
+                                */
                        case -ENOMEM:
                                err = 0;
                                goto out;
@@ -1605,7 +1612,6 @@ static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state
                        goto out;
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
-               case -EKEYEXPIRED:
                        nfs4_handle_exception(server, err, &exception);
                        err = 0;
                }
@@ -1975,7 +1981,6 @@ int nfs4_do_close(struct path *path, struct nfs4_state *state, gfp_t gfp_mask, i
        calldata->res.fattr = &calldata->fattr;
        calldata->res.seqid = calldata->arg.seqid;
        calldata->res.server = server;
-       calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        path_get(path);
        calldata->path = *path;
 
@@ -1998,120 +2003,17 @@ out:
        return status;
 }
 
-static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state, fmode_t fmode)
+static struct inode *
+nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr)
 {
-       struct file *filp;
-       int ret;
-
-       /* If the open_intent is for execute, we have an extra check to make */
-       if (fmode & FMODE_EXEC) {
-               ret = nfs_may_open(state->inode,
-                               state->owner->so_cred,
-                               nd->intent.open.flags);
-               if (ret < 0)
-                       goto out_close;
-       }
-       filp = lookup_instantiate_filp(nd, path->dentry, NULL);
-       if (!IS_ERR(filp)) {
-               struct nfs_open_context *ctx;
-               ctx = nfs_file_open_context(filp);
-               ctx->state = state;
-               return 0;
-       }
-       ret = PTR_ERR(filp);
-out_close:
-       nfs4_close_sync(path, state, fmode & (FMODE_READ|FMODE_WRITE));
-       return ret;
-}
-
-struct dentry *
-nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-       struct path path = {
-               .mnt = nd->path.mnt,
-               .dentry = dentry,
-       };
-       struct dentry *parent;
-       struct iattr attr;
-       struct rpc_cred *cred;
        struct nfs4_state *state;
-       struct dentry *res;
-       int open_flags = nd->intent.open.flags;
-       fmode_t fmode = open_flags & (FMODE_READ | FMODE_WRITE | FMODE_EXEC);
-
-       if (nd->flags & LOOKUP_CREATE) {
-               attr.ia_mode = nd->intent.open.create_mode;
-               attr.ia_valid = ATTR_MODE;
-               if (!IS_POSIXACL(dir))
-                       attr.ia_mode &= ~current_umask();
-       } else {
-               open_flags &= ~O_EXCL;
-               attr.ia_valid = 0;
-               BUG_ON(open_flags & O_CREAT);
-       }
 
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred))
-               return (struct dentry *)cred;
-       parent = dentry->d_parent;
        /* Protect against concurrent sillydeletes */
-       nfs_block_sillyrename(parent);
-       state = nfs4_do_open(dir, &path, fmode, open_flags, &attr, cred);
-       put_rpccred(cred);
-       if (IS_ERR(state)) {
-               if (PTR_ERR(state) == -ENOENT) {
-                       d_add(dentry, NULL);
-                       nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-               }
-               nfs_unblock_sillyrename(parent);
-               return (struct dentry *)state;
-       }
-       res = d_add_unique(dentry, igrab(state->inode));
-       if (res != NULL)
-               path.dentry = res;
-       nfs_set_verifier(path.dentry, nfs_save_change_attribute(dir));
-       nfs_unblock_sillyrename(parent);
-       nfs4_intent_set_file(nd, &path, state, fmode);
-       return res;
-}
-
-int
-nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, struct nameidata *nd)
-{
-       struct path path = {
-               .mnt = nd->path.mnt,
-               .dentry = dentry,
-       };
-       struct rpc_cred *cred;
-       struct nfs4_state *state;
-       fmode_t fmode = openflags & (FMODE_READ | FMODE_WRITE);
-
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred))
-               return PTR_ERR(cred);
-       state = nfs4_do_open(dir, &path, fmode, openflags, NULL, cred);
-       put_rpccred(cred);
-       if (IS_ERR(state)) {
-               switch (PTR_ERR(state)) {
-                       case -EPERM:
-                       case -EACCES:
-                       case -EDQUOT:
-                       case -ENOSPC:
-                       case -EROFS:
-                               return PTR_ERR(state);
-                       default:
-                               goto out_drop;
-               }
-       }
-       if (state->inode == dentry->d_inode) {
-               nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-               nfs4_intent_set_file(nd, &path, state, fmode);
-               return 1;
-       }
-       nfs4_close_sync(&path, state, fmode);
-out_drop:
-       d_drop(dentry);
-       return 0;
+       state = nfs4_do_open(dir, &ctx->path, ctx->mode, open_flags, attr, ctx->cred);
+       if (IS_ERR(state))
+               return ERR_CAST(state);
+       ctx->state = state;
+       return igrab(state->inode);
 }
 
 static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
@@ -2568,36 +2470,34 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
 
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags, struct nameidata *nd)
+                 int flags, struct nfs_open_context *ctx)
 {
-       struct path path = {
-               .mnt = nd->path.mnt,
+       struct path my_path = {
                .dentry = dentry,
        };
+       struct path *path = &my_path;
        struct nfs4_state *state;
-       struct rpc_cred *cred;
-       fmode_t fmode = flags & (FMODE_READ | FMODE_WRITE);
+       struct rpc_cred *cred = NULL;
+       fmode_t fmode = 0;
        int status = 0;
 
-       cred = rpc_lookup_cred();
-       if (IS_ERR(cred)) {
-               status = PTR_ERR(cred);
-               goto out;
+       if (ctx != NULL) {
+               cred = ctx->cred;
+               path = &ctx->path;
+               fmode = ctx->mode;
        }
-       state = nfs4_do_open(dir, &path, fmode, flags, sattr, cred);
+       state = nfs4_do_open(dir, path, fmode, flags, sattr, cred);
        d_drop(dentry);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
-               goto out_putcred;
+               goto out;
        }
        d_add(dentry, igrab(state->inode));
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-       if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
-               status = nfs4_intent_set_file(nd, &path, state, fmode);
+       if (ctx != NULL)
+               ctx->state = state;
        else
-               nfs4_close_sync(&path, state, fmode);
-out_putcred:
-       put_rpccred(cred);
+               nfs4_close_sync(path, state, fmode);
 out:
        return status;
 }
@@ -2655,6 +2555,7 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir)
 
        args->bitmask = server->cache_consistency_bitmask;
        res->server = server;
+       res->seq_res.sr_slot = NULL;
        msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
 }
 
@@ -2671,18 +2572,46 @@ static int nfs4_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        return 1;
 }
 
+static void nfs4_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+       struct nfs_server *server = NFS_SERVER(dir);
+       struct nfs_renameargs *arg = msg->rpc_argp;
+       struct nfs_renameres *res = msg->rpc_resp;
+
+       msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
+       arg->bitmask = server->attr_bitmask;
+       res->server = server;
+}
+
+static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+                                struct inode *new_dir)
+{
+       struct nfs_renameres *res = task->tk_msg.rpc_resp;
+
+       if (!nfs4_sequence_done(task, &res->seq_res))
+               return 0;
+       if (nfs4_async_handle_error(task, res->server, NULL) == -EAGAIN)
+               return 0;
+
+       update_changeattr(old_dir, &res->old_cinfo);
+       nfs_post_op_update_inode(old_dir, res->old_fattr);
+       update_changeattr(new_dir, &res->new_cinfo);
+       nfs_post_op_update_inode(new_dir, res->new_fattr);
+       return 1;
+}
+
 static int _nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name,
                struct inode *new_dir, struct qstr *new_name)
 {
        struct nfs_server *server = NFS_SERVER(old_dir);
-       struct nfs4_rename_arg arg = {
+       struct nfs_renameargs arg = {
                .old_dir = NFS_FH(old_dir),
                .new_dir = NFS_FH(new_dir),
                .old_name = old_name,
                .new_name = new_name,
                .bitmask = server->attr_bitmask,
        };
-       struct nfs4_rename_res res = {
+       struct nfs_renameres res = {
                .server = server,
        };
        struct rpc_message msg = {
@@ -2896,15 +2825,16 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
 }
 
 static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+               u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
        struct nfs4_readdir_arg args = {
                .fh = NFS_FH(dir),
-               .pages = &page,
+               .pages = pages,
                .pgbase = 0,
                .count = count,
                .bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
+               .plus = plus,
        };
        struct nfs4_readdir_res res;
        struct rpc_message msg = {
@@ -2932,14 +2862,14 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
 }
 
 static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                  u64 cookie, struct page *page, unsigned int count, int plus)
+               u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct nfs4_exception exception = { };
        int err;
        do {
                err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode),
                                _nfs4_proc_readdir(dentry, cred, cookie,
-                                       page, count, plus),
+                                       pages, count, plus),
                                &exception);
        } while (exception.retry);
        return err;
@@ -3490,9 +3420,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
                        nfs4_state_mark_reclaim_nograce(clp, state);
                        goto do_state_recovery;
                case -NFS4ERR_STALE_STATEID:
-                       if (state == NULL)
-                               break;
-                       nfs4_state_mark_reclaim_reboot(clp, state);
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_EXPIRED:
                        goto do_state_recovery;
@@ -3626,7 +3553,6 @@ int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
                        case -NFS4ERR_RESOURCE:
                                /* The IBM lawyers misread another document! */
                        case -NFS4ERR_DELAY:
-                       case -EKEYEXPIRED:
                                err = nfs4_delay(clp->cl_rpcclient, &timeout);
                }
        } while (err == 0);
@@ -3721,7 +3647,6 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
        memcpy(&data->stateid, stateid, sizeof(data->stateid));
        data->res.fattr = &data->fattr;
        data->res.server = server;
-       data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        nfs_fattr_init(data->res.fattr);
        data->timestamp = jiffies;
        data->rpc_status = 0;
@@ -3874,7 +3799,6 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
        p->arg.fl = &p->fl;
        p->arg.seqid = seqid;
        p->res.seqid = seqid;
-       p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        p->arg.stateid = &lsp->ls_stateid;
        p->lsp = lsp;
        atomic_inc(&lsp->ls_count);
@@ -4054,7 +3978,6 @@ static struct nfs4_lockdata *nfs4_alloc_lockdata(struct file_lock *fl,
        p->arg.lock_owner.clientid = server->nfs_client->cl_clientid;
        p->arg.lock_owner.id = lsp->ls_id.id;
        p->res.lock_seqid = p->arg.lock_seqid;
-       p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        p->lsp = lsp;
        p->server = server;
        atomic_inc(&lsp->ls_count);
@@ -4241,7 +4164,7 @@ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request
                if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
                        return 0;
                err = _nfs4_do_setlk(state, F_SETLK, request, NFS_LOCK_RECLAIM);
-               if (err != -NFS4ERR_DELAY && err != -EKEYEXPIRED)
+               if (err != -NFS4ERR_DELAY)
                        break;
                nfs4_handle_exception(server, err, &exception);
        } while (exception.retry);
@@ -4266,7 +4189,6 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
                        goto out;
                case -NFS4ERR_GRACE:
                case -NFS4ERR_DELAY:
-               case -EKEYEXPIRED:
                        nfs4_handle_exception(server, err, &exception);
                        err = 0;
                }
@@ -4412,13 +4334,21 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
                                nfs4_state_mark_reclaim_nograce(server->nfs_client, state);
                                err = 0;
                                goto out;
+                       case -EKEYEXPIRED:
+                               /*
+                                * User RPCSEC_GSS context has expired.
+                                * We cannot recover this stateid now, so
+                                * skip it and allow recovery thread to
+                                * proceed.
+                                */
+                               err = 0;
+                               goto out;
                        case -ENOMEM:
                        case -NFS4ERR_DENIED:
                                /* kill_proc(fl->fl_pid, SIGLOST, 1); */
                                err = 0;
                                goto out;
                        case -NFS4ERR_DELAY:
-                       case -EKEYEXPIRED:
                                break;
                }
                err = nfs4_handle_exception(server, err, &exception);
@@ -4647,7 +4577,6 @@ static void nfs4_get_lease_time_done(struct rpc_task *task, void *calldata)
        switch (task->tk_status) {
        case -NFS4ERR_DELAY:
        case -NFS4ERR_GRACE:
-       case -EKEYEXPIRED:
                dprintk("%s Retry: tk_status %d\n", __func__, task->tk_status);
                rpc_delay(task, NFS4_POLL_RETRY_MIN);
                task->tk_status = 0;
@@ -4687,7 +4616,6 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
        };
        int status;
 
-       res.lr_seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        dprintk("--> %s\n", __func__);
        task = rpc_run_task(&task_setup);
 
@@ -4914,49 +4842,56 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
                args->bc_attrs.max_reqs);
 }
 
-static int _verify_channel_attr(char *chan, char *attr_name, u32 sent, u32 rcvd)
+static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
 {
-       if (rcvd <= sent)
-               return 0;
-       printk(KERN_WARNING "%s: Session INVALID: %s channel %s increased. "
-               "sent=%u rcvd=%u\n", __func__, chan, attr_name, sent, rcvd);
-       return -EINVAL;
+       struct nfs4_channel_attrs *sent = &args->fc_attrs;
+       struct nfs4_channel_attrs *rcvd = &session->fc_attrs;
+
+       if (rcvd->headerpadsz > sent->headerpadsz)
+               return -EINVAL;
+       if (rcvd->max_resp_sz > sent->max_resp_sz)
+               return -EINVAL;
+       /*
+        * Our requested max_ops is the minimum we need; we're not
+        * prepared to break up compounds into smaller pieces than that.
+        * So, no point even trying to continue if the server won't
+        * cooperate:
+        */
+       if (rcvd->max_ops < sent->max_ops)
+               return -EINVAL;
+       if (rcvd->max_reqs == 0)
+               return -EINVAL;
+       return 0;
 }
 
-#define _verify_fore_channel_attr(_name_) \
-       _verify_channel_attr("fore", #_name_, \
-                            args->fc_attrs._name_, \
-                            session->fc_attrs._name_)
+static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args, struct nfs4_session *session)
+{
+       struct nfs4_channel_attrs *sent = &args->bc_attrs;
+       struct nfs4_channel_attrs *rcvd = &session->bc_attrs;
 
-#define _verify_back_channel_attr(_name_) \
-       _verify_channel_attr("back", #_name_, \
-                            args->bc_attrs._name_, \
-                            session->bc_attrs._name_)
+       if (rcvd->max_rqst_sz > sent->max_rqst_sz)
+               return -EINVAL;
+       if (rcvd->max_resp_sz < sent->max_resp_sz)
+               return -EINVAL;
+       if (rcvd->max_resp_sz_cached > sent->max_resp_sz_cached)
+               return -EINVAL;
+       /* These would render the backchannel useless: */
+       if (rcvd->max_ops  == 0)
+               return -EINVAL;
+       if (rcvd->max_reqs == 0)
+               return -EINVAL;
+       return 0;
+}
 
-/*
- * The server is not allowed to increase the fore channel header pad size,
- * maximum response size, or maximum number of operations.
- *
- * The back channel attributes are only negotiatied down: We send what the
- * (back channel) server insists upon.
- */
 static int nfs4_verify_channel_attrs(struct nfs41_create_session_args *args,
                                     struct nfs4_session *session)
 {
-       int ret = 0;
-
-       ret |= _verify_fore_channel_attr(headerpadsz);
-       ret |= _verify_fore_channel_attr(max_resp_sz);
-       ret |= _verify_fore_channel_attr(max_ops);
-
-       ret |= _verify_back_channel_attr(headerpadsz);
-       ret |= _verify_back_channel_attr(max_rqst_sz);
-       ret |= _verify_back_channel_attr(max_resp_sz);
-       ret |= _verify_back_channel_attr(max_resp_sz_cached);
-       ret |= _verify_back_channel_attr(max_ops);
-       ret |= _verify_back_channel_attr(max_reqs);
+       int ret;
 
-       return ret;
+       ret = nfs4_verify_fore_channel_attrs(args, session);
+       if (ret)
+               return ret;
+       return nfs4_verify_back_channel_attrs(args, session);
 }
 
 static int _nfs4_proc_create_session(struct nfs_client *clp)
@@ -5111,7 +5046,6 @@ static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client
 {
        switch(task->tk_status) {
        case -NFS4ERR_DELAY:
-       case -EKEYEXPIRED:
                rpc_delay(task, NFS4_POLL_RETRY_MAX);
                return -EAGAIN;
        default:
@@ -5180,12 +5114,11 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_
 
        if (!atomic_inc_not_zero(&clp->cl_count))
                return ERR_PTR(-EIO);
-       calldata = kmalloc(sizeof(*calldata), GFP_NOFS);
+       calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
        if (calldata == NULL) {
                nfs_put_client(clp);
                return ERR_PTR(-ENOMEM);
        }
-       calldata->res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        msg.rpc_argp = &calldata->args;
        msg.rpc_resp = &calldata->res;
        calldata->clp = clp;
@@ -5254,7 +5187,6 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
        case -NFS4ERR_WRONG_CRED: /* What to do here? */
                break;
        case -NFS4ERR_DELAY:
-       case -EKEYEXPIRED:
                rpc_delay(task, NFS4_POLL_RETRY_MAX);
                return -EAGAIN;
        default:
@@ -5317,7 +5249,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp)
                goto out;
        calldata->clp = clp;
        calldata->arg.one_fs = 0;
-       calldata->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
 
        msg.rpc_argp = &calldata->arg;
        msg.rpc_resp = &calldata->res;
@@ -5333,6 +5264,147 @@ out:
        dprintk("<-- %s status=%d\n", __func__, status);
        return status;
 }
+
+static void
+nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
+{
+       struct nfs4_layoutget *lgp = calldata;
+       struct inode *ino = lgp->args.inode;
+       struct nfs_server *server = NFS_SERVER(ino);
+
+       dprintk("--> %s\n", __func__);
+       if (nfs4_setup_sequence(server, &lgp->args.seq_args,
+                               &lgp->res.seq_res, 0, task))
+               return;
+       rpc_call_start(task);
+}
+
+static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
+{
+       struct nfs4_layoutget *lgp = calldata;
+       struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+
+       dprintk("--> %s\n", __func__);
+
+       if (!nfs4_sequence_done(task, &lgp->res.seq_res))
+               return;
+
+       switch (task->tk_status) {
+       case 0:
+               break;
+       case -NFS4ERR_LAYOUTTRYLATER:
+       case -NFS4ERR_RECALLCONFLICT:
+               task->tk_status = -NFS4ERR_DELAY;
+               /* Fall through */
+       default:
+               if (nfs4_async_handle_error(task, server, NULL) == -EAGAIN) {
+                       rpc_restart_call_prepare(task);
+                       return;
+               }
+       }
+       lgp->status = task->tk_status;
+       dprintk("<-- %s\n", __func__);
+}
+
+static void nfs4_layoutget_release(void *calldata)
+{
+       struct nfs4_layoutget *lgp = calldata;
+
+       dprintk("--> %s\n", __func__);
+       put_layout_hdr(lgp->args.inode);
+       if (lgp->res.layout.buf != NULL)
+               free_page((unsigned long) lgp->res.layout.buf);
+       put_nfs_open_context(lgp->args.ctx);
+       kfree(calldata);
+       dprintk("<-- %s\n", __func__);
+}
+
+static const struct rpc_call_ops nfs4_layoutget_call_ops = {
+       .rpc_call_prepare = nfs4_layoutget_prepare,
+       .rpc_call_done = nfs4_layoutget_done,
+       .rpc_release = nfs4_layoutget_release,
+};
+
+int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
+{
+       struct nfs_server *server = NFS_SERVER(lgp->args.inode);
+       struct rpc_task *task;
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
+               .rpc_argp = &lgp->args,
+               .rpc_resp = &lgp->res,
+       };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_client = server->client,
+               .rpc_message = &msg,
+               .callback_ops = &nfs4_layoutget_call_ops,
+               .callback_data = lgp,
+               .flags = RPC_TASK_ASYNC,
+       };
+       int status = 0;
+
+       dprintk("--> %s\n", __func__);
+
+       lgp->res.layout.buf = (void *)__get_free_page(GFP_NOFS);
+       if (lgp->res.layout.buf == NULL) {
+               nfs4_layoutget_release(lgp);
+               return -ENOMEM;
+       }
+
+       lgp->res.seq_res.sr_slot = NULL;
+       task = rpc_run_task(&task_setup_data);
+       if (IS_ERR(task))
+               return PTR_ERR(task);
+       status = nfs4_wait_for_completion_rpc_task(task);
+       if (status != 0)
+               goto out;
+       status = lgp->status;
+       if (status != 0)
+               goto out;
+       status = pnfs_layout_process(lgp);
+out:
+       rpc_put_task(task);
+       dprintk("<-- %s status=%d\n", __func__, status);
+       return status;
+}
+
+static int
+_nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
+{
+       struct nfs4_getdeviceinfo_args args = {
+               .pdev = pdev,
+       };
+       struct nfs4_getdeviceinfo_res res = {
+               .pdev = pdev,
+       };
+       struct rpc_message msg = {
+               .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETDEVICEINFO],
+               .rpc_argp = &args,
+               .rpc_resp = &res,
+       };
+       int status;
+
+       dprintk("--> %s\n", __func__);
+       status = nfs4_call_sync(server, &msg, &args, &res, 0);
+       dprintk("<-- %s status=%d\n", __func__, status);
+
+       return status;
+}
+
+int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *pdev)
+{
+       struct nfs4_exception exception = { };
+       int err;
+
+       do {
+               err = nfs4_handle_exception(server,
+                                       _nfs4_proc_getdeviceinfo(server, pdev),
+                                       &exception);
+       } while (exception.retry);
+       return err;
+}
+EXPORT_SYMBOL_GPL(nfs4_proc_getdeviceinfo);
+
 #endif /* CONFIG_NFS_V4_1 */
 
 struct nfs4_state_recovery_ops nfs40_reboot_recovery_ops = {
@@ -5443,6 +5515,8 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .unlink_setup   = nfs4_proc_unlink_setup,
        .unlink_done    = nfs4_proc_unlink_done,
        .rename         = nfs4_proc_rename,
+       .rename_setup   = nfs4_proc_rename_setup,
+       .rename_done    = nfs4_proc_rename_done,
        .link           = nfs4_proc_link,
        .symlink        = nfs4_proc_symlink,
        .mkdir          = nfs4_proc_mkdir,
@@ -5463,6 +5537,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .lock           = nfs4_proc_lock,
        .clear_acl_cache = nfs4_zap_acl_attr,
        .close_context  = nfs4_close_context,
+       .open_context   = nfs4_atomic_open,
 };
 
 /*
index 96524c5..f575a31 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/kthread.h>
 #include <linux/module.h>
 #include <linux/random.h>
+#include <linux/ratelimit.h>
 #include <linux/workqueue.h>
 #include <linux/bitops.h>
 
@@ -53,6 +54,7 @@
 #include "callback.h"
 #include "delegation.h"
 #include "internal.h"
+#include "pnfs.h"
 
 #define OPENOWNER_POOL_SIZE    8
 
@@ -1063,6 +1065,14 @@ restart:
                                /* Mark the file as being 'closed' */
                                state->state = 0;
                                break;
+                       case -EKEYEXPIRED:
+                               /*
+                                * User RPCSEC_GSS context has expired.
+                                * We cannot recover this stateid now, so
+                                * skip it and allow recovery thread to
+                                * proceed.
+                                */
+                               break;
                        case -NFS4ERR_ADMIN_REVOKED:
                        case -NFS4ERR_STALE_STATEID:
                        case -NFS4ERR_BAD_STATEID:
@@ -1138,16 +1148,14 @@ static void nfs4_reclaim_complete(struct nfs_client *clp,
                (void)ops->reclaim_complete(clp);
 }
 
-static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+static int nfs4_state_clear_reclaim_reboot(struct nfs_client *clp)
 {
        struct nfs4_state_owner *sp;
        struct rb_node *pos;
        struct nfs4_state *state;
 
        if (!test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
-               return;
-
-       nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
+               return 0;
 
        for (pos = rb_first(&clp->cl_state_owners); pos != NULL; pos = rb_next(pos)) {
                sp = rb_entry(pos, struct nfs4_state_owner, so_client_node);
@@ -1161,6 +1169,14 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
        }
 
        nfs_delegation_reap_unclaimed(clp);
+       return 1;
+}
+
+static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
+{
+       if (!nfs4_state_clear_reclaim_reboot(clp))
+               return;
+       nfs4_reclaim_complete(clp, clp->cl_mvops->reboot_recovery_ops);
 }
 
 static void nfs_delegation_clear_all(struct nfs_client *clp)
@@ -1175,6 +1191,14 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
        nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
 }
 
+static void nfs4_warn_keyexpired(const char *s)
+{
+       printk_ratelimited(KERN_WARNING "Error: state manager"
+                       " encountered RPCSEC_GSS session"
+                       " expired against NFSv4 server %s.\n",
+                       s);
+}
+
 static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
 {
        switch (error) {
@@ -1187,7 +1211,7 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                case -NFS4ERR_STALE_CLIENTID:
                case -NFS4ERR_LEASE_MOVED:
                        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-                       nfs4_state_end_reclaim_reboot(clp);
+                       nfs4_state_clear_reclaim_reboot(clp);
                        nfs4_state_start_reclaim_reboot(clp);
                        break;
                case -NFS4ERR_EXPIRED:
@@ -1204,6 +1228,10 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                        set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
                        /* Zero session reset errors */
                        return 0;
+               case -EKEYEXPIRED:
+                       /* Nothing we can do */
+                       nfs4_warn_keyexpired(clp->cl_hostname);
+                       return 0;
        }
        return error;
 }
@@ -1414,9 +1442,10 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
                case -NFS4ERR_DELAY:
                case -NFS4ERR_CLID_INUSE:
                case -EAGAIN:
-               case -EKEYEXPIRED:
                        break;
 
+               case -EKEYEXPIRED:
+                       nfs4_warn_keyexpired(clp->cl_hostname);
                case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
                                         * in nfs4_exchange_id */
                default:
@@ -1447,6 +1476,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                        }
                        clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state);
                        set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
+                       pnfs_destroy_all_layouts(clp);
                }
 
                if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
index 08ef912..f313c4c 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/nfs_idmap.h>
 #include "nfs4_fs.h"
 #include "internal.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_XDR
 
@@ -310,6 +311,19 @@ static int nfs4_stat_to_errno(int);
                                XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
 #define encode_reclaim_complete_maxsz  (op_encode_hdr_maxsz + 4)
 #define decode_reclaim_complete_maxsz  (op_decode_hdr_maxsz + 4)
+#define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + 4 + \
+                               XDR_QUADLEN(NFS4_DEVICEID4_SIZE))
+#define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
+                               1 /* layout type */ + \
+                               1 /* opaque devaddr4 length */ + \
+                                 /* devaddr4 payload is read into page */ \
+                               1 /* notification bitmap length */ + \
+                               1 /* notification bitmap */)
+#define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \
+                               encode_stateid_maxsz)
+#define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \
+                               decode_stateid_maxsz + \
+                               XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE))
 #else /* CONFIG_NFS_V4_1 */
 #define encode_sequence_maxsz  0
 #define decode_sequence_maxsz  0
@@ -699,6 +713,20 @@ static int nfs4_stat_to_errno(int);
 #define NFS4_dec_reclaim_complete_sz   (compound_decode_hdr_maxsz + \
                                         decode_sequence_maxsz + \
                                         decode_reclaim_complete_maxsz)
+#define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz +    \
+                               encode_sequence_maxsz +\
+                               encode_getdeviceinfo_maxsz)
+#define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz +    \
+                               decode_sequence_maxsz + \
+                               decode_getdeviceinfo_maxsz)
+#define NFS4_enc_layoutget_sz  (compound_encode_hdr_maxsz + \
+                               encode_sequence_maxsz + \
+                               encode_putfh_maxsz +        \
+                               encode_layoutget_maxsz)
+#define NFS4_dec_layoutget_sz  (compound_decode_hdr_maxsz + \
+                               decode_sequence_maxsz + \
+                               decode_putfh_maxsz +        \
+                               decode_layoutget_maxsz)
 
 const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
                                      compound_encode_hdr_maxsz +
@@ -816,7 +844,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
        if (iap->ia_valid & ATTR_MODE)
                len += 4;
        if (iap->ia_valid & ATTR_UID) {
-               owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name);
+               owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name, IDMAP_NAMESZ);
                if (owner_namelen < 0) {
                        dprintk("nfs: couldn't resolve uid %d to string\n",
                                        iap->ia_uid);
@@ -828,7 +856,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const
                len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
        }
        if (iap->ia_valid & ATTR_GID) {
-               owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group);
+               owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group, IDMAP_NAMESZ);
                if (owner_grouplen < 0) {
                        dprintk("nfs: couldn't resolve gid %d to string\n",
                                        iap->ia_gid);
@@ -1385,24 +1413,35 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
 
 static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
 {
-       uint32_t attrs[2] = {
-               FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
-               FATTR4_WORD1_MOUNTED_ON_FILEID,
-       };
+       uint32_t attrs[2] = {0, 0};
+       uint32_t dircount = readdir->count >> 1;
        __be32 *p;
 
+       if (readdir->plus) {
+               attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
+                       FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE;
+               attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
+                       FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
+                       FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
+                       FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
+               dircount >>= 1;
+       }
+       attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID;
+       attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
+       /* Switch to mounted_on_fileid if the server supports it */
+       if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
+               attrs[0] &= ~FATTR4_WORD0_FILEID;
+       else
+               attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+
        p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
        *p++ = cpu_to_be32(OP_READDIR);
        p = xdr_encode_hyper(p, readdir->cookie);
        p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
-       *p++ = cpu_to_be32(readdir->count >> 1);  /* We're not doing readdirplus */
+       *p++ = cpu_to_be32(dircount);
        *p++ = cpu_to_be32(readdir->count);
        *p++ = cpu_to_be32(2);
-       /* Switch to mounted_on_fileid if the server supports it */
-       if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
-               attrs[0] &= ~FATTR4_WORD0_FILEID;
-       else
-               attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+
        *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
        *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
        hdr->nops++;
@@ -1726,6 +1765,58 @@ static void encode_sequence(struct xdr_stream *xdr,
 #endif /* CONFIG_NFS_V4_1 */
 }
 
+#ifdef CONFIG_NFS_V4_1
+static void
+encode_getdeviceinfo(struct xdr_stream *xdr,
+                    const struct nfs4_getdeviceinfo_args *args,
+                    struct compound_hdr *hdr)
+{
+       __be32 *p;
+
+       p = reserve_space(xdr, 16 + NFS4_DEVICEID4_SIZE);
+       *p++ = cpu_to_be32(OP_GETDEVICEINFO);
+       p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data,
+                                   NFS4_DEVICEID4_SIZE);
+       *p++ = cpu_to_be32(args->pdev->layout_type);
+       *p++ = cpu_to_be32(args->pdev->pglen);          /* gdia_maxcount */
+       *p++ = cpu_to_be32(0);                          /* bitmap length 0 */
+       hdr->nops++;
+       hdr->replen += decode_getdeviceinfo_maxsz;
+}
+
+static void
+encode_layoutget(struct xdr_stream *xdr,
+                     const struct nfs4_layoutget_args *args,
+                     struct compound_hdr *hdr)
+{
+       nfs4_stateid stateid;
+       __be32 *p;
+
+       p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE);
+       *p++ = cpu_to_be32(OP_LAYOUTGET);
+       *p++ = cpu_to_be32(0);     /* Signal layout available */
+       *p++ = cpu_to_be32(args->type);
+       *p++ = cpu_to_be32(args->range.iomode);
+       p = xdr_encode_hyper(p, args->range.offset);
+       p = xdr_encode_hyper(p, args->range.length);
+       p = xdr_encode_hyper(p, args->minlength);
+       pnfs_get_layout_stateid(&stateid, NFS_I(args->inode)->layout,
+                               args->ctx->state);
+       p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE);
+       *p = cpu_to_be32(args->maxcount);
+
+       dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n",
+               __func__,
+               args->type,
+               args->range.iomode,
+               (unsigned long)args->range.offset,
+               (unsigned long)args->range.length,
+               args->maxcount);
+       hdr->nops++;
+       hdr->replen += decode_layoutget_maxsz;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
 /*
  * END OF "GENERIC" ENCODE ROUTINES.
  */
@@ -1823,7 +1914,7 @@ static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs
 /*
  * Encode RENAME request
  */
-static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args)
+static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs_renameargs *args)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr = {
@@ -2543,6 +2634,51 @@ static int nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, uint32_t *p,
        return 0;
 }
 
+/*
+ * Encode GETDEVICEINFO request
+ */
+static int nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req, uint32_t *p,
+                                     struct nfs4_getdeviceinfo_args *args)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr = {
+               .minorversion = nfs4_xdr_minorversion(&args->seq_args),
+       };
+
+       xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+       encode_compound_hdr(&xdr, req, &hdr);
+       encode_sequence(&xdr, &args->seq_args, &hdr);
+       encode_getdeviceinfo(&xdr, args, &hdr);
+
+       /* set up reply kvec. Subtract notification bitmap max size (2)
+        * so that notification bitmap is put in xdr_buf tail */
+       xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2,
+                        args->pdev->pages, args->pdev->pgbase,
+                        args->pdev->pglen);
+
+       encode_nops(&hdr);
+       return 0;
+}
+
+/*
+ *  Encode LAYOUTGET request
+ */
+static int nfs4_xdr_enc_layoutget(struct rpc_rqst *req, uint32_t *p,
+                                 struct nfs4_layoutget_args *args)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr = {
+               .minorversion = nfs4_xdr_minorversion(&args->seq_args),
+       };
+
+       xdr_init_encode(&xdr, &req->rq_snd_buf, p);
+       encode_compound_hdr(&xdr, req, &hdr);
+       encode_sequence(&xdr, &args->seq_args, &hdr);
+       encode_putfh(&xdr, NFS_FH(args->inode), &hdr);
+       encode_layoutget(&xdr, args, &hdr);
+       encode_nops(&hdr);
+       return 0;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
@@ -2676,7 +2812,10 @@ out_overflow:
 static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
 {
        if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
-               decode_attr_bitmap(xdr, bitmask);
+               int ret;
+               ret = decode_attr_bitmap(xdr, bitmask);
+               if (unlikely(ret < 0))
+                       return ret;
                bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
        } else
                bitmask[0] = bitmask[1] = 0;
@@ -2848,6 +2987,56 @@ out_overflow:
        return -EIO;
 }
 
+static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
+{
+       __be32 *p;
+
+       if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U)))
+               return -EIO;
+       if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
+       }
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
+static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
+{
+       __be32 *p;
+       int len;
+
+       if (fh != NULL)
+               memset(fh, 0, sizeof(*fh));
+
+       if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U)))
+               return -EIO;
+       if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               len = be32_to_cpup(p);
+               if (len > NFS4_FHSIZE)
+                       return -EIO;
+               p = xdr_inline_decode(xdr, len);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (fh != NULL) {
+                       memcpy(fh->data, p, len);
+                       fh->size = len;
+               }
+               bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
+       }
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
 static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
 {
        __be32 *p;
@@ -3521,6 +3710,24 @@ static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, s
        return status;
 }
 
+static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap,
+                                 struct timespec *time)
+{
+       int status = 0;
+
+       time->tv_sec = 0;
+       time->tv_nsec = 0;
+       if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U)))
+               return -EIO;
+       if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) {
+               status = decode_attr_time(xdr, time);
+               bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA;
+       }
+       dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec,
+               (long)time->tv_nsec);
+       return status;
+}
+
 static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
 {
        int status = 0;
@@ -3744,29 +3951,14 @@ xdr_error:
        return status;
 }
 
-static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
+               struct nfs_fattr *fattr, struct nfs_fh *fh,
                const struct nfs_server *server, int may_sleep)
 {
-       __be32 *savep;
-       uint32_t attrlen,
-                bitmap[2] = {0},
-                type;
        int status;
        umode_t fmode = 0;
        uint64_t fileid;
-
-       status = decode_op_hdr(xdr, OP_GETATTR);
-       if (status < 0)
-               goto xdr_error;
-
-       status = decode_attr_bitmap(xdr, bitmap);
-       if (status < 0)
-               goto xdr_error;
-
-       status = decode_attr_length(xdr, &attrlen, &savep);
-       if (status < 0)
-               goto xdr_error;
-
+       uint32_t type;
 
        status = decode_attr_type(xdr, bitmap, &type);
        if (status < 0)
@@ -3792,6 +3984,14 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
                goto xdr_error;
        fattr->valid |= status;
 
+       status = decode_attr_error(xdr, bitmap);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_attr_filehandle(xdr, bitmap, fh);
+       if (status < 0)
+               goto xdr_error;
+
        status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
        if (status < 0)
                goto xdr_error;
@@ -3862,12 +4062,101 @@ static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
                fattr->valid |= status;
        }
 
+xdr_error:
+       dprintk("%s: xdr returned %d\n", __func__, -status);
+       return status;
+}
+
+static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+               struct nfs_fh *fh, const struct nfs_server *server, int may_sleep)
+{
+       __be32 *savep;
+       uint32_t attrlen,
+                bitmap[2] = {0};
+       int status;
+
+       status = decode_op_hdr(xdr, OP_GETATTR);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_attr_bitmap(xdr, bitmap);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_attr_length(xdr, &attrlen, &savep);
+       if (status < 0)
+               goto xdr_error;
+
+       status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep);
+       if (status < 0)
+               goto xdr_error;
+
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
        dprintk("%s: xdr returned %d\n", __func__, -status);
        return status;
 }
 
+static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
+               const struct nfs_server *server, int may_sleep)
+{
+       return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep);
+}
+
+/*
+ * Decode potentially multiple layout types. Currently we only support
+ * one layout driver per file system.
+ */
+static int decode_first_pnfs_layout_type(struct xdr_stream *xdr,
+                                        uint32_t *layouttype)
+{
+       uint32_t *p;
+       int num;
+
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       num = be32_to_cpup(p);
+
+       /* pNFS is not supported by the underlying file system */
+       if (num == 0) {
+               *layouttype = 0;
+               return 0;
+       }
+       if (num > 1)
+               printk(KERN_INFO "%s: Warning: Multiple pNFS layout drivers "
+                       "per filesystem not supported\n", __func__);
+
+       /* Decode and set first layout type, move xdr->p past unused types */
+       p = xdr_inline_decode(xdr, num * 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       *layouttype = be32_to_cpup(p);
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
+/*
+ * The type of file system exported.
+ * Note we must ensure that layouttype is set in any non-error case.
+ */
+static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
+                               uint32_t *layouttype)
+{
+       int status = 0;
+
+       dprintk("%s: bitmap is %x\n", __func__, bitmap[1]);
+       if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U)))
+               return -EIO;
+       if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) {
+               status = decode_first_pnfs_layout_type(xdr, layouttype);
+               bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES;
+       } else
+               *layouttype = 0;
+       return status;
+}
 
 static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
 {
@@ -3894,6 +4183,12 @@ static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
        if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
                goto xdr_error;
        fsinfo->wtpref = fsinfo->wtmax;
+       status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
+       if (status != 0)
+               goto xdr_error;
+       status = decode_attr_pnfstype(xdr, bitmap, &fsinfo->layouttype);
+       if (status != 0)
+               goto xdr_error;
 
        status = verify_attr_len(xdr, savep, attrlen);
 xdr_error:
@@ -3950,13 +4245,13 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
        __be32 *p;
        uint32_t namelen, type;
 
-       p = xdr_inline_decode(xdr, 32);
+       p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
        if (unlikely(!p))
                goto out_overflow;
-       p = xdr_decode_hyper(p, &offset);
+       p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
        p = xdr_decode_hyper(p, &length);
-       type = be32_to_cpup(p++);
-       if (fl != NULL) {
+       type = be32_to_cpup(p++); /* 4 byte read */
+       if (fl != NULL) { /* manipulate file lock */
                fl->fl_start = (loff_t)offset;
                fl->fl_end = fl->fl_start + (loff_t)length - 1;
                if (length == ~(uint64_t)0)
@@ -3966,9 +4261,9 @@ static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
                        fl->fl_type = F_RDLCK;
                fl->fl_pid = 0;
        }
-       p = xdr_decode_hyper(p, &clientid);
-       namelen = be32_to_cpup(p);
-       p = xdr_inline_decode(xdr, namelen);
+       p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
+       namelen = be32_to_cpup(p); /* read 4 bytes */  /* have read all 32 bytes now */
+       p = xdr_inline_decode(xdr, namelen); /* variable size field */
        if (likely(p))
                return -NFS4ERR_DENIED;
 out_overflow:
@@ -4200,12 +4495,9 @@ out_overflow:
 static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
 {
        struct xdr_buf  *rcvbuf = &req->rq_rcv_buf;
-       struct page     *page = *rcvbuf->pages;
        struct kvec     *iov = rcvbuf->head;
        size_t          hdrlen;
        u32             recvd, pglen = rcvbuf->page_len;
-       __be32          *end, *entry, *p, *kaddr;
-       unsigned int    nr = 0;
        int             status;
 
        status = decode_op_hdr(xdr, OP_READDIR);
@@ -4225,71 +4517,8 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n
                pglen = recvd;
        xdr_read_pages(xdr, pglen);
 
-       BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
-       kaddr = p = kmap_atomic(page, KM_USER0);
-       end = p + ((pglen + readdir->pgbase) >> 2);
-       entry = p;
-
-       /* Make sure the packet actually has a value_follows and EOF entry */
-       if ((entry + 1) > end)
-               goto short_pkt;
-
-       for (; *p++; nr++) {
-               u32 len, attrlen, xlen;
-               if (end - p < 3)
-                       goto short_pkt;
-               dprintk("cookie = %Lu, ", *((unsigned long long *)p));
-               p += 2;                 /* cookie */
-               len = ntohl(*p++);      /* filename length */
-               if (len > NFS4_MAXNAMLEN) {
-                       dprintk("NFS: giant filename in readdir (len 0x%x)\n",
-                                       len);
-                       goto err_unmap;
-               }
-               xlen = XDR_QUADLEN(len);
-               if (end - p < xlen + 1)
-                       goto short_pkt;
-               dprintk("filename = %*s\n", len, (char *)p);
-               p += xlen;
-               len = ntohl(*p++);      /* bitmap length */
-               if (end - p < len + 1)
-                       goto short_pkt;
-               p += len;
-               attrlen = XDR_QUADLEN(ntohl(*p++));
-               if (end - p < attrlen + 2)
-                       goto short_pkt;
-               p += attrlen;           /* attributes */
-               entry = p;
-       }
-       /*
-        * Apparently some server sends responses that are a valid size, but
-        * contain no entries, and have value_follows==0 and EOF==0. For
-        * those, just set the EOF marker.
-        */
-       if (!nr && entry[1] == 0) {
-               dprintk("NFS: readdir reply truncated!\n");
-               entry[1] = 1;
-       }
-out:
-       kunmap_atomic(kaddr, KM_USER0);
+
        return 0;
-short_pkt:
-       /*
-        * When we get a short packet there are 2 possibilities. We can
-        * return an error, or fix up the response to look like a valid
-        * response and return what we have so far. If there are no
-        * entries and the packet was short, then return -EIO. If there
-        * are valid entries in the response, return them and pretend that
-        * the call was successful, but incomplete. The caller can retry the
-        * readdir starting at the last cookie.
-        */
-       dprintk("%s: short packet at entry %d\n", __func__, nr);
-       entry[0] = entry[1] = 0;
-       if (nr)
-               goto out;
-err_unmap:
-       kunmap_atomic(kaddr, KM_USER0);
-       return -errno_NFSERR_IO;
 }
 
 static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
@@ -4299,7 +4528,6 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
        size_t hdrlen;
        u32 len, recvd;
        __be32 *p;
-       char *kaddr;
        int status;
 
        status = decode_op_hdr(xdr, OP_READLINK);
@@ -4330,9 +4558,7 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
         * and and null-terminate the text (the VFS expects
         * null-termination).
         */
-       kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
-       kaddr[len+rcvbuf->page_base] = '\0';
-       kunmap_atomic(kaddr, KM_USER0);
+       xdr_terminate_string(rcvbuf, len);
        return 0;
 out_overflow:
        print_overflow_msg(__func__, xdr);
@@ -4668,7 +4894,6 @@ static int decode_sequence(struct xdr_stream *xdr,
                           struct rpc_rqst *rqstp)
 {
 #if defined(CONFIG_NFS_V4_1)
-       struct nfs4_slot *slot;
        struct nfs4_sessionid id;
        u32 dummy;
        int status;
@@ -4700,15 +4925,14 @@ static int decode_sequence(struct xdr_stream *xdr,
                goto out_overflow;
 
        /* seqid */
-       slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
        dummy = be32_to_cpup(p++);
-       if (dummy != slot->seq_nr) {
+       if (dummy != res->sr_slot->seq_nr) {
                dprintk("%s Invalid sequence number\n", __func__);
                goto out_err;
        }
        /* slot id */
        dummy = be32_to_cpup(p++);
-       if (dummy != res->sr_slotid) {
+       if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
                dprintk("%s Invalid slot id\n", __func__);
                goto out_err;
        }
@@ -4731,6 +4955,134 @@ out_overflow:
 #endif /* CONFIG_NFS_V4_1 */
 }
 
+#if defined(CONFIG_NFS_V4_1)
+
+static int decode_getdeviceinfo(struct xdr_stream *xdr,
+                               struct pnfs_device *pdev)
+{
+       __be32 *p;
+       uint32_t len, type;
+       int status;
+
+       status = decode_op_hdr(xdr, OP_GETDEVICEINFO);
+       if (status) {
+               if (status == -ETOOSMALL) {
+                       p = xdr_inline_decode(xdr, 4);
+                       if (unlikely(!p))
+                               goto out_overflow;
+                       pdev->mincount = be32_to_cpup(p);
+                       dprintk("%s: Min count too small. mincnt = %u\n",
+                               __func__, pdev->mincount);
+               }
+               return status;
+       }
+
+       p = xdr_inline_decode(xdr, 8);
+       if (unlikely(!p))
+               goto out_overflow;
+       type = be32_to_cpup(p++);
+       if (type != pdev->layout_type) {
+               dprintk("%s: layout mismatch req: %u pdev: %u\n",
+                       __func__, pdev->layout_type, type);
+               return -EINVAL;
+       }
+       /*
+        * Get the length of the opaque device_addr4. xdr_read_pages places
+        * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages)
+        * and places the remaining xdr data in xdr_buf->tail
+        */
+       pdev->mincount = be32_to_cpup(p);
+       xdr_read_pages(xdr, pdev->mincount); /* include space for the length */
+
+       /* Parse notification bitmap, verifying that it is zero. */
+       p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       len = be32_to_cpup(p);
+       if (len) {
+               int i;
+
+               p = xdr_inline_decode(xdr, 4 * len);
+               if (unlikely(!p))
+                       goto out_overflow;
+               for (i = 0; i < len; i++, p++) {
+                       if (be32_to_cpup(p)) {
+                               dprintk("%s: notifications not supported\n",
+                                       __func__);
+                               return -EIO;
+                       }
+               }
+       }
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+
+static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+                           struct nfs4_layoutget_res *res)
+{
+       __be32 *p;
+       int status;
+       u32 layout_count;
+
+       status = decode_op_hdr(xdr, OP_LAYOUTGET);
+       if (status)
+               return status;
+       p = xdr_inline_decode(xdr, 8 + NFS4_STATEID_SIZE);
+       if (unlikely(!p))
+               goto out_overflow;
+       res->return_on_close = be32_to_cpup(p++);
+       p = xdr_decode_opaque_fixed(p, res->stateid.data, NFS4_STATEID_SIZE);
+       layout_count = be32_to_cpup(p);
+       if (!layout_count) {
+               dprintk("%s: server responded with empty layout array\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       p = xdr_inline_decode(xdr, 24);
+       if (unlikely(!p))
+               goto out_overflow;
+       p = xdr_decode_hyper(p, &res->range.offset);
+       p = xdr_decode_hyper(p, &res->range.length);
+       res->range.iomode = be32_to_cpup(p++);
+       res->type = be32_to_cpup(p++);
+
+       status = decode_opaque_inline(xdr, &res->layout.len, (char **)&p);
+       if (unlikely(status))
+               return status;
+
+       dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n",
+               __func__,
+               (unsigned long)res->range.offset,
+               (unsigned long)res->range.length,
+               res->range.iomode,
+               res->type,
+               res->layout.len);
+
+       /* nfs4_proc_layoutget allocated a single page */
+       if (res->layout.len > PAGE_SIZE)
+               return -ENOMEM;
+       memcpy(res->layout.buf, p, res->layout.len);
+
+       if (layout_count > 1) {
+               /* We only handle a length one array at the moment.  Any
+                * further entries are just ignored.  Note that this means
+                * the client may see a response that is less than the
+                * minimum it requested.
+                */
+               dprintk("%s: server responded with %d layouts, dropping tail\n",
+                       __func__, layout_count);
+       }
+
+       return 0;
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return -EIO;
+}
+#endif /* CONFIG_NFS_V4_1 */
+
 /*
  * END OF "GENERIC" DECODE ROUTINES.
  */
@@ -4873,7 +5225,7 @@ out:
 /*
  * Decode RENAME response
  */
-static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res)
+static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs_renameres *res)
 {
        struct xdr_stream xdr;
        struct compound_hdr hdr;
@@ -5758,25 +6110,84 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p,
                status = decode_reclaim_complete(&xdr, (void *)NULL);
        return status;
 }
+
+/*
+ * Decode GETDEVINFO response
+ */
+static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp, uint32_t *p,
+                                     struct nfs4_getdeviceinfo_res *res)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr;
+       int status;
+
+       xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+       status = decode_compound_hdr(&xdr, &hdr);
+       if (status != 0)
+               goto out;
+       status = decode_sequence(&xdr, &res->seq_res, rqstp);
+       if (status != 0)
+               goto out;
+       status = decode_getdeviceinfo(&xdr, res->pdev);
+out:
+       return status;
+}
+
+/*
+ * Decode LAYOUTGET response
+ */
+static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp, uint32_t *p,
+                                 struct nfs4_layoutget_res *res)
+{
+       struct xdr_stream xdr;
+       struct compound_hdr hdr;
+       int status;
+
+       xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
+       status = decode_compound_hdr(&xdr, &hdr);
+       if (status)
+               goto out;
+       status = decode_sequence(&xdr, &res->seq_res, rqstp);
+       if (status)
+               goto out;
+       status = decode_putfh(&xdr);
+       if (status)
+               goto out;
+       status = decode_layoutget(&xdr, rqstp, res);
+out:
+       return status;
+}
 #endif /* CONFIG_NFS_V4_1 */
 
-__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
+__be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
+                          struct nfs_server *server, int plus)
 {
        uint32_t bitmap[2] = {0};
        uint32_t len;
-
-       if (!*p++) {
-               if (!*p)
+       __be32 *p = xdr_inline_decode(xdr, 4);
+       if (unlikely(!p))
+               goto out_overflow;
+       if (!ntohl(*p++)) {
+               p = xdr_inline_decode(xdr, 4);
+               if (unlikely(!p))
+                       goto out_overflow;
+               if (!ntohl(*p++))
                        return ERR_PTR(-EAGAIN);
                entry->eof = 1;
                return ERR_PTR(-EBADCOOKIE);
        }
 
+       p = xdr_inline_decode(xdr, 12);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->prev_cookie = entry->cookie;
        p = xdr_decode_hyper(p, &entry->cookie);
        entry->len = ntohl(*p++);
+
+       p = xdr_inline_decode(xdr, entry->len);
+       if (unlikely(!p))
+               goto out_overflow;
        entry->name = (const char *) p;
-       p += XDR_QUADLEN(entry->len);
 
        /*
         * In case the server doesn't return an inode number,
@@ -5784,32 +6195,33 @@ __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
         * since glibc seems to choke on it...)
         */
        entry->ino = 1;
+       entry->fattr->valid = 0;
 
-       len = ntohl(*p++);              /* bitmap length */
-       if (len-- > 0) {
-               bitmap[0] = ntohl(*p++);
-               if (len-- > 0) {
-                       bitmap[1] = ntohl(*p++);
-                       p += len;
-               }
-       }
-       len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
-       if (len > 0) {
-               if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
-                       bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
-                       /* Ignore the return value of rdattr_error for now */
-                       p++;
-                       len--;
-               }
-               if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
-                       xdr_decode_hyper(p, &entry->ino);
-               else if (bitmap[0] == FATTR4_WORD0_FILEID)
-                       xdr_decode_hyper(p, &entry->ino);
-               p += len;
-       }
+       if (decode_attr_bitmap(xdr, bitmap) < 0)
+               goto out_overflow;
+
+       if (decode_attr_length(xdr, &len, &p) < 0)
+               goto out_overflow;
+
+       if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, server, 1) < 0)
+               goto out_overflow;
+       if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
+               entry->ino = entry->fattr->fileid;
+
+       if (verify_attr_len(xdr, p, len) < 0)
+               goto out_overflow;
+
+       p = xdr_inline_peek(xdr, 8);
+       if (p != NULL)
+               entry->eof = !p[0] && p[1];
+       else
+               entry->eof = 0;
 
-       entry->eof = !p[0] && p[1];
        return p;
+
+out_overflow:
+       print_overflow_msg(__func__, xdr);
+       return ERR_PTR(-EIO);
 }
 
 /*
@@ -5936,6 +6348,8 @@ struct rpc_procinfo       nfs4_procedures[] = {
   PROC(SEQUENCE,       enc_sequence,   dec_sequence),
   PROC(GET_LEASE_TIME, enc_get_lease_time,     dec_get_lease_time),
   PROC(RECLAIM_COMPLETE, enc_reclaim_complete,  dec_reclaim_complete),
+  PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo),
+  PROC(LAYOUTGET,  enc_layoutget,     dec_layoutget),
 #endif /* CONFIG_NFS_V4_1 */
 };
 
index df101d9..903908a 100644 (file)
@@ -3,9 +3,10 @@
  *
  *  Allow an NFS filesystem to be mounted as root. The way this works is:
  *     (1) Use the IP autoconfig mechanism to set local IP addresses and routes.
- *     (2) Handle RPC negotiation with the system which replied to RARP or
- *         was reported as a boot server by BOOTP or manually.
- *     (3) The actual mounting is done later, when init() is running.
+ *     (2) Construct the device string and the options string using DHCP
+ *         option 17 and/or kernel command line options.
+ *     (3) When mount_root() sets up the root file system, pass these strings
+ *         to the NFS client's regular mount interface via sys_mount().
  *
  *
  *     Changes:
  *     Hua Qin         :       Support for mounting root file system via
  *                             NFS over TCP.
  *     Fabian Frederick:       Option parser rebuilt (using parser lib)
-*/
+ *     Chuck Lever     :       Use super.c's text-based mount option parsing
+ *     Chuck Lever     :       Add "nfsrootdebug".
+ */
 
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/fs.h>
 #include <linux/init.h>
-#include <linux/sunrpc/clnt.h>
-#include <linux/sunrpc/xprtsock.h>
 #include <linux/nfs.h>
 #include <linux/nfs_fs.h>
-#include <linux/nfs_mount.h>
-#include <linux/in.h>
-#include <linux/major.h>
 #include <linux/utsname.h>
-#include <linux/inet.h>
 #include <linux/root_dev.h>
 #include <net/ipconfig.h>
-#include <linux/parser.h>
 
 #include "internal.h"
 
-/* Define this to allow debugging output */
-#undef NFSROOT_DEBUG
 #define NFSDBG_FACILITY NFSDBG_ROOT
 
-/* Default port to use if server is not running a portmapper */
-#define NFS_MNT_PORT   627
-
 /* Default path we try to mount. "%s" gets replaced by our IP address */
 #define NFS_ROOT               "/tftpboot/%s"
 
 /* Parameters passed from the kernel command line */
-static char nfs_root_name[256] __initdata = "";
+static char nfs_root_parms[256] __initdata = "";
+
+/* Text-based mount options passed to super.c */
+static char nfs_root_options[256] __initdata = "";
 
 /* Address of NFS server */
-static __be32 servaddr __initdata = 0;
+static __be32 servaddr __initdata = htonl(INADDR_NONE);
 
 /* Name of directory to mount */
-static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = { 0, };
-
-/* NFS-related data */
-static struct nfs_mount_data nfs_data __initdata = { 0, };/* NFS mount info */
-static int nfs_port __initdata = 0;            /* Port to connect to for NFS */
-static int mount_port __initdata = 0;          /* Mount daemon port number */
-
-
-/***************************************************************************
-
-                            Parsing of options
-
- ***************************************************************************/
-
-enum {
-       /* Options that take integer arguments */
-       Opt_port, Opt_rsize, Opt_wsize, Opt_timeo, Opt_retrans, Opt_acregmin,
-       Opt_acregmax, Opt_acdirmin, Opt_acdirmax,
-       /* Options that take no arguments */
-       Opt_soft, Opt_hard, Opt_intr,
-       Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, 
-       Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
-       Opt_acl, Opt_noacl,
-       /* Error token */
-       Opt_err
-};
-
-static const match_table_t tokens __initconst = {
-       {Opt_port, "port=%u"},
-       {Opt_rsize, "rsize=%u"},
-       {Opt_wsize, "wsize=%u"},
-       {Opt_timeo, "timeo=%u"},
-       {Opt_retrans, "retrans=%u"},
-       {Opt_acregmin, "acregmin=%u"},
-       {Opt_acregmax, "acregmax=%u"},
-       {Opt_acdirmin, "acdirmin=%u"},
-       {Opt_acdirmax, "acdirmax=%u"},
-       {Opt_soft, "soft"},
-       {Opt_hard, "hard"},
-       {Opt_intr, "intr"},
-       {Opt_nointr, "nointr"},
-       {Opt_posix, "posix"},
-       {Opt_noposix, "noposix"},
-       {Opt_cto, "cto"},
-       {Opt_nocto, "nocto"},
-       {Opt_ac, "ac"},
-       {Opt_noac, "noac"},
-       {Opt_lock, "lock"},
-       {Opt_nolock, "nolock"},
-       {Opt_v2, "nfsvers=2"},
-       {Opt_v2, "v2"},
-       {Opt_v3, "nfsvers=3"},
-       {Opt_v3, "v3"},
-       {Opt_udp, "proto=udp"},
-       {Opt_udp, "udp"},
-       {Opt_tcp, "proto=tcp"},
-       {Opt_tcp, "tcp"},
-       {Opt_acl, "acl"},
-       {Opt_noacl, "noacl"},
-       {Opt_err, NULL}
-       
-};
+static char nfs_export_path[NFS_MAXPATHLEN + 1] __initdata = "";
 
+/* server:export path string passed to super.c */
+static char nfs_root_device[NFS_MAXPATHLEN + 1] __initdata = "";
+
+#ifdef RPC_DEBUG
 /*
- *  Parse option string.
+ * When the "nfsrootdebug" kernel command line option is specified,
+ * enable debugging messages for NFSROOT.
  */
-
-static int __init root_nfs_parse(char *name, char *buf)
+static int __init nfs_root_debug(char *__unused)
 {
-
-       char *p;
-       substring_t args[MAX_OPT_ARGS];
-       int option;
-
-       if (!name)
-               return 1;
-
-       /* Set the NFS remote path */
-       p = strsep(&name, ",");
-       if (p[0] != '\0' && strcmp(p, "default") != 0)
-               strlcpy(buf, p, NFS_MAXPATHLEN);
-
-       while ((p = strsep (&name, ",")) != NULL) {
-               int token; 
-               if (!*p)
-                       continue;
-               token = match_token(p, tokens, args);
-
-               /* %u tokens only. Beware if you add new tokens! */
-               if (token < Opt_soft && match_int(&args[0], &option))
-                       return 0;
-               switch (token) {
-                       case Opt_port:
-                               nfs_port = option;
-                               break;
-                       case Opt_rsize:
-                               nfs_data.rsize = option;
-                               break;
-                       case Opt_wsize:
-                               nfs_data.wsize = option;
-                               break;
-                       case Opt_timeo:
-                               nfs_data.timeo = option;
-                               break;
-                       case Opt_retrans:
-                               nfs_data.retrans = option;
-                               break;
-                       case Opt_acregmin:
-                               nfs_data.acregmin = option;
-                               break;
-                       case Opt_acregmax:
-                               nfs_data.acregmax = option;
-                               break;
-                       case Opt_acdirmin:
-                               nfs_data.acdirmin = option;
-                               break;
-                       case Opt_acdirmax:
-                               nfs_data.acdirmax = option;
-                               break;
-                       case Opt_soft:
-                               nfs_data.flags |= NFS_MOUNT_SOFT;
-                               break;
-                       case Opt_hard:
-                               nfs_data.flags &= ~NFS_MOUNT_SOFT;
-                               break;
-                       case Opt_intr:
-                       case Opt_nointr:
-                               break;
-                       case Opt_posix:
-                               nfs_data.flags |= NFS_MOUNT_POSIX;
-                               break;
-                       case Opt_noposix:
-                               nfs_data.flags &= ~NFS_MOUNT_POSIX;
-                               break;
-                       case Opt_cto:
-                               nfs_data.flags &= ~NFS_MOUNT_NOCTO;
-                               break;
-                       case Opt_nocto:
-                               nfs_data.flags |= NFS_MOUNT_NOCTO;
-                               break;
-                       case Opt_ac:
-                               nfs_data.flags &= ~NFS_MOUNT_NOAC;
-                               break;
-                       case Opt_noac:
-                               nfs_data.flags |= NFS_MOUNT_NOAC;
-                               break;
-                       case Opt_lock:
-                               nfs_data.flags &= ~NFS_MOUNT_NONLM;
-                               break;
-                       case Opt_nolock:
-                               nfs_data.flags |= NFS_MOUNT_NONLM;
-                               break;
-                       case Opt_v2:
-                               nfs_data.flags &= ~NFS_MOUNT_VER3;
-                               break;
-                       case Opt_v3:
-                               nfs_data.flags |= NFS_MOUNT_VER3;
-                               break;
-                       case Opt_udp:
-                               nfs_data.flags &= ~NFS_MOUNT_TCP;
-                               break;
-                       case Opt_tcp:
-                               nfs_data.flags |= NFS_MOUNT_TCP;
-                               break;
-                       case Opt_acl:
-                               nfs_data.flags &= ~NFS_MOUNT_NOACL;
-                               break;
-                       case Opt_noacl:
-                               nfs_data.flags |= NFS_MOUNT_NOACL;
-                               break;
-                       default:
-                               printk(KERN_WARNING "Root-NFS: unknown "
-                                       "option: %s\n", p);
-                               return 0;
-               }
-       }
-
+       nfs_debug |= NFSDBG_ROOT | NFSDBG_MOUNT;
        return 1;
 }
 
+__setup("nfsrootdebug", nfs_root_debug);
+#endif
+
 /*
- *  Prepare the NFS data structure and parse all options.
+ *  Parse NFS server and directory information passed on the kernel
+ *  command line.
+ *
+ *  nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
+ *
+ *  If there is a "%s" token in the <root-dir> string, it is replaced
+ *  by the ASCII-representation of the client's IP address.
  */
-static int __init root_nfs_name(char *name)
+static int __init nfs_root_setup(char *line)
 {
-       static char buf[NFS_MAXPATHLEN] __initdata;
-       char *cp;
-
-       /* Set some default values */
-       memset(&nfs_data, 0, sizeof(nfs_data));
-       nfs_port          = -1;
-       nfs_data.version  = NFS_MOUNT_VERSION;
-       nfs_data.flags    = NFS_MOUNT_NONLM;    /* No lockd in nfs root yet */
-       nfs_data.rsize    = NFS_DEF_FILE_IO_SIZE;
-       nfs_data.wsize    = NFS_DEF_FILE_IO_SIZE;
-       nfs_data.acregmin = NFS_DEF_ACREGMIN;
-       nfs_data.acregmax = NFS_DEF_ACREGMAX;
-       nfs_data.acdirmin = NFS_DEF_ACDIRMIN;
-       nfs_data.acdirmax = NFS_DEF_ACDIRMAX;
-       strcpy(buf, NFS_ROOT);
-
-       /* Process options received from the remote server */
-       root_nfs_parse(root_server_path, buf);
-
-       /* Override them by options set on kernel command-line */
-       root_nfs_parse(name, buf);
-
-       cp = utsname()->nodename;
-       if (strlen(buf) + strlen(cp) > NFS_MAXPATHLEN) {
-               printk(KERN_ERR "Root-NFS: Pathname for remote directory too long.\n");
-               return -1;
+       ROOT_DEV = Root_NFS;
+
+       if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
+               strlcpy(nfs_root_parms, line, sizeof(nfs_root_parms));
+       } else {
+               size_t n = strlen(line) + sizeof(NFS_ROOT) - 1;
+               if (n >= sizeof(nfs_root_parms))
+                       line[sizeof(nfs_root_parms) - sizeof(NFS_ROOT) - 2] = '\0';
+               sprintf(nfs_root_parms, NFS_ROOT, line);
        }
-       sprintf(nfs_export_path, buf, cp);
+
+       /*
+        * Extract the IP address of the NFS server containing our
+        * root file system, if one was specified.
+        *
+        * Note: root_nfs_parse_addr() removes the server-ip from
+        *       nfs_root_parms, if it exists.
+        */
+       root_server_addr = root_nfs_parse_addr(nfs_root_parms);
 
        return 1;
 }
 
+__setup("nfsroot=", nfs_root_setup);
 
-/*
- *  Get NFS server address.
- */
-static int __init root_nfs_addr(void)
+static int __init root_nfs_copy(char *dest, const char *src,
+                                    const size_t destlen)
 {
-       if ((servaddr = root_server_addr) == htonl(INADDR_NONE)) {
-               printk(KERN_ERR "Root-NFS: No NFS server available, giving up.\n");
+       if (strlcpy(dest, src, destlen) > destlen)
                return -1;
-       }
+       return 0;
+}
 
-       snprintf(nfs_data.hostname, sizeof(nfs_data.hostname),
-                "%pI4", &servaddr);
+static int __init root_nfs_cat(char *dest, const char *src,
+                                 const size_t destlen)
+{
+       if (strlcat(dest, src, destlen) > destlen)
+               return -1;
        return 0;
 }
 
 /*
- *  Tell the user what's going on.
+ * Parse out root export path and mount options from
+ * passed-in string @incoming.
+ *
+ * Copy the export path into @exppath.
  */
-#ifdef NFSROOT_DEBUG
-static void __init root_nfs_print(void)
+static int __init root_nfs_parse_options(char *incoming, char *exppath,
+                                        const size_t exppathlen)
 {
-       printk(KERN_NOTICE "Root-NFS: Mounting %s on server %s as root\n",
-               nfs_export_path, nfs_data.hostname);
-       printk(KERN_NOTICE "Root-NFS:     rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
-               nfs_data.rsize, nfs_data.wsize, nfs_data.timeo, nfs_data.retrans);
-       printk(KERN_NOTICE "Root-NFS:     acreg (min,max) = (%d,%d), acdir (min,max) = (%d,%d)\n",
-               nfs_data.acregmin, nfs_data.acregmax,
-               nfs_data.acdirmin, nfs_data.acdirmax);
-       printk(KERN_NOTICE "Root-NFS:     nfsd port = %d, mountd port = %d, flags = %08x\n",
-               nfs_port, mount_port, nfs_data.flags);
-}
-#endif
-
+       char *p;
 
-static int __init root_nfs_init(void)
-{
-#ifdef NFSROOT_DEBUG
-       nfs_debug |= NFSDBG_ROOT;
-#endif
+       /*
+        * Set the NFS remote path
+        */
+       p = strsep(&incoming, ",");
+       if (*p != '\0' && strcmp(p, "default") != 0)
+               if (root_nfs_copy(exppath, p, exppathlen))
+                       return -1;
 
        /*
-        * Decode the root directory path name and NFS options from
-        * the kernel command line. This has to go here in order to
-        * be able to use the client IP address for the remote root
-        * directory (necessary for pure RARP booting).
+        * @incoming now points to the rest of the string; if it
+        * contains something, append it to our root options buffer
         */
-       if (root_nfs_name(nfs_root_name) < 0 ||
-           root_nfs_addr() < 0)
-               return -1;
+       if (incoming != NULL && *incoming != '\0')
+               if (root_nfs_cat(nfs_root_options, incoming,
+                                               sizeof(nfs_root_options)))
+                       return -1;
 
-#ifdef NFSROOT_DEBUG
-       root_nfs_print();
-#endif
+       /*
+        * Possibly prepare for more options to be appended
+        */
+       if (nfs_root_options[0] != '\0' &&
+           nfs_root_options[strlen(nfs_root_options)] != ',')
+               if (root_nfs_cat(nfs_root_options, ",",
+                                               sizeof(nfs_root_options)))
+                       return -1;
 
        return 0;
 }
 
-
 /*
- *  Parse NFS server and directory information passed on the kernel
- *  command line.
+ *  Decode the export directory path name and NFS options from
+ *  the kernel command line.  This has to be done late in order to
+ *  use a dynamically acquired client IP address for the remote
+ *  root directory path.
+ *
+ *  Returns zero if successful; otherwise -1 is returned.
  */
-static int __init nfs_root_setup(char *line)
+static int __init root_nfs_data(char *cmdline)
 {
-       ROOT_DEV = Root_NFS;
-       if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
-               strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
-       } else {
-               int n = strlen(line) + sizeof(NFS_ROOT) - 1;
-               if (n >= sizeof(nfs_root_name))
-                       line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0';
-               sprintf(nfs_root_name, NFS_ROOT, line);
+       char addr_option[sizeof("nolock,addr=") + INET_ADDRSTRLEN + 1];
+       int len, retval = -1;
+       char *tmp = NULL;
+       const size_t tmplen = sizeof(nfs_export_path);
+
+       tmp = kzalloc(tmplen, GFP_KERNEL);
+       if (tmp == NULL)
+               goto out_nomem;
+       strcpy(tmp, NFS_ROOT);
+
+       if (root_server_path[0] != '\0') {
+               dprintk("Root-NFS: DHCPv4 option 17: %s\n",
+                       root_server_path);
+               if (root_nfs_parse_options(root_server_path, tmp, tmplen))
+                       goto out_optionstoolong;
        }
-       root_server_addr = root_nfs_parse_addr(nfs_root_name);
-       return 1;
-}
-
-__setup("nfsroot=", nfs_root_setup);
-
-/***************************************************************************
 
-              Routines to actually mount the root directory
+       if (cmdline[0] != '\0') {
+               dprintk("Root-NFS: nfsroot=%s\n", cmdline);
+               if (root_nfs_parse_options(cmdline, tmp, tmplen))
+                       goto out_optionstoolong;
+       }
 
- ***************************************************************************/
+       /*
+        * Append mandatory options for nfsroot so they override
+        * what has come before
+        */
+       snprintf(addr_option, sizeof(addr_option), "nolock,addr=%pI4",
+                       &servaddr);
+       if (root_nfs_cat(nfs_root_options, addr_option,
+                                               sizeof(nfs_root_options)))
+               goto out_optionstoolong;
 
-/*
- *  Construct sockaddr_in from address and port number.
- */
-static inline void
-set_sockaddr(struct sockaddr_in *sin, __be32 addr, __be16 port)
-{
-       sin->sin_family = AF_INET;
-       sin->sin_addr.s_addr = addr;
-       sin->sin_port = port;
-}
+       /*
+        * Set up nfs_root_device.  For NFS mounts, this looks like
+        *
+        *      server:/path
+        *
+        * At this point, utsname()->nodename contains our local
+        * IP address or hostname, set by ipconfig.  If "%s" exists
+        * in tmp, substitute the nodename, then shovel the whole
+        * mess into nfs_root_device.
+        */
+       len = snprintf(nfs_export_path, sizeof(nfs_export_path),
+                               tmp, utsname()->nodename);
+       if (len > (int)sizeof(nfs_export_path))
+               goto out_devnametoolong;
+       len = snprintf(nfs_root_device, sizeof(nfs_root_device),
+                               "%pI4:%s", &servaddr, nfs_export_path);
+       if (len > (int)sizeof(nfs_root_device))
+               goto out_devnametoolong;
 
-/*
- *  Query server portmapper for the port of a daemon program.
- */
-static int __init root_nfs_getport(int program, int version, int proto)
-{
-       struct sockaddr_in sin;
+       retval = 0;
 
-       printk(KERN_NOTICE "Looking up port of RPC %d/%d on %pI4\n",
-               program, version, &servaddr);
-       set_sockaddr(&sin, servaddr, 0);
-       return rpcb_getport_sync(&sin, program, version, proto);
+out:
+       kfree(tmp);
+       return retval;
+out_nomem:
+       printk(KERN_ERR "Root-NFS: could not allocate memory\n");
+       goto out;
+out_optionstoolong:
+       printk(KERN_ERR "Root-NFS: mount options string too long\n");
+       goto out;
+out_devnametoolong:
+       printk(KERN_ERR "Root-NFS: root device name too long.\n");
+       goto out;
 }
 
-
-/*
- *  Use portmapper to find mountd and nfsd port numbers if not overriden
- *  by the user. Use defaults if portmapper is not available.
- *  XXX: Is there any nfs server with no portmapper?
+/**
+ * nfs_root_data - Return prepared 'data' for NFSROOT mount
+ * @root_device: OUT: address of string containing NFSROOT device
+ * @root_data: OUT: address of string containing NFSROOT mount options
+ *
+ * Returns zero and sets @root_device and @root_data if successful,
+ * otherwise -1 is returned.
  */
-static int __init root_nfs_ports(void)
+int __init nfs_root_data(char **root_device, char **root_data)
 {
-       int port;
-       int nfsd_ver, mountd_ver;
-       int nfsd_port, mountd_port;
-       int proto;
-
-       if (nfs_data.flags & NFS_MOUNT_VER3) {
-               nfsd_ver = NFS3_VERSION;
-               mountd_ver = NFS_MNT3_VERSION;
-               nfsd_port = NFS_PORT;
-               mountd_port = NFS_MNT_PORT;
-       } else {
-               nfsd_ver = NFS2_VERSION;
-               mountd_ver = NFS_MNT_VERSION;
-               nfsd_port = NFS_PORT;
-               mountd_port = NFS_MNT_PORT;
-       }
-
-       proto = (nfs_data.flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP;
-
-       if (nfs_port < 0) {
-               if ((port = root_nfs_getport(NFS_PROGRAM, nfsd_ver, proto)) < 0) {
-                       printk(KERN_ERR "Root-NFS: Unable to get nfsd port "
-                                       "number from server, using default\n");
-                       port = nfsd_port;
-               }
-               nfs_port = port;
-               dprintk("Root-NFS: Portmapper on server returned %d "
-                       "as nfsd port\n", port);
+       servaddr = root_server_addr;
+       if (servaddr == htonl(INADDR_NONE)) {
+               printk(KERN_ERR "Root-NFS: no NFS server address\n");
+               return -1;
        }
 
-       if ((port = root_nfs_getport(NFS_MNT_PROGRAM, mountd_ver, proto)) < 0) {
-               printk(KERN_ERR "Root-NFS: Unable to get mountd port "
-                               "number from server, using default\n");
-               port = mountd_port;
-       }
-       mount_port = port;
-       dprintk("Root-NFS: mountd port is %d\n", port);
+       if (root_nfs_data(nfs_root_parms) < 0)
+               return -1;
 
+       *root_device = nfs_root_device;
+       *root_data = nfs_root_options;
        return 0;
 }
-
-
-/*
- *  Get a file handle from the server for the directory which is to be
- *  mounted.
- */
-static int __init root_nfs_get_handle(void)
-{
-       struct sockaddr_in sin;
-       unsigned int auth_flav_len = 0;
-       struct nfs_mount_request request = {
-               .sap            = (struct sockaddr *)&sin,
-               .salen          = sizeof(sin),
-               .dirpath        = nfs_export_path,
-               .version        = (nfs_data.flags & NFS_MOUNT_VER3) ?
-                                       NFS_MNT3_VERSION : NFS_MNT_VERSION,
-               .protocol       = (nfs_data.flags & NFS_MOUNT_TCP) ?
-                                       XPRT_TRANSPORT_TCP : XPRT_TRANSPORT_UDP,
-               .auth_flav_len  = &auth_flav_len,
-       };
-       int status = -ENOMEM;
-
-       request.fh = nfs_alloc_fhandle();
-       if (!request.fh)
-               goto out;
-       set_sockaddr(&sin, servaddr, htons(mount_port));
-       status = nfs_mount(&request);
-       if (status < 0)
-               printk(KERN_ERR "Root-NFS: Server returned error %d "
-                               "while mounting %s\n", status, nfs_export_path);
-       else {
-               nfs_data.root.size = request.fh->size;
-               memcpy(&nfs_data.root.data, request.fh->data, request.fh->size);
-       }
-       nfs_free_fhandle(request.fh);
-out:
-       return status;
-}
-
-/*
- *  Get the NFS port numbers and file handle, and return the prepared 'data'
- *  argument for mount() if everything went OK. Return NULL otherwise.
- */
-void * __init nfs_root_data(void)
-{
-       if (root_nfs_init() < 0
-        || root_nfs_ports() < 0
-        || root_nfs_get_handle() < 0)
-               return NULL;
-       set_sockaddr((struct sockaddr_in *) &nfs_data.addr, servaddr, htons(nfs_port));
-       return (void*)&nfs_data;
-}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
new file mode 100644 (file)
index 0000000..db77342
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ *  pNFS functions to call and manage layout drivers.
+ *
+ *  Copyright (c) 2002 [year of first publication]
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#include <linux/nfs_fs.h>
+#include "internal.h"
+#include "pnfs.h"
+
+#define NFSDBG_FACILITY                NFSDBG_PNFS
+
+/* Locking:
+ *
+ * pnfs_spinlock:
+ *      protects pnfs_modules_tbl.
+ */
+static DEFINE_SPINLOCK(pnfs_spinlock);
+
+/*
+ * pnfs_modules_tbl holds all pnfs modules
+ */
+static LIST_HEAD(pnfs_modules_tbl);
+
+/* Return the registered pnfs layout driver module matching given id */
+static struct pnfs_layoutdriver_type *
+find_pnfs_driver_locked(u32 id)
+{
+       struct pnfs_layoutdriver_type *local;
+
+       list_for_each_entry(local, &pnfs_modules_tbl, pnfs_tblid)
+               if (local->id == id)
+                       goto out;
+       local = NULL;
+out:
+       dprintk("%s: Searching for id %u, found %p\n", __func__, id, local);
+       return local;
+}
+
+static struct pnfs_layoutdriver_type *
+find_pnfs_driver(u32 id)
+{
+       struct pnfs_layoutdriver_type *local;
+
+       spin_lock(&pnfs_spinlock);
+       local = find_pnfs_driver_locked(id);
+       spin_unlock(&pnfs_spinlock);
+       return local;
+}
+
+void
+unset_pnfs_layoutdriver(struct nfs_server *nfss)
+{
+       if (nfss->pnfs_curr_ld) {
+               nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
+               module_put(nfss->pnfs_curr_ld->owner);
+       }
+       nfss->pnfs_curr_ld = NULL;
+}
+
+/*
+ * Try to set the server's pnfs module to the pnfs layout type specified by id.
+ * Currently only one pNFS layout driver per filesystem is supported.
+ *
+ * @id layout type. Zero (illegal layout type) indicates pNFS not in use.
+ */
+void
+set_pnfs_layoutdriver(struct nfs_server *server, u32 id)
+{
+       struct pnfs_layoutdriver_type *ld_type = NULL;
+
+       if (id == 0)
+               goto out_no_driver;
+       if (!(server->nfs_client->cl_exchange_flags &
+                (EXCHGID4_FLAG_USE_NON_PNFS | EXCHGID4_FLAG_USE_PNFS_MDS))) {
+               printk(KERN_ERR "%s: id %u cl_exchange_flags 0x%x\n", __func__,
+                      id, server->nfs_client->cl_exchange_flags);
+               goto out_no_driver;
+       }
+       ld_type = find_pnfs_driver(id);
+       if (!ld_type) {
+               request_module("%s-%u", LAYOUT_NFSV4_1_MODULE_PREFIX, id);
+               ld_type = find_pnfs_driver(id);
+               if (!ld_type) {
+                       dprintk("%s: No pNFS module found for %u.\n",
+                               __func__, id);
+                       goto out_no_driver;
+               }
+       }
+       if (!try_module_get(ld_type->owner)) {
+               dprintk("%s: Could not grab reference on module\n", __func__);
+               goto out_no_driver;
+       }
+       server->pnfs_curr_ld = ld_type;
+       if (ld_type->set_layoutdriver(server)) {
+               printk(KERN_ERR
+                      "%s: Error initializing mount point for layout driver %u.\n",
+                      __func__, id);
+               module_put(ld_type->owner);
+               goto out_no_driver;
+       }
+       dprintk("%s: pNFS module for %u set\n", __func__, id);
+       return;
+
+out_no_driver:
+       dprintk("%s: Using NFSv4 I/O\n", __func__);
+       server->pnfs_curr_ld = NULL;
+}
+
+int
+pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
+{
+       int status = -EINVAL;
+       struct pnfs_layoutdriver_type *tmp;
+
+       if (ld_type->id == 0) {
+               printk(KERN_ERR "%s id 0 is reserved\n", __func__);
+               return status;
+       }
+       if (!ld_type->alloc_lseg || !ld_type->free_lseg) {
+               printk(KERN_ERR "%s Layout driver must provide "
+                      "alloc_lseg and free_lseg.\n", __func__);
+               return status;
+       }
+
+       spin_lock(&pnfs_spinlock);
+       tmp = find_pnfs_driver_locked(ld_type->id);
+       if (!tmp) {
+               list_add(&ld_type->pnfs_tblid, &pnfs_modules_tbl);
+               status = 0;
+               dprintk("%s Registering id:%u name:%s\n", __func__, ld_type->id,
+                       ld_type->name);
+       } else {
+               printk(KERN_ERR "%s Module with id %d already loaded!\n",
+                       __func__, ld_type->id);
+       }
+       spin_unlock(&pnfs_spinlock);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(pnfs_register_layoutdriver);
+
+void
+pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *ld_type)
+{
+       dprintk("%s Deregistering id:%u\n", __func__, ld_type->id);
+       spin_lock(&pnfs_spinlock);
+       list_del(&ld_type->pnfs_tblid);
+       spin_unlock(&pnfs_spinlock);
+}
+EXPORT_SYMBOL_GPL(pnfs_unregister_layoutdriver);
+
+/*
+ * pNFS client layout cache
+ */
+
+static void
+get_layout_hdr_locked(struct pnfs_layout_hdr *lo)
+{
+       assert_spin_locked(&lo->inode->i_lock);
+       lo->refcount++;
+}
+
+static void
+put_layout_hdr_locked(struct pnfs_layout_hdr *lo)
+{
+       assert_spin_locked(&lo->inode->i_lock);
+       BUG_ON(lo->refcount == 0);
+
+       lo->refcount--;
+       if (!lo->refcount) {
+               dprintk("%s: freeing layout cache %p\n", __func__, lo);
+               BUG_ON(!list_empty(&lo->layouts));
+               NFS_I(lo->inode)->layout = NULL;
+               kfree(lo);
+       }
+}
+
+void
+put_layout_hdr(struct inode *inode)
+{
+       spin_lock(&inode->i_lock);
+       put_layout_hdr_locked(NFS_I(inode)->layout);
+       spin_unlock(&inode->i_lock);
+}
+
+static void
+init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg)
+{
+       INIT_LIST_HEAD(&lseg->fi_list);
+       kref_init(&lseg->kref);
+       lseg->layout = lo;
+}
+
+/* Called without i_lock held, as the free_lseg call may sleep */
+static void
+destroy_lseg(struct kref *kref)
+{
+       struct pnfs_layout_segment *lseg =
+               container_of(kref, struct pnfs_layout_segment, kref);
+       struct inode *ino = lseg->layout->inode;
+
+       dprintk("--> %s\n", __func__);
+       NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
+       /* Matched by get_layout_hdr_locked in pnfs_insert_layout */
+       put_layout_hdr(ino);
+}
+
+static void
+put_lseg(struct pnfs_layout_segment *lseg)
+{
+       if (!lseg)
+               return;
+
+       dprintk("%s: lseg %p ref %d\n", __func__, lseg,
+               atomic_read(&lseg->kref.refcount));
+       kref_put(&lseg->kref, destroy_lseg);
+}
+
+static void
+pnfs_clear_lseg_list(struct pnfs_layout_hdr *lo, struct list_head *tmp_list)
+{
+       struct pnfs_layout_segment *lseg, *next;
+       struct nfs_client *clp;
+
+       dprintk("%s:Begin lo %p\n", __func__, lo);
+
+       assert_spin_locked(&lo->inode->i_lock);
+       list_for_each_entry_safe(lseg, next, &lo->segs, fi_list) {
+               dprintk("%s: freeing lseg %p\n", __func__, lseg);
+               list_move(&lseg->fi_list, tmp_list);
+       }
+       clp = NFS_SERVER(lo->inode)->nfs_client;
+       spin_lock(&clp->cl_lock);
+       /* List does not take a reference, so no need for put here */
+       list_del_init(&lo->layouts);
+       spin_unlock(&clp->cl_lock);
+       write_seqlock(&lo->seqlock);
+       clear_bit(NFS_LAYOUT_STATEID_SET, &lo->state);
+       write_sequnlock(&lo->seqlock);
+
+       dprintk("%s:Return\n", __func__);
+}
+
+static void
+pnfs_free_lseg_list(struct list_head *tmp_list)
+{
+       struct pnfs_layout_segment *lseg;
+
+       while (!list_empty(tmp_list)) {
+               lseg = list_entry(tmp_list->next, struct pnfs_layout_segment,
+                               fi_list);
+               dprintk("%s calling put_lseg on %p\n", __func__, lseg);
+               list_del(&lseg->fi_list);
+               put_lseg(lseg);
+       }
+}
+
+void
+pnfs_destroy_layout(struct nfs_inode *nfsi)
+{
+       struct pnfs_layout_hdr *lo;
+       LIST_HEAD(tmp_list);
+
+       spin_lock(&nfsi->vfs_inode.i_lock);
+       lo = nfsi->layout;
+       if (lo) {
+               pnfs_clear_lseg_list(lo, &tmp_list);
+               /* Matched by refcount set to 1 in alloc_init_layout_hdr */
+               put_layout_hdr_locked(lo);
+       }
+       spin_unlock(&nfsi->vfs_inode.i_lock);
+       pnfs_free_lseg_list(&tmp_list);
+}
+
+/*
+ * Called by the state manger to remove all layouts established under an
+ * expired lease.
+ */
+void
+pnfs_destroy_all_layouts(struct nfs_client *clp)
+{
+       struct pnfs_layout_hdr *lo;
+       LIST_HEAD(tmp_list);
+
+       spin_lock(&clp->cl_lock);
+       list_splice_init(&clp->cl_layouts, &tmp_list);
+       spin_unlock(&clp->cl_lock);
+
+       while (!list_empty(&tmp_list)) {
+               lo = list_entry(tmp_list.next, struct pnfs_layout_hdr,
+                               layouts);
+               dprintk("%s freeing layout for inode %lu\n", __func__,
+                       lo->inode->i_ino);
+               pnfs_destroy_layout(NFS_I(lo->inode));
+       }
+}
+
+/* update lo->stateid with new if is more recent
+ *
+ * lo->stateid could be the open stateid, in which case we just use what given.
+ */
+static void
+pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
+                       const nfs4_stateid *new)
+{
+       nfs4_stateid *old = &lo->stateid;
+       bool overwrite = false;
+
+       write_seqlock(&lo->seqlock);
+       if (!test_bit(NFS_LAYOUT_STATEID_SET, &lo->state) ||
+           memcmp(old->stateid.other, new->stateid.other, sizeof(new->stateid.other)))
+               overwrite = true;
+       else {
+               u32 oldseq, newseq;
+
+               oldseq = be32_to_cpu(old->stateid.seqid);
+               newseq = be32_to_cpu(new->stateid.seqid);
+               if ((int)(newseq - oldseq) > 0)
+                       overwrite = true;
+       }
+       if (overwrite)
+               memcpy(&old->stateid, &new->stateid, sizeof(new->stateid));
+       write_sequnlock(&lo->seqlock);
+}
+
+static void
+pnfs_layout_from_open_stateid(struct pnfs_layout_hdr *lo,
+                             struct nfs4_state *state)
+{
+       int seq;
+
+       dprintk("--> %s\n", __func__);
+       write_seqlock(&lo->seqlock);
+       do {
+               seq = read_seqbegin(&state->seqlock);
+               memcpy(lo->stateid.data, state->stateid.data,
+                      sizeof(state->stateid.data));
+       } while (read_seqretry(&state->seqlock, seq));
+       set_bit(NFS_LAYOUT_STATEID_SET, &lo->state);
+       write_sequnlock(&lo->seqlock);
+       dprintk("<-- %s\n", __func__);
+}
+
+void
+pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
+                       struct nfs4_state *open_state)
+{
+       int seq;
+
+       dprintk("--> %s\n", __func__);
+       do {
+               seq = read_seqbegin(&lo->seqlock);
+               if (!test_bit(NFS_LAYOUT_STATEID_SET, &lo->state)) {
+                       /* This will trigger retry of the read */
+                       pnfs_layout_from_open_stateid(lo, open_state);
+               } else
+                       memcpy(dst->data, lo->stateid.data,
+                              sizeof(lo->stateid.data));
+       } while (read_seqretry(&lo->seqlock, seq));
+       dprintk("<-- %s\n", __func__);
+}
+
+/*
+* Get layout from server.
+*    for now, assume that whole file layouts are requested.
+*    arg->offset: 0
+*    arg->length: all ones
+*/
+static struct pnfs_layout_segment *
+send_layoutget(struct pnfs_layout_hdr *lo,
+          struct nfs_open_context *ctx,
+          u32 iomode)
+{
+       struct inode *ino = lo->inode;
+       struct nfs_server *server = NFS_SERVER(ino);
+       struct nfs4_layoutget *lgp;
+       struct pnfs_layout_segment *lseg = NULL;
+
+       dprintk("--> %s\n", __func__);
+
+       BUG_ON(ctx == NULL);
+       lgp = kzalloc(sizeof(*lgp), GFP_KERNEL);
+       if (lgp == NULL) {
+               put_layout_hdr(lo->inode);
+               return NULL;
+       }
+       lgp->args.minlength = NFS4_MAX_UINT64;
+       lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
+       lgp->args.range.iomode = iomode;
+       lgp->args.range.offset = 0;
+       lgp->args.range.length = NFS4_MAX_UINT64;
+       lgp->args.type = server->pnfs_curr_ld->id;
+       lgp->args.inode = ino;
+       lgp->args.ctx = get_nfs_open_context(ctx);
+       lgp->lsegpp = &lseg;
+
+       /* Synchronously retrieve layout information from server and
+        * store in lseg.
+        */
+       nfs4_proc_layoutget(lgp);
+       if (!lseg) {
+               /* remember that LAYOUTGET failed and suspend trying */
+               set_bit(lo_fail_bit(iomode), &lo->state);
+       }
+       return lseg;
+}
+
+/*
+ * Compare two layout segments for sorting into layout cache.
+ * We want to preferentially return RW over RO layouts, so ensure those
+ * are seen first.
+ */
+static s64
+cmp_layout(u32 iomode1, u32 iomode2)
+{
+       /* read > read/write */
+       return (int)(iomode2 == IOMODE_READ) - (int)(iomode1 == IOMODE_READ);
+}
+
+static void
+pnfs_insert_layout(struct pnfs_layout_hdr *lo,
+                  struct pnfs_layout_segment *lseg)
+{
+       struct pnfs_layout_segment *lp;
+       int found = 0;
+
+       dprintk("%s:Begin\n", __func__);
+
+       assert_spin_locked(&lo->inode->i_lock);
+       if (list_empty(&lo->segs)) {
+               struct nfs_client *clp = NFS_SERVER(lo->inode)->nfs_client;
+
+               spin_lock(&clp->cl_lock);
+               BUG_ON(!list_empty(&lo->layouts));
+               list_add_tail(&lo->layouts, &clp->cl_layouts);
+               spin_unlock(&clp->cl_lock);
+       }
+       list_for_each_entry(lp, &lo->segs, fi_list) {
+               if (cmp_layout(lp->range.iomode, lseg->range.iomode) > 0)
+                       continue;
+               list_add_tail(&lseg->fi_list, &lp->fi_list);
+               dprintk("%s: inserted lseg %p "
+                       "iomode %d offset %llu length %llu before "
+                       "lp %p iomode %d offset %llu length %llu\n",
+                       __func__, lseg, lseg->range.iomode,
+                       lseg->range.offset, lseg->range.length,
+                       lp, lp->range.iomode, lp->range.offset,
+                       lp->range.length);
+               found = 1;
+               break;
+       }
+       if (!found) {
+               list_add_tail(&lseg->fi_list, &lo->segs);
+               dprintk("%s: inserted lseg %p "
+                       "iomode %d offset %llu length %llu at tail\n",
+                       __func__, lseg, lseg->range.iomode,
+                       lseg->range.offset, lseg->range.length);
+       }
+       get_layout_hdr_locked(lo);
+
+       dprintk("%s:Return\n", __func__);
+}
+
+static struct pnfs_layout_hdr *
+alloc_init_layout_hdr(struct inode *ino)
+{
+       struct pnfs_layout_hdr *lo;
+
+       lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL);
+       if (!lo)
+               return NULL;
+       lo->refcount = 1;
+       INIT_LIST_HEAD(&lo->layouts);
+       INIT_LIST_HEAD(&lo->segs);
+       seqlock_init(&lo->seqlock);
+       lo->inode = ino;
+       return lo;
+}
+
+static struct pnfs_layout_hdr *
+pnfs_find_alloc_layout(struct inode *ino)
+{
+       struct nfs_inode *nfsi = NFS_I(ino);
+       struct pnfs_layout_hdr *new = NULL;
+
+       dprintk("%s Begin ino=%p layout=%p\n", __func__, ino, nfsi->layout);
+
+       assert_spin_locked(&ino->i_lock);
+       if (nfsi->layout)
+               return nfsi->layout;
+
+       spin_unlock(&ino->i_lock);
+       new = alloc_init_layout_hdr(ino);
+       spin_lock(&ino->i_lock);
+
+       if (likely(nfsi->layout == NULL))       /* Won the race? */
+               nfsi->layout = new;
+       else
+               kfree(new);
+       return nfsi->layout;
+}
+
+/*
+ * iomode matching rules:
+ * iomode      lseg    match
+ * -----       -----   -----
+ * ANY         READ    true
+ * ANY         RW      true
+ * RW          READ    false
+ * RW          RW      true
+ * READ                READ    true
+ * READ                RW      true
+ */
+static int
+is_matching_lseg(struct pnfs_layout_segment *lseg, u32 iomode)
+{
+       return (iomode != IOMODE_RW || lseg->range.iomode == IOMODE_RW);
+}
+
+/*
+ * lookup range in layout
+ */
+static struct pnfs_layout_segment *
+pnfs_has_layout(struct pnfs_layout_hdr *lo, u32 iomode)
+{
+       struct pnfs_layout_segment *lseg, *ret = NULL;
+
+       dprintk("%s:Begin\n", __func__);
+
+       assert_spin_locked(&lo->inode->i_lock);
+       list_for_each_entry(lseg, &lo->segs, fi_list) {
+               if (is_matching_lseg(lseg, iomode)) {
+                       ret = lseg;
+                       break;
+               }
+               if (cmp_layout(iomode, lseg->range.iomode) > 0)
+                       break;
+       }
+
+       dprintk("%s:Return lseg %p ref %d\n",
+               __func__, ret, ret ? atomic_read(&ret->kref.refcount) : 0);
+       return ret;
+}
+
+/*
+ * Layout segment is retreived from the server if not cached.
+ * The appropriate layout segment is referenced and returned to the caller.
+ */
+struct pnfs_layout_segment *
+pnfs_update_layout(struct inode *ino,
+                  struct nfs_open_context *ctx,
+                  enum pnfs_iomode iomode)
+{
+       struct nfs_inode *nfsi = NFS_I(ino);
+       struct pnfs_layout_hdr *lo;
+       struct pnfs_layout_segment *lseg = NULL;
+
+       if (!pnfs_enabled_sb(NFS_SERVER(ino)))
+               return NULL;
+       spin_lock(&ino->i_lock);
+       lo = pnfs_find_alloc_layout(ino);
+       if (lo == NULL) {
+               dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
+               goto out_unlock;
+       }
+
+       /* Check to see if the layout for the given range already exists */
+       lseg = pnfs_has_layout(lo, iomode);
+       if (lseg) {
+               dprintk("%s: Using cached lseg %p for iomode %d)\n",
+                       __func__, lseg, iomode);
+               goto out_unlock;
+       }
+
+       /* if LAYOUTGET already failed once we don't try again */
+       if (test_bit(lo_fail_bit(iomode), &nfsi->layout->state))
+               goto out_unlock;
+
+       get_layout_hdr_locked(lo); /* Matched in nfs4_layoutget_release */
+       spin_unlock(&ino->i_lock);
+
+       lseg = send_layoutget(lo, ctx, iomode);
+out:
+       dprintk("%s end, state 0x%lx lseg %p\n", __func__,
+               nfsi->layout->state, lseg);
+       return lseg;
+out_unlock:
+       spin_unlock(&ino->i_lock);
+       goto out;
+}
+
+int
+pnfs_layout_process(struct nfs4_layoutget *lgp)
+{
+       struct pnfs_layout_hdr *lo = NFS_I(lgp->args.inode)->layout;
+       struct nfs4_layoutget_res *res = &lgp->res;
+       struct pnfs_layout_segment *lseg;
+       struct inode *ino = lo->inode;
+       int status = 0;
+
+       /* Inject layout blob into I/O device driver */
+       lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res);
+       if (!lseg || IS_ERR(lseg)) {
+               if (!lseg)
+                       status = -ENOMEM;
+               else
+                       status = PTR_ERR(lseg);
+               dprintk("%s: Could not allocate layout: error %d\n",
+                      __func__, status);
+               goto out;
+       }
+
+       spin_lock(&ino->i_lock);
+       init_lseg(lo, lseg);
+       lseg->range = res->range;
+       *lgp->lsegpp = lseg;
+       pnfs_insert_layout(lo, lseg);
+
+       /* Done processing layoutget. Set the layout stateid */
+       pnfs_set_layout_stateid(lo, &res->stateid);
+       spin_unlock(&ino->i_lock);
+out:
+       return status;
+}
+
+/*
+ * Device ID cache. Currently supports one layout type per struct nfs_client.
+ * Add layout type to the lookup key to expand to support multiple types.
+ */
+int
+pnfs_alloc_init_deviceid_cache(struct nfs_client *clp,
+                        void (*free_callback)(struct pnfs_deviceid_node *))
+{
+       struct pnfs_deviceid_cache *c;
+
+       c = kzalloc(sizeof(struct pnfs_deviceid_cache), GFP_KERNEL);
+       if (!c)
+               return -ENOMEM;
+       spin_lock(&clp->cl_lock);
+       if (clp->cl_devid_cache != NULL) {
+               atomic_inc(&clp->cl_devid_cache->dc_ref);
+               dprintk("%s [kref [%d]]\n", __func__,
+                       atomic_read(&clp->cl_devid_cache->dc_ref));
+               kfree(c);
+       } else {
+               /* kzalloc initializes hlists */
+               spin_lock_init(&c->dc_lock);
+               atomic_set(&c->dc_ref, 1);
+               c->dc_free_callback = free_callback;
+               clp->cl_devid_cache = c;
+               dprintk("%s [new]\n", __func__);
+       }
+       spin_unlock(&clp->cl_lock);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pnfs_alloc_init_deviceid_cache);
+
+/*
+ * Called from pnfs_layoutdriver_type->free_lseg
+ * last layout segment reference frees deviceid
+ */
+void
+pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
+                 struct pnfs_deviceid_node *devid)
+{
+       struct nfs4_deviceid *id = &devid->de_id;
+       struct pnfs_deviceid_node *d;
+       struct hlist_node *n;
+       long h = nfs4_deviceid_hash(id);
+
+       dprintk("%s [%d]\n", __func__, atomic_read(&devid->de_ref));
+       if (!atomic_dec_and_lock(&devid->de_ref, &c->dc_lock))
+               return;
+
+       hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[h], de_node)
+               if (!memcmp(&d->de_id, id, sizeof(*id))) {
+                       hlist_del_rcu(&d->de_node);
+                       spin_unlock(&c->dc_lock);
+                       synchronize_rcu();
+                       c->dc_free_callback(devid);
+                       return;
+               }
+       spin_unlock(&c->dc_lock);
+       /* Why wasn't it found in  the list? */
+       BUG();
+}
+EXPORT_SYMBOL_GPL(pnfs_put_deviceid);
+
+/* Find and reference a deviceid */
+struct pnfs_deviceid_node *
+pnfs_find_get_deviceid(struct pnfs_deviceid_cache *c, struct nfs4_deviceid *id)
+{
+       struct pnfs_deviceid_node *d;
+       struct hlist_node *n;
+       long hash = nfs4_deviceid_hash(id);
+
+       dprintk("--> %s hash %ld\n", __func__, hash);
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(d, n, &c->dc_deviceids[hash], de_node) {
+               if (!memcmp(&d->de_id, id, sizeof(*id))) {
+                       if (!atomic_inc_not_zero(&d->de_ref)) {
+                               goto fail;
+                       } else {
+                               rcu_read_unlock();
+                               return d;
+                       }
+               }
+       }
+fail:
+       rcu_read_unlock();
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(pnfs_find_get_deviceid);
+
+/*
+ * Add a deviceid to the cache.
+ * GETDEVICEINFOs for same deviceid can race. If deviceid is found, discard new
+ */
+struct pnfs_deviceid_node *
+pnfs_add_deviceid(struct pnfs_deviceid_cache *c, struct pnfs_deviceid_node *new)
+{
+       struct pnfs_deviceid_node *d;
+       long hash = nfs4_deviceid_hash(&new->de_id);
+
+       dprintk("--> %s hash %ld\n", __func__, hash);
+       spin_lock(&c->dc_lock);
+       d = pnfs_find_get_deviceid(c, &new->de_id);
+       if (d) {
+               spin_unlock(&c->dc_lock);
+               dprintk("%s [discard]\n", __func__);
+               c->dc_free_callback(new);
+               return d;
+       }
+       INIT_HLIST_NODE(&new->de_node);
+       atomic_set(&new->de_ref, 1);
+       hlist_add_head_rcu(&new->de_node, &c->dc_deviceids[hash]);
+       spin_unlock(&c->dc_lock);
+       dprintk("%s [new]\n", __func__);
+       return new;
+}
+EXPORT_SYMBOL_GPL(pnfs_add_deviceid);
+
+void
+pnfs_put_deviceid_cache(struct nfs_client *clp)
+{
+       struct pnfs_deviceid_cache *local = clp->cl_devid_cache;
+
+       dprintk("--> %s cl_devid_cache %p\n", __func__, clp->cl_devid_cache);
+       if (atomic_dec_and_lock(&local->dc_ref, &clp->cl_lock)) {
+               int i;
+               /* Verify cache is empty */
+               for (i = 0; i < NFS4_DEVICE_ID_HASH_SIZE; i++)
+                       BUG_ON(!hlist_empty(&local->dc_deviceids[i]));
+               clp->cl_devid_cache = NULL;
+               spin_unlock(&clp->cl_lock);
+               kfree(local);
+       }
+}
+EXPORT_SYMBOL_GPL(pnfs_put_deviceid_cache);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
new file mode 100644 (file)
index 0000000..e12367d
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ *  pNFS client data structures.
+ *
+ *  Copyright (c) 2002
+ *  The Regents of the University of Michigan
+ *  All Rights Reserved
+ *
+ *  Dean Hildebrand <dhildebz@umich.edu>
+ *
+ *  Permission is granted to use, copy, create derivative works, and
+ *  redistribute this software and such derivative works for any purpose,
+ *  so long as the name of the University of Michigan is not used in
+ *  any advertising or publicity pertaining to the use or distribution
+ *  of this software without specific, written prior authorization. If
+ *  the above copyright notice or any other identification of the
+ *  University of Michigan is included in any copy of any portion of
+ *  this software, then the disclaimer below must also be included.
+ *
+ *  This software is provided as is, without representation or warranty
+ *  of any kind either express or implied, including without limitation
+ *  the implied warranties of merchantability, fitness for a particular
+ *  purpose, or noninfringement.  The Regents of the University of
+ *  Michigan shall not be liable for any damages, including special,
+ *  indirect, incidental, or consequential damages, with respect to any
+ *  claim arising out of or in connection with the use of the software,
+ *  even if it has been or is hereafter advised of the possibility of
+ *  such damages.
+ */
+
+#ifndef FS_NFS_PNFS_H
+#define FS_NFS_PNFS_H
+
+struct pnfs_layout_segment {
+       struct list_head fi_list;
+       struct pnfs_layout_range range;
+       struct kref kref;
+       struct pnfs_layout_hdr *layout;
+};
+
+#ifdef CONFIG_NFS_V4_1
+
+#define LAYOUT_NFSV4_1_MODULE_PREFIX "nfs-layouttype4"
+
+enum {
+       NFS_LAYOUT_RO_FAILED = 0,       /* get ro layout failed stop trying */
+       NFS_LAYOUT_RW_FAILED,           /* get rw layout failed stop trying */
+       NFS_LAYOUT_STATEID_SET,         /* have a valid layout stateid */
+};
+
+/* Per-layout driver specific registration structure */
+struct pnfs_layoutdriver_type {
+       struct list_head pnfs_tblid;
+       const u32 id;
+       const char *name;
+       struct module *owner;
+       int (*set_layoutdriver) (struct nfs_server *);
+       int (*clear_layoutdriver) (struct nfs_server *);
+       struct pnfs_layout_segment * (*alloc_lseg) (struct pnfs_layout_hdr *layoutid, struct nfs4_layoutget_res *lgr);
+       void (*free_lseg) (struct pnfs_layout_segment *lseg);
+};
+
+struct pnfs_layout_hdr {
+       unsigned long           refcount;
+       struct list_head        layouts;   /* other client layouts */
+       struct list_head        segs;      /* layout segments list */
+       seqlock_t               seqlock;   /* Protects the stateid */
+       nfs4_stateid            stateid;
+       unsigned long           state;
+       struct inode            *inode;
+};
+
+struct pnfs_device {
+       struct nfs4_deviceid dev_id;
+       unsigned int  layout_type;
+       unsigned int  mincount;
+       struct page **pages;
+       void          *area;
+       unsigned int  pgbase;
+       unsigned int  pglen;
+};
+
+/*
+ * Device ID RCU cache. A device ID is unique per client ID and layout type.
+ */
+#define NFS4_DEVICE_ID_HASH_BITS       5
+#define NFS4_DEVICE_ID_HASH_SIZE       (1 << NFS4_DEVICE_ID_HASH_BITS)
+#define NFS4_DEVICE_ID_HASH_MASK       (NFS4_DEVICE_ID_HASH_SIZE - 1)
+
+static inline u32
+nfs4_deviceid_hash(struct nfs4_deviceid *id)
+{
+       unsigned char *cptr = (unsigned char *)id->data;
+       unsigned int nbytes = NFS4_DEVICEID4_SIZE;
+       u32 x = 0;
+
+       while (nbytes--) {
+               x *= 37;
+               x += *cptr++;
+       }
+       return x & NFS4_DEVICE_ID_HASH_MASK;
+}
+
+struct pnfs_deviceid_node {
+       struct hlist_node       de_node;
+       struct nfs4_deviceid    de_id;
+       atomic_t                de_ref;
+};
+
+struct pnfs_deviceid_cache {
+       spinlock_t              dc_lock;
+       atomic_t                dc_ref;
+       void                    (*dc_free_callback)(struct pnfs_deviceid_node *);
+       struct hlist_head       dc_deviceids[NFS4_DEVICE_ID_HASH_SIZE];
+};
+
+extern int pnfs_alloc_init_deviceid_cache(struct nfs_client *,
+                       void (*free_callback)(struct pnfs_deviceid_node *));
+extern void pnfs_put_deviceid_cache(struct nfs_client *);
+extern struct pnfs_deviceid_node *pnfs_find_get_deviceid(
+                               struct pnfs_deviceid_cache *,
+                               struct nfs4_deviceid *);
+extern struct pnfs_deviceid_node *pnfs_add_deviceid(
+                               struct pnfs_deviceid_cache *,
+                               struct pnfs_deviceid_node *);
+extern void pnfs_put_deviceid(struct pnfs_deviceid_cache *c,
+                             struct pnfs_deviceid_node *devid);
+
+extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
+extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
+
+/* nfs4proc.c */
+extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
+                                  struct pnfs_device *dev);
+extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp);
+
+/* pnfs.c */
+struct pnfs_layout_segment *
+pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
+                  enum pnfs_iomode access_type);
+void set_pnfs_layoutdriver(struct nfs_server *, u32 id);
+void unset_pnfs_layoutdriver(struct nfs_server *);
+int pnfs_layout_process(struct nfs4_layoutget *lgp);
+void pnfs_destroy_layout(struct nfs_inode *);
+void pnfs_destroy_all_layouts(struct nfs_client *);
+void put_layout_hdr(struct inode *inode);
+void pnfs_get_layout_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
+                            struct nfs4_state *open_state);
+
+
+static inline int lo_fail_bit(u32 iomode)
+{
+       return iomode == IOMODE_RW ?
+                        NFS_LAYOUT_RW_FAILED : NFS_LAYOUT_RO_FAILED;
+}
+
+/* Return true if a layout driver is being used for this mountpoint */
+static inline int pnfs_enabled_sb(struct nfs_server *nfss)
+{
+       return nfss->pnfs_curr_ld != NULL;
+}
+
+#else  /* CONFIG_NFS_V4_1 */
+
+static inline void pnfs_destroy_all_layouts(struct nfs_client *clp)
+{
+}
+
+static inline void pnfs_destroy_layout(struct nfs_inode *nfsi)
+{
+}
+
+static inline struct pnfs_layout_segment *
+pnfs_update_layout(struct inode *ino, struct nfs_open_context *ctx,
+                  enum pnfs_iomode access_type)
+{
+       return NULL;
+}
+
+static inline void set_pnfs_layoutdriver(struct nfs_server *s, u32 id)
+{
+}
+
+static inline void unset_pnfs_layoutdriver(struct nfs_server *s)
+{
+}
+
+#endif /* CONFIG_NFS_V4_1 */
+
+#endif /* FS_NFS_PNFS_H */
index 611bec2..58e7f84 100644 (file)
@@ -258,7 +258,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-               int flags, struct nameidata *nd)
+               int flags, struct nfs_open_context *ctx)
 {
        struct nfs_createdata *data;
        struct rpc_message msg = {
@@ -365,17 +365,32 @@ static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir)
        return 1;
 }
 
+static void
+nfs_proc_rename_setup(struct rpc_message *msg, struct inode *dir)
+{
+       msg->rpc_proc = &nfs_procedures[NFSPROC_RENAME];
+}
+
+static int
+nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
+                    struct inode *new_dir)
+{
+       if (nfs_async_handle_expired_key(task))
+               return 0;
+       nfs_mark_for_revalidate(old_dir);
+       nfs_mark_for_revalidate(new_dir);
+       return 1;
+}
+
 static int
 nfs_proc_rename(struct inode *old_dir, struct qstr *old_name,
                struct inode *new_dir, struct qstr *new_name)
 {
        struct nfs_renameargs   arg = {
-               .fromfh         = NFS_FH(old_dir),
-               .fromname       = old_name->name,
-               .fromlen        = old_name->len,
-               .tofh           = NFS_FH(new_dir),
-               .toname         = new_name->name,
-               .tolen          = new_name->len
+               .old_dir        = NFS_FH(old_dir),
+               .old_name       = old_name,
+               .new_dir        = NFS_FH(new_dir),
+               .new_name       = new_name,
        };
        struct rpc_message msg = {
                .rpc_proc       = &nfs_procedures[NFSPROC_RENAME],
@@ -519,14 +534,14 @@ nfs_proc_rmdir(struct inode *dir, struct qstr *name)
  */
 static int
 nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
-                u64 cookie, struct page *page, unsigned int count, int plus)
+                u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
        struct nfs_readdirargs  arg = {
                .fh             = NFS_FH(dir),
                .cookie         = cookie,
                .count          = count,
-               .pages          = &page,
+               .pages          = pages,
        };
        struct rpc_message      msg = {
                .rpc_proc       = &nfs_procedures[NFSPROC_READDIR],
@@ -705,6 +720,8 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .unlink_setup   = nfs_proc_unlink_setup,
        .unlink_done    = nfs_proc_unlink_done,
        .rename         = nfs_proc_rename,
+       .rename_setup   = nfs_proc_rename_setup,
+       .rename_done    = nfs_proc_rename_done,
        .link           = nfs_proc_link,
        .symlink        = nfs_proc_symlink,
        .mkdir          = nfs_proc_mkdir,
index 87adc27..e4b62c6 100644 (file)
@@ -25,6 +25,7 @@
 #include "internal.h"
 #include "iostat.h"
 #include "fscache.h"
+#include "pnfs.h"
 
 #define NFSDBG_FACILITY                NFSDBG_PAGECACHE
 
@@ -46,7 +47,6 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->pages);
                p->npages = pagecount;
-               p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
                if (pagecount <= ARRAY_SIZE(p->page_array))
                        p->pagevec = p->page_array;
                else {
@@ -121,6 +121,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
        len = nfs_page_length(page);
        if (len == 0)
                return nfs_return_empty_page(page);
+       pnfs_update_layout(inode, ctx, IOMODE_READ);
        new = nfs_create_request(ctx, inode, page, 0, len);
        if (IS_ERR(new)) {
                unlock_page(page);
@@ -625,6 +626,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
        if (ret == 0)
                goto read_complete; /* all pages were read */
 
+       pnfs_update_layout(inode, desc.ctx, IOMODE_READ);
        if (rsize < PAGE_CACHE_SIZE)
                nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
        else
index f4cbf0c..3600ec7 100644 (file)
@@ -100,6 +100,7 @@ enum {
        Opt_addr, Opt_mountaddr, Opt_clientaddr,
        Opt_lookupcache,
        Opt_fscache_uniq,
+       Opt_local_lock,
 
        /* Special mount options */
        Opt_userspace, Opt_deprecated, Opt_sloppy,
@@ -171,6 +172,7 @@ static const match_table_t nfs_mount_option_tokens = {
 
        { Opt_lookupcache, "lookupcache=%s" },
        { Opt_fscache_uniq, "fsc=%s" },
+       { Opt_local_lock, "local_lock=%s" },
 
        { Opt_err, NULL }
 };
@@ -236,6 +238,22 @@ static match_table_t nfs_lookupcache_tokens = {
        { Opt_lookupcache_err, NULL }
 };
 
+enum {
+       Opt_local_lock_all, Opt_local_lock_flock, Opt_local_lock_posix,
+       Opt_local_lock_none,
+
+       Opt_local_lock_err
+};
+
+static match_table_t nfs_local_lock_tokens = {
+       { Opt_local_lock_all, "all" },
+       { Opt_local_lock_flock, "flock" },
+       { Opt_local_lock_posix, "posix" },
+       { Opt_local_lock_none, "none" },
+
+       { Opt_local_lock_err, NULL }
+};
+
 
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct dentry *, struct kstatfs *);
@@ -622,6 +640,7 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
        const struct proc_nfs_info *nfs_infop;
        struct nfs_client *clp = nfss->nfs_client;
        u32 version = clp->rpc_ops->version;
+       int local_flock, local_fcntl;
 
        seq_printf(m, ",vers=%u", version);
        seq_printf(m, ",rsize=%u", nfss->rsize);
@@ -670,6 +689,18 @@ static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss,
                else
                        seq_printf(m, ",lookupcache=pos");
        }
+
+       local_flock = nfss->flags & NFS_MOUNT_LOCAL_FLOCK;
+       local_fcntl = nfss->flags & NFS_MOUNT_LOCAL_FCNTL;
+
+       if (!local_flock && !local_fcntl)
+               seq_printf(m, ",local_lock=none");
+       else if (local_flock && local_fcntl)
+               seq_printf(m, ",local_lock=all");
+       else if (local_flock)
+               seq_printf(m, ",local_lock=flock");
+       else
+               seq_printf(m, ",local_lock=posix");
 }
 
 /*
@@ -1017,9 +1048,13 @@ static int nfs_parse_mount_options(char *raw,
                        break;
                case Opt_lock:
                        mnt->flags &= ~NFS_MOUNT_NONLM;
+                       mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+                                       NFS_MOUNT_LOCAL_FCNTL);
                        break;
                case Opt_nolock:
                        mnt->flags |= NFS_MOUNT_NONLM;
+                       mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+                                      NFS_MOUNT_LOCAL_FCNTL);
                        break;
                case Opt_v2:
                        mnt->flags &= ~NFS_MOUNT_VER3;
@@ -1420,6 +1455,34 @@ static int nfs_parse_mount_options(char *raw,
                        mnt->fscache_uniq = string;
                        mnt->options |= NFS_OPTION_FSCACHE;
                        break;
+               case Opt_local_lock:
+                       string = match_strdup(args);
+                       if (string == NULL)
+                               goto out_nomem;
+                       token = match_token(string, nfs_local_lock_tokens,
+                                       args);
+                       kfree(string);
+                       switch (token) {
+                       case Opt_local_lock_all:
+                               mnt->flags |= (NFS_MOUNT_LOCAL_FLOCK |
+                                              NFS_MOUNT_LOCAL_FCNTL);
+                               break;
+                       case Opt_local_lock_flock:
+                               mnt->flags |= NFS_MOUNT_LOCAL_FLOCK;
+                               break;
+                       case Opt_local_lock_posix:
+                               mnt->flags |= NFS_MOUNT_LOCAL_FCNTL;
+                               break;
+                       case Opt_local_lock_none:
+                               mnt->flags &= ~(NFS_MOUNT_LOCAL_FLOCK |
+                                               NFS_MOUNT_LOCAL_FCNTL);
+                               break;
+                       default:
+                               dfprintk(MOUNT, "NFS:   invalid "
+                                               "local_lock argument\n");
+                               return 0;
+                       };
+                       break;
 
                /*
                 * Special options
@@ -1825,6 +1888,12 @@ static int nfs_validate_mount_data(void *options,
                if (!args->nfs_server.hostname)
                        goto out_nomem;
 
+               if (!(data->flags & NFS_MOUNT_NONLM))
+                       args->flags &= ~(NFS_MOUNT_LOCAL_FLOCK|
+                                        NFS_MOUNT_LOCAL_FCNTL);
+               else
+                       args->flags |= (NFS_MOUNT_LOCAL_FLOCK|
+                                       NFS_MOUNT_LOCAL_FCNTL);
                /*
                 * The legacy version 6 binary mount data from userspace has a
                 * field used only to transport selinux information into the
@@ -2441,7 +2510,8 @@ static void nfs4_fill_super(struct super_block *sb)
 
 static void nfs4_validate_mount_flags(struct nfs_parsed_mount_data *args)
 {
-       args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3);
+       args->flags &= ~(NFS_MOUNT_NONLM|NFS_MOUNT_NOACL|NFS_MOUNT_VER3|
+                        NFS_MOUNT_LOCAL_FLOCK|NFS_MOUNT_LOCAL_FCNTL);
 }
 
 static int nfs4_validate_text_mount_data(void *options,
index ad4d2e7..978aaeb 100644 (file)
@@ -32,6 +32,7 @@ static ctl_table nfs_cb_sysctls[] = {
                .extra1 = (int *)&nfs_set_port_min,
                .extra2 = (int *)&nfs_set_port_max,
        },
+#ifndef CONFIG_NFS_USE_NEW_IDMAPPER
        {
                .procname = "idmap_cache_timeout",
                .data = &nfs_idmap_cache_timeout,
@@ -39,6 +40,7 @@ static ctl_table nfs_cb_sysctls[] = {
                .mode = 0644,
                .proc_handler = proc_dointvec_jiffies,
        },
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
 #endif
        {
                .procname       = "nfs_mountpoint_timeout",
index 2f84ada..9a16bad 100644 (file)
 #include <linux/nfs_fs.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/namei.h>
 
 #include "internal.h"
 #include "nfs4_fs.h"
+#include "iostat.h"
+#include "delegation.h"
 
 struct nfs_unlinkdata {
        struct hlist_node list;
@@ -244,7 +247,7 @@ void nfs_unblock_sillyrename(struct dentry *dentry)
  * @dir: parent directory of dentry
  * @dentry: dentry to unlink
  */
-int
+static int
 nfs_async_unlink(struct inode *dir, struct dentry *dentry)
 {
        struct nfs_unlinkdata *data;
@@ -259,7 +262,6 @@ nfs_async_unlink(struct inode *dir, struct dentry *dentry)
                status = PTR_ERR(data->cred);
                goto out_free;
        }
-       data->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        data->res.dir_attr = &data->dir_attr;
 
        status = -EBUSY;
@@ -303,3 +305,256 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
        if (data != NULL && (NFS_STALE(inode) || !nfs_call_unlink(dentry, data)))
                nfs_free_unlinkdata(data);
 }
+
+/* Cancel a queued async unlink. Called when a sillyrename run fails. */
+static void
+nfs_cancel_async_unlink(struct dentry *dentry)
+{
+       spin_lock(&dentry->d_lock);
+       if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
+               struct nfs_unlinkdata *data = dentry->d_fsdata;
+
+               dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
+               spin_unlock(&dentry->d_lock);
+               nfs_free_unlinkdata(data);
+               return;
+       }
+       spin_unlock(&dentry->d_lock);
+}
+
+struct nfs_renamedata {
+       struct nfs_renameargs   args;
+       struct nfs_renameres    res;
+       struct rpc_cred         *cred;
+       struct inode            *old_dir;
+       struct dentry           *old_dentry;
+       struct nfs_fattr        old_fattr;
+       struct inode            *new_dir;
+       struct dentry           *new_dentry;
+       struct nfs_fattr        new_fattr;
+};
+
+/**
+ * nfs_async_rename_done - Sillyrename post-processing
+ * @task: rpc_task of the sillyrename
+ * @calldata: nfs_renamedata for the sillyrename
+ *
+ * Do the directory attribute updates and the d_move
+ */
+static void nfs_async_rename_done(struct rpc_task *task, void *calldata)
+{
+       struct nfs_renamedata *data = calldata;
+       struct inode *old_dir = data->old_dir;
+       struct inode *new_dir = data->new_dir;
+
+       if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) {
+               nfs_restart_rpc(task, NFS_SERVER(old_dir)->nfs_client);
+               return;
+       }
+
+       if (task->tk_status != 0) {
+               nfs_cancel_async_unlink(data->old_dentry);
+               return;
+       }
+
+       nfs_set_verifier(data->old_dentry, nfs_save_change_attribute(old_dir));
+       d_move(data->old_dentry, data->new_dentry);
+}
+
+/**
+ * nfs_async_rename_release - Release the sillyrename data.
+ * @calldata: the struct nfs_renamedata to be released
+ */
+static void nfs_async_rename_release(void *calldata)
+{
+       struct nfs_renamedata   *data = calldata;
+       struct super_block *sb = data->old_dir->i_sb;
+
+       if (data->old_dentry->d_inode)
+               nfs_mark_for_revalidate(data->old_dentry->d_inode);
+
+       dput(data->old_dentry);
+       dput(data->new_dentry);
+       iput(data->old_dir);
+       iput(data->new_dir);
+       nfs_sb_deactive(sb);
+       put_rpccred(data->cred);
+       kfree(data);
+}
+
+#if defined(CONFIG_NFS_V4_1)
+static void nfs_rename_prepare(struct rpc_task *task, void *calldata)
+{
+       struct nfs_renamedata *data = calldata;
+       struct nfs_server *server = NFS_SERVER(data->old_dir);
+
+       if (nfs4_setup_sequence(server, &data->args.seq_args,
+                               &data->res.seq_res, 1, task))
+               return;
+       rpc_call_start(task);
+}
+#endif /* CONFIG_NFS_V4_1 */
+
+static const struct rpc_call_ops nfs_rename_ops = {
+       .rpc_call_done = nfs_async_rename_done,
+       .rpc_release = nfs_async_rename_release,
+#if defined(CONFIG_NFS_V4_1)
+       .rpc_call_prepare = nfs_rename_prepare,
+#endif /* CONFIG_NFS_V4_1 */
+};
+
+/**
+ * nfs_async_rename - perform an asynchronous rename operation
+ * @old_dir: directory that currently holds the dentry to be renamed
+ * @new_dir: target directory for the rename
+ * @old_dentry: original dentry to be renamed
+ * @new_dentry: dentry to which the old_dentry should be renamed
+ *
+ * It's expected that valid references to the dentries and inodes are held
+ */
+static struct rpc_task *
+nfs_async_rename(struct inode *old_dir, struct inode *new_dir,
+                struct dentry *old_dentry, struct dentry *new_dentry)
+{
+       struct nfs_renamedata *data;
+       struct rpc_message msg = { };
+       struct rpc_task_setup task_setup_data = {
+               .rpc_message = &msg,
+               .callback_ops = &nfs_rename_ops,
+               .workqueue = nfsiod_workqueue,
+               .rpc_client = NFS_CLIENT(old_dir),
+               .flags = RPC_TASK_ASYNC,
+       };
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
+               return ERR_PTR(-ENOMEM);
+       task_setup_data.callback_data = data,
+
+       data->cred = rpc_lookup_cred();
+       if (IS_ERR(data->cred)) {
+               struct rpc_task *task = ERR_CAST(data->cred);
+               kfree(data);
+               return task;
+       }
+
+       msg.rpc_argp = &data->args;
+       msg.rpc_resp = &data->res;
+       msg.rpc_cred = data->cred;
+
+       /* set up nfs_renamedata */
+       data->old_dir = old_dir;
+       atomic_inc(&old_dir->i_count);
+       data->new_dir = new_dir;
+       atomic_inc(&new_dir->i_count);
+       data->old_dentry = dget(old_dentry);
+       data->new_dentry = dget(new_dentry);
+       nfs_fattr_init(&data->old_fattr);
+       nfs_fattr_init(&data->new_fattr);
+
+       /* set up nfs_renameargs */
+       data->args.old_dir = NFS_FH(old_dir);
+       data->args.old_name = &old_dentry->d_name;
+       data->args.new_dir = NFS_FH(new_dir);
+       data->args.new_name = &new_dentry->d_name;
+
+       /* set up nfs_renameres */
+       data->res.old_fattr = &data->old_fattr;
+       data->res.new_fattr = &data->new_fattr;
+
+       nfs_sb_active(old_dir->i_sb);
+
+       NFS_PROTO(data->old_dir)->rename_setup(&msg, old_dir);
+
+       return rpc_run_task(&task_setup_data);
+}
+
+/**
+ * nfs_sillyrename - Perform a silly-rename of a dentry
+ * @dir: inode of directory that contains dentry
+ * @dentry: dentry to be sillyrenamed
+ *
+ * NFSv2/3 is stateless and the server doesn't know when the client is
+ * holding a file open. To prevent application problems when a file is
+ * unlinked while it's still open, the client performs a "silly-rename".
+ * That is, it renames the file to a hidden file in the same directory,
+ * and only performs the unlink once the last reference to it is put.
+ *
+ * The final cleanup is done during dentry_iput.
+ */
+int
+nfs_sillyrename(struct inode *dir, struct dentry *dentry)
+{
+       static unsigned int sillycounter;
+       const int      fileidsize  = sizeof(NFS_FILEID(dentry->d_inode))*2;
+       const int      countersize = sizeof(sillycounter)*2;
+       const int      slen        = sizeof(".nfs")+fileidsize+countersize-1;
+       char           silly[slen+1];
+       struct dentry *sdentry;
+       struct rpc_task *task;
+       int            error = -EIO;
+
+       dfprintk(VFS, "NFS: silly-rename(%s/%s, ct=%d)\n",
+               dentry->d_parent->d_name.name, dentry->d_name.name,
+               atomic_read(&dentry->d_count));
+       nfs_inc_stats(dir, NFSIOS_SILLYRENAME);
+
+       /*
+        * We don't allow a dentry to be silly-renamed twice.
+        */
+       error = -EBUSY;
+       if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
+               goto out;
+
+       sprintf(silly, ".nfs%*.*Lx",
+               fileidsize, fileidsize,
+               (unsigned long long)NFS_FILEID(dentry->d_inode));
+
+       /* Return delegation in anticipation of the rename */
+       nfs_inode_return_delegation(dentry->d_inode);
+
+       sdentry = NULL;
+       do {
+               char *suffix = silly + slen - countersize;
+
+               dput(sdentry);
+               sillycounter++;
+               sprintf(suffix, "%*.*x", countersize, countersize, sillycounter);
+
+               dfprintk(VFS, "NFS: trying to rename %s to %s\n",
+                               dentry->d_name.name, silly);
+
+               sdentry = lookup_one_len(silly, dentry->d_parent, slen);
+               /*
+                * N.B. Better to return EBUSY here ... it could be
+                * dangerous to delete the file while it's in use.
+                */
+               if (IS_ERR(sdentry))
+                       goto out;
+       } while (sdentry->d_inode != NULL); /* need negative lookup */
+
+       /* queue unlink first. Can't do this from rpc_release as it
+        * has to allocate memory
+        */
+       error = nfs_async_unlink(dir, dentry);
+       if (error)
+               goto out_dput;
+
+       /* run the rename task, undo unlink if it fails */
+       task = nfs_async_rename(dir, dir, dentry, sdentry);
+       if (IS_ERR(task)) {
+               error = -EBUSY;
+               nfs_cancel_async_unlink(dentry);
+               goto out_dput;
+       }
+
+       /* wait for the RPC task to complete, unless a SIGKILL intervenes */
+       error = rpc_wait_for_completion_task(task);
+       if (error == 0)
+               error = task->tk_status;
+       rpc_put_task(task);
+out_dput:
+       dput(sdentry);
+out:
+       return error;
+}
index 874972d..4c14c17 100644 (file)
@@ -55,7 +55,6 @@ struct nfs_write_data *nfs_commitdata_alloc(void)
        if (p) {
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->pages);
-               p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
        }
        return p;
 }
@@ -75,7 +74,6 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount)
                memset(p, 0, sizeof(*p));
                INIT_LIST_HEAD(&p->pages);
                p->npages = pagecount;
-               p->res.seq_res.sr_slotid = NFS4_MAX_SLOT_TABLE;
                if (pagecount <= ARRAY_SIZE(p->page_array))
                        p->pagevec = p->page_array;
                else {
@@ -292,9 +290,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc, st
        nfs_add_stats(inode, NFSIOS_WRITEPAGES, 1);
 
        nfs_pageio_cond_complete(pgio, page->index);
-       ret = nfs_page_async_flush(pgio, page,
-                       wbc->sync_mode == WB_SYNC_NONE ||
-                       wbc->nonblocking != 0);
+       ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE);
        if (ret == -EAGAIN) {
                redirty_page_for_writepage(wbc, page);
                ret = 0;
@@ -1433,15 +1429,17 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr
        int flags = FLUSH_SYNC;
        int ret = 0;
 
-       /* Don't commit yet if this is a non-blocking flush and there are
-        * lots of outstanding writes for this mapping.
-        */
-       if (wbc->sync_mode == WB_SYNC_NONE &&
-           nfsi->ncommit <= (nfsi->npages >> 1))
-               goto out_mark_dirty;
+       if (wbc->sync_mode == WB_SYNC_NONE) {
+               /* Don't commit yet if this is a non-blocking flush and there
+                * are a lot of outstanding writes for this mapping.
+                */
+               if (nfsi->ncommit <= (nfsi->npages >> 1))
+                       goto out_mark_dirty;
 
-       if (wbc->nonblocking || wbc->for_background)
+               /* don't wait for the COMMIT response */
                flags = 0;
+       }
+
        ret = nfs_commit_inode(inode, flags);
        if (ret >= 0) {
                if (wbc->sync_mode == WB_SYNC_NONE) {
index 7cf4dda..31a78fc 100644 (file)
@@ -29,6 +29,18 @@ config NFSD
 
          If unsure, say N.
 
+config NFSD_DEPRECATED
+       bool "Include support for deprecated syscall interface to NFSD"
+       depends on NFSD
+       default y
+       help
+         The syscall interface to nfsd was obsoleted in 2.6.0 by a new
+         filesystem based interface.  The old interface is due for removal
+         in 2.6.40.  If you wish to remove the interface before then
+         say N.
+
+         In unsure, say Y.
+
 config NFSD_V2_ACL
        bool
        depends on NFSD
index c2a4f71..c0fcb7a 100644 (file)
@@ -28,9 +28,6 @@
 typedef struct auth_domain     svc_client;
 typedef struct svc_export      svc_export;
 
-static void            exp_do_unexport(svc_export *unexp);
-static int             exp_verify_string(char *cp, int max);
-
 /*
  * We have two caches.
  * One maps client+vfsmnt+dentry to export options - the export map
@@ -802,6 +799,7 @@ exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp)
        return ek;
 }
 
+#ifdef CONFIG_NFSD_DEPRECATED
 static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
                       struct svc_export *exp)
 {
@@ -852,6 +850,7 @@ exp_get_fsid_key(svc_client *clp, int fsid)
 
        return exp_find_key(clp, FSID_NUM, fsidv, NULL);
 }
+#endif
 
 static svc_export *exp_get_by_name(svc_client *clp, const struct path *path,
                                     struct cache_req *reqp)
@@ -893,6 +892,7 @@ static struct svc_export *exp_parent(svc_client *clp, struct path *path)
        return exp;
 }
 
+#ifdef CONFIG_NFSD_DEPRECATED
 /*
  * Hashtable locking. Write locks are placed only by user processes
  * wanting to modify export information.
@@ -925,6 +925,19 @@ exp_writeunlock(void)
 {
        up_write(&hash_sem);
 }
+#else
+
+/* hash_sem not needed once deprecated interface is removed */
+void exp_readlock(void) {}
+static inline void exp_writelock(void){}
+void exp_readunlock(void) {}
+static inline void exp_writeunlock(void){}
+
+#endif
+
+#ifdef CONFIG_NFSD_DEPRECATED
+static void            exp_do_unexport(svc_export *unexp);
+static int             exp_verify_string(char *cp, int max);
 
 static void exp_fsid_unhash(struct svc_export *exp)
 {
@@ -935,10 +948,9 @@ static void exp_fsid_unhash(struct svc_export *exp)
 
        ek = exp_get_fsid_key(exp->ex_client, exp->ex_fsid);
        if (!IS_ERR(ek)) {
-               ek->h.expiry_time = get_seconds()-1;
+               sunrpc_invalidate(&ek->h, &svc_expkey_cache);
                cache_put(&ek->h, &svc_expkey_cache);
        }
-       svc_expkey_cache.nextcheck = get_seconds();
 }
 
 static int exp_fsid_hash(svc_client *clp, struct svc_export *exp)
@@ -973,10 +985,9 @@ static void exp_unhash(struct svc_export *exp)
 
        ek = exp_get_key(exp->ex_client, inode->i_sb->s_dev, inode->i_ino);
        if (!IS_ERR(ek)) {
-               ek->h.expiry_time = get_seconds()-1;
+               sunrpc_invalidate(&ek->h, &svc_expkey_cache);
                cache_put(&ek->h, &svc_expkey_cache);
        }
-       svc_expkey_cache.nextcheck = get_seconds();
 }
        
 /*
@@ -1097,8 +1108,7 @@ out:
 static void
 exp_do_unexport(svc_export *unexp)
 {
-       unexp->h.expiry_time = get_seconds()-1;
-       svc_export_cache.nextcheck = get_seconds();
+       sunrpc_invalidate(&unexp->h, &svc_export_cache);
        exp_unhash(unexp);
        exp_fsid_unhash(unexp);
 }
@@ -1150,6 +1160,7 @@ out_unlock:
        exp_writeunlock();
        return err;
 }
+#endif /* CONFIG_NFSD_DEPRECATED */
 
 /*
  * Obtain the root fh on behalf of a client.
@@ -1459,25 +1470,43 @@ static void show_secinfo_flags(struct seq_file *m, int flags)
        show_expflags(m, flags, NFSEXP_SECINFO_FLAGS);
 }
 
+static bool secinfo_flags_equal(int f, int g)
+{
+       f &= NFSEXP_SECINFO_FLAGS;
+       g &= NFSEXP_SECINFO_FLAGS;
+       return f == g;
+}
+
+static int show_secinfo_run(struct seq_file *m, struct exp_flavor_info **fp, struct exp_flavor_info *end)
+{
+       int flags;
+
+       flags = (*fp)->flags;
+       seq_printf(m, ",sec=%d", (*fp)->pseudoflavor);
+       (*fp)++;
+       while (*fp != end && secinfo_flags_equal(flags, (*fp)->flags)) {
+               seq_printf(m, ":%d", (*fp)->pseudoflavor);
+               (*fp)++;
+       }
+       return flags;
+}
+
 static void show_secinfo(struct seq_file *m, struct svc_export *exp)
 {
        struct exp_flavor_info *f;
        struct exp_flavor_info *end = exp->ex_flavors + exp->ex_nflavors;
-       int lastflags = 0, first = 0;
+       int flags;
 
        if (exp->ex_nflavors == 0)
                return;
-       for (f = exp->ex_flavors; f < end; f++) {
-               if (first || f->flags != lastflags) {
-                       if (!first)
-                               show_secinfo_flags(m, lastflags);
-                       seq_printf(m, ",sec=%d", f->pseudoflavor);
-                       lastflags = f->flags;
-               } else {
-                       seq_printf(m, ":%d", f->pseudoflavor);
-               }
+       f = exp->ex_flavors;
+       flags = show_secinfo_run(m, &f, end);
+       if (!secinfo_flags_equal(flags, exp->ex_flags))
+               show_secinfo_flags(m, flags);
+       while (f != end) {
+               flags = show_secinfo_run(m, &f, end);
+               show_secinfo_flags(m, flags);
        }
-       show_secinfo_flags(m, lastflags);
 }
 
 static void exp_flags(struct seq_file *m, int flag, int fsid,
@@ -1532,6 +1561,7 @@ const struct seq_operations nfs_exports_op = {
        .show   = e_show,
 };
 
+#ifdef CONFIG_NFSD_DEPRECATED
 /*
  * Add or modify a client.
  * Change requests may involve the list of host addresses. The list of
@@ -1563,7 +1593,7 @@ exp_addclient(struct nfsctl_client *ncp)
        /* Insert client into hashtable. */
        for (i = 0; i < ncp->cl_naddr; i++) {
                ipv6_addr_set_v4mapped(ncp->cl_addrlist[i].s_addr, &addr6);
-               auth_unix_add_addr(&addr6, dom);
+               auth_unix_add_addr(&init_net, &addr6, dom);
        }
        auth_unix_forget_old(dom);
        auth_domain_put(dom);
@@ -1621,6 +1651,7 @@ exp_verify_string(char *cp, int max)
        printk(KERN_NOTICE "nfsd: couldn't validate string %s\n", cp);
        return 0;
 }
+#endif /* CONFIG_NFSD_DEPRECATED */
 
 /*
  * Initialize the exports module.
index 988cbb3..143da2e 100644 (file)
@@ -41,7 +41,6 @@
 
 #define NFSPROC4_CB_NULL 0
 #define NFSPROC4_CB_COMPOUND 1
-#define NFS4_STATEID_SIZE 16
 
 /* Index of predefined Linux callback client operations */
 
@@ -248,10 +247,11 @@ encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp,
 }
 
 static void
-encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *args,
+encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
                   struct nfs4_cb_compound_hdr *hdr)
 {
        __be32 *p;
+       struct nfsd4_session *ses = cb->cb_clp->cl_cb_session;
 
        if (hdr->minorversion == 0)
                return;
@@ -259,8 +259,8 @@ encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *args,
        RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20);
 
        WRITE32(OP_CB_SEQUENCE);
-       WRITEMEM(args->cbs_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN);
-       WRITE32(args->cbs_clp->cl_cb_seq_nr);
+       WRITEMEM(ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN);
+       WRITE32(ses->se_cb_seq_nr);
        WRITE32(0);             /* slotid, always 0 */
        WRITE32(0);             /* highest slotid always 0 */
        WRITE32(0);             /* cachethis always 0 */
@@ -280,18 +280,18 @@ nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p)
 
 static int
 nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p,
-               struct nfs4_rpc_args *rpc_args)
+               struct nfsd4_callback *cb)
 {
        struct xdr_stream xdr;
-       struct nfs4_delegation *args = rpc_args->args_op;
+       struct nfs4_delegation *args = cb->cb_op;
        struct nfs4_cb_compound_hdr hdr = {
-               .ident = args->dl_ident,
-               .minorversion = rpc_args->args_seq.cbs_minorversion,
+               .ident = cb->cb_clp->cl_cb_ident,
+               .minorversion = cb->cb_minorversion,
        };
 
        xdr_init_encode(&xdr, &req->rq_snd_buf, p);
        encode_cb_compound_hdr(&xdr, &hdr);
-       encode_cb_sequence(&xdr, &rpc_args->args_seq, &hdr);
+       encode_cb_sequence(&xdr, cb, &hdr);
        encode_cb_recall(&xdr, args, &hdr);
        encode_cb_nops(&hdr);
        return 0;
@@ -339,15 +339,16 @@ decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
  * with a single slot.
  */
 static int
-decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res,
+decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_callback *cb,
                   struct rpc_rqst *rqstp)
 {
+       struct nfsd4_session *ses = cb->cb_clp->cl_cb_session;
        struct nfs4_sessionid id;
        int status;
        u32 dummy;
        __be32 *p;
 
-       if (res->cbs_minorversion == 0)
+       if (cb->cb_minorversion == 0)
                return 0;
 
        status = decode_cb_op_hdr(xdr, OP_CB_SEQUENCE);
@@ -363,13 +364,12 @@ decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res,
        READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
        memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN);
        p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN);
-       if (memcmp(id.data, res->cbs_clp->cl_sessionid.data,
-                  NFS4_MAX_SESSIONID_LEN)) {
+       if (memcmp(id.data, ses->se_sessionid.data, NFS4_MAX_SESSIONID_LEN)) {
                dprintk("%s Invalid session id\n", __func__);
                goto out;
        }
        READ32(dummy);
-       if (dummy != res->cbs_clp->cl_cb_seq_nr) {
+       if (dummy != ses->se_cb_seq_nr) {
                dprintk("%s Invalid sequence number\n", __func__);
                goto out;
        }
@@ -393,7 +393,7 @@ nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p)
 
 static int
 nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
-               struct nfsd4_cb_sequence *seq)
+               struct nfsd4_callback *cb)
 {
        struct xdr_stream xdr;
        struct nfs4_cb_compound_hdr hdr;
@@ -403,8 +403,8 @@ nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p,
        status = decode_cb_compound_hdr(&xdr, &hdr);
        if (status)
                goto out;
-       if (seq) {
-               status = decode_cb_sequence(&xdr, seq, rqstp);
+       if (cb) {
+               status = decode_cb_sequence(&xdr, cb, rqstp);
                if (status)
                        goto out;
        }
@@ -473,30 +473,34 @@ static int max_cb_time(void)
 /* Reference counting, callback cleanup, etc., all look racy as heck.
  * And why is cl_cb_set an atomic? */
 
-int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
 {
        struct rpc_timeout      timeparms = {
                .to_initval     = max_cb_time(),
                .to_retries     = 0,
        };
        struct rpc_create_args args = {
-               .protocol       = XPRT_TRANSPORT_TCP,
-               .address        = (struct sockaddr *) &cb->cb_addr,
-               .addrsize       = cb->cb_addrlen,
+               .net            = &init_net,
+               .address        = (struct sockaddr *) &conn->cb_addr,
+               .addrsize       = conn->cb_addrlen,
                .timeout        = &timeparms,
                .program        = &cb_program,
-               .prognumber     = cb->cb_prog,
                .version        = 0,
                .authflavor     = clp->cl_flavor,
                .flags          = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET),
-               .client_name    = clp->cl_principal,
        };
        struct rpc_clnt *client;
 
-       if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
-               return -EINVAL;
-       if (cb->cb_minorversion) {
-               args.bc_xprt = cb->cb_xprt;
+       if (clp->cl_minorversion == 0) {
+               if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+                       return -EINVAL;
+               args.client_name = clp->cl_principal;
+               args.prognumber = conn->cb_prog,
+               args.protocol = XPRT_TRANSPORT_TCP;
+               clp->cl_cb_ident = conn->cb_ident;
+       } else {
+               args.bc_xprt = conn->cb_xprt;
+               args.prognumber = clp->cl_cb_session->se_cb_prog;
                args.protocol = XPRT_TRANSPORT_BC_TCP;
        }
        /* Create RPC client */
@@ -506,7 +510,7 @@ int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
                        PTR_ERR(client));
                return PTR_ERR(client);
        }
-       nfsd4_set_callback_client(clp, client);
+       clp->cl_cb_client = client;
        return 0;
 
 }
@@ -519,7 +523,7 @@ static void warn_no_callback_path(struct nfs4_client *clp, int reason)
 
 static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
 {
-       struct nfs4_client *clp = calldata;
+       struct nfs4_client *clp = container_of(calldata, struct nfs4_client, cl_cb_null);
 
        if (task->tk_status)
                warn_no_callback_path(clp, task->tk_status);
@@ -528,6 +532,8 @@ static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata)
 }
 
 static const struct rpc_call_ops nfsd4_cb_probe_ops = {
+       /* XXX: release method to ensure we set the cb channel down if
+        * necessary on early failure? */
        .rpc_call_done = nfsd4_cb_probe_done,
 };
 
@@ -543,38 +549,42 @@ int set_callback_cred(void)
        return 0;
 }
 
+static struct workqueue_struct *callback_wq;
 
-void do_probe_callback(struct nfs4_client *clp)
+static void do_probe_callback(struct nfs4_client *clp)
 {
-       struct rpc_message msg = {
-               .rpc_proc       = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL],
-               .rpc_argp       = clp,
-               .rpc_cred       = callback_cred
-       };
-       int status;
+       struct nfsd4_callback *cb = &clp->cl_cb_null;
 
-       status = rpc_call_async(clp->cl_cb_client, &msg,
-                               RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
-                               &nfsd4_cb_probe_ops, (void *)clp);
-       if (status)
-               warn_no_callback_path(clp, status);
+       cb->cb_op = NULL;
+       cb->cb_clp = clp;
+
+       cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL];
+       cb->cb_msg.rpc_argp = NULL;
+       cb->cb_msg.rpc_resp = NULL;
+       cb->cb_msg.rpc_cred = callback_cred;
+
+       cb->cb_ops = &nfsd4_cb_probe_ops;
+
+       queue_work(callback_wq, &cb->cb_work);
 }
 
 /*
- * Set up the callback client and put a NFSPROC4_CB_NULL on the wire...
+ * Poke the callback thread to process any updates to the callback
+ * parameters, and send a null probe.
  */
-void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
+void nfsd4_probe_callback(struct nfs4_client *clp)
 {
-       int status;
+       set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+       do_probe_callback(clp);
+}
 
+void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *conn)
+{
        BUG_ON(atomic_read(&clp->cl_cb_set));
 
-       status = setup_callback_client(clp, cb);
-       if (status) {
-               warn_no_callback_path(clp, status);
-               return;
-       }
-       do_probe_callback(clp);
+       spin_lock(&clp->cl_lock);
+       memcpy(&clp->cl_cb_conn, conn, sizeof(struct nfs4_cb_conn));
+       spin_unlock(&clp->cl_lock);
 }
 
 /*
@@ -585,8 +595,7 @@ void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *cb)
 static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
                struct rpc_task *task)
 {
-       struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
-       u32 *ptr = (u32 *)clp->cl_sessionid.data;
+       u32 *ptr = (u32 *)clp->cl_cb_session->se_sessionid.data;
        int status = 0;
 
        dprintk("%s: %u:%u:%u:%u\n", __func__,
@@ -598,14 +607,6 @@ static int nfsd41_cb_setup_sequence(struct nfs4_client *clp,
                status = -EAGAIN;
                goto out;
        }
-
-       /*
-        * We'll need the clp during XDR encoding and decoding,
-        * and the sequence during decoding to verify the reply
-        */
-       args->args_seq.cbs_clp = clp;
-       task->tk_msg.rpc_resp = &args->args_seq;
-
 out:
        dprintk("%s status=%d\n", __func__, status);
        return status;
@@ -617,13 +618,13 @@ out:
  */
 static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
 {
-       struct nfs4_delegation *dp = calldata;
+       struct nfsd4_callback *cb = calldata;
+       struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
        struct nfs4_client *clp = dp->dl_client;
-       struct nfs4_rpc_args *args = task->tk_msg.rpc_argp;
-       u32 minorversion = clp->cl_cb_conn.cb_minorversion;
+       u32 minorversion = clp->cl_minorversion;
        int status = 0;
 
-       args->args_seq.cbs_minorversion = minorversion;
+       cb->cb_minorversion = minorversion;
        if (minorversion) {
                status = nfsd41_cb_setup_sequence(clp, task);
                if (status) {
@@ -640,19 +641,20 @@ static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata)
 
 static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
 {
-       struct nfs4_delegation *dp = calldata;
+       struct nfsd4_callback *cb = calldata;
+       struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
        struct nfs4_client *clp = dp->dl_client;
 
        dprintk("%s: minorversion=%d\n", __func__,
-               clp->cl_cb_conn.cb_minorversion);
+               clp->cl_minorversion);
 
-       if (clp->cl_cb_conn.cb_minorversion) {
+       if (clp->cl_minorversion) {
                /* No need for lock, access serialized in nfsd4_cb_prepare */
-               ++clp->cl_cb_seq_nr;
+               ++clp->cl_cb_session->se_cb_seq_nr;
                clear_bit(0, &clp->cl_cb_slot_busy);
                rpc_wake_up_next(&clp->cl_cb_waitq);
                dprintk("%s: freed slot, new seqid=%d\n", __func__,
-                       clp->cl_cb_seq_nr);
+                       clp->cl_cb_session->se_cb_seq_nr);
 
                /* We're done looking into the sequence information */
                task->tk_msg.rpc_resp = NULL;
@@ -662,7 +664,8 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata)
 
 static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
 {
-       struct nfs4_delegation *dp = calldata;
+       struct nfsd4_callback *cb = calldata;
+       struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
        struct nfs4_client *clp = dp->dl_client;
        struct rpc_clnt *current_rpc_client = clp->cl_cb_client;
 
@@ -707,7 +710,8 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
 
 static void nfsd4_cb_recall_release(void *calldata)
 {
-       struct nfs4_delegation *dp = calldata;
+       struct nfsd4_callback *cb = calldata;
+       struct nfs4_delegation *dp = container_of(cb, struct nfs4_delegation, dl_recall);
 
        nfs4_put_delegation(dp);
 }
@@ -718,8 +722,6 @@ static const struct rpc_call_ops nfsd4_cb_recall_ops = {
        .rpc_release = nfsd4_cb_recall_release,
 };
 
-static struct workqueue_struct *callback_wq;
-
 int nfsd4_create_callback_queue(void)
 {
        callback_wq = create_singlethread_workqueue("nfsd4_callbacks");
@@ -734,57 +736,88 @@ void nfsd4_destroy_callback_queue(void)
 }
 
 /* must be called under the state lock */
-void nfsd4_set_callback_client(struct nfs4_client *clp, struct rpc_clnt *new)
+void nfsd4_shutdown_callback(struct nfs4_client *clp)
 {
-       struct rpc_clnt *old = clp->cl_cb_client;
-
-       clp->cl_cb_client = new;
+       set_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags);
        /*
-        * After this, any work that saw the old value of cl_cb_client will
-        * be gone:
+        * Note this won't actually result in a null callback;
+        * instead, nfsd4_do_callback_rpc() will detect the killed
+        * client, destroy the rpc client, and stop:
         */
+       do_probe_callback(clp);
        flush_workqueue(callback_wq);
-       /* So we can safely shut it down: */
-       if (old)
-               rpc_shutdown_client(old);
 }
 
-/*
- * called with dp->dl_count inc'ed.
- */
-static void _nfsd4_cb_recall(struct nfs4_delegation *dp)
+void nfsd4_release_cb(struct nfsd4_callback *cb)
 {
-       struct nfs4_client *clp = dp->dl_client;
-       struct rpc_clnt *clnt = clp->cl_cb_client;
-       struct nfs4_rpc_args *args = &dp->dl_recall.cb_args;
-       struct rpc_message msg = {
-               .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
-               .rpc_cred = callback_cred
-       };
+       if (cb->cb_ops->rpc_release)
+               cb->cb_ops->rpc_release(cb);
+}
 
-       if (clnt == NULL) {
-               nfs4_put_delegation(dp);
-               return; /* Client is shutting down; give up. */
+void nfsd4_process_cb_update(struct nfsd4_callback *cb)
+{
+       struct nfs4_cb_conn conn;
+       struct nfs4_client *clp = cb->cb_clp;
+       int err;
+
+       /*
+        * This is either an update, or the client dying; in either case,
+        * kill the old client:
+        */
+       if (clp->cl_cb_client) {
+               rpc_shutdown_client(clp->cl_cb_client);
+               clp->cl_cb_client = NULL;
        }
+       if (test_bit(NFSD4_CLIENT_KILL, &clp->cl_cb_flags))
+               return;
+       spin_lock(&clp->cl_lock);
+       /*
+        * Only serialized callback code is allowed to clear these
+        * flags; main nfsd code can only set them:
+        */
+       BUG_ON(!clp->cl_cb_flags);
+       clear_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_cb_flags);
+       memcpy(&conn, &cb->cb_clp->cl_cb_conn, sizeof(struct nfs4_cb_conn));
+       spin_unlock(&clp->cl_lock);
 
-       args->args_op = dp;
-       msg.rpc_argp = args;
-       dp->dl_retries = 1;
-       rpc_call_async(clnt, &msg, RPC_TASK_SOFT, &nfsd4_cb_recall_ops, dp);
+       err = setup_callback_client(clp, &conn);
+       if (err)
+               warn_no_callback_path(clp, err);
 }
 
 void nfsd4_do_callback_rpc(struct work_struct *w)
 {
-       /* XXX: for now, just send off delegation recall. */
-       /* In future, generalize to handle any sort of callback. */
-       struct nfsd4_callback *c = container_of(w, struct nfsd4_callback, cb_work);
-       struct nfs4_delegation *dp = container_of(c, struct nfs4_delegation, dl_recall);
+       struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, cb_work);
+       struct nfs4_client *clp = cb->cb_clp;
+       struct rpc_clnt *clnt;
 
-       _nfsd4_cb_recall(dp);
-}
+       if (clp->cl_cb_flags)
+               nfsd4_process_cb_update(cb);
 
+       clnt = clp->cl_cb_client;
+       if (!clnt) {
+               /* Callback channel broken, or client killed; give up: */
+               nfsd4_release_cb(cb);
+               return;
+       }
+       rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
+                       cb->cb_ops, cb);
+}
 
 void nfsd4_cb_recall(struct nfs4_delegation *dp)
 {
+       struct nfsd4_callback *cb = &dp->dl_recall;
+
+       dp->dl_retries = 1;
+       cb->cb_op = dp;
+       cb->cb_clp = dp->dl_client;
+       cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL];
+       cb->cb_msg.rpc_argp = cb;
+       cb->cb_msg.rpc_resp = cb;
+       cb->cb_msg.rpc_cred = callback_cred;
+
+       cb->cb_ops = &nfsd4_cb_recall_ops;
+       dp->dl_retries = 1;
+
        queue_work(callback_wq, &dp->dl_recall.cb_work);
 }
index c78dbf4..f0695e8 100644 (file)
@@ -482,109 +482,26 @@ nfsd_idmap_shutdown(void)
        cache_unregister(&nametoid_cache);
 }
 
-/*
- * Deferred request handling
- */
-
-struct idmap_defer_req {
-       struct cache_req                req;
-       struct cache_deferred_req deferred_req;
-       wait_queue_head_t       waitq;
-       atomic_t                        count;
-};
-
-static inline void
-put_mdr(struct idmap_defer_req *mdr)
-{
-       if (atomic_dec_and_test(&mdr->count))
-               kfree(mdr);
-}
-
-static inline void
-get_mdr(struct idmap_defer_req *mdr)
-{
-       atomic_inc(&mdr->count);
-}
-
-static void
-idmap_revisit(struct cache_deferred_req *dreq, int toomany)
-{
-       struct idmap_defer_req *mdr =
-               container_of(dreq, struct idmap_defer_req, deferred_req);
-
-       wake_up(&mdr->waitq);
-       put_mdr(mdr);
-}
-
-static struct cache_deferred_req *
-idmap_defer(struct cache_req *req)
-{
-       struct idmap_defer_req *mdr =
-               container_of(req, struct idmap_defer_req, req);
-
-       mdr->deferred_req.revisit = idmap_revisit;
-       get_mdr(mdr);
-       return (&mdr->deferred_req);
-}
-
-static inline int
-do_idmap_lookup(struct ent *(*lookup_fn)(struct ent *), struct ent *key,
-               struct cache_detail *detail, struct ent **item,
-               struct idmap_defer_req *mdr)
-{
-       *item = lookup_fn(key);
-       if (!*item)
-               return -ENOMEM;
-       return cache_check(detail, &(*item)->h, &mdr->req);
-}
-
-static inline int
-do_idmap_lookup_nowait(struct ent *(*lookup_fn)(struct ent *),
-                       struct ent *key, struct cache_detail *detail,
-                       struct ent **item)
-{
-       int ret = -ENOMEM;
-
-       *item = lookup_fn(key);
-       if (!*item)
-               goto out_err;
-       ret = -ETIMEDOUT;
-       if (!test_bit(CACHE_VALID, &(*item)->h.flags)
-                       || (*item)->h.expiry_time < get_seconds()
-                       || detail->flush_time > (*item)->h.last_refresh)
-               goto out_put;
-       ret = -ENOENT;
-       if (test_bit(CACHE_NEGATIVE, &(*item)->h.flags))
-               goto out_put;
-       return 0;
-out_put:
-       cache_put(&(*item)->h, detail);
-out_err:
-       *item = NULL;
-       return ret;
-}
-
 static int
 idmap_lookup(struct svc_rqst *rqstp,
                struct ent *(*lookup_fn)(struct ent *), struct ent *key,
                struct cache_detail *detail, struct ent **item)
 {
-       struct idmap_defer_req *mdr;
        int ret;
 
-       mdr = kzalloc(sizeof(*mdr), GFP_KERNEL);
-       if (!mdr)
+       *item = lookup_fn(key);
+       if (!*item)
                return -ENOMEM;
-       atomic_set(&mdr->count, 1);
-       init_waitqueue_head(&mdr->waitq);
-       mdr->req.defer = idmap_defer;
-       ret = do_idmap_lookup(lookup_fn, key, detail, item, mdr);
-       if (ret == -EAGAIN) {
-               wait_event_interruptible_timeout(mdr->waitq,
-                       test_bit(CACHE_VALID, &(*item)->h.flags), 1 * HZ);
-               ret = do_idmap_lookup_nowait(lookup_fn, key, detail, item);
+ retry:
+       ret = cache_check(detail, &(*item)->h, &rqstp->rq_chandle);
+
+       if (ret == -ETIMEDOUT) {
+               struct ent *prev_item = *item;
+               *item = lookup_fn(key);
+               if (*item != prev_item)
+                       goto retry;
+               cache_put(&(*item)->h, detail);
        }
-       put_mdr(mdr);
        return ret;
 }
 
index 59ec449..0cdfd02 100644 (file)
@@ -1031,8 +1031,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
        resp->cstate.session = NULL;
        fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
        fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
-       /* Use the deferral mechanism only for NFSv4.0 compounds */
-       rqstp->rq_usedeferral = (args->minorversion == 0);
+       /*
+        * Don't use the deferral mechanism for NFSv4; compounds make it
+        * too hard to avoid non-idempotency problems.
+        */
+       rqstp->rq_usedeferral = 0;
 
        /*
         * According to RFC3010, this takes precedence over all other errors.
index a7292fc..9019e8e 100644 (file)
@@ -207,7 +207,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
 {
        struct nfs4_delegation *dp;
        struct nfs4_file *fp = stp->st_file;
-       struct nfs4_cb_conn *cb = &stp->st_stateowner->so_client->cl_cb_conn;
 
        dprintk("NFSD alloc_init_deleg\n");
        /*
@@ -234,7 +233,6 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
        nfs4_file_get_access(fp, O_RDONLY);
        dp->dl_flock = NULL;
        dp->dl_type = type;
-       dp->dl_ident = cb->cb_ident;
        dp->dl_stateid.si_boot = boot_time;
        dp->dl_stateid.si_stateownerid = current_delegid++;
        dp->dl_stateid.si_fileid = 0;
@@ -535,171 +533,258 @@ gen_sessionid(struct nfsd4_session *ses)
  */
 #define NFSD_MIN_HDR_SEQ_SZ  (24 + 12 + 44)
 
+static void
+free_session_slots(struct nfsd4_session *ses)
+{
+       int i;
+
+       for (i = 0; i < ses->se_fchannel.maxreqs; i++)
+               kfree(ses->se_slots[i]);
+}
+
 /*
- * Give the client the number of ca_maxresponsesize_cached slots it
- * requests, of size bounded by NFSD_SLOT_CACHE_SIZE,
- * NFSD_MAX_MEM_PER_SESSION, and nfsd_drc_max_mem. Do not allow more
- * than NFSD_MAX_SLOTS_PER_SESSION.
- *
- * If we run out of reserved DRC memory we should (up to a point)
+ * We don't actually need to cache the rpc and session headers, so we
+ * can allocate a little less for each slot:
+ */
+static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
+{
+       return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
+}
+
+static int nfsd4_sanitize_slot_size(u32 size)
+{
+       size -= NFSD_MIN_HDR_SEQ_SZ; /* We don't cache the rpc header */
+       size = min_t(u32, size, NFSD_SLOT_CACHE_SIZE);
+
+       return size;
+}
+
+/*
+ * XXX: If we run out of reserved DRC memory we could (up to a point)
  * re-negotiate active sessions and reduce their slot usage to make
  * rooom for new connections. For now we just fail the create session.
  */
-static int set_forechannel_drc_size(struct nfsd4_channel_attrs *fchan)
+static int nfsd4_get_drc_mem(int slotsize, u32 num)
 {
-       int mem, size = fchan->maxresp_cached;
+       int avail;
 
-       if (fchan->maxreqs < 1)
-               return nfserr_inval;
+       num = min_t(u32, num, NFSD_MAX_SLOTS_PER_SESSION);
 
-       if (size < NFSD_MIN_HDR_SEQ_SZ)
-               size = NFSD_MIN_HDR_SEQ_SZ;
-       size -= NFSD_MIN_HDR_SEQ_SZ;
-       if (size > NFSD_SLOT_CACHE_SIZE)
-               size = NFSD_SLOT_CACHE_SIZE;
-
-       /* bound the maxreqs by NFSD_MAX_MEM_PER_SESSION */
-       mem = fchan->maxreqs * size;
-       if (mem > NFSD_MAX_MEM_PER_SESSION) {
-               fchan->maxreqs = NFSD_MAX_MEM_PER_SESSION / size;
-               if (fchan->maxreqs > NFSD_MAX_SLOTS_PER_SESSION)
-                       fchan->maxreqs = NFSD_MAX_SLOTS_PER_SESSION;
-               mem = fchan->maxreqs * size;
-       }
+       spin_lock(&nfsd_drc_lock);
+       avail = min_t(int, NFSD_MAX_MEM_PER_SESSION,
+                       nfsd_drc_max_mem - nfsd_drc_mem_used);
+       num = min_t(int, num, avail / slotsize);
+       nfsd_drc_mem_used += num * slotsize;
+       spin_unlock(&nfsd_drc_lock);
 
+       return num;
+}
+
+static void nfsd4_put_drc_mem(int slotsize, int num)
+{
        spin_lock(&nfsd_drc_lock);
-       /* bound the total session drc memory ussage */
-       if (mem + nfsd_drc_mem_used > nfsd_drc_max_mem) {
-               fchan->maxreqs = (nfsd_drc_max_mem - nfsd_drc_mem_used) / size;
-               mem = fchan->maxreqs * size;
-       }
-       nfsd_drc_mem_used += mem;
+       nfsd_drc_mem_used -= slotsize * num;
        spin_unlock(&nfsd_drc_lock);
+}
 
-       if (fchan->maxreqs == 0)
-               return nfserr_jukebox;
+static struct nfsd4_session *alloc_session(int slotsize, int numslots)
+{
+       struct nfsd4_session *new;
+       int mem, i;
 
-       fchan->maxresp_cached = size + NFSD_MIN_HDR_SEQ_SZ;
-       return 0;
+       BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot *)
+                       + sizeof(struct nfsd4_session) > PAGE_SIZE);
+       mem = numslots * sizeof(struct nfsd4_slot *);
+
+       new = kzalloc(sizeof(*new) + mem, GFP_KERNEL);
+       if (!new)
+               return NULL;
+       /* allocate each struct nfsd4_slot and data cache in one piece */
+       for (i = 0; i < numslots; i++) {
+               mem = sizeof(struct nfsd4_slot) + slotsize;
+               new->se_slots[i] = kzalloc(mem, GFP_KERNEL);
+               if (!new->se_slots[i])
+                       goto out_free;
+       }
+       return new;
+out_free:
+       while (i--)
+               kfree(new->se_slots[i]);
+       kfree(new);
+       return NULL;
 }
 
-/*
- * fchan holds the client values on input, and the server values on output
- * sv_max_mesg is the maximum payload plus one page for overhead.
- */
-static int init_forechannel_attrs(struct svc_rqst *rqstp,
-                                 struct nfsd4_channel_attrs *session_fchan,
-                                 struct nfsd4_channel_attrs *fchan)
+static void init_forechannel_attrs(struct nfsd4_channel_attrs *new, struct nfsd4_channel_attrs *req, int numslots, int slotsize)
 {
-       int status = 0;
-       __u32   maxcount = nfsd_serv->sv_max_mesg;
+       u32 maxrpc = nfsd_serv->sv_max_mesg;
 
-       /* headerpadsz set to zero in encode routine */
+       new->maxreqs = numslots;
+       new->maxresp_cached = slotsize + NFSD_MIN_HDR_SEQ_SZ;
+       new->maxreq_sz = min_t(u32, req->maxreq_sz, maxrpc);
+       new->maxresp_sz = min_t(u32, req->maxresp_sz, maxrpc);
+       new->maxops = min_t(u32, req->maxops, NFSD_MAX_OPS_PER_COMPOUND);
+}
 
-       /* Use the client's max request and max response size if possible */
-       if (fchan->maxreq_sz > maxcount)
-               fchan->maxreq_sz = maxcount;
-       session_fchan->maxreq_sz = fchan->maxreq_sz;
+static void free_conn(struct nfsd4_conn *c)
+{
+       svc_xprt_put(c->cn_xprt);
+       kfree(c);
+}
 
-       if (fchan->maxresp_sz > maxcount)
-               fchan->maxresp_sz = maxcount;
-       session_fchan->maxresp_sz = fchan->maxresp_sz;
+static void nfsd4_conn_lost(struct svc_xpt_user *u)
+{
+       struct nfsd4_conn *c = container_of(u, struct nfsd4_conn, cn_xpt_user);
+       struct nfs4_client *clp = c->cn_session->se_client;
 
-       /* Use the client's maxops if possible */
-       if (fchan->maxops > NFSD_MAX_OPS_PER_COMPOUND)
-               fchan->maxops = NFSD_MAX_OPS_PER_COMPOUND;
-       session_fchan->maxops = fchan->maxops;
+       spin_lock(&clp->cl_lock);
+       if (!list_empty(&c->cn_persession)) {
+               list_del(&c->cn_persession);
+               free_conn(c);
+       }
+       spin_unlock(&clp->cl_lock);
+}
 
-       /* FIXME: Error means no more DRC pages so the server should
-        * recover pages from existing sessions. For now fail session
-        * creation.
-        */
-       status = set_forechannel_drc_size(fchan);
+static struct nfsd4_conn *alloc_conn(struct svc_rqst *rqstp, u32 flags)
+{
+       struct nfsd4_conn *conn;
 
-       session_fchan->maxresp_cached = fchan->maxresp_cached;
-       session_fchan->maxreqs = fchan->maxreqs;
+       conn = kmalloc(sizeof(struct nfsd4_conn), GFP_KERNEL);
+       if (!conn)
+               return NULL;
+       svc_xprt_get(rqstp->rq_xprt);
+       conn->cn_xprt = rqstp->rq_xprt;
+       conn->cn_flags = flags;
+       INIT_LIST_HEAD(&conn->cn_xpt_user.list);
+       return conn;
+}
 
-       dprintk("%s status %d\n", __func__, status);
-       return status;
+static void __nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
+{
+       conn->cn_session = ses;
+       list_add(&conn->cn_persession, &ses->se_conns);
 }
 
-static void
-free_session_slots(struct nfsd4_session *ses)
+static void nfsd4_hash_conn(struct nfsd4_conn *conn, struct nfsd4_session *ses)
 {
-       int i;
+       struct nfs4_client *clp = ses->se_client;
 
-       for (i = 0; i < ses->se_fchannel.maxreqs; i++)
-               kfree(ses->se_slots[i]);
+       spin_lock(&clp->cl_lock);
+       __nfsd4_hash_conn(conn, ses);
+       spin_unlock(&clp->cl_lock);
 }
 
-/*
- * We don't actually need to cache the rpc and session headers, so we
- * can allocate a little less for each slot:
- */
-static inline int slot_bytes(struct nfsd4_channel_attrs *ca)
+static void nfsd4_register_conn(struct nfsd4_conn *conn)
 {
-       return ca->maxresp_cached - NFSD_MIN_HDR_SEQ_SZ;
+       conn->cn_xpt_user.callback = nfsd4_conn_lost;
+       register_xpt_user(conn->cn_xprt, &conn->cn_xpt_user);
 }
 
-static int
-alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp,
-                  struct nfsd4_create_session *cses)
+static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses)
 {
-       struct nfsd4_session *new, tmp;
-       struct nfsd4_slot *sp;
-       int idx, slotsize, cachesize, i;
-       int status;
+       struct nfsd4_conn *conn;
+       u32 flags = NFS4_CDFC4_FORE;
 
-       memset(&tmp, 0, sizeof(tmp));
+       if (ses->se_flags & SESSION4_BACK_CHAN)
+               flags |= NFS4_CDFC4_BACK;
+       conn = alloc_conn(rqstp, flags);
+       if (!conn)
+               return nfserr_jukebox;
+       nfsd4_hash_conn(conn, ses);
+       nfsd4_register_conn(conn);
+       return nfs_ok;
+}
 
-       /* FIXME: For now, we just accept the client back channel attributes. */
-       tmp.se_bchannel = cses->back_channel;
-       status = init_forechannel_attrs(rqstp, &tmp.se_fchannel,
-                                       &cses->fore_channel);
-       if (status)
-               goto out;
+static void nfsd4_del_conns(struct nfsd4_session *s)
+{
+       struct nfs4_client *clp = s->se_client;
+       struct nfsd4_conn *c;
 
-       BUILD_BUG_ON(NFSD_MAX_SLOTS_PER_SESSION * sizeof(struct nfsd4_slot)
-                    + sizeof(struct nfsd4_session) > PAGE_SIZE);
+       spin_lock(&clp->cl_lock);
+       while (!list_empty(&s->se_conns)) {
+               c = list_first_entry(&s->se_conns, struct nfsd4_conn, cn_persession);
+               list_del_init(&c->cn_persession);
+               spin_unlock(&clp->cl_lock);
 
-       status = nfserr_jukebox;
-       /* allocate struct nfsd4_session and slot table pointers in one piece */
-       slotsize = tmp.se_fchannel.maxreqs * sizeof(struct nfsd4_slot *);
-       new = kzalloc(sizeof(*new) + slotsize, GFP_KERNEL);
-       if (!new)
-               goto out;
+               unregister_xpt_user(c->cn_xprt, &c->cn_xpt_user);
+               free_conn(c);
 
-       memcpy(new, &tmp, sizeof(*new));
+               spin_lock(&clp->cl_lock);
+       }
+       spin_unlock(&clp->cl_lock);
+}
 
-       /* allocate each struct nfsd4_slot and data cache in one piece */
-       cachesize = slot_bytes(&new->se_fchannel);
-       for (i = 0; i < new->se_fchannel.maxreqs; i++) {
-               sp = kzalloc(sizeof(*sp) + cachesize, GFP_KERNEL);
-               if (!sp)
-                       goto out_free;
-               new->se_slots[i] = sp;
+void free_session(struct kref *kref)
+{
+       struct nfsd4_session *ses;
+       int mem;
+
+       ses = container_of(kref, struct nfsd4_session, se_ref);
+       nfsd4_del_conns(ses);
+       spin_lock(&nfsd_drc_lock);
+       mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
+       nfsd_drc_mem_used -= mem;
+       spin_unlock(&nfsd_drc_lock);
+       free_session_slots(ses);
+       kfree(ses);
+}
+
+static struct nfsd4_session *alloc_init_session(struct svc_rqst *rqstp, struct nfs4_client *clp, struct nfsd4_create_session *cses)
+{
+       struct nfsd4_session *new;
+       struct nfsd4_channel_attrs *fchan = &cses->fore_channel;
+       int numslots, slotsize;
+       int status;
+       int idx;
+
+       /*
+        * Note decreasing slot size below client's request may
+        * make it difficult for client to function correctly, whereas
+        * decreasing the number of slots will (just?) affect
+        * performance.  When short on memory we therefore prefer to
+        * decrease number of slots instead of their size.
+        */
+       slotsize = nfsd4_sanitize_slot_size(fchan->maxresp_cached);
+       numslots = nfsd4_get_drc_mem(slotsize, fchan->maxreqs);
+
+       new = alloc_session(slotsize, numslots);
+       if (!new) {
+               nfsd4_put_drc_mem(slotsize, fchan->maxreqs);
+               return NULL;
        }
+       init_forechannel_attrs(&new->se_fchannel, fchan, numslots, slotsize);
 
        new->se_client = clp;
        gen_sessionid(new);
-       idx = hash_sessionid(&new->se_sessionid);
-       memcpy(clp->cl_sessionid.data, new->se_sessionid.data,
-              NFS4_MAX_SESSIONID_LEN);
 
+       INIT_LIST_HEAD(&new->se_conns);
+
+       new->se_cb_seq_nr = 1;
        new->se_flags = cses->flags;
+       new->se_cb_prog = cses->callback_prog;
        kref_init(&new->se_ref);
+       idx = hash_sessionid(&new->se_sessionid);
        spin_lock(&client_lock);
        list_add(&new->se_hash, &sessionid_hashtbl[idx]);
        list_add(&new->se_perclnt, &clp->cl_sessions);
        spin_unlock(&client_lock);
 
-       status = nfs_ok;
-out:
-       return status;
-out_free:
-       free_session_slots(new);
-       kfree(new);
-       goto out;
+       status = nfsd4_new_conn(rqstp, new);
+       /* whoops: benny points out, status is ignored! (err, or bogus) */
+       if (status) {
+               free_session(&new->se_ref);
+               return NULL;
+       }
+       if (!clp->cl_cb_session && (cses->flags & SESSION4_BACK_CHAN)) {
+               struct sockaddr *sa = svc_addr(rqstp);
+
+               clp->cl_cb_session = new;
+               clp->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
+               svc_xprt_get(rqstp->rq_xprt);
+               rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
+               clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
+               nfsd4_probe_callback(clp);
+       }
+       return new;
 }
 
 /* caller must hold client_lock */
@@ -731,21 +816,6 @@ unhash_session(struct nfsd4_session *ses)
        list_del(&ses->se_perclnt);
 }
 
-void
-free_session(struct kref *kref)
-{
-       struct nfsd4_session *ses;
-       int mem;
-
-       ses = container_of(kref, struct nfsd4_session, se_ref);
-       spin_lock(&nfsd_drc_lock);
-       mem = ses->se_fchannel.maxreqs * slot_bytes(&ses->se_fchannel);
-       nfsd_drc_mem_used -= mem;
-       spin_unlock(&nfsd_drc_lock);
-       free_session_slots(ses);
-       kfree(ses);
-}
-
 /* must be called under the client_lock */
 static inline void
 renew_client_locked(struct nfs4_client *clp)
@@ -812,6 +882,13 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
 static inline void
 free_client(struct nfs4_client *clp)
 {
+       while (!list_empty(&clp->cl_sessions)) {
+               struct nfsd4_session *ses;
+               ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
+                               se_perclnt);
+               list_del(&ses->se_perclnt);
+               nfsd4_put_session(ses);
+       }
        if (clp->cl_cred.cr_group_info)
                put_group_info(clp->cl_cred.cr_group_info);
        kfree(clp->cl_principal);
@@ -838,15 +915,12 @@ release_session_client(struct nfsd4_session *session)
 static inline void
 unhash_client_locked(struct nfs4_client *clp)
 {
+       struct nfsd4_session *ses;
+
        mark_client_expired(clp);
        list_del(&clp->cl_lru);
-       while (!list_empty(&clp->cl_sessions)) {
-               struct nfsd4_session  *ses;
-               ses = list_entry(clp->cl_sessions.next, struct nfsd4_session,
-                                se_perclnt);
-               unhash_session(ses);
-               nfsd4_put_session(ses);
-       }
+       list_for_each_entry(ses, &clp->cl_sessions, se_perclnt)
+               list_del_init(&ses->se_hash);
 }
 
 static void
@@ -875,7 +949,7 @@ expire_client(struct nfs4_client *clp)
                sop = list_entry(clp->cl_openowners.next, struct nfs4_stateowner, so_perclient);
                release_openowner(sop);
        }
-       nfsd4_set_callback_client(clp, NULL);
+       nfsd4_shutdown_callback(clp);
        if (clp->cl_cb_conn.cb_xprt)
                svc_xprt_put(clp->cl_cb_conn.cb_xprt);
        list_del(&clp->cl_idhash);
@@ -960,6 +1034,8 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
        if (clp == NULL)
                return NULL;
 
+       INIT_LIST_HEAD(&clp->cl_sessions);
+
        princ = svc_gss_principal(rqstp);
        if (princ) {
                clp->cl_principal = kstrdup(princ, GFP_KERNEL);
@@ -976,8 +1052,9 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
        INIT_LIST_HEAD(&clp->cl_strhash);
        INIT_LIST_HEAD(&clp->cl_openowners);
        INIT_LIST_HEAD(&clp->cl_delegations);
-       INIT_LIST_HEAD(&clp->cl_sessions);
        INIT_LIST_HEAD(&clp->cl_lru);
+       spin_lock_init(&clp->cl_lock);
+       INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
        clp->cl_time = get_seconds();
        clear_bit(0, &clp->cl_cb_slot_busy);
        rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
@@ -986,7 +1063,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
        clp->cl_flavor = rqstp->rq_flavor;
        copy_cred(&clp->cl_cred, &rqstp->rq_cred);
        gen_confirm(clp);
-
+       clp->cl_cb_session = NULL;
        return clp;
 }
 
@@ -1098,7 +1175,7 @@ find_unconfirmed_client_by_str(const char *dname, unsigned int hashval,
 static void
 gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid)
 {
-       struct nfs4_cb_conn *cb = &clp->cl_cb_conn;
+       struct nfs4_cb_conn *conn = &clp->cl_cb_conn;
        unsigned short expected_family;
 
        /* Currently, we only support tcp and tcp6 for the callback channel */
@@ -1111,24 +1188,23 @@ gen_callback(struct nfs4_client *clp, struct nfsd4_setclientid *se, u32 scopeid)
        else
                goto out_err;
 
-       cb->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
+       conn->cb_addrlen = rpc_uaddr2sockaddr(se->se_callback_addr_val,
                                            se->se_callback_addr_len,
-                                           (struct sockaddr *) &cb->cb_addr,
-                                           sizeof(cb->cb_addr));
+                                           (struct sockaddr *)&conn->cb_addr,
+                                           sizeof(conn->cb_addr));
 
-       if (!cb->cb_addrlen || cb->cb_addr.ss_family != expected_family)
+       if (!conn->cb_addrlen || conn->cb_addr.ss_family != expected_family)
                goto out_err;
 
-       if (cb->cb_addr.ss_family == AF_INET6)
-               ((struct sockaddr_in6 *) &cb->cb_addr)->sin6_scope_id = scopeid;
+       if (conn->cb_addr.ss_family == AF_INET6)
+               ((struct sockaddr_in6 *)&conn->cb_addr)->sin6_scope_id = scopeid;
 
-       cb->cb_minorversion = 0;
-       cb->cb_prog = se->se_callback_prog;
-       cb->cb_ident = se->se_callback_ident;
+       conn->cb_prog = se->se_callback_prog;
+       conn->cb_ident = se->se_callback_ident;
        return;
 out_err:
-       cb->cb_addr.ss_family = AF_UNSPEC;
-       cb->cb_addrlen = 0;
+       conn->cb_addr.ss_family = AF_UNSPEC;
+       conn->cb_addrlen = 0;
        dprintk(KERN_INFO "NFSD: this client (clientid %08x/%08x) "
                "will not receive delegations\n",
                clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
@@ -1415,7 +1491,9 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 {
        struct sockaddr *sa = svc_addr(rqstp);
        struct nfs4_client *conf, *unconf;
+       struct nfsd4_session *new;
        struct nfsd4_clid_slot *cs_slot = NULL;
+       bool confirm_me = false;
        int status = 0;
 
        nfs4_lock_state();
@@ -1438,7 +1516,6 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                                cs_slot->sl_seqid, cr_ses->seqid);
                        goto out;
                }
-               cs_slot->sl_seqid++;
        } else if (unconf) {
                if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
                    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
@@ -1451,25 +1528,10 @@ nfsd4_create_session(struct svc_rqst *rqstp,
                if (status) {
                        /* an unconfirmed replay returns misordered */
                        status = nfserr_seq_misordered;
-                       goto out_cache;
+                       goto out;
                }
 
-               cs_slot->sl_seqid++; /* from 0 to 1 */
-               move_to_confirmed(unconf);
-
-               if (cr_ses->flags & SESSION4_BACK_CHAN) {
-                       unconf->cl_cb_conn.cb_xprt = rqstp->rq_xprt;
-                       svc_xprt_get(rqstp->rq_xprt);
-                       rpc_copy_addr(
-                               (struct sockaddr *)&unconf->cl_cb_conn.cb_addr,
-                               sa);
-                       unconf->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
-                       unconf->cl_cb_conn.cb_minorversion =
-                               cstate->minorversion;
-                       unconf->cl_cb_conn.cb_prog = cr_ses->callback_prog;
-                       unconf->cl_cb_seq_nr = 1;
-                       nfsd4_probe_callback(unconf, &unconf->cl_cb_conn);
-               }
+               confirm_me = true;
                conf = unconf;
        } else {
                status = nfserr_stale_clientid;
@@ -1477,22 +1539,30 @@ nfsd4_create_session(struct svc_rqst *rqstp,
        }
 
        /*
+        * XXX: we should probably set this at creation time, and check
+        * for consistent minorversion use throughout:
+        */
+       conf->cl_minorversion = 1;
+       /*
         * We do not support RDMA or persistent sessions
         */
        cr_ses->flags &= ~SESSION4_PERSIST;
        cr_ses->flags &= ~SESSION4_RDMA;
 
-       status = alloc_init_session(rqstp, conf, cr_ses);
-       if (status)
+       status = nfserr_jukebox;
+       new = alloc_init_session(rqstp, conf, cr_ses);
+       if (!new)
                goto out;
-
-       memcpy(cr_ses->sessionid.data, conf->cl_sessionid.data,
+       status = nfs_ok;
+       memcpy(cr_ses->sessionid.data, new->se_sessionid.data,
               NFS4_MAX_SESSIONID_LEN);
+       cs_slot->sl_seqid++;
        cr_ses->seqid = cs_slot->sl_seqid;
 
-out_cache:
        /* cache solo and embedded create sessions under the state lock */
        nfsd4_cache_create_session(cr_ses, cs_slot, status);
+       if (confirm_me)
+               move_to_confirmed(conf);
 out:
        nfs4_unlock_state();
        dprintk("%s returns %d\n", __func__, ntohl(status));
@@ -1546,8 +1616,11 @@ nfsd4_destroy_session(struct svc_rqst *r,
 
        nfs4_lock_state();
        /* wait for callbacks */
-       nfsd4_set_callback_client(ses->se_client, NULL);
+       nfsd4_shutdown_callback(ses->se_client);
        nfs4_unlock_state();
+
+       nfsd4_del_conns(ses);
+
        nfsd4_put_session(ses);
        status = nfs_ok;
 out:
@@ -1555,6 +1628,36 @@ out:
        return status;
 }
 
+static struct nfsd4_conn *__nfsd4_find_conn(struct svc_xprt *xpt, struct nfsd4_session *s)
+{
+       struct nfsd4_conn *c;
+
+       list_for_each_entry(c, &s->se_conns, cn_persession) {
+               if (c->cn_xprt == xpt) {
+                       return c;
+               }
+       }
+       return NULL;
+}
+
+static void nfsd4_sequence_check_conn(struct nfsd4_conn *new, struct nfsd4_session *ses)
+{
+       struct nfs4_client *clp = ses->se_client;
+       struct nfsd4_conn *c;
+
+       spin_lock(&clp->cl_lock);
+       c = __nfsd4_find_conn(new->cn_xprt, ses);
+       if (c) {
+               spin_unlock(&clp->cl_lock);
+               free_conn(new);
+               return;
+       }
+       __nfsd4_hash_conn(new, ses);
+       spin_unlock(&clp->cl_lock);
+       nfsd4_register_conn(new);
+       return;
+}
+
 __be32
 nfsd4_sequence(struct svc_rqst *rqstp,
               struct nfsd4_compound_state *cstate,
@@ -1563,11 +1666,20 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        struct nfsd4_compoundres *resp = rqstp->rq_resp;
        struct nfsd4_session *session;
        struct nfsd4_slot *slot;
+       struct nfsd4_conn *conn;
        int status;
 
        if (resp->opcnt != 1)
                return nfserr_sequence_pos;
 
+       /*
+        * Will be either used or freed by nfsd4_sequence_check_conn
+        * below.
+        */
+       conn = alloc_conn(rqstp, NFS4_CDFC4_FORE);
+       if (!conn)
+               return nfserr_jukebox;
+
        spin_lock(&client_lock);
        status = nfserr_badsession;
        session = find_in_sessionid_hashtbl(&seq->sessionid);
@@ -1599,6 +1711,9 @@ nfsd4_sequence(struct svc_rqst *rqstp,
        if (status)
                goto out;
 
+       nfsd4_sequence_check_conn(conn, session);
+       conn = NULL;
+
        /* Success! bump slot seqid */
        slot->sl_inuse = true;
        slot->sl_seqid = seq->seqid;
@@ -1613,6 +1728,7 @@ out:
                nfsd4_get_session(cstate->session);
                atomic_inc(&session->se_client->cl_refcount);
        }
+       kfree(conn);
        spin_unlock(&client_lock);
        dprintk("%s: return %d\n", __func__, ntohl(status));
        return status;
@@ -1747,6 +1863,11 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        goto out;
                gen_clid(new);
        }
+       /*
+        * XXX: we should probably set this at creation time, and check
+        * for consistent minorversion use throughout:
+        */
+       new->cl_minorversion = 0;
        gen_callback(new, setclid, rpc_get_scope_id(sa));
        add_to_unconfirmed(new, strhashval);
        setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot;
@@ -1807,7 +1928,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                        status = nfserr_clid_inuse;
                else {
                        atomic_set(&conf->cl_cb_set, 0);
-                       nfsd4_probe_callback(conf, &unconf->cl_cb_conn);
+                       nfsd4_change_callback(conf, &unconf->cl_cb_conn);
+                       nfsd4_probe_callback(conf);
                        expire_client(unconf);
                        status = nfs_ok;
 
@@ -1841,7 +1963,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
                        }
                        move_to_confirmed(unconf);
                        conf = unconf;
-                       nfsd4_probe_callback(conf, &conf->cl_cb_conn);
+                       nfsd4_probe_callback(conf);
                        status = nfs_ok;
                }
        } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm)))
@@ -2944,7 +3066,11 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
        if (STALE_STATEID(stateid)) 
                goto out;
 
-       status = nfserr_bad_stateid;
+       /*
+        * We assume that any stateid that has the current boot time,
+        * but that we can't find, is expired:
+        */
+       status = nfserr_expired;
        if (is_delegation_stateid(stateid)) {
                dp = find_delegation_stateid(ino, stateid);
                if (!dp)
@@ -2964,6 +3090,7 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
                stp = find_stateid(stateid, flags);
                if (!stp)
                        goto out;
+               status = nfserr_bad_stateid;
                if (nfs4_check_fh(current_fh, stp))
                        goto out;
                if (!stp->st_stateowner->so_confirmed)
@@ -3038,8 +3165,9 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
                 * a replayed close:
                 */
                sop = search_close_lru(stateid->si_stateownerid, flags);
+               /* It's not stale; let's assume it's expired: */
                if (sop == NULL)
-                       return nfserr_bad_stateid;
+                       return nfserr_expired;
                *sopp = sop;
                goto check_replay;
        }
@@ -3304,6 +3432,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        status = nfserr_bad_stateid;
        if (!is_delegation_stateid(stateid))
                goto out;
+       status = nfserr_expired;
        dp = find_delegation_stateid(inode, stateid);
        if (!dp)
                goto out;
index 1a468bb..f35a94a 100644 (file)
@@ -1805,19 +1805,23 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
                                goto out_nfserr;
                }
        }
-       if ((buflen -= 16) < 0)
-               goto out_resource;
 
-       if (unlikely(bmval2)) {
+       if (bmval2) {
+               if ((buflen -= 16) < 0)
+                       goto out_resource;
                WRITE32(3);
                WRITE32(bmval0);
                WRITE32(bmval1);
                WRITE32(bmval2);
-       } else if (likely(bmval1)) {
+       } else if (bmval1) {
+               if ((buflen -= 12) < 0)
+                       goto out_resource;
                WRITE32(2);
                WRITE32(bmval0);
                WRITE32(bmval1);
        } else {
+               if ((buflen -= 8) < 0)
+                       goto out_resource;
                WRITE32(1);
                WRITE32(bmval0);
        }
@@ -1828,15 +1832,17 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
                u32 word1 = nfsd_suppattrs1(minorversion);
                u32 word2 = nfsd_suppattrs2(minorversion);
 
-               if ((buflen -= 12) < 0)
-                       goto out_resource;
                if (!aclsupport)
                        word0 &= ~FATTR4_WORD0_ACL;
                if (!word2) {
+                       if ((buflen -= 12) < 0)
+                               goto out_resource;
                        WRITE32(2);
                        WRITE32(word0);
                        WRITE32(word1);
                } else {
+                       if ((buflen -= 16) < 0)
+                               goto out_resource;
                        WRITE32(3);
                        WRITE32(word0);
                        WRITE32(word1);
index 06fa87e..d6dc3f6 100644 (file)
@@ -22,6 +22,7 @@
  */
 enum {
        NFSD_Root = 1,
+#ifdef CONFIG_NFSD_DEPRECATED
        NFSD_Svc,
        NFSD_Add,
        NFSD_Del,
@@ -29,6 +30,7 @@ enum {
        NFSD_Unexport,
        NFSD_Getfd,
        NFSD_Getfs,
+#endif
        NFSD_List,
        NFSD_Export_features,
        NFSD_Fh,
@@ -54,6 +56,7 @@ enum {
 /*
  * write() for these nodes.
  */
+#ifdef CONFIG_NFSD_DEPRECATED
 static ssize_t write_svc(struct file *file, char *buf, size_t size);
 static ssize_t write_add(struct file *file, char *buf, size_t size);
 static ssize_t write_del(struct file *file, char *buf, size_t size);
@@ -61,6 +64,7 @@ static ssize_t write_export(struct file *file, char *buf, size_t size);
 static ssize_t write_unexport(struct file *file, char *buf, size_t size);
 static ssize_t write_getfd(struct file *file, char *buf, size_t size);
 static ssize_t write_getfs(struct file *file, char *buf, size_t size);
+#endif
 static ssize_t write_filehandle(struct file *file, char *buf, size_t size);
 static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size);
 static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size);
@@ -76,6 +80,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size);
 #endif
 
 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
+#ifdef CONFIG_NFSD_DEPRECATED
        [NFSD_Svc] = write_svc,
        [NFSD_Add] = write_add,
        [NFSD_Del] = write_del,
@@ -83,6 +88,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = {
        [NFSD_Unexport] = write_unexport,
        [NFSD_Getfd] = write_getfd,
        [NFSD_Getfs] = write_getfs,
+#endif
        [NFSD_Fh] = write_filehandle,
        [NFSD_FO_UnlockIP] = write_unlock_ip,
        [NFSD_FO_UnlockFS] = write_unlock_fs,
@@ -121,6 +127,14 @@ static ssize_t nfsctl_transaction_write(struct file *file, const char __user *bu
 
 static ssize_t nfsctl_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
 {
+       static int warned;
+       if (file->f_dentry->d_name.name[0] == '.' && !warned) {
+               printk(KERN_INFO
+                      "Warning: \"%s\" uses deprecated NFSD interface: %s."
+                      "  This will be removed in 2.6.40\n",
+                      current->comm, file->f_dentry->d_name.name);
+               warned = 1;
+       }
        if (! file->private_data) {
                /* An attempt to read a transaction file without writing
                 * causes a 0-byte write so that the file can return
@@ -187,6 +201,7 @@ static const struct file_operations pool_stats_operations = {
  * payload - write methods
  */
 
+#ifdef CONFIG_NFSD_DEPRECATED
 /**
  * write_svc - Start kernel's NFSD server
  *
@@ -402,7 +417,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size)
 
        ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
 
-       clp = auth_unix_lookup(&in6);
+       clp = auth_unix_lookup(&init_net, &in6);
        if (!clp)
                err = -EPERM;
        else {
@@ -465,7 +480,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
 
        ipv6_addr_set_v4mapped(sin->sin_addr.s_addr, &in6);
 
-       clp = auth_unix_lookup(&in6);
+       clp = auth_unix_lookup(&init_net, &in6);
        if (!clp)
                err = -EPERM;
        else {
@@ -482,6 +497,7 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
  out:
        return err;
 }
+#endif /* CONFIG_NFSD_DEPRECATED */
 
 /**
  * write_unlock_ip - Release all locks used by a client
@@ -1000,12 +1016,12 @@ static ssize_t __write_ports_addxprt(char *buf)
        if (err != 0)
                return err;
 
-       err = svc_create_xprt(nfsd_serv, transport,
+       err = svc_create_xprt(nfsd_serv, transport, &init_net,
                                PF_INET, port, SVC_SOCK_ANONYMOUS);
        if (err < 0)
                goto out_err;
 
-       err = svc_create_xprt(nfsd_serv, transport,
+       err = svc_create_xprt(nfsd_serv, transport, &init_net,
                                PF_INET6, port, SVC_SOCK_ANONYMOUS);
        if (err < 0 && err != -EAFNOSUPPORT)
                goto out_close;
@@ -1356,6 +1372,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size)
 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 {
        static struct tree_descr nfsd_files[] = {
+#ifdef CONFIG_NFSD_DEPRECATED
                [NFSD_Svc] = {".svc", &transaction_ops, S_IWUSR},
                [NFSD_Add] = {".add", &transaction_ops, S_IWUSR},
                [NFSD_Del] = {".del", &transaction_ops, S_IWUSR},
@@ -1363,6 +1380,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
                [NFSD_Unexport] = {".unexport", &transaction_ops, S_IWUSR},
                [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR},
+#endif
                [NFSD_List] = {"exports", &exports_operations, S_IRUGO},
                [NFSD_Export_features] = {"export_features",
                                        &export_features_operations, S_IRUGO},
index b76ac3a..6b641cf 100644 (file)
@@ -249,7 +249,7 @@ extern time_t nfsd4_grace;
 #define        COMPOUND_SLACK_SPACE            140    /* OP_GETFH */
 #define COMPOUND_ERR_SLACK_SPACE       12     /* OP_SETATTR */
 
-#define NFSD_LAUNDROMAT_MINTIMEOUT      10   /* seconds */
+#define NFSD_LAUNDROMAT_MINTIMEOUT      1   /* seconds */
 
 /*
  * The following attributes are currently not supported by the NFSv4 server:
index e2c4346..2bae1d8 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/lockd/bind.h>
 #include <linux/nfsacl.h>
 #include <linux/seq_file.h>
+#include <net/net_namespace.h>
 #include "nfsd.h"
 #include "cache.h"
 #include "vfs.h"
@@ -186,12 +187,12 @@ static int nfsd_init_socks(int port)
        if (!list_empty(&nfsd_serv->sv_permsocks))
                return 0;
 
-       error = svc_create_xprt(nfsd_serv, "udp", PF_INET, port,
+       error = svc_create_xprt(nfsd_serv, "udp", &init_net, PF_INET, port,
                                        SVC_SOCK_DEFAULTS);
        if (error < 0)
                return error;
 
-       error = svc_create_xprt(nfsd_serv, "tcp", PF_INET, port,
+       error = svc_create_xprt(nfsd_serv, "tcp", &init_net, PF_INET, port,
                                        SVC_SOCK_DEFAULTS);
        if (error < 0)
                return error;
index 322518c..39adc27 100644 (file)
@@ -35,6 +35,7 @@
 #ifndef _NFSD4_STATE_H
 #define _NFSD4_STATE_H
 
+#include <linux/sunrpc/svc_xprt.h>
 #include <linux/nfsd/nfsfh.h>
 #include "nfsfh.h"
 
@@ -64,19 +65,12 @@ typedef struct {
        (s)->si_fileid, \
        (s)->si_generation
 
-struct nfsd4_cb_sequence {
-       /* args/res */
-       u32                     cbs_minorversion;
-       struct nfs4_client      *cbs_clp;
-};
-
-struct nfs4_rpc_args {
-       void                            *args_op;
-       struct nfsd4_cb_sequence        args_seq;
-};
-
 struct nfsd4_callback {
-       struct nfs4_rpc_args cb_args;
+       void *cb_op;
+       struct nfs4_client *cb_clp;
+       u32 cb_minorversion;
+       struct rpc_message cb_msg;
+       const struct rpc_call_ops *cb_ops;
        struct work_struct cb_work;
 };
 
@@ -91,7 +85,6 @@ struct nfs4_delegation {
        u32                     dl_type;
        time_t                  dl_time;
 /* For recall: */
-       u32                     dl_ident;
        stateid_t               dl_stateid;
        struct knfsd_fh         dl_fh;
        int                     dl_retries;
@@ -103,8 +96,8 @@ struct nfs4_cb_conn {
        /* SETCLIENTID info */
        struct sockaddr_storage cb_addr;
        size_t                  cb_addrlen;
-       u32                     cb_prog;
-       u32                     cb_minorversion;
+       u32                     cb_prog; /* used only in 4.0 case;
+                                           per-session otherwise */
        u32                     cb_ident;       /* minorversion 0 only */
        struct svc_xprt         *cb_xprt;       /* minorversion 1 only */
 };
@@ -160,6 +153,15 @@ struct nfsd4_clid_slot {
        struct nfsd4_create_session     sl_cr_ses;
 };
 
+struct nfsd4_conn {
+       struct list_head cn_persession;
+       struct svc_xprt *cn_xprt;
+       struct svc_xpt_user cn_xpt_user;
+       struct nfsd4_session *cn_session;
+/* CDFC4_FORE, CDFC4_BACK: */
+       unsigned char cn_flags;
+};
+
 struct nfsd4_session {
        struct kref             se_ref;
        struct list_head        se_hash;        /* hash by sessionid */
@@ -169,6 +171,9 @@ struct nfsd4_session {
        struct nfs4_sessionid   se_sessionid;
        struct nfsd4_channel_attrs se_fchannel;
        struct nfsd4_channel_attrs se_bchannel;
+       struct list_head        se_conns;
+       u32                     se_cb_prog;
+       u32                     se_cb_seq_nr;
        struct nfsd4_slot       *se_slots[];    /* forward channel slots */
 };
 
@@ -221,24 +226,32 @@ struct nfs4_client {
        clientid_t              cl_clientid;    /* generated by server */
        nfs4_verifier           cl_confirm;     /* generated by server */
        u32                     cl_firststate;  /* recovery dir creation */
+       u32                     cl_minorversion;
 
        /* for v4.0 and v4.1 callbacks: */
        struct nfs4_cb_conn     cl_cb_conn;
+#define NFSD4_CLIENT_CB_UPDATE 1
+#define NFSD4_CLIENT_KILL      2
+       unsigned long           cl_cb_flags;
        struct rpc_clnt         *cl_cb_client;
+       u32                     cl_cb_ident;
        atomic_t                cl_cb_set;
+       struct nfsd4_callback   cl_cb_null;
+       struct nfsd4_session    *cl_cb_session;
+
+       /* for all client information that callback code might need: */
+       spinlock_t              cl_lock;
 
        /* for nfs41 */
        struct list_head        cl_sessions;
        struct nfsd4_clid_slot  cl_cs_slot;     /* create_session slot */
        u32                     cl_exchange_flags;
-       struct nfs4_sessionid   cl_sessionid;
        /* number of rpc's in progress over an associated session: */
        atomic_t                cl_refcount;
 
        /* for nfs41 callbacks */
        /* We currently support a single back channel with a single slot */
        unsigned long           cl_cb_slot_busy;
-       u32                     cl_cb_seq_nr;
        struct rpc_wait_queue   cl_cb_waitq;    /* backchannel callers may */
                                                /* wait here for slots */
 };
@@ -440,12 +453,13 @@ extern int nfs4_in_grace(void);
 extern __be32 nfs4_check_open_reclaim(clientid_t *clid);
 extern void nfs4_free_stateowner(struct kref *kref);
 extern int set_callback_cred(void);
-extern void nfsd4_probe_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
+extern void nfsd4_probe_callback(struct nfs4_client *clp);
+extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
 extern void nfsd4_do_callback_rpc(struct work_struct *);
 extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
 extern int nfsd4_create_callback_queue(void);
 extern void nfsd4_destroy_callback_queue(void);
-extern void nfsd4_set_callback_client(struct nfs4_client *, struct rpc_clnt *);
+extern void nfsd4_shutdown_callback(struct nfs4_client *);
 extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
 extern void nfsd4_init_recdir(char *recdir_name);
index d926af6..687d090 100644 (file)
@@ -1609,7 +1609,7 @@ nilfs_copy_replace_page_buffers(struct page *page, struct list_head *out)
        kunmap_atomic(kaddr, KM_USER0);
 
        if (!TestSetPageWriteback(clone_page))
-               inc_zone_page_state(clone_page, NR_WRITEBACK);
+               account_page_writeback(clone_page);
        unlock_page(clone_page);
 
        return 0;
index 50f8f06..6a00688 100644 (file)
@@ -33,8 +33,8 @@ config PROC_KCORE
        depends on PROC_FS && MMU
 
 config PROC_VMCORE
-        bool "/proc/vmcore support (EXPERIMENTAL)"
-        depends on PROC_FS && CRASH_DUMP
+       bool "/proc/vmcore support"
+       depends on PROC_FS && CRASH_DUMP
        default y
         help
         Exports the dump image of crashed kernel in ELF format.
index 9883f1e..9b094c1 100644 (file)
@@ -1025,28 +1025,47 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
        memset(buffer, 0, sizeof(buffer));
        if (count > sizeof(buffer) - 1)
                count = sizeof(buffer) - 1;
-       if (copy_from_user(buffer, buf, count))
-               return -EFAULT;
+       if (copy_from_user(buffer, buf, count)) {
+               err = -EFAULT;
+               goto out;
+       }
 
        err = strict_strtol(strstrip(buffer), 0, &oom_adjust);
        if (err)
-               return -EINVAL;
+               goto out;
        if ((oom_adjust < OOM_ADJUST_MIN || oom_adjust > OOM_ADJUST_MAX) &&
-            oom_adjust != OOM_DISABLE)
-               return -EINVAL;
+            oom_adjust != OOM_DISABLE) {
+               err = -EINVAL;
+               goto out;
+       }
 
        task = get_proc_task(file->f_path.dentry->d_inode);
-       if (!task)
-               return -ESRCH;
+       if (!task) {
+               err = -ESRCH;
+               goto out;
+       }
+
+       task_lock(task);
+       if (!task->mm) {
+               err = -EINVAL;
+               goto err_task_lock;
+       }
+
        if (!lock_task_sighand(task, &flags)) {
-               put_task_struct(task);
-               return -ESRCH;
+               err = -ESRCH;
+               goto err_task_lock;
        }
 
        if (oom_adjust < task->signal->oom_adj && !capable(CAP_SYS_RESOURCE)) {
-               unlock_task_sighand(task, &flags);
-               put_task_struct(task);
-               return -EACCES;
+               err = -EACCES;
+               goto err_sighand;
+       }
+
+       if (oom_adjust != task->signal->oom_adj) {
+               if (oom_adjust == OOM_DISABLE)
+                       atomic_inc(&task->mm->oom_disable_count);
+               if (task->signal->oom_adj == OOM_DISABLE)
+                       atomic_dec(&task->mm->oom_disable_count);
        }
 
        /*
@@ -1067,10 +1086,13 @@ static ssize_t oom_adjust_write(struct file *file, const char __user *buf,
        else
                task->signal->oom_score_adj = (oom_adjust * OOM_SCORE_ADJ_MAX) /
                                                                -OOM_DISABLE;
+err_sighand:
        unlock_task_sighand(task, &flags);
+err_task_lock:
+       task_unlock(task);
        put_task_struct(task);
-
-       return count;
+out:
+       return err < 0 ? err : count;
 }
 
 static const struct file_operations proc_oom_adjust_operations = {
@@ -1111,30 +1133,49 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
        memset(buffer, 0, sizeof(buffer));
        if (count > sizeof(buffer) - 1)
                count = sizeof(buffer) - 1;
-       if (copy_from_user(buffer, buf, count))
-               return -EFAULT;
+       if (copy_from_user(buffer, buf, count)) {
+               err = -EFAULT;
+               goto out;
+       }
 
        err = strict_strtol(strstrip(buffer), 0, &oom_score_adj);
        if (err)
-               return -EINVAL;
+               goto out;
        if (oom_score_adj < OOM_SCORE_ADJ_MIN ||
-                       oom_score_adj > OOM_SCORE_ADJ_MAX)
-               return -EINVAL;
+                       oom_score_adj > OOM_SCORE_ADJ_MAX) {
+               err = -EINVAL;
+               goto out;
+       }
 
        task = get_proc_task(file->f_path.dentry->d_inode);
-       if (!task)
-               return -ESRCH;
+       if (!task) {
+               err = -ESRCH;
+               goto out;
+       }
+
+       task_lock(task);
+       if (!task->mm) {
+               err = -EINVAL;
+               goto err_task_lock;
+       }
+
        if (!lock_task_sighand(task, &flags)) {
-               put_task_struct(task);
-               return -ESRCH;
+               err = -ESRCH;
+               goto err_task_lock;
        }
+
        if (oom_score_adj < task->signal->oom_score_adj &&
                        !capable(CAP_SYS_RESOURCE)) {
-               unlock_task_sighand(task, &flags);
-               put_task_struct(task);
-               return -EACCES;
+               err = -EACCES;
+               goto err_sighand;
        }
 
+       if (oom_score_adj != task->signal->oom_score_adj) {
+               if (oom_score_adj == OOM_SCORE_ADJ_MIN)
+                       atomic_inc(&task->mm->oom_disable_count);
+               if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+                       atomic_dec(&task->mm->oom_disable_count);
+       }
        task->signal->oom_score_adj = oom_score_adj;
        /*
         * Scale /proc/pid/oom_adj appropriately ensuring that OOM_DISABLE is
@@ -1145,9 +1186,13 @@ static ssize_t oom_score_adj_write(struct file *file, const char __user *buf,
        else
                task->signal->oom_adj = (oom_score_adj * OOM_ADJUST_MAX) /
                                                        OOM_SCORE_ADJ_MAX;
+err_sighand:
        unlock_task_sighand(task, &flags);
+err_task_lock:
+       task_unlock(task);
        put_task_struct(task);
-       return count;
+out:
+       return err < 0 ? err : count;
 }
 
 static const struct file_operations proc_oom_score_adj_operations = {
index 4dcb880..41656d4 100644 (file)
@@ -2437,7 +2437,7 @@ static int reiserfs_write_full_page(struct page *page,
                /* from this point on, we know the buffer is mapped to a
                 * real block and not a direct item
                 */
-               if (wbc->sync_mode != WB_SYNC_NONE || !wbc->nonblocking) {
+               if (wbc->sync_mode != WB_SYNC_NONE) {
                        lock_buffer(bh);
                } else {
                        if (!trylock_buffer(bh)) {
index 7404730..492465b 100644 (file)
@@ -99,6 +99,16 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
 #ifdef __ARCH_SI_TRAPNO
                err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno);
 #endif
+#ifdef BUS_MCEERR_AO
+               /* 
+                * Other callers might not initialize the si_lsb field,
+                * so check explicitly for the right codes here.
+                */
+               if (kinfo->si_code == BUS_MCEERR_AR ||
+                   kinfo->si_code == BUS_MCEERR_AO)
+                       err |= __put_user((short) kinfo->si_addr_lsb,
+                                         &uinfo->ssi_addr_lsb);
+#endif
                break;
        case __SI_CHLD:
                err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
index b552f81..c9af48f 100644 (file)
@@ -1139,8 +1139,7 @@ xfs_vm_writepage(
                                type = IO_DELAY;
                                flags = BMAPI_ALLOCATE;
 
-                               if (wbc->sync_mode == WB_SYNC_NONE &&
-                                   wbc->nonblocking)
+                               if (wbc->sync_mode == WB_SYNC_NONE)
                                        flags |= BMAPI_TRYLOCK;
                        }
 
index 4de84ce..359ef11 100644 (file)
@@ -184,7 +184,7 @@ struct acpi_device_pnp {
 
 #define acpi_device_bid(d)     ((d)->pnp.bus_id)
 #define acpi_device_adr(d)     ((d)->pnp.bus_address)
-char *acpi_device_hid(struct acpi_device *device);
+const char *acpi_device_hid(struct acpi_device *device);
 #define acpi_device_name(d)    ((d)->pnp.device_name)
 #define acpi_device_class(d)   ((d)->pnp.device_class)
 
@@ -389,21 +389,25 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_OPS
 int acpi_pm_device_sleep_state(struct device *, int *);
-int acpi_pm_device_sleep_wake(struct device *, bool);
-#else /* !CONFIG_PM_SLEEP */
+#else
 static inline int acpi_pm_device_sleep_state(struct device *d, int *p)
 {
        if (p)
                *p = ACPI_STATE_D0;
        return ACPI_STATE_D3;
 }
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+int acpi_pm_device_sleep_wake(struct device *, bool);
+#else
 static inline int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 {
        return -ENODEV;
 }
-#endif /* !CONFIG_PM_SLEEP */
+#endif
 
 #endif                         /* CONFIG_ACPI */
 
index 23d78b4..3090471 100644 (file)
@@ -115,8 +115,6 @@ void pci_acpi_crs_quirks(void);
 #define ACPI_PROCESSOR_LIMIT_INCREMENT 0x01
 #define ACPI_PROCESSOR_LIMIT_DECREMENT 0x02
 
-int acpi_processor_set_thermal_limit(acpi_handle handle, int type);
-
 /*--------------------------------------------------------------------------
                                   Dock Station
   -------------------------------------------------------------------------- */
index 29bf945..65b3f58 100644 (file)
@@ -98,8 +98,6 @@ acpi_os_table_override(struct acpi_table_header *existing_table,
 /*
  * Spinlock primitives
  */
-acpi_status acpi_os_create_lock(acpi_spinlock * out_handle);
-
 void acpi_os_delete_lock(acpi_spinlock handle);
 
 acpi_cpu_flags acpi_os_acquire_lock(acpi_spinlock handle);
@@ -223,25 +221,15 @@ acpi_os_write_memory(acpi_physical_address address, u32 value, u32 width);
  */
 acpi_status
 acpi_os_read_pci_configuration(struct acpi_pci_id *pci_id,
-                              u32 reg, u32 *value, u32 width);
+                              u32 reg, u64 *value, u32 width);
 
 acpi_status
 acpi_os_write_pci_configuration(struct acpi_pci_id *pci_id,
                                u32 reg, u64 value, u32 width);
 
 /*
- * Interim function needed for PCI IRQ routing
- */
-void
-acpi_os_derive_pci_id(acpi_handle device,
-                     acpi_handle region, struct acpi_pci_id **pci_id);
-
-/*
  * Miscellaneous
  */
-acpi_status acpi_os_validate_interface(char *interface);
-acpi_status acpi_osi_invalidate(char* interface);
-
 acpi_status
 acpi_os_validate_address(u8 space_id, acpi_physical_address address,
                         acpi_size length, char *name);
index 984cdc6..53b7cfd 100644 (file)
@@ -47,7 +47,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20100702
+#define ACPI_CA_VERSION                 0x20101013
 
 #include "actypes.h"
 #include "actbl.h"
@@ -72,6 +72,7 @@ extern u8 acpi_gbl_truncate_io_addresses;
 
 extern u32 acpi_current_gpe_count;
 extern struct acpi_table_fadt acpi_gbl_FADT;
+extern u8 acpi_gbl_system_awake_and_running;
 
 extern u32 acpi_rsdt_forced;
 /*
@@ -105,6 +106,10 @@ const char *acpi_format_exception(acpi_status exception);
 
 acpi_status acpi_purge_cached_objects(void);
 
+acpi_status acpi_install_interface(acpi_string interface_name);
+
+acpi_status acpi_remove_interface(acpi_string interface_name);
+
 /*
  * ACPI Memory management
  */
@@ -263,6 +268,8 @@ acpi_remove_gpe_handler(acpi_handle gpe_device,
 acpi_status acpi_install_exception_handler(acpi_exception_handler handler);
 #endif
 
+acpi_status acpi_install_interface_handler(acpi_interface_handler handler);
+
 /*
  * Event interfaces
  */
@@ -308,6 +315,8 @@ acpi_install_gpe_block(acpi_handle gpe_device,
 
 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device);
 
+acpi_status acpi_update_gpes(void);
+
 /*
  * Resource interfaces
  */
index 5db8f47..2b134b6 100644 (file)
  *
  * ACPI_SIZE        16/32/64-bit unsigned value
  * ACPI_NATIVE_INT  16/32/64-bit signed value
- *
  */
 
 /*******************************************************************************
@@ -132,6 +131,16 @@ typedef COMPILER_DEPENDENT_INT64 INT64;
 
 /*! [End] no source code translation !*/
 
+/*
+ * Value returned by acpi_os_get_thread_id. There is no standard "thread_id"
+ * across operating systems or even the various UNIX systems. Since ACPICA
+ * only needs the thread ID as a unique thread identifier, we use a u64
+ * as the only common data type - it will accommodate any type of pointer or
+ * any type of integer. It is up to the host-dependent OSL to cast the
+ * native thread ID type to a u64 (in acpi_os_get_thread_id).
+ */
+#define acpi_thread_id                  u64
+
 /*******************************************************************************
  *
  * Types specific to 64-bit targets
@@ -211,12 +220,6 @@ typedef u32 acpi_physical_address;
  *
  ******************************************************************************/
 
-/* Value returned by acpi_os_get_thread_id */
-
-#ifndef acpi_thread_id
-#define acpi_thread_id                 acpi_size
-#endif
-
 /* Flags for acpi_os_acquire_lock/acpi_os_release_lock */
 
 #ifndef acpi_cpu_flags
@@ -375,16 +378,6 @@ typedef void *acpi_handle; /* Actually a ptr to a NS Node */
 typedef u8 acpi_owner_id;
 #define ACPI_OWNER_ID_MAX               0xFF
 
-struct uint64_struct {
-       u32 lo;
-       u32 hi;
-};
-
-union uint64_overlay {
-       u64 full;
-       struct uint64_struct part;
-};
-
 #define ACPI_INTEGER_BIT_SIZE           64
 #define ACPI_MAX_DECIMAL_DIGITS         20     /* 2^64 = 18,446,744,073,709,551,616 */
 
@@ -950,6 +943,9 @@ acpi_status(*acpi_walk_callback) (acpi_handle object,
                                  u32 nesting_level,
                                  void *context, void **return_value);
 
+typedef
+u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
+
 /* Interrupt handler return values */
 
 #define ACPI_INTERRUPT_NOT_HANDLED      0x00
index c05aeba..a3e334a 100644 (file)
 #define ACPI_MUTEX_TYPE             ACPI_BINARY_SEMAPHORE
 #endif
 
+/* "inline" keywords - configurable since inline is not standardized */
+
+#ifndef ACPI_INLINE
+#define ACPI_INLINE
+#endif
+
 /*
  * Debugger threading model
  * Use single threaded if the entire subsystem is contained in an application
index 0cd53e3..5dcb953 100644 (file)
@@ -44,6 +44,8 @@
 #ifndef __ACGCC_H__
 #define __ACGCC_H__
 
+#define ACPI_INLINE             __inline__
+
 /* Function name is used for debug output. Non-ANSI, compiler-dependent */
 
 #define ACPI_GET_FUNCTION_NAME          __func__
index 103f08a..572189e 100644 (file)
@@ -75,7 +75,6 @@
 #define acpi_cache_t                        struct kmem_cache
 #define acpi_spinlock                       spinlock_t *
 #define acpi_cpu_flags                      unsigned long
-#define acpi_thread_id                      struct task_struct *
 
 #else /* !__KERNEL__ */
 
@@ -88,7 +87,7 @@
 /* Host-dependent types and defines for user-space ACPICA */
 
 #define ACPI_FLUSH_CPU_CACHE()
-#define acpi_thread_id                      pthread_t
+#define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread))
 
 #if defined(__ia64__) || defined(__x86_64__)
 #define ACPI_MACHINE_WIDTH          64
 
 
 #ifdef __KERNEL__
+#include <acpi/actypes.h>
 /*
  * Overrides for in-kernel ACPICA
  */
 static inline acpi_thread_id acpi_os_get_thread_id(void)
 {
-       return current;
+       return (acpi_thread_id)(unsigned long)current;
 }
 
 /*
@@ -127,7 +127,6 @@ static inline acpi_thread_id acpi_os_get_thread_id(void)
  * However, boot has  (system_state != SYSTEM_RUNNING)
  * to quiet __might_sleep() in kmalloc() and resume does not.
  */
-#include <acpi/actypes.h>
 static inline void *acpi_os_allocate(acpi_size size)
 {
        return kmalloc(size, irqs_disabled() ? GFP_ATOMIC : GFP_KERNEL);
index f4229fb..2c0fc10 100644 (file)
 #define DATA_DATA                                                      \
        *(.data)                                                        \
        *(.ref.data)                                                    \
+       *(.data..shared_aligned) /* percpu related */                   \
        DEV_KEEP(init.data)                                             \
        DEV_KEEP(exit.data)                                             \
        CPU_KEEP(init.data)                                             \
 
 #ifdef CONFIG_BLK_DEV_INITRD
 #define INIT_RAM_FS                                                    \
-       . = ALIGN(PAGE_SIZE);                                           \
+       . = ALIGN(4);                                                   \
        VMLINUX_SYMBOL(__initramfs_start) = .;                          \
        *(.init.ramfs)                                                  \
        VMLINUX_SYMBOL(__initramfs_end) = .;
index c227757..050a7bc 100644 (file)
@@ -245,8 +245,6 @@ int acpi_check_resource_conflict(const struct resource *res);
 
 int acpi_check_region(resource_size_t start, resource_size_t n,
                      const char *name);
-int acpi_check_mem_region(resource_size_t start, resource_size_t n,
-                     const char *name);
 
 int acpi_resources_are_enforced(void);
 
@@ -308,6 +306,9 @@ extern acpi_status acpi_pci_osc_control_set(acpi_handle handle,
                                             u32 *mask, u32 req);
 extern void acpi_early_init(void);
 
+int acpi_os_map_generic_address(struct acpi_generic_address *addr);
+void acpi_os_unmap_generic_address(struct acpi_generic_address *addr);
+
 #else  /* !CONFIG_ACPI */
 
 #define acpi_disabled 1
@@ -344,12 +345,6 @@ static inline int acpi_check_region(resource_size_t start, resource_size_t n,
        return 0;
 }
 
-static inline int acpi_check_mem_region(resource_size_t start,
-                                       resource_size_t n, const char *name)
-{
-       return 0;
-}
-
 struct acpi_table_header;
 static inline int acpi_table_parse(char *id,
                                int (*handler)(struct acpi_table_header *))
index 35b0074..4ce34fa 100644 (file)
@@ -111,6 +111,7 @@ void bdi_wakeup_thread_delayed(struct backing_dev_info *bdi);
 
 extern spinlock_t bdi_lock;
 extern struct list_head bdi_list;
+extern struct list_head bdi_pending_list;
 
 static inline int wb_has_dirty_io(struct bdi_writeback *wb)
 {
@@ -285,7 +286,7 @@ enum {
 void clear_bdi_congested(struct backing_dev_info *bdi, int sync);
 void set_bdi_congested(struct backing_dev_info *bdi, int sync);
 long congestion_wait(int sync, long timeout);
-
+long wait_iff_congested(struct zone *zone, int sync, long timeout);
 
 static inline bool bdi_cap_writeback_dirty(struct backing_dev_info *bdi)
 {
diff --git a/include/linux/bfin_mac.h b/include/linux/bfin_mac.h
new file mode 100644 (file)
index 0000000..904dec7
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Blackfin On-Chip MAC Driver
+ *
+ * Copyright 2004-2010 Analog Devices Inc.
+ *
+ * Enter bugs at http://blackfin.uclinux.org/
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef _LINUX_BFIN_MAC_H_
+#define _LINUX_BFIN_MAC_H_
+
+#include <linux/phy.h>
+
+struct bfin_phydev_platform_data {
+       unsigned short addr;
+       int irq;
+};
+
+struct bfin_mii_bus_platform_data {
+       int phydev_number;
+       struct bfin_phydev_platform_data *phydev_data;
+       const unsigned short *mac_peripherals;
+       int phy_mode;
+       unsigned int phy_mask;
+};
+
+#endif
index 51e3145..36d57f7 100644 (file)
@@ -10,7 +10,7 @@
 
 #include <linux/wait.h>
 
-/**
+/*
  * struct completion - structure used to maintain state for a "completion"
  *
  * This is the opaque structure used to maintain the state for a "completion".
@@ -34,7 +34,7 @@ struct completion {
        ({ init_completion(&work); work; })
 
 /**
- * DECLARE_COMPLETION: - declare and initialize a completion structure
+ * DECLARE_COMPLETION - declare and initialize a completion structure
  * @work:  identifier for the completion structure
  *
  * This macro declares and initializes a completion structure. Generally used
@@ -50,7 +50,7 @@ struct completion {
  * are on the kernel stack:
  */
 /**
- * DECLARE_COMPLETION_ONSTACK: - declare and initialize a completion structure
+ * DECLARE_COMPLETION_ONSTACK - declare and initialize a completion structure
  * @work:  identifier for the completion structure
  *
  * This macro declares and initializes a completion structure on the kernel
@@ -64,7 +64,7 @@ struct completion {
 #endif
 
 /**
- * init_completion: - Initialize a dynamically allocated completion
+ * init_completion - Initialize a dynamically allocated completion
  * @x:  completion structure that is to be initialized
  *
  * This inline function will initialize a dynamically created completion
@@ -92,7 +92,7 @@ extern void complete(struct completion *);
 extern void complete_all(struct completion *);
 
 /**
- * INIT_COMPLETION: - reinitialize a completion structure
+ * INIT_COMPLETION - reinitialize a completion structure
  * @x:  completion structure to be reinitialized
  *
  * This macro should be used to reinitialize a completion structure so it can
index f300a65..240eb1d 100644 (file)
@@ -234,6 +234,7 @@ struct inodes_stat_t {
 #define S_NOCMTIME     128     /* Do not update file c/mtime */
 #define S_SWAPFILE     256     /* Do not truncate: swapon got its bmaps */
 #define S_PRIVATE      512     /* Inode is fs-internal */
+#define S_IMA          1024    /* Inode has an associated IMA struct */
 
 /*
  * Note that nosuid etc flags are inode-specific: setting some file-system
@@ -268,6 +269,7 @@ struct inodes_stat_t {
 #define IS_NOCMTIME(inode)     ((inode)->i_flags & S_NOCMTIME)
 #define IS_SWAPFILE(inode)     ((inode)->i_flags & S_SWAPFILE)
 #define IS_PRIVATE(inode)      ((inode)->i_flags & S_PRIVATE)
+#define IS_IMA(inode)          ((inode)->i_flags & S_IMA)
 
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
@@ -776,6 +778,10 @@ struct inode {
 
        unsigned int            i_flags;
 
+#ifdef CONFIG_IMA
+       /* protected by i_lock */
+       unsigned int            i_readcount; /* struct files open RO */
+#endif
        atomic_t                i_writecount;
 #ifdef CONFIG_SECURITY
        void                    *i_security;
index 975609c..e8713d5 100644 (file)
@@ -9,6 +9,32 @@
 
 struct vm_area_struct;
 
+/* Plain integer GFP bitmasks. Do not use this directly. */
+#define ___GFP_DMA             0x01u
+#define ___GFP_HIGHMEM         0x02u
+#define ___GFP_DMA32           0x04u
+#define ___GFP_MOVABLE         0x08u
+#define ___GFP_WAIT            0x10u
+#define ___GFP_HIGH            0x20u
+#define ___GFP_IO              0x40u
+#define ___GFP_FS              0x80u
+#define ___GFP_COLD            0x100u
+#define ___GFP_NOWARN          0x200u
+#define ___GFP_REPEAT          0x400u
+#define ___GFP_NOFAIL          0x800u
+#define ___GFP_NORETRY         0x1000u
+#define ___GFP_COMP            0x4000u
+#define ___GFP_ZERO            0x8000u
+#define ___GFP_NOMEMALLOC      0x10000u
+#define ___GFP_HARDWALL                0x20000u
+#define ___GFP_THISNODE                0x40000u
+#define ___GFP_RECLAIMABLE     0x80000u
+#ifdef CONFIG_KMEMCHECK
+#define ___GFP_NOTRACK         0x200000u
+#else
+#define ___GFP_NOTRACK         0
+#endif
+
 /*
  * GFP bitmasks..
  *
@@ -18,10 +44,10 @@ struct vm_area_struct;
  * without the underscores and use them consistently. The definitions here may
  * be used in bit comparisons.
  */
-#define __GFP_DMA      ((__force gfp_t)0x01u)
-#define __GFP_HIGHMEM  ((__force gfp_t)0x02u)
-#define __GFP_DMA32    ((__force gfp_t)0x04u)
-#define __GFP_MOVABLE  ((__force gfp_t)0x08u)  /* Page is movable */
+#define __GFP_DMA      ((__force gfp_t)___GFP_DMA)
+#define __GFP_HIGHMEM  ((__force gfp_t)___GFP_HIGHMEM)
+#define __GFP_DMA32    ((__force gfp_t)___GFP_DMA32)
+#define __GFP_MOVABLE  ((__force gfp_t)___GFP_MOVABLE)  /* Page is movable */
 #define GFP_ZONEMASK   (__GFP_DMA|__GFP_HIGHMEM|__GFP_DMA32|__GFP_MOVABLE)
 /*
  * Action modifiers - doesn't change the zoning
@@ -38,27 +64,22 @@ struct vm_area_struct;
  * __GFP_MOVABLE: Flag that this page will be movable by the page migration
  * mechanism or reclaimed
  */
-#define __GFP_WAIT     ((__force gfp_t)0x10u)  /* Can wait and reschedule? */
-#define __GFP_HIGH     ((__force gfp_t)0x20u)  /* Should access emergency pools? */
-#define __GFP_IO       ((__force gfp_t)0x40u)  /* Can start physical IO? */
-#define __GFP_FS       ((__force gfp_t)0x80u)  /* Can call down to low-level FS? */
-#define __GFP_COLD     ((__force gfp_t)0x100u) /* Cache-cold page required */
-#define __GFP_NOWARN   ((__force gfp_t)0x200u) /* Suppress page allocation failure warning */
-#define __GFP_REPEAT   ((__force gfp_t)0x400u) /* See above */
-#define __GFP_NOFAIL   ((__force gfp_t)0x800u) /* See above */
-#define __GFP_NORETRY  ((__force gfp_t)0x1000u)/* See above */
-#define __GFP_COMP     ((__force gfp_t)0x4000u)/* Add compound page metadata */
-#define __GFP_ZERO     ((__force gfp_t)0x8000u)/* Return zeroed page on success */
-#define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */
-#define __GFP_HARDWALL   ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */
-#define __GFP_THISNODE ((__force gfp_t)0x40000u)/* No fallback, no policies */
-#define __GFP_RECLAIMABLE ((__force gfp_t)0x80000u) /* Page is reclaimable */
-
-#ifdef CONFIG_KMEMCHECK
-#define __GFP_NOTRACK  ((__force gfp_t)0x200000u)  /* Don't track with kmemcheck */
-#else
-#define __GFP_NOTRACK  ((__force gfp_t)0)
-#endif
+#define __GFP_WAIT     ((__force gfp_t)___GFP_WAIT)    /* Can wait and reschedule? */
+#define __GFP_HIGH     ((__force gfp_t)___GFP_HIGH)    /* Should access emergency pools? */
+#define __GFP_IO       ((__force gfp_t)___GFP_IO)      /* Can start physical IO? */
+#define __GFP_FS       ((__force gfp_t)___GFP_FS)      /* Can call down to low-level FS? */
+#define __GFP_COLD     ((__force gfp_t)___GFP_COLD)    /* Cache-cold page required */
+#define __GFP_NOWARN   ((__force gfp_t)___GFP_NOWARN)  /* Suppress page allocation failure warning */
+#define __GFP_REPEAT   ((__force gfp_t)___GFP_REPEAT)  /* See above */
+#define __GFP_NOFAIL   ((__force gfp_t)___GFP_NOFAIL)  /* See above */
+#define __GFP_NORETRY  ((__force gfp_t)___GFP_NORETRY) /* See above */
+#define __GFP_COMP     ((__force gfp_t)___GFP_COMP)    /* Add compound page metadata */
+#define __GFP_ZERO     ((__force gfp_t)___GFP_ZERO)    /* Return zeroed page on success */
+#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves */
+#define __GFP_HARDWALL   ((__force gfp_t)___GFP_HARDWALL) /* Enforce hardwall cpuset memory allocs */
+#define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)/* No fallback, no policies */
+#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */
+#define __GFP_NOTRACK  ((__force gfp_t)___GFP_NOTRACK)  /* Don't track with kmemcheck */
 
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
@@ -186,14 +207,14 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags)
 #endif
 
 #define GFP_ZONE_TABLE ( \
-       (ZONE_NORMAL << 0 * ZONES_SHIFT)                                \
-       | (OPT_ZONE_DMA << __GFP_DMA * ZONES_SHIFT)                     \
-       | (OPT_ZONE_HIGHMEM << __GFP_HIGHMEM * ZONES_SHIFT)             \
-       | (OPT_ZONE_DMA32 << __GFP_DMA32 * ZONES_SHIFT)                 \
-       | (ZONE_NORMAL << __GFP_MOVABLE * ZONES_SHIFT)                  \
-       | (OPT_ZONE_DMA << (__GFP_MOVABLE | __GFP_DMA) * ZONES_SHIFT)   \
-       | (ZONE_MOVABLE << (__GFP_MOVABLE | __GFP_HIGHMEM) * ZONES_SHIFT)\
-       | (OPT_ZONE_DMA32 << (__GFP_MOVABLE | __GFP_DMA32) * ZONES_SHIFT)\
+       (ZONE_NORMAL << 0 * ZONES_SHIFT)                                      \
+       | (OPT_ZONE_DMA << ___GFP_DMA * ZONES_SHIFT)                          \
+       | (OPT_ZONE_HIGHMEM << ___GFP_HIGHMEM * ZONES_SHIFT)                  \
+       | (OPT_ZONE_DMA32 << ___GFP_DMA32 * ZONES_SHIFT)                      \
+       | (ZONE_NORMAL << ___GFP_MOVABLE * ZONES_SHIFT)                       \
+       | (OPT_ZONE_DMA << (___GFP_MOVABLE | ___GFP_DMA) * ZONES_SHIFT)       \
+       | (ZONE_MOVABLE << (___GFP_MOVABLE | ___GFP_HIGHMEM) * ZONES_SHIFT)   \
+       | (OPT_ZONE_DMA32 << (___GFP_MOVABLE | ___GFP_DMA32) * ZONES_SHIFT)   \
 )
 
 /*
@@ -203,20 +224,20 @@ static inline int allocflags_to_migratetype(gfp_t gfp_flags)
  * allowed.
  */
 #define GFP_ZONE_BAD ( \
-       1 << (__GFP_DMA | __GFP_HIGHMEM)                                \
-       | 1 << (__GFP_DMA | __GFP_DMA32)                                \
-       | 1 << (__GFP_DMA32 | __GFP_HIGHMEM)                            \
-       | 1 << (__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM)                \
-       | 1 << (__GFP_MOVABLE | __GFP_HIGHMEM | __GFP_DMA)              \
-       | 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_DMA)                \
-       | 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_HIGHMEM)            \
-       | 1 << (__GFP_MOVABLE | __GFP_DMA32 | __GFP_DMA | __GFP_HIGHMEM)\
+       1 << (___GFP_DMA | ___GFP_HIGHMEM)                                    \
+       | 1 << (___GFP_DMA | ___GFP_DMA32)                                    \
+       | 1 << (___GFP_DMA32 | ___GFP_HIGHMEM)                                \
+       | 1 << (___GFP_DMA | ___GFP_DMA32 | ___GFP_HIGHMEM)                   \
+       | 1 << (___GFP_MOVABLE | ___GFP_HIGHMEM | ___GFP_DMA)                 \
+       | 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_DMA)                   \
+       | 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_HIGHMEM)               \
+       | 1 << (___GFP_MOVABLE | ___GFP_DMA32 | ___GFP_DMA | ___GFP_HIGHMEM)  \
 )
 
 static inline enum zone_type gfp_zone(gfp_t flags)
 {
        enum zone_type z;
-       int bit = flags & GFP_ZONEMASK;
+       int bit = (__force int) (flags & GFP_ZONEMASK);
 
        z = (GFP_ZONE_TABLE >> (bit * ZONES_SHIFT)) &
                                         ((1 << ZONES_SHIFT) - 1);
diff --git a/include/linux/gpio-fan.h b/include/linux/gpio-fan.h
new file mode 100644 (file)
index 0000000..0966591
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * include/linux/gpio-fan.h
+ *
+ * Platform data structure for GPIO fan driver
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __LINUX_GPIO_FAN_H
+#define __LINUX_GPIO_FAN_H
+
+struct gpio_fan_alarm {
+       unsigned        gpio;
+       unsigned        active_low;
+};
+
+struct gpio_fan_speed {
+       int rpm;
+       int ctrl_val;
+};
+
+struct gpio_fan_platform_data {
+       int                     num_ctrl;
+       unsigned                *ctrl;  /* fan control GPIOs. */
+       struct gpio_fan_alarm   *alarm; /* fan alarm GPIO. */
+       /*
+        * Speed conversion array: rpm from/to GPIO bit field.
+        * This array _must_ be sorted in ascending rpm order.
+        */
+       int                     num_speed;
+       struct gpio_fan_speed   *speed;
+};
+
+#endif /* __LINUX_GPIO_FAN_H */
index e3060ef..8a85ec1 100644 (file)
@@ -28,18 +28,6 @@ static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
 
 #include <asm/kmap_types.h>
 
-#ifdef CONFIG_DEBUG_HIGHMEM
-
-void debug_kmap_atomic(enum km_type type);
-
-#else
-
-static inline void debug_kmap_atomic(enum km_type type)
-{
-}
-
-#endif
-
 #ifdef CONFIG_HIGHMEM
 #include <asm/highmem.h>
 
@@ -49,6 +37,27 @@ extern unsigned long totalhigh_pages;
 
 void kmap_flush_unused(void);
 
+DECLARE_PER_CPU(int, __kmap_atomic_idx);
+
+static inline int kmap_atomic_idx_push(void)
+{
+       int idx = __get_cpu_var(__kmap_atomic_idx)++;
+#ifdef CONFIG_DEBUG_HIGHMEM
+       WARN_ON_ONCE(in_irq() && !irqs_disabled());
+       BUG_ON(idx > KM_TYPE_NR);
+#endif
+       return idx;
+}
+
+static inline int kmap_atomic_idx_pop(void)
+{
+       int idx = --__get_cpu_var(__kmap_atomic_idx);
+#ifdef CONFIG_DEBUG_HIGHMEM
+       BUG_ON(idx < 0);
+#endif
+       return idx;
+}
+
 #else /* CONFIG_HIGHMEM */
 
 static inline unsigned int nr_free_highpages(void) { return 0; }
@@ -66,19 +75,19 @@ static inline void kunmap(struct page *page)
 {
 }
 
-static inline void *kmap_atomic(struct page *page, enum km_type idx)
+static inline void *__kmap_atomic(struct page *page)
 {
        pagefault_disable();
        return page_address(page);
 }
-#define kmap_atomic_prot(page, idx, prot)      kmap_atomic(page, idx)
+#define kmap_atomic_prot(page, prot)   __kmap_atomic(page)
 
-static inline void kunmap_atomic_notypecheck(void *addr, enum km_type idx)
+static inline void __kunmap_atomic(void *addr)
 {
        pagefault_enable();
 }
 
-#define kmap_atomic_pfn(pfn, idx)      kmap_atomic(pfn_to_page(pfn), (idx))
+#define kmap_atomic_pfn(pfn)   kmap_atomic(pfn_to_page(pfn))
 #define kmap_atomic_to_page(ptr)       virt_to_page(ptr)
 
 #define kmap_flush_unused()    do {} while(0)
@@ -86,12 +95,20 @@ static inline void kunmap_atomic_notypecheck(void *addr, enum km_type idx)
 
 #endif /* CONFIG_HIGHMEM */
 
-/* Prevent people trying to call kunmap_atomic() as if it were kunmap() */
-/* kunmap_atomic() should get the return value of kmap_atomic, not the page. */
-#define kunmap_atomic(addr, idx) do { \
-               BUILD_BUG_ON(__same_type((addr), struct page *)); \
-               kunmap_atomic_notypecheck((addr), (idx)); \
-       } while (0)
+/*
+ * Make both: kmap_atomic(page, idx) and kmap_atomic(page) work.
+ */
+#define kmap_atomic(page, args...) __kmap_atomic(page)
+
+/*
+ * Prevent people trying to call kunmap_atomic() as if it were kunmap()
+ * kunmap_atomic() should get the return value of kmap_atomic, not the page.
+ */
+#define kunmap_atomic(addr, args...)                           \
+do {                                                           \
+       BUILD_BUG_ON(__same_type((addr), struct page *));       \
+       __kunmap_atomic(addr);                                  \
+} while (0)
 
 /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */
 #ifndef clear_user_highpage
@@ -201,8 +218,8 @@ static inline void copy_user_highpage(struct page *to, struct page *from,
        vfrom = kmap_atomic(from, KM_USER0);
        vto = kmap_atomic(to, KM_USER1);
        copy_user_page(vto, vfrom, vaddr, to);
-       kunmap_atomic(vfrom, KM_USER0);
        kunmap_atomic(vto, KM_USER1);
+       kunmap_atomic(vfrom, KM_USER0);
 }
 
 #endif
@@ -214,8 +231,8 @@ static inline void copy_highpage(struct page *to, struct page *from)
        vfrom = kmap_atomic(from, KM_USER0);
        vto = kmap_atomic(to, KM_USER1);
        copy_page(vto, vfrom);
-       kunmap_atomic(vfrom, KM_USER0);
        kunmap_atomic(vto, KM_USER1);
+       kunmap_atomic(vfrom, KM_USER0);
 }
 
 #endif /* _LINUX_HIGHMEM_H */
index f479700..943c76b 100644 (file)
@@ -43,7 +43,8 @@ int hugetlb_reserve_pages(struct inode *inode, long from, long to,
                                                struct vm_area_struct *vma,
                                                int acctflags);
 void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed);
-void __isolate_hwpoisoned_huge_page(struct page *page);
+int dequeue_hwpoisoned_huge_page(struct page *page);
+void copy_huge_page(struct page *dst, struct page *src);
 
 extern unsigned long hugepages_treat_as_movable;
 extern const unsigned long hugetlb_zero, hugetlb_infinity;
@@ -101,7 +102,10 @@ static inline void hugetlb_report_meminfo(struct seq_file *m)
 #define hugetlb_free_pgd_range(tlb, addr, end, floor, ceiling) ({BUG(); 0; })
 #define hugetlb_fault(mm, vma, addr, flags)    ({ BUG(); 0; })
 #define huge_pte_offset(mm, address)   0
-#define __isolate_hwpoisoned_huge_page(page)   0
+#define dequeue_hwpoisoned_huge_page(page)     0
+static inline void copy_huge_page(struct page *dst, struct page *src)
+{
+}
 
 #define hugetlb_change_protection(vma, address, end, newprot)
 
@@ -228,6 +232,8 @@ struct huge_bootmem_page {
        struct hstate *hstate;
 };
 
+struct page *alloc_huge_page_node(struct hstate *h, int nid);
+
 /* arch callback */
 int __init alloc_bootmem_huge_page(struct hstate *h);
 
@@ -301,8 +307,14 @@ static inline struct hstate *page_hstate(struct page *page)
        return size_to_hstate(PAGE_SIZE << compound_order(page));
 }
 
+static inline unsigned hstate_index_to_shift(unsigned index)
+{
+       return hstates[index].order + PAGE_SHIFT;
+}
+
 #else
 struct hstate {};
+#define alloc_huge_page_node(h, nid) NULL
 #define alloc_bootmem_huge_page(h) NULL
 #define hstate_file(f) NULL
 #define hstate_vma(v) NULL
@@ -317,6 +329,7 @@ static inline unsigned int pages_per_huge_page(struct hstate *h)
 {
        return 1;
 }
+#define hstate_index_to_shift(index) 0
 #endif
 
 #endif /* _LINUX_HUGETLB_H */
diff --git a/include/linux/i2c/apds990x.h b/include/linux/i2c/apds990x.h
new file mode 100644 (file)
index 0000000..d186fcc
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * This file is part of the APDS990x sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __APDS990X_H__
+#define __APDS990X_H__
+
+
+#define APDS_IRLED_CURR_12mA   0x3
+#define APDS_IRLED_CURR_25mA   0x2
+#define APDS_IRLED_CURR_50mA   0x1
+#define APDS_IRLED_CURR_100mA  0x0
+
+/**
+ * struct apds990x_chip_factors - defines effect of the cover window
+ * @ga: Total glass attenuation
+ * @cf1: clear channel factor 1 for raw to lux conversion
+ * @irf1: IR channel factor 1 for raw to lux conversion
+ * @cf2: clear channel factor 2 for raw to lux conversion
+ * @irf2: IR channel factor 2 for raw to lux conversion
+ * @df: device factor for conversion formulas
+ *
+ * Structure for tuning ALS calculation to match with environment.
+ * Values depend on the material above the sensor and the sensor
+ * itself. If the GA is zero, driver will use uncovered sensor default values
+ * format: decimal value * APDS_PARAM_SCALE except df which is plain integer.
+ */
+#define APDS_PARAM_SCALE 4096
+struct apds990x_chip_factors {
+       int ga;
+       int cf1;
+       int irf1;
+       int cf2;
+       int irf2;
+       int df;
+};
+
+/**
+ * struct apds990x_platform_data - platform data for apsd990x.c driver
+ * @cf: chip factor data
+ * @pddrive: IR-led driving current
+ * @ppcount: number of IR pulses used for proximity estimation
+ * @setup_resources: interrupt line setup call back function
+ * @release_resources: interrupt line release call back function
+ *
+ * Proximity detection result depends heavily on correct ppcount, pdrive
+ * and cover window.
+ *
+ */
+
+struct apds990x_platform_data {
+       struct apds990x_chip_factors cf;
+       u8     pdrive;
+       u8     ppcount;
+       int    (*setup_resources)(void);
+       int    (*release_resources)(void);
+};
+
+#endif
diff --git a/include/linux/i2c/bh1770glc.h b/include/linux/i2c/bh1770glc.h
new file mode 100644 (file)
index 0000000..8b5e2df
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the ROHM BH1770GLC / OSRAM SFH7770 sensor driver.
+ * Chip is combined proximity and ambient light sensor.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __BH1770_H__
+#define __BH1770_H__
+
+/**
+ * struct bh1770_platform_data - platform data for bh1770glc driver
+ * @led_def_curr: IR led driving current.
+ * @glass_attenuation: Attenuation factor for covering window.
+ * @setup_resources: Call back for interrupt line setup function
+ * @release_resources: Call back for interrupte line release function
+ *
+ * Example of glass attenuation: 16384 * 385 / 100 means attenuation factor
+ * of 3.85. i.e. light_above_sensor = light_above_cover_window / 3.85
+ */
+
+struct bh1770_platform_data {
+#define BH1770_LED_5mA 0
+#define BH1770_LED_10mA        1
+#define BH1770_LED_20mA        2
+#define BH1770_LED_50mA        3
+#define BH1770_LED_100mA 4
+#define BH1770_LED_150mA 5
+#define BH1770_LED_200mA 6
+       __u8 led_def_curr;
+#define BH1770_NEUTRAL_GA 16384 /* 16384 / 16384 = 1 */
+       __u32 glass_attenuation;
+       int (*setup_resources)(void);
+       int (*release_resources)(void);
+};
+#endif
index 928ae71..13a801f 100644 (file)
@@ -81,6 +81,7 @@ struct idr {
 #define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC)
 
 /**
+ * DOC: idr sync
  * idr synchronization (stolen from radix-tree.h)
  *
  * idr_find() is able to be called locklessly, using RCU. The caller must
index 7fb5927..8cdcc2a 100644 (file)
@@ -81,8 +81,7 @@ io_mapping_free(struct io_mapping *mapping)
 /* Atomic map/unmap */
 static inline void __iomem *
 io_mapping_map_atomic_wc(struct io_mapping *mapping,
-                        unsigned long offset,
-                        int slot)
+                        unsigned long offset)
 {
        resource_size_t phys_addr;
        unsigned long pfn;
@@ -90,13 +89,13 @@ io_mapping_map_atomic_wc(struct io_mapping *mapping,
        BUG_ON(offset >= mapping->size);
        phys_addr = mapping->base + offset;
        pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
-       return iomap_atomic_prot_pfn(pfn, slot, mapping->prot);
+       return iomap_atomic_prot_pfn(pfn, mapping->prot);
 }
 
 static inline void
-io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
+io_mapping_unmap_atomic(void __iomem *vaddr)
 {
-       iounmap_atomic(vaddr, slot);
+       iounmap_atomic(vaddr);
 }
 
 static inline void __iomem *
@@ -137,14 +136,13 @@ io_mapping_free(struct io_mapping *mapping)
 /* Atomic map/unmap */
 static inline void __iomem *
 io_mapping_map_atomic_wc(struct io_mapping *mapping,
-                        unsigned long offset,
-                        int slot)
+                        unsigned long offset)
 {
        return ((char __force __iomem *) mapping) + offset;
 }
 
 static inline void
-io_mapping_unmap_atomic(void __iomem *vaddr, int slot)
+io_mapping_unmap_atomic(void __iomem *vaddr)
 {
 }
 
index edef168..450092c 100644 (file)
@@ -173,6 +173,11 @@ extern int _cond_resched(void);
                (__x < 0) ? -__x : __x;         \
        })
 
+#define abs64(x) ({                            \
+               s64 __x = (x);                  \
+               (__x < 0) ? -__x : __x;         \
+       })
+
 #ifdef CONFIG_PROVE_LOCKING
 void might_fault(void);
 #else
@@ -203,10 +208,10 @@ extern unsigned long simple_strtoul(const char *,char **,unsigned int);
 extern long simple_strtol(const char *,char **,unsigned int);
 extern unsigned long long simple_strtoull(const char *,char **,unsigned int);
 extern long long simple_strtoll(const char *,char **,unsigned int);
-extern int strict_strtoul(const char *, unsigned int, unsigned long *);
-extern int strict_strtol(const char *, unsigned int, long *);
-extern int strict_strtoull(const char *, unsigned int, unsigned long long *);
-extern int strict_strtoll(const char *, unsigned int, long long *);
+extern int __must_check strict_strtoul(const char *, unsigned int, unsigned long *);
+extern int __must_check strict_strtol(const char *, unsigned int, long *);
+extern int __must_check strict_strtoull(const char *, unsigned int, unsigned long long *);
+extern int __must_check strict_strtoll(const char *, unsigned int, long long *);
 extern int sprintf(char * buf, const char * fmt, ...)
        __attribute__ ((format (printf, 2, 3)));
 extern int vsprintf(char *buf, const char *, va_list)
@@ -277,6 +282,11 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 asmlinkage int printk(const char * fmt, ...)
        __attribute__ ((format (printf, 1, 2))) __cold;
 
+/*
+ * Please don't use printk_ratelimit(), because it shares ratelimiting state
+ * with all other unrelated printk_ratelimit() callsites.  Instead use
+ * printk_ratelimited() or plain old __ratelimit().
+ */
 extern int __printk_ratelimit(const char *func);
 #define printk_ratelimit() __printk_ratelimit(__func__)
 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
@@ -651,6 +661,24 @@ static inline void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { }
        (void) (&_max1 == &_max2);              \
        _max1 > _max2 ? _max1 : _max2; })
 
+#define min3(x, y, z) ({                       \
+       typeof(x) _min1 = (x);                  \
+       typeof(y) _min2 = (y);                  \
+       typeof(z) _min3 = (z);                  \
+       (void) (&_min1 == &_min2);              \
+       (void) (&_min1 == &_min3);              \
+       _min1 < _min2 ? (_min1 < _min3 ? _min1 : _min3) : \
+               (_min2 < _min3 ? _min2 : _min3); })
+
+#define max3(x, y, z) ({                       \
+       typeof(x) _max1 = (x);                  \
+       typeof(y) _max2 = (y);                  \
+       typeof(z) _max3 = (z);                  \
+       (void) (&_max1 == &_max2);              \
+       (void) (&_max1 == &_max3);              \
+       _max1 > _max2 ? (_max1 > _max3 ? _max1 : _max3) : \
+               (_max2 > _max3 ? _max2 : _max3); })
+
 /**
  * min_not_zero - return the minimum that is _not_ zero, unless both are zero
  * @x: value1
index 62dbee5..c238ad2 100644 (file)
@@ -171,11 +171,8 @@ struct kfifo_rec_ptr_2 __STRUCT_KFIFO_PTR(unsigned char, 2, void);
        }
 
 
-static inline unsigned int __must_check
-__kfifo_must_check_helper(unsigned int val)
-{
-       return val;
-}
+/* __kfifo_must_check_helper() is temporarily disabled because it was faulty */
+#define __kfifo_must_check_helper(x) (x)
 
 /**
  * kfifo_initialized - Check if the fifo is initialized
index 0e8a346..d4292c8 100644 (file)
@@ -1,6 +1,52 @@
 #ifndef __LIS3LV02D_H_
 #define __LIS3LV02D_H_
 
+/**
+ * struct lis3lv02d_platform_data - lis3 chip family platform data
+ * @click_flags:       Click detection unit configuration
+ * @click_thresh_x:    Click detection unit x axis threshold
+ * @click_thresh_y:    Click detection unit y axis threshold
+ * @click_thresh_z:    Click detection unit z axis threshold
+ * @click_time_limit:  Click detection unit time parameter
+ * @click_latency:     Click detection unit latency parameter
+ * @click_window:      Click detection unit window parameter
+ * @irq_cfg:           On chip irq source and type configuration (click /
+ *                     data available / wake up, open drain, polarity)
+ * @irq_flags1:                Additional irq triggering flags for irq channel 0
+ * @irq_flags2:                Additional irq triggering flags for irq channel 1
+ * @duration1:         Wake up unit 1 duration parameter
+ * @duration2:         Wake up unit 2 duration parameter
+ * @wakeup_flags:      Wake up unit 1 flags
+ * @wakeup_thresh:     Wake up unit 1 threshold value
+ * @wakeup_flags2:     Wake up unit 2 flags
+ * @wakeup_thresh2:    Wake up unit 2 threshold value
+ * @hipass_ctrl:       High pass filter control (enable / disable, cut off
+ *                     frequency)
+ * @axis_x:            Sensor orientation remapping for x-axis
+ * @axis_y:            Sensor orientation remapping for y-axis
+ * @axis_z:            Sensor orientation remapping for z-axis
+ * @driver_features:   Enable bits for different features. Disabled by default
+ * @default_rate:      Default sampling rate. 0 means reset default
+ * @setup_resources:   Interrupt line setup call back function
+ * @release_resources: Interrupt line release call back function
+ * @st_min_limits[3]:  Selftest acceptance minimum values
+ * @st_max_limits[3]:  Selftest acceptance maximum values
+ * @irq2:              Irq line 2 number
+ *
+ * Platform data is used to setup the sensor chip. Meaning of the different
+ * chip features can be found from the data sheet. It is publicly available
+ * at www.st.com web pages. Currently the platform data is used
+ * only for the 8 bit device. The 8 bit device has two wake up / free fall
+ * detection units and click detection unit. There are plenty of ways to
+ * configure the chip which makes is quite hard to explain deeper meaning of
+ * the fields here. Behaviour of the detection blocks varies heavily depending
+ * on the configuration. For example, interrupt detection block can use high
+ * pass filtered data which makes it react to the changes in the acceleration.
+ * Irq_flags can be used to enable interrupt detection on the both edges.
+ * With proper chip configuration this produces interrupt when some trigger
+ * starts and when it goes away.
+ */
+
 struct lis3lv02d_platform_data {
        /* please note: the 'click' feature is only supported for
         * LIS[32]02DL variants of the chip and will be ignored for
@@ -36,7 +82,10 @@ struct lis3lv02d_platform_data {
 #define LIS3_IRQ_OPEN_DRAIN    (1 << 6)
 #define LIS3_IRQ_ACTIVE_LOW    (1 << 7)
        unsigned char irq_cfg;
-
+       unsigned char irq_flags1; /* Additional irq edge / level flags */
+       unsigned char irq_flags2; /* Additional irq edge / level flags */
+       unsigned char duration1;
+       unsigned char duration2;
 #define LIS3_WAKEUP_X_LO       (1 << 0)
 #define LIS3_WAKEUP_X_HI       (1 << 1)
 #define LIS3_WAKEUP_Y_LO       (1 << 2)
@@ -64,6 +113,10 @@ struct lis3lv02d_platform_data {
        s8 axis_x;
        s8 axis_y;
        s8 axis_z;
+#define LIS3_USE_REGULATOR_CTRL 0x01
+#define LIS3_USE_BLOCK_READ    0x02
+       u16 driver_features;
+       int default_rate;
        int (*setup_resources)(void);
        int (*release_resources)(void);
        /* Limits for selftest are specified in chip data sheet */
index c87f152..23fcdfc 100644 (file)
@@ -35,6 +35,14 @@ static inline u64 div64_u64(u64 dividend, u64 divisor)
        return dividend / divisor;
 }
 
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ */
+static inline s64 div64_s64(s64 dividend, s64 divisor)
+{
+       return dividend / divisor;
+}
+
 #elif BITS_PER_LONG == 32
 
 #ifndef div_u64_rem
@@ -53,6 +61,10 @@ extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
 extern u64 div64_u64(u64 dividend, u64 divisor);
 #endif
 
+#ifndef div64_s64
+extern s64 div64_s64(s64 dividend, s64 divisor);
+#endif
+
 #endif /* BITS_PER_LONG */
 
 /**
index 864035f..4307231 100644 (file)
@@ -70,6 +70,10 @@ extern void online_page(struct page *page);
 extern int online_pages(unsigned long, unsigned long);
 extern void __offline_isolated_pages(unsigned long, unsigned long);
 
+#ifdef CONFIG_MEMORY_HOTREMOVE
+extern bool is_pageblock_removable_nolock(struct page *page);
+#endif /* CONFIG_MEMORY_HOTREMOVE */
+
 /* reasonably generic interface to expand the physical pages in a zone  */
 extern int __add_pages(int nid, struct zone *zone, unsigned long start_pfn,
        unsigned long nr_pages);
index 7238231..085527f 100644 (file)
@@ -14,6 +14,8 @@ extern int migrate_page(struct address_space *,
                        struct page *, struct page *);
 extern int migrate_pages(struct list_head *l, new_page_t x,
                        unsigned long private, int offlining);
+extern int migrate_huge_pages(struct list_head *l, new_page_t x,
+                       unsigned long private, int offlining);
 
 extern int fail_migrate_page(struct address_space *,
                        struct page *, struct page *);
@@ -23,12 +25,17 @@ extern int migrate_prep_local(void);
 extern int migrate_vmas(struct mm_struct *mm,
                const nodemask_t *from, const nodemask_t *to,
                unsigned long flags);
+extern void migrate_page_copy(struct page *newpage, struct page *page);
+extern int migrate_huge_page_move_mapping(struct address_space *mapping,
+                                 struct page *newpage, struct page *page);
 #else
 #define PAGE_MIGRATION 0
 
 static inline void putback_lru_pages(struct list_head *l) {}
 static inline int migrate_pages(struct list_head *l, new_page_t x,
                unsigned long private, int offlining) { return -ENOSYS; }
+static inline int migrate_huge_pages(struct list_head *l, new_page_t x,
+               unsigned long private, int offlining) { return -ENOSYS; }
 
 static inline int migrate_prep(void) { return -ENOSYS; }
 static inline int migrate_prep_local(void) { return -ENOSYS; }
@@ -40,6 +47,15 @@ static inline int migrate_vmas(struct mm_struct *mm,
        return -ENOSYS;
 }
 
+static inline void migrate_page_copy(struct page *newpage,
+                                    struct page *page) {}
+
+static inline int migrate_huge_page_move_mapping(struct address_space *mapping,
+                                 struct page *newpage, struct page *page)
+{
+       return -ENOSYS;
+}
+
 /* Possible settings for the migrate_page() method in address_operations */
 #define migrate_page NULL
 #define fail_migrate_page NULL
index 78a1b96..9a18667 100644 (file)
@@ -58,6 +58,7 @@ enum {
        MLX4_CMD_SENSE_PORT      = 0x4d,
        MLX4_CMD_HW_HEALTH_CHECK = 0x50,
        MLX4_CMD_SET_PORT        = 0xc,
+       MLX4_CMD_SET_NODE        = 0x5a,
        MLX4_CMD_ACCESS_DDR      = 0x2e,
        MLX4_CMD_MAP_ICM         = 0xffa,
        MLX4_CMD_UNMAP_ICM       = 0xff9,
@@ -141,6 +142,7 @@ enum {
        MLX4_SET_PORT_MAC_TABLE = 0x2,
        MLX4_SET_PORT_VLAN_TABLE = 0x3,
        MLX4_SET_PORT_PRIO_MAP  = 0x4,
+       MLX4_SET_PORT_GID_TABLE = 0x5,
 };
 
 struct mlx4_dev;
index 7338654..a7b15bc 100644 (file)
@@ -67,7 +67,8 @@ enum {
        MLX4_DEV_CAP_FLAG_ATOMIC        = 1 << 18,
        MLX4_DEV_CAP_FLAG_RAW_MCAST     = 1 << 19,
        MLX4_DEV_CAP_FLAG_UD_AV_PORT    = 1 << 20,
-       MLX4_DEV_CAP_FLAG_UD_MCAST      = 1 << 21
+       MLX4_DEV_CAP_FLAG_UD_MCAST      = 1 << 21,
+       MLX4_DEV_CAP_FLAG_IBOE          = 1 << 30
 };
 
 enum {
@@ -171,6 +172,10 @@ enum {
        MLX4_NUM_FEXCH          = 64 * 1024,
 };
 
+enum {
+       MLX4_MAX_FAST_REG_PAGES = 511,
+};
+
 static inline u64 mlx4_fw_ver(u64 major, u64 minor, u64 subminor)
 {
        return (major << 32) | (minor << 16) | subminor;
@@ -379,6 +384,27 @@ struct mlx4_av {
        u8                      dgid[16];
 };
 
+struct mlx4_eth_av {
+       __be32          port_pd;
+       u8              reserved1;
+       u8              smac_idx;
+       u16             reserved2;
+       u8              reserved3;
+       u8              gid_index;
+       u8              stat_rate;
+       u8              hop_limit;
+       __be32          sl_tclass_flowlabel;
+       u8              dgid[16];
+       u32             reserved4[2];
+       __be16          vlan;
+       u8              mac[6];
+};
+
+union mlx4_ext_av {
+       struct mlx4_av          ib;
+       struct mlx4_eth_av      eth;
+};
+
 struct mlx4_dev {
        struct pci_dev         *pdev;
        unsigned long           flags;
@@ -407,6 +433,12 @@ struct mlx4_init_port_param {
                if (((type) == MLX4_PORT_TYPE_IB ? (dev)->caps.port_mask : \
                     ~(dev)->caps.port_mask) & 1 << ((port) - 1))
 
+#define mlx4_foreach_ib_transport_port(port, dev)                      \
+       for ((port) = 1; (port) <= (dev)->caps.num_ports; (port)++)     \
+               if (((dev)->caps.port_mask & 1 << ((port) - 1)) ||      \
+                   ((dev)->caps.flags & MLX4_DEV_CAP_FLAG_IBOE))
+
+
 int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
                   struct mlx4_buf *buf);
 void mlx4_buf_free(struct mlx4_dev *dev, int size, struct mlx4_buf *buf);
@@ -474,6 +506,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16]);
 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index);
 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index);
 
+int mlx4_find_cached_vlan(struct mlx4_dev *dev, u8 port, u16 vid, int *idx);
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index);
 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index);
 
index 53c5fdb..f407cd4 100644 (file)
@@ -44,15 +44,24 @@ enum mlx4_dev_event {
        MLX4_DEV_EVENT_PORT_REINIT,
 };
 
+enum mlx4_protocol {
+       MLX4_PROTOCOL_IB,
+       MLX4_PROTOCOL_EN,
+};
+
 struct mlx4_interface {
        void *                  (*add)   (struct mlx4_dev *dev);
        void                    (*remove)(struct mlx4_dev *dev, void *context);
        void                    (*event) (struct mlx4_dev *dev, void *context,
                                          enum mlx4_dev_event event, int port);
+       void *                  (*get_dev)(struct mlx4_dev *dev, void *context, u8 port);
        struct list_head        list;
+       enum mlx4_protocol      protocol;
 };
 
 int mlx4_register_interface(struct mlx4_interface *intf);
 void mlx4_unregister_interface(struct mlx4_interface *intf);
 
+void *mlx4_get_protocol_dev(struct mlx4_dev *dev, enum mlx4_protocol proto, int port);
+
 #endif /* MLX4_DRIVER_H */
index 7abe643..0eeb2a1 100644 (file)
@@ -109,10 +109,11 @@ struct mlx4_qp_path {
        __be32                  tclass_flowlabel;
        u8                      rgid[16];
        u8                      sched_queue;
-       u8                      snooper_flags;
+       u8                      vlan_index;
        u8                      reserved3[2];
        u8                      counter_index;
-       u8                      reserved4[7];
+       u8                      reserved4;
+       u8                      dmac[6];
 };
 
 struct mlx4_qp_context {
@@ -166,6 +167,7 @@ enum {
        MLX4_WQE_CTRL_TCP_UDP_CSUM      = 1 << 5,
        MLX4_WQE_CTRL_INS_VLAN          = 1 << 6,
        MLX4_WQE_CTRL_STRONG_ORDER      = 1 << 7,
+       MLX4_WQE_CTRL_FORCE_LOOPBACK    = 1 << 0,
 };
 
 struct mlx4_wqe_ctrl_seg {
@@ -219,7 +221,8 @@ struct mlx4_wqe_datagram_seg {
        __be32                  av[8];
        __be32                  dqpn;
        __be32                  qkey;
-       __be32                  reservd[2];
+       __be16                  vlan;
+       u8                      mac[6];
 };
 
 struct mlx4_wqe_lso_seg {
index 7687228..721f451 100644 (file)
@@ -144,6 +144,7 @@ extern pgprot_t protection_map[16];
 #define FAULT_FLAG_WRITE       0x01    /* Fault was a write access */
 #define FAULT_FLAG_NONLINEAR   0x02    /* Fault was via a nonlinear mapping */
 #define FAULT_FLAG_MKWRITE     0x04    /* Fault was mkwrite of existing pte */
+#define FAULT_FLAG_ALLOW_RETRY 0x08    /* Retry fault if blocking */
 
 /*
  * This interface is used by x86 PAT code to identify a pfn mapping that is
@@ -497,8 +498,8 @@ static inline void set_compound_order(struct page *page, unsigned long order)
 #define NODES_PGSHIFT          (NODES_PGOFF * (NODES_WIDTH != 0))
 #define ZONES_PGSHIFT          (ZONES_PGOFF * (ZONES_WIDTH != 0))
 
-/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allcator */
-#ifdef NODE_NOT_IN_PAGEFLAGS
+/* NODE:ZONE or SECTION:ZONE is used to ID a zone for the buddy allocator */
+#ifdef NODE_NOT_IN_PAGE_FLAGS
 #define ZONEID_SHIFT           (SECTIONS_SHIFT + ZONES_SHIFT)
 #define ZONEID_PGOFF           ((SECTIONS_PGOFF < ZONES_PGOFF)? \
                                                SECTIONS_PGOFF : ZONES_PGOFF)
@@ -718,12 +719,21 @@ static inline int page_mapped(struct page *page)
 #define VM_FAULT_SIGBUS        0x0002
 #define VM_FAULT_MAJOR 0x0004
 #define VM_FAULT_WRITE 0x0008  /* Special case for get_user_pages */
-#define VM_FAULT_HWPOISON 0x0010       /* Hit poisoned page */
+#define VM_FAULT_HWPOISON 0x0010       /* Hit poisoned small page */
+#define VM_FAULT_HWPOISON_LARGE 0x0020  /* Hit poisoned large page. Index encoded in upper bits */
 
 #define VM_FAULT_NOPAGE        0x0100  /* ->fault installed the pte, not return page */
 #define VM_FAULT_LOCKED        0x0200  /* ->fault locked the returned page */
+#define VM_FAULT_RETRY 0x0400  /* ->fault blocked, must retry */
+
+#define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
+
+#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON | \
+                        VM_FAULT_HWPOISON_LARGE)
 
-#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_HWPOISON)
+/* Encode hstate index for a hwpoisoned large page */
+#define VM_FAULT_SET_HINDEX(x) ((x) << 12)
+#define VM_FAULT_GET_HINDEX(x) (((x) >> 12) & 0xf)
 
 /*
  * Can be called by the pagefault handler when it gets a VM_FAULT_OOM.
@@ -860,6 +870,7 @@ int __set_page_dirty_no_writeback(struct page *page);
 int redirty_page_for_writepage(struct writeback_control *wbc,
                                struct page *page);
 void account_page_dirtied(struct page *page, struct address_space *mapping);
+void account_page_writeback(struct page *page);
 int set_page_dirty(struct page *page);
 int set_page_dirty_lock(struct page *page);
 int clear_page_dirty_for_io(struct page *page);
@@ -1023,7 +1034,15 @@ extern void unregister_shrinker(struct shrinker *);
 
 int vma_wants_writenotify(struct vm_area_struct *vma);
 
-extern pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl);
+extern pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr,
+                              spinlock_t **ptl);
+static inline pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
+                                   spinlock_t **ptl)
+{
+       pte_t *ptep;
+       __cond_lock(*ptl, ptep = __get_locked_pte(mm, addr, ptl));
+       return ptep;
+}
 
 #ifdef __PAGETABLE_PUD_FOLDED
 static inline int __pud_alloc(struct mm_struct *mm, pgd_t *pgd,
index cb57d65..bb7288a 100644 (file)
@@ -310,6 +310,8 @@ struct mm_struct {
 #ifdef CONFIG_MMU_NOTIFIER
        struct mmu_notifier_mm *mmu_notifier_mm;
 #endif
+       /* How many tasks sharing this mm are OOM_DISABLE */
+       atomic_t oom_disable_count;
 };
 
 /* Future-safe accessor for struct mm_struct's cpu_vm_mask. */
index 3984c4e..39c24eb 100644 (file)
@@ -104,6 +104,8 @@ enum zone_stat_item {
        NR_ISOLATED_ANON,       /* Temporary isolated pages from anon lru */
        NR_ISOLATED_FILE,       /* Temporary isolated pages from file lru */
        NR_SHMEM,               /* shmem pages (included tmpfs/GEM pages) */
+       NR_DIRTIED,             /* page dirtyings since bootup */
+       NR_WRITTEN,             /* page writings since bootup */
 #ifdef CONFIG_NUMA
        NUMA_HIT,               /* allocated in intended node */
        NUMA_MISS,              /* allocated in non intended node */
@@ -421,6 +423,9 @@ struct zone {
 typedef enum {
        ZONE_RECLAIM_LOCKED,            /* prevents concurrent reclaim */
        ZONE_OOM_LOCKED,                /* zone is in OOM killer zonelist */
+       ZONE_CONGESTED,                 /* zone has many dirty pages backed by
+                                        * a congested BDI
+                                        */
 } zone_flags_t;
 
 static inline void zone_set_flag(struct zone *zone, zone_flags_t flag)
@@ -438,6 +443,11 @@ static inline void zone_clear_flag(struct zone *zone, zone_flags_t flag)
        clear_bit(flag, &zone->flags);
 }
 
+static inline int zone_is_reclaim_congested(const struct zone *zone)
+{
+       return test_bit(ZONE_CONGESTED, &zone->flags);
+}
+
 static inline int zone_is_reclaim_locked(const struct zone *zone)
 {
        return test_bit(ZONE_RECLAIM_LOCKED, &zone->flags);
index 9d2f183..112adf8 100644 (file)
@@ -21,8 +21,8 @@
 #define __module_cat(a,b) ___module_cat(a,b)
 #define __MODULE_INFO(tag, name, info)                                   \
 static const char __module_cat(name,__LINE__)[]                                  \
-  __used                                                                 \
-  __attribute__((section(".modinfo"),unused)) = __stringify(tag) "=" info
+  __used __attribute__((section(".modinfo"), unused, aligned(1)))        \
+  = __stringify(tag) "=" info
 #else  /* !MODULE */
 #define __MODULE_INFO(tag, name, info)
 #endif
index dee0b11..16faa13 100644 (file)
@@ -229,6 +229,8 @@ enum {
 extern int          sock_wake_async(struct socket *sk, int how, int band);
 extern int          sock_register(const struct net_proto_family *fam);
 extern void         sock_unregister(int family);
+extern int          __sock_create(struct net *net, int family, int type, int proto,
+                                struct socket **res, int kern);
 extern int          sock_create(int family, int type, int proto,
                                 struct socket **res);
 extern int          sock_create_kern(int family, int type, int proto,
index 07e40c6..4925b22 100644 (file)
@@ -17,7 +17,9 @@
 
 #define NFS4_BITMAP_SIZE       2
 #define NFS4_VERIFIER_SIZE     8
-#define NFS4_STATEID_SIZE      16
+#define NFS4_STATEID_SEQID_SIZE 4
+#define NFS4_STATEID_OTHER_SIZE 12
+#define NFS4_STATEID_SIZE      (NFS4_STATEID_SEQID_SIZE + NFS4_STATEID_OTHER_SIZE)
 #define NFS4_FHSIZE            128
 #define NFS4_MAXPATHLEN                PATH_MAX
 #define NFS4_MAXNAMLEN         NAME_MAX
@@ -61,6 +63,9 @@
 #define NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL       0x10000
 #define NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED         0x20000
 
+#define NFS4_CDFC4_FORE        0x1
+#define NFS4_CDFC4_BACK 0x2
+
 #define NFS4_SET_TO_SERVER_TIME        0
 #define NFS4_SET_TO_CLIENT_TIME        1
 
@@ -167,7 +172,16 @@ struct nfs4_acl {
 };
 
 typedef struct { char data[NFS4_VERIFIER_SIZE]; } nfs4_verifier;
-typedef struct { char data[NFS4_STATEID_SIZE]; } nfs4_stateid;
+
+struct nfs41_stateid {
+       __be32 seqid;
+       char other[NFS4_STATEID_OTHER_SIZE];
+} __attribute__ ((packed));
+
+typedef union {
+       char data[NFS4_STATEID_SIZE];
+       struct nfs41_stateid stateid;
+} nfs4_stateid;
 
 enum nfs_opnum4 {
        OP_ACCESS = 3,
@@ -471,6 +485,8 @@ enum lock_type4 {
 #define FATTR4_WORD1_TIME_MODIFY        (1UL << 21)
 #define FATTR4_WORD1_TIME_MODIFY_SET    (1UL << 22)
 #define FATTR4_WORD1_MOUNTED_ON_FILEID  (1UL << 23)
+#define FATTR4_WORD1_FS_LAYOUT_TYPES    (1UL << 30)
+#define FATTR4_WORD2_LAYOUT_BLKSIZE     (1UL << 1)
 
 #define NFSPROC4_NULL 0
 #define NFSPROC4_COMPOUND 1
@@ -532,6 +548,8 @@ enum {
        NFSPROC4_CLNT_SEQUENCE,
        NFSPROC4_CLNT_GET_LEASE_TIME,
        NFSPROC4_CLNT_RECLAIM_COMPLETE,
+       NFSPROC4_CLNT_LAYOUTGET,
+       NFSPROC4_CLNT_GETDEVICEINFO,
 };
 
 /* nfs41 types */
@@ -550,6 +568,49 @@ enum state_protect_how4 {
        SP4_SSV         = 2
 };
 
+enum pnfs_layouttype {
+       LAYOUT_NFSV4_1_FILES  = 1,
+       LAYOUT_OSD2_OBJECTS = 2,
+       LAYOUT_BLOCK_VOLUME = 3,
+};
+
+/* used for both layout return and recall */
+enum pnfs_layoutreturn_type {
+       RETURN_FILE = 1,
+       RETURN_FSID = 2,
+       RETURN_ALL  = 3
+};
+
+enum pnfs_iomode {
+       IOMODE_READ = 1,
+       IOMODE_RW = 2,
+       IOMODE_ANY = 3,
+};
+
+enum pnfs_notify_deviceid_type4 {
+       NOTIFY_DEVICEID4_CHANGE = 1 << 1,
+       NOTIFY_DEVICEID4_DELETE = 1 << 2,
+};
+
+#define NFL4_UFLG_MASK                 0x0000003F
+#define NFL4_UFLG_DENSE                        0x00000001
+#define NFL4_UFLG_COMMIT_THRU_MDS      0x00000002
+#define NFL4_UFLG_STRIPE_UNIT_SIZE_MASK        0xFFFFFFC0
+
+/* Encoded in the loh_body field of type layouthint4 */
+enum filelayout_hint_care4 {
+       NFLH4_CARE_DENSE                = NFL4_UFLG_DENSE,
+       NFLH4_CARE_COMMIT_THRU_MDS      = NFL4_UFLG_COMMIT_THRU_MDS,
+       NFLH4_CARE_STRIPE_UNIT_SIZE     = 0x00000040,
+       NFLH4_CARE_STRIPE_COUNT         = 0x00000080
+};
+
+#define NFS4_DEVICEID4_SIZE 16
+
+struct nfs4_deviceid {
+       char data[NFS4_DEVICEID4_SIZE];
+};
+
 #endif
 #endif
 
index d0edf7d..bba2668 100644 (file)
@@ -188,6 +188,9 @@ struct nfs_inode {
        struct nfs_delegation __rcu *delegation;
        fmode_t                  delegation_state;
        struct rw_semaphore     rwsem;
+
+       /* pNFS layout information */
+       struct pnfs_layout_hdr *layout;
 #endif /* CONFIG_NFS_V4*/
 #ifdef CONFIG_NFS_FSCACHE
        struct fscache_cookie   *fscache;
@@ -360,10 +363,13 @@ extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr);
 extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx);
 extern void put_nfs_open_context(struct nfs_open_context *ctx);
 extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode);
+extern struct nfs_open_context *alloc_nfs_open_context(struct path *path, struct rpc_cred *cred, fmode_t f_mode);
+extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx);
 extern struct nfs_lock_context *nfs_get_lock_context(struct nfs_open_context *ctx);
 extern void nfs_put_lock_context(struct nfs_lock_context *l_ctx);
 extern u64 nfs_compat_user_ino64(u64 fileid);
 extern void nfs_fattr_init(struct nfs_fattr *fattr);
+extern unsigned long nfs_inc_attr_generation_counter(void);
 
 extern struct nfs_fattr *nfs_alloc_fattr(void);
 
@@ -379,9 +385,12 @@ static inline void nfs_free_fhandle(const struct nfs_fh *fh)
        kfree(fh);
 }
 
+/*
+ * linux/fs/nfs/nfsroot.c
+ */
+extern int  nfs_root_data(char **root_device, char **root_data); /*__init*/
 /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */
 extern __be32 root_nfs_parse_addr(char *name); /*__init*/
-extern unsigned long nfs_inc_attr_generation_counter(void);
 
 /*
  * linux/fs/nfs/file.c
@@ -479,10 +488,10 @@ extern void nfs_release_automount_timer(void);
 /*
  * linux/fs/nfs/unlink.c
  */
-extern int  nfs_async_unlink(struct inode *dir, struct dentry *dentry);
 extern void nfs_complete_unlink(struct dentry *dentry, struct inode *);
 extern void nfs_block_sillyrename(struct dentry *dentry);
 extern void nfs_unblock_sillyrename(struct dentry *dentry);
+extern int  nfs_sillyrename(struct inode *dir, struct dentry *dentry);
 
 /*
  * linux/fs/nfs/write.c
@@ -584,10 +593,6 @@ nfs_fileid_to_ino_t(u64 fileid)
        return ino;
 }
 
-/* NFS root */
-
-extern void * nfs_root_data(void);
-
 #define nfs_wait_event(clnt, wq, condition)                            \
 ({                                                                     \
        int __retval = wait_event_killable(wq, condition);              \
@@ -613,6 +618,8 @@ extern void * nfs_root_data(void);
 #define NFSDBG_CLIENT          0x0200
 #define NFSDBG_MOUNT           0x0400
 #define NFSDBG_FSCACHE         0x0800
+#define NFSDBG_PNFS            0x1000
+#define NFSDBG_PNFS_LD         0x2000
 #define NFSDBG_ALL             0xFFFF
 
 #ifdef __KERNEL__
index c82ee7c..452d964 100644 (file)
@@ -82,6 +82,8 @@ struct nfs_client {
        /* The flags used for obtaining the clientid during EXCHANGE_ID */
        u32                     cl_exchange_flags;
        struct nfs4_session     *cl_session;    /* sharred session */
+       struct list_head        cl_layouts;
+       struct pnfs_deviceid_cache *cl_devid_cache; /* pNFS deviceid cache */
 #endif /* CONFIG_NFS_V4_1 */
 
 #ifdef CONFIG_NFS_FSCACHE
@@ -124,6 +126,7 @@ struct nfs_server {
 
        struct nfs_fsid         fsid;
        __u64                   maxfilesize;    /* maximum file size */
+       struct timespec         time_delta;     /* smallest time granularity */
        unsigned long           mount_time;     /* when this fs was mounted */
        dev_t                   s_dev;          /* superblock dev numbers */
 
@@ -144,6 +147,7 @@ struct nfs_server {
        u32                     acl_bitmask;    /* V4 bitmask representing the ACEs
                                                   that are supported on this
                                                   filesystem */
+       struct pnfs_layoutdriver_type  *pnfs_curr_ld; /* Active layout driver */
 #endif
        void (*destroy)(struct nfs_server *);
 
index 91a1c24..e8352dc 100644 (file)
@@ -66,13 +66,40 @@ struct idmap_msg {
 /* Forward declaration to make this header independent of others */
 struct nfs_client;
 
+#ifdef CONFIG_NFS_USE_NEW_IDMAPPER
+
+int nfs_idmap_init(void);
+void nfs_idmap_quit(void);
+
+static inline int nfs_idmap_new(struct nfs_client *clp)
+{
+       return 0;
+}
+
+static inline void nfs_idmap_delete(struct nfs_client *clp)
+{
+}
+
+#else /* CONFIG_NFS_USE_NEW_IDMAPPER not set */
+
+static inline int nfs_idmap_init(void)
+{
+       return 0;
+}
+
+static inline void nfs_idmap_quit(void)
+{
+}
+
 int nfs_idmap_new(struct nfs_client *);
 void nfs_idmap_delete(struct nfs_client *);
 
+#endif /* CONFIG_NFS_USE_NEW_IDMAPPER */
+
 int nfs_map_name_to_uid(struct nfs_client *, const char *, size_t, __u32 *);
 int nfs_map_group_to_gid(struct nfs_client *, const char *, size_t, __u32 *);
-int nfs_map_uid_to_name(struct nfs_client *, __u32, char *);
-int nfs_map_gid_to_group(struct nfs_client *, __u32, char *);
+int nfs_map_uid_to_name(struct nfs_client *, __u32, char *, size_t);
+int nfs_map_gid_to_group(struct nfs_client *, __u32, char *, size_t);
 
 extern unsigned int nfs_idmap_cache_timeout;
 #endif /* __KERNEL__ */
index 5d59ae8..576bddd 100644 (file)
@@ -71,4 +71,7 @@ struct nfs_mount_data {
 #define NFS_MOUNT_NORESVPORT           0x40000
 #define NFS_MOUNT_LEGACY_INTERFACE     0x80000
 
+#define NFS_MOUNT_LOCAL_FLOCK  0x100000
+#define NFS_MOUNT_LOCAL_FCNTL  0x200000
+
 #endif
index fc46192..ba6cc8f 100644 (file)
@@ -112,7 +112,9 @@ struct nfs_fsinfo {
        __u32                   wtmult; /* writes should be multiple of this */
        __u32                   dtpref; /* pref. readdir transfer size */
        __u64                   maxfilesize;
+       struct timespec         time_delta; /* server time granularity */
        __u32                   lease_time; /* in seconds */
+       __u32                   layouttype; /* supported pnfs layout driver */
 };
 
 struct nfs_fsstat {
@@ -170,7 +172,7 @@ struct nfs4_sequence_args {
 
 struct nfs4_sequence_res {
        struct nfs4_session     *sr_session;
-       u8                      sr_slotid;      /* slot used to send request */
+       struct nfs4_slot        *sr_slot;       /* slot used to send request */
        int                     sr_status;      /* sequence operation status */
        unsigned long           sr_renewal_time;
        u32                     sr_status_flags;
@@ -185,6 +187,55 @@ struct nfs4_get_lease_time_res {
        struct nfs4_sequence_res        lr_seq_res;
 };
 
+#define PNFS_LAYOUT_MAXSIZE 4096
+
+struct nfs4_layoutdriver_data {
+       __u32 len;
+       void *buf;
+};
+
+struct pnfs_layout_range {
+       u32 iomode;
+       u64 offset;
+       u64 length;
+};
+
+struct nfs4_layoutget_args {
+       __u32 type;
+       struct pnfs_layout_range range;
+       __u64 minlength;
+       __u32 maxcount;
+       struct inode *inode;
+       struct nfs_open_context *ctx;
+       struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_layoutget_res {
+       __u32 return_on_close;
+       struct pnfs_layout_range range;
+       __u32 type;
+       nfs4_stateid stateid;
+       struct nfs4_layoutdriver_data layout;
+       struct nfs4_sequence_res seq_res;
+};
+
+struct nfs4_layoutget {
+       struct nfs4_layoutget_args args;
+       struct nfs4_layoutget_res res;
+       struct pnfs_layout_segment **lsegpp;
+       int status;
+};
+
+struct nfs4_getdeviceinfo_args {
+       struct pnfs_device *pdev;
+       struct nfs4_sequence_args seq_args;
+};
+
+struct nfs4_getdeviceinfo_res {
+       struct pnfs_device *pdev;
+       struct nfs4_sequence_res seq_res;
+};
+
 /*
  * Arguments to the open call.
  */
@@ -400,6 +451,27 @@ struct nfs_removeres {
 };
 
 /*
+ * Common arguments to the rename call
+ */
+struct nfs_renameargs {
+       const struct nfs_fh             *old_dir;
+       const struct nfs_fh             *new_dir;
+       const struct qstr               *old_name;
+       const struct qstr               *new_name;
+       const u32                       *bitmask;
+       struct nfs4_sequence_args       seq_args;
+};
+
+struct nfs_renameres {
+       const struct nfs_server         *server;
+       struct nfs4_change_info         old_cinfo;
+       struct nfs_fattr                *old_fattr;
+       struct nfs4_change_info         new_cinfo;
+       struct nfs_fattr                *new_fattr;
+       struct nfs4_sequence_res        seq_res;
+};
+
+/*
  * Argument struct for decode_entry function
  */
 struct nfs_entry {
@@ -434,15 +506,6 @@ struct nfs_createargs {
        struct iattr *          sattr;
 };
 
-struct nfs_renameargs {
-       struct nfs_fh *         fromfh;
-       const char *            fromname;
-       unsigned int            fromlen;
-       struct nfs_fh *         tofh;
-       const char *            toname;
-       unsigned int            tolen;
-};
-
 struct nfs_setattrargs {
        struct nfs_fh *                 fh;
        nfs4_stateid                    stateid;
@@ -586,15 +649,6 @@ struct nfs3_mknodargs {
        dev_t                   rdev;
 };
 
-struct nfs3_renameargs {
-       struct nfs_fh *         fromfh;
-       const char *            fromname;
-       unsigned int            fromlen;
-       struct nfs_fh *         tofh;
-       const char *            toname;
-       unsigned int            tolen;
-};
-
 struct nfs3_linkargs {
        struct nfs_fh *         fromfh;
        struct nfs_fh *         tofh;
@@ -629,11 +683,6 @@ struct nfs3_readlinkargs {
        struct page **          pages;
 };
 
-struct nfs3_renameres {
-       struct nfs_fattr *      fromattr;
-       struct nfs_fattr *      toattr;
-};
-
 struct nfs3_linkres {
        struct nfs_fattr *      dir_attr;
        struct nfs_fattr *      fattr;
@@ -780,6 +829,7 @@ struct nfs4_readdir_arg {
        struct page **                  pages;  /* zero-copy data */
        unsigned int                    pgbase; /* zero-copy data */
        const u32 *                     bitmask;
+       int                             plus;
        struct nfs4_sequence_args       seq_args;
 };
 
@@ -801,24 +851,6 @@ struct nfs4_readlink_res {
        struct nfs4_sequence_res        seq_res;
 };
 
-struct nfs4_rename_arg {
-       const struct nfs_fh *           old_dir;
-       const struct nfs_fh *           new_dir;
-       const struct qstr *             old_name;
-       const struct qstr *             new_name;
-       const u32 *                     bitmask;
-       struct nfs4_sequence_args       seq_args;
-};
-
-struct nfs4_rename_res {
-       const struct nfs_server *       server;
-       struct nfs4_change_info         old_cinfo;
-       struct nfs_fattr *              old_fattr;
-       struct nfs4_change_info         new_cinfo;
-       struct nfs_fattr *              new_fattr;
-       struct nfs4_sequence_res        seq_res;
-};
-
 #define NFS4_SETCLIENTID_NAMELEN       (127)
 struct nfs4_setclientid {
        const nfs4_verifier *           sc_verifier;
@@ -1032,19 +1064,21 @@ struct nfs_rpc_ops {
        int     (*readlink)(struct inode *, struct page *, unsigned int,
                            unsigned int);
        int     (*create)  (struct inode *, struct dentry *,
-                           struct iattr *, int, struct nameidata *);
+                           struct iattr *, int, struct nfs_open_context *);
        int     (*remove)  (struct inode *, struct qstr *);
        void    (*unlink_setup)  (struct rpc_message *, struct inode *dir);
        int     (*unlink_done) (struct rpc_task *, struct inode *);
        int     (*rename)  (struct inode *, struct qstr *,
                            struct inode *, struct qstr *);
+       void    (*rename_setup)  (struct rpc_message *msg, struct inode *dir);
+       int     (*rename_done) (struct rpc_task *task, struct inode *old_dir, struct inode *new_dir);
        int     (*link)    (struct inode *, struct inode *, struct qstr *);
        int     (*symlink) (struct inode *, struct dentry *, struct page *,
                            unsigned int, struct iattr *);
        int     (*mkdir)   (struct inode *, struct dentry *, struct iattr *);
        int     (*rmdir)   (struct inode *, struct qstr *);
        int     (*readdir) (struct dentry *, struct rpc_cred *,
-                           u64, struct page *, unsigned int, int);
+                           u64, struct page **, unsigned int, int);
        int     (*mknod)   (struct inode *, struct dentry *, struct iattr *,
                            dev_t);
        int     (*statfs)  (struct nfs_server *, struct nfs_fh *,
@@ -1054,7 +1088,7 @@ struct nfs_rpc_ops {
        int     (*pathconf) (struct nfs_server *, struct nfs_fh *,
                             struct nfs_pathconf *);
        int     (*set_capabilities)(struct nfs_server *, struct nfs_fh *);
-       __be32 *(*decode_dirent)(__be32 *, struct nfs_entry *, int plus);
+       __be32 *(*decode_dirent)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int plus);
        void    (*read_setup)   (struct nfs_read_data *, struct rpc_message *);
        int     (*read_done)  (struct rpc_task *, struct nfs_read_data *);
        void    (*write_setup)  (struct nfs_write_data *, struct rpc_message *);
@@ -1065,6 +1099,10 @@ struct nfs_rpc_ops {
        int     (*lock_check_bounds)(const struct file_lock *);
        void    (*clear_acl_cache)(struct inode *);
        void    (*close_context)(struct nfs_open_context *ctx, int);
+       struct inode * (*open_context) (struct inode *dir,
+                               struct nfs_open_context *ctx,
+                               int open_flags,
+                               struct iattr *iattr);
 };
 
 /*
index e8c0612..19ef95d 100644 (file)
@@ -67,7 +67,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
 
 #define get_pageblock_flags(page) \
                        get_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
-#define set_pageblock_flags(page) \
-                       set_pageblock_flags_group(page, 0, NR_PAGEBLOCK_BITS-1)
+#define set_pageblock_flags(page, flags) \
+                       set_pageblock_flags_group(page, flags,  \
+                                                 0, NR_PAGEBLOCK_BITS-1)
 
 #endif /* PAGEBLOCK_FLAGS_H */
index e12cdc6..2d1ffe3 100644 (file)
@@ -299,6 +299,8 @@ static inline pgoff_t linear_page_index(struct vm_area_struct *vma,
 extern void __lock_page(struct page *page);
 extern int __lock_page_killable(struct page *page);
 extern void __lock_page_nosync(struct page *page);
+extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
+                               unsigned int flags);
 extern void unlock_page(struct page *page);
 
 static inline void __set_page_locked(struct page *page)
@@ -351,6 +353,17 @@ static inline void lock_page_nosync(struct page *page)
 }
        
 /*
+ * lock_page_or_retry - Lock the page, unless this would block and the
+ * caller indicated that it can handle a retry.
+ */
+static inline int lock_page_or_retry(struct page *page, struct mm_struct *mm,
+                                    unsigned int flags)
+{
+       might_sleep();
+       return trylock_page(page) || __lock_page_or_retry(page, mm, flags);
+}
+
+/*
  * This is exported only for wait_on_page_locked/wait_on_page_writeback.
  * Never use this directly!
  */
index 30083a8..7d73256 100644 (file)
@@ -89,6 +89,7 @@ enum power_supply_property {
        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_VOLTAGE_AVG,
+       POWER_SUPPLY_PROP_CURRENT_MAX,
        POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_CURRENT_AVG,
        POWER_SUPPLY_PROP_POWER_NOW,
@@ -125,7 +126,10 @@ enum power_supply_type {
        POWER_SUPPLY_TYPE_BATTERY = 0,
        POWER_SUPPLY_TYPE_UPS,
        POWER_SUPPLY_TYPE_MAINS,
-       POWER_SUPPLY_TYPE_USB,
+       POWER_SUPPLY_TYPE_USB,          /* Standard Downstream Port */
+       POWER_SUPPLY_TYPE_USB_DCP,      /* Dedicated Charging Port */
+       POWER_SUPPLY_TYPE_USB_CDP,      /* Charging Downstream Port */
+       POWER_SUPPLY_TYPE_USB_ACA,      /* Accessory Charger Adapters */
 };
 
 union power_supply_propval {
index 8f69d09..03ff67b 100644 (file)
@@ -36,6 +36,8 @@ static inline void ratelimit_state_init(struct ratelimit_state *rs,
        rs->begin = 0;
 }
 
+extern struct ratelimit_state printk_ratelimit_state;
+
 extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
 #define __ratelimit(state) ___ratelimit(state, __func__)
 
index 31b2fd7..bb83c0d 100644 (file)
@@ -25,8 +25,8 @@
  * pointing to this anon_vma once its vma list is empty.
  */
 struct anon_vma {
-       spinlock_t lock;        /* Serialize access to vma list */
        struct anon_vma *root;  /* Root of this anon_vma tree */
+       spinlock_t lock;        /* Serialize access to vma list */
 #if defined(CONFIG_KSM) || defined(CONFIG_MIGRATION)
 
        /*
@@ -205,9 +205,20 @@ int try_to_unmap_one(struct page *, struct vm_area_struct *,
 /*
  * Called from mm/filemap_xip.c to unmap empty zero page
  */
-pte_t *page_check_address(struct page *, struct mm_struct *,
+pte_t *__page_check_address(struct page *, struct mm_struct *,
                                unsigned long, spinlock_t **, int);
 
+static inline pte_t *page_check_address(struct page *page, struct mm_struct *mm,
+                                       unsigned long address,
+                                       spinlock_t **ptlp, int sync)
+{
+       pte_t *ptep;
+
+       __cond_lock(*ptlp, ptep = __page_check_address(page, mm, address,
+                                                      ptlp, sync));
+       return ptep;
+}
+
 /*
  * Used by swapoff to help locate where page is expected in vma.
  */
@@ -230,7 +241,20 @@ int try_to_munlock(struct page *);
 /*
  * Called by memory-failure.c to kill processes.
  */
-struct anon_vma *page_lock_anon_vma(struct page *page);
+struct anon_vma *__page_lock_anon_vma(struct page *page);
+
+static inline struct anon_vma *page_lock_anon_vma(struct page *page)
+{
+       struct anon_vma *anon_vma;
+
+       __cond_lock(RCU, anon_vma = __page_lock_anon_vma(page));
+
+       /* (void) is needed to make gcc happy */
+       (void) __cond_lock(&anon_vma->root->lock, anon_vma);
+
+       return anon_vma;
+}
+
 void page_unlock_anon_vma(struct anon_vma *anon_vma);
 int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma);
 
index 56154bb..393ce94 100644 (file)
@@ -1706,7 +1706,6 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
 #define PF_DUMPCORE    0x00000200      /* dumped core */
 #define PF_SIGNALED    0x00000400      /* killed by a signal */
 #define PF_MEMALLOC    0x00000800      /* Allocating memory */
-#define PF_FLUSHER     0x00001000      /* responsible for disk writeback */
 #define PF_USED_MATH   0x00002000      /* if unset the fpu must be initialized before use */
 #define PF_FREEZING    0x00004000      /* freeze in progress. do not account to load */
 #define PF_NOFREEZE    0x00008000      /* this thread should not be frozen */
index 99e5994..212eb4c 100644 (file)
 /* High Speed UART for Medfield */
 #define PORT_MFD       95
 
+/* TI OMAP-UART */
+#define PORT_OMAP      96
+
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
index 0299b4c..7f770c6 100644 (file)
@@ -70,9 +70,6 @@
 #define SFI_SIG_APIC           "APIC"
 #define SFI_SIG_XSDT           "XSDT"
 #define SFI_SIG_WAKE           "WAKE"
-#define SFI_SIG_SPIB           "SPIB"
-#define SFI_SIG_I2CB           "I2CB"
-#define SFI_SIG_GPEM           "GPEM"
 #define SFI_SIG_DEVS           "DEVS"
 #define SFI_SIG_GPIO           "GPIO"
 
@@ -168,27 +165,6 @@ struct sfi_gpio_table_entry {
        char    pin_name[16];
 } __packed;
 
-struct sfi_spi_table_entry {
-       u16     host_num;       /* attached to host 0, 1...*/
-       u16     cs;             /* chip select */
-       u16     irq_info;
-       char    name[16];
-       u8      dev_info[10];
-} __packed;
-
-struct sfi_i2c_table_entry {
-       u16     host_num;
-       u16     addr;           /* slave addr */
-       u16     irq_info;
-       char    name[16];
-       u8      dev_info[10];
-} __packed;
-
-struct sfi_gpe_table_entry {
-       u16     logical_id;     /* logical id */
-       u16     phys_id;        /* physical GPE id */
-} __packed;
-
 typedef int (*sfi_table_handler) (struct sfi_table_header *table);
 
 #ifdef CONFIG_SFI
index b363b91..3ff4961 100644 (file)
@@ -33,6 +33,7 @@ struct signalfd_siginfo {
        __u64 ssi_utime;
        __u64 ssi_stime;
        __u64 ssi_addr;
+       __u16 ssi_addr_lsb;
 
        /*
         * Pad strcture to 128 bytes. Remember to update the
@@ -43,7 +44,7 @@ struct signalfd_siginfo {
         * comes out of a read(2) and we really don't want to have
         * a compat on read(2).
         */
-       __u8 __pad[48];
+       __u8 __pad[46];
 };
 
 
index 5bbc447..b202475 100644 (file)
@@ -122,8 +122,8 @@ extern const struct rpc_authops     authnull_ops;
 int __init             rpc_init_authunix(void);
 int __init             rpc_init_generic_auth(void);
 int __init             rpcauth_init_module(void);
-void __exit            rpcauth_remove_module(void);
-void __exit            rpc_destroy_generic_auth(void);
+void                   rpcauth_remove_module(void);
+void                   rpc_destroy_generic_auth(void);
 void                   rpc_destroy_authunix(void);
 
 struct rpc_cred *      rpc_lookup_cred(void);
index 7bf3e84..6950c98 100644 (file)
@@ -125,12 +125,15 @@ struct cache_detail {
  */
 struct cache_req {
        struct cache_deferred_req *(*defer)(struct cache_req *req);
+       int thread_wait;  /* How long (jiffies) we can block the
+                          * current thread to wait for updates.
+                          */
 };
 /* this must be embedded in a deferred_request that is being
  * delayed awaiting cache-fill
  */
 struct cache_deferred_req {
-       struct list_head        hash;   /* on hash chain */
+       struct hlist_node       hash;   /* on hash chain */
        struct list_head        recent; /* on fifo */
        struct cache_head       *item;  /* cache item we wait on */
        void                    *owner; /* we might need to discard all defered requests
@@ -194,7 +197,9 @@ extern void cache_purge(struct cache_detail *detail);
 #define NEVER (0x7FFFFFFF)
 extern void __init cache_initialize(void);
 extern int cache_register(struct cache_detail *cd);
+extern int cache_register_net(struct cache_detail *cd, struct net *net);
 extern void cache_unregister(struct cache_detail *cd);
+extern void cache_unregister_net(struct cache_detail *cd, struct net *net);
 
 extern int sunrpc_cache_register_pipefs(struct dentry *parent, const char *,
                                        mode_t, struct cache_detail *);
@@ -218,14 +223,42 @@ static inline int get_int(char **bpp, int *anint)
        return 0;
 }
 
+/*
+ * timestamps kept in the cache are expressed in seconds
+ * since boot.  This is the best for measuring differences in
+ * real time.
+ */
+static inline time_t seconds_since_boot(void)
+{
+       struct timespec boot;
+       getboottime(&boot);
+       return get_seconds() - boot.tv_sec;
+}
+
+static inline time_t convert_to_wallclock(time_t sinceboot)
+{
+       struct timespec boot;
+       getboottime(&boot);
+       return boot.tv_sec + sinceboot;
+}
+
 static inline time_t get_expiry(char **bpp)
 {
        int rv;
+       struct timespec boot;
+
        if (get_int(bpp, &rv))
                return 0;
        if (rv < 0)
                return 0;
-       return rv;
+       getboottime(&boot);
+       return rv - boot.tv_sec;
 }
 
+static inline void sunrpc_invalidate(struct cache_head *h,
+                                    struct cache_detail *detail)
+{
+       h->expiry_time = seconds_since_boot() - 1;
+       detail->nextcheck = seconds_since_boot();
+}
 #endif /*  _LINUX_SUNRPC_CACHE_H_ */
index 85f38a6..a5a55f2 100644 (file)
@@ -102,6 +102,7 @@ struct rpc_procinfo {
 #ifdef __KERNEL__
 
 struct rpc_create_args {
+       struct net              *net;
        int                     protocol;
        struct sockaddr         *address;
        size_t                  addrsize;
@@ -137,7 +138,6 @@ int         rpcb_register(u32, u32, int, unsigned short);
 int            rpcb_v4_register(const u32 program, const u32 version,
                                 const struct sockaddr *address,
                                 const char *netid);
-int            rpcb_getport_sync(struct sockaddr_in *, u32, u32, int);
 void           rpcb_getport_async(struct rpc_task *);
 
 void           rpc_call_start(struct rpc_task *);
diff --git a/include/linux/sunrpc/gss_spkm3.h b/include/linux/sunrpc/gss_spkm3.h
deleted file mode 100644 (file)
index e3e6a34..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  linux/include/linux/sunrpc/gss_spkm3.h
- *
- *  Copyright (c) 2000 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson   <andros@umich.edu>
- */
-
-#include <linux/sunrpc/auth_gss.h>
-#include <linux/sunrpc/gss_err.h>
-#include <linux/sunrpc/gss_asn1.h>
-
-struct spkm3_ctx {
-       struct xdr_netobj       ctx_id;  /* per message context id */
-       int                     endtime; /* endtime of the context */
-       struct xdr_netobj       mech_used;
-       unsigned int            ret_flags ;
-       struct xdr_netobj       conf_alg;
-       struct xdr_netobj       derived_conf_key;
-       struct xdr_netobj       intg_alg;
-       struct xdr_netobj       derived_integ_key;
-};
-
-/* OIDs declarations for K-ALG, I-ALG, C-ALG, and OWF-ALG */
-extern const struct xdr_netobj hmac_md5_oid;
-extern const struct xdr_netobj cast5_cbc_oid;
-
-/* SPKM InnerContext Token types */
-
-#define SPKM_ERROR_TOK 3
-#define SPKM_MIC_TOK   4
-#define SPKM_WRAP_TOK  5
-#define SPKM_DEL_TOK   6
-
-u32 spkm3_make_token(struct spkm3_ctx *ctx, struct xdr_buf * text, struct xdr_netobj * token, int toktype);
-
-u32 spkm3_read_token(struct spkm3_ctx *ctx, struct xdr_netobj *read_token, struct xdr_buf *message_buffer, int toktype);
-
-#define CKSUMTYPE_RSA_MD5            0x0007
-#define CKSUMTYPE_HMAC_MD5           0x0008
-
-s32 make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
-               unsigned int hdrlen, struct xdr_buf *body,
-               unsigned int body_offset, struct xdr_netobj *cksum);
-void asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits);
-int decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen,
-                   int explen);
-void spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, 
-                   unsigned char *ctxhdr, int elen, int zbit);
-void spkm3_make_mic_token(unsigned  char **tokp, int toklen, 
-                   struct xdr_netobj *mic_hdr,
-                   struct xdr_netobj *md5cksum, int md5elen, int md5zbit);
-u32 spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, 
-                   unsigned char **cksum);
index 5fa0f20..680471d 100644 (file)
@@ -38,8 +38,21 @@ struct svc_stat {
                                rpcbadclnt;
 };
 
-void                   rpc_proc_init(void);
-void                   rpc_proc_exit(void);
+struct net;
+#ifdef CONFIG_PROC_FS
+int                    rpc_proc_init(struct net *);
+void                   rpc_proc_exit(struct net *);
+#else
+static inline int rpc_proc_init(struct net *net)
+{
+       return 0;
+}
+
+static inline void rpc_proc_exit(struct net *net)
+{
+}
+#endif
+
 #ifdef MODULE
 void                   rpc_modcount(struct inode *, int);
 #endif
@@ -54,9 +67,6 @@ void                  svc_proc_unregister(const char *);
 
 void                   svc_seq_show(struct seq_file *,
                                     const struct svc_stat *);
-
-extern struct proc_dir_entry   *proc_net_rpc;
-
 #else
 
 static inline struct proc_dir_entry *rpc_proc_register(struct rpc_stat *s) { return NULL; }
@@ -69,9 +79,6 @@ static inline void svc_proc_unregister(const char *p) {}
 
 static inline void svc_seq_show(struct seq_file *seq,
                                const struct svc_stat *st) {}
-
-#define proc_net_rpc NULL
-
 #endif
 
 #endif /* _LINUX_SUNRPC_STATS_H */
index 5f4e18b..bbdb680 100644 (file)
@@ -12,6 +12,7 @@
 
 struct svc_xprt_ops {
        struct svc_xprt *(*xpo_create)(struct svc_serv *,
+                                      struct net *net,
                                       struct sockaddr *, int,
                                       int);
        struct svc_xprt *(*xpo_accept)(struct svc_xprt *);
@@ -32,6 +33,16 @@ struct svc_xprt_class {
        u32                     xcl_max_payload;
 };
 
+/*
+ * This is embedded in an object that wants a callback before deleting
+ * an xprt; intended for use by NFSv4.1, which needs to know when a
+ * client's tcp connection (and hence possibly a backchannel) goes away.
+ */
+struct svc_xpt_user {
+       struct list_head list;
+       void (*callback)(struct svc_xpt_user *);
+};
+
 struct svc_xprt {
        struct svc_xprt_class   *xpt_class;
        struct svc_xprt_ops     *xpt_ops;
@@ -66,14 +77,31 @@ struct svc_xprt {
        struct sockaddr_storage xpt_remote;     /* remote peer's address */
        size_t                  xpt_remotelen;  /* length of address */
        struct rpc_wait_queue   xpt_bc_pending; /* backchannel wait queue */
+       struct list_head        xpt_users;      /* callbacks on free */
+
+       struct net              *xpt_net;
 };
 
+static inline void register_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
+{
+       spin_lock(&xpt->xpt_lock);
+       list_add(&u->list, &xpt->xpt_users);
+       spin_unlock(&xpt->xpt_lock);
+}
+
+static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
+{
+       spin_lock(&xpt->xpt_lock);
+       list_del_init(&u->list);
+       spin_unlock(&xpt->xpt_lock);
+}
+
 int    svc_reg_xprt_class(struct svc_xprt_class *);
 void   svc_unreg_xprt_class(struct svc_xprt_class *);
 void   svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *,
                      struct svc_serv *);
-int    svc_create_xprt(struct svc_serv *, const char *, const int,
-                       const unsigned short, int);
+int    svc_create_xprt(struct svc_serv *, const char *, struct net *,
+                       const int, const unsigned short, int);
 void   svc_xprt_enqueue(struct svc_xprt *xprt);
 void   svc_xprt_received(struct svc_xprt *);
 void   svc_xprt_put(struct svc_xprt *xprt);
index d39dbdc..25d333c 100644 (file)
@@ -108,10 +108,15 @@ struct auth_ops {
 #define        SVC_NEGATIVE    4
 #define        SVC_OK          5
 #define        SVC_DROP        6
-#define        SVC_DENIED      7
-#define        SVC_PENDING     8
-#define        SVC_COMPLETE    9
+#define        SVC_CLOSE       7       /* Like SVC_DROP, but request is definitely
+                                * lost so if there is a tcp connection, it
+                                * should be closed
+                                */
+#define        SVC_DENIED      8
+#define        SVC_PENDING     9
+#define        SVC_COMPLETE    10
 
+struct svc_xprt;
 
 extern int     svc_authenticate(struct svc_rqst *rqstp, __be32 *authp);
 extern int     svc_authorise(struct svc_rqst *rqstp);
@@ -121,13 +126,13 @@ extern void       svc_auth_unregister(rpc_authflavor_t flavor);
 
 extern struct auth_domain *unix_domain_find(char *name);
 extern void auth_domain_put(struct auth_domain *item);
-extern int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom);
+extern int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom);
 extern struct auth_domain *auth_domain_lookup(char *name, struct auth_domain *new);
 extern struct auth_domain *auth_domain_find(char *name);
-extern struct auth_domain *auth_unix_lookup(struct in6_addr *addr);
+extern struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr);
 extern int auth_unix_forget_old(struct auth_domain *dom);
 extern void svcauth_unix_purge(void);
-extern void svcauth_unix_info_release(void *);
+extern void svcauth_unix_info_release(struct svc_xprt *xpt);
 extern int svcauth_unix_set_client(struct svc_rqst *rqstp);
 
 static inline unsigned long hash_str(char *name, int bits)
index 35cf2e8..498ab93 100644 (file)
@@ -108,6 +108,7 @@ void        xdr_encode_pages(struct xdr_buf *, struct page **, unsigned int,
                         unsigned int);
 void   xdr_inline_pages(struct xdr_buf *, unsigned int,
                         struct page **, unsigned int, unsigned int);
+void   xdr_terminate_string(struct xdr_buf *, const u32);
 
 static inline __be32 *xdr_encode_array(__be32 *p, const void *s, unsigned int len)
 {
@@ -131,6 +132,13 @@ xdr_decode_hyper(__be32 *p, __u64 *valp)
        return p + 2;
 }
 
+static inline __be32 *
+xdr_decode_opaque_fixed(__be32 *p, void *ptr, unsigned int len)
+{
+       memcpy(ptr, p, len);
+       return p + XDR_QUADLEN(len);
+}
+
 /*
  * Adjust kvec to reflect end of xdr'ed data (RPC client XDR)
  */
@@ -200,6 +208,7 @@ extern __be32 *xdr_reserve_space(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_write_pages(struct xdr_stream *xdr, struct page **pages,
                unsigned int base, unsigned int len);
 extern void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p);
+extern __be32 *xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes);
 extern __be32 *xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes);
 extern void xdr_read_pages(struct xdr_stream *xdr, unsigned int len);
 extern void xdr_enter_page(struct xdr_stream *xdr, unsigned int len);
index ff5a77b..89d10d2 100644 (file)
@@ -224,6 +224,7 @@ struct rpc_xprt {
                                        bklog_u;        /* backlog queue utilization */
        } stat;
 
+       struct net              *xprt_net;
        const char              *address_strings[RPC_DISPLAY_MAX];
 };
 
@@ -249,6 +250,7 @@ static inline int bc_prealloc(struct rpc_rqst *req)
 
 struct xprt_create {
        int                     ident;          /* XPRT_TRANSPORT identifier */
+       struct net *            net;
        struct sockaddr *       srcaddr;        /* optional local address */
        struct sockaddr *       dstaddr;        /* remote peer address */
        size_t                  addrlen;
@@ -280,6 +282,8 @@ void                        xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
 void                   xprt_release(struct rpc_task *task);
 struct rpc_xprt *      xprt_get(struct rpc_xprt *xprt);
 void                   xprt_put(struct rpc_xprt *xprt);
+struct rpc_xprt *      xprt_alloc(struct net *net, int size, int max_req);
+void                   xprt_free(struct rpc_xprt *);
 
 static inline __be32 *xprt_skip_transport_header(struct rpc_xprt *xprt, __be32 *p)
 {
index 7cdd633..eba53e7 100644 (file)
@@ -271,8 +271,18 @@ extern void scan_mapping_unevictable_pages(struct address_space *);
 extern unsigned long scan_unevictable_pages;
 extern int scan_unevictable_handler(struct ctl_table *, int,
                                        void __user *, size_t *, loff_t *);
+#ifdef CONFIG_NUMA
 extern int scan_unevictable_register_node(struct node *node);
 extern void scan_unevictable_unregister_node(struct node *node);
+#else
+static inline int scan_unevictable_register_node(struct node *node)
+{
+       return 0;
+}
+static inline void scan_unevictable_unregister_node(struct node *node)
+{
+}
+#endif
 
 extern int kswapd_run(int nid);
 extern void kswapd_stop(int nid);
index 357dbc1..c2a9eb4 100644 (file)
@@ -121,15 +121,7 @@ typedef            __u64           u_int64_t;
 typedef                __s64           int64_t;
 #endif
 
-/*
- * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
- * common 32/64-bit compat problems.
- * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
- * architectures) and to 8-byte boundaries on 64-bit architetures.  The new
- * aligned_64 type enforces 8-byte alignment so that structs containing
- * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
- * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
- */
+/* this is a special 64bit data type that is 8-byte aligned */
 #define aligned_u64 __u64 __attribute__((aligned(8)))
 #define aligned_be64 __be64 __attribute__((aligned(8)))
 #define aligned_le64 __le64 __attribute__((aligned(8)))
@@ -186,7 +178,15 @@ typedef __u64 __bitwise __be64;
 typedef __u16 __bitwise __sum16;
 typedef __u32 __bitwise __wsum;
 
-/* this is a special 64bit data type that is 8-byte aligned */
+/*
+ * aligned_u64 should be used in defining kernel<->userspace ABIs to avoid
+ * common 32/64-bit compat problems.
+ * 64-bit values align to 4-byte boundaries on x86_32 (and possibly other
+ * architectures) and to 8-byte boundaries on 64-bit architetures.  The new
+ * aligned_64 type enforces 8-byte alignment so that structs containing
+ * aligned_64 values have the same alignment on 32-bit and 64-bit architectures.
+ * No conversions are necessary between 32-bit user-space and a 64-bit kernel.
+ */
 #define __aligned_u64 __u64 __attribute__((aligned(8)))
 #define __aligned_be64 __be64 __attribute__((aligned(8)))
 #define __aligned_le64 __le64 __attribute__((aligned(8)))
index 63a4fe6..a03dcf6 100644 (file)
@@ -53,8 +53,10 @@ static inline void vmalloc_init(void)
 #endif
 
 extern void *vmalloc(unsigned long size);
+extern void *vzalloc(unsigned long size);
 extern void *vmalloc_user(unsigned long size);
 extern void *vmalloc_node(unsigned long size, int node);
+extern void *vzalloc_node(unsigned long size, int node);
 extern void *vmalloc_exec(unsigned long size);
 extern void *vmalloc_32(unsigned long size);
 extern void *vmalloc_32_user(unsigned long size);
index 070bb7a..0c0771f 100644 (file)
@@ -190,7 +190,7 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
                __INIT_WORK((_work), (_func), 0);               \
        } while (0)
 
-#define INIT_WORK_ON_STACK(_work, _func)                       \
+#define INIT_WORK_ONSTACK(_work, _func)                                \
        do {                                                    \
                __INIT_WORK((_work), (_func), 1);               \
        } while (0)
@@ -201,9 +201,9 @@ static inline unsigned int work_static(struct work_struct *work) { return 0; }
                init_timer(&(_work)->timer);                    \
        } while (0)
 
-#define INIT_DELAYED_WORK_ON_STACK(_work, _func)               \
+#define INIT_DELAYED_WORK_ONSTACK(_work, _func)                        \
        do {                                                    \
-               INIT_WORK_ON_STACK(&(_work)->work, (_func));    \
+               INIT_WORK_ONSTACK(&(_work)->work, (_func));     \
                init_timer_on_stack(&(_work)->timer);           \
        } while (0)
 
index 242b6f8..d5c7aaa 100644 (file)
@@ -147,6 +147,8 @@ int write_cache_pages(struct address_space *mapping,
 int do_writepages(struct address_space *mapping, struct writeback_control *wbc);
 void set_page_dirty_balance(struct page *page, int page_mkwrite);
 void writeback_set_ratelimit(void);
+void tag_pages_for_writeback(struct address_space *mapping,
+                            pgoff_t start, pgoff_t end);
 
 /* pdflush.c */
 extern int nr_pdflush_threads; /* Global so it can be exported to sysctl
index fa0d52b..b5fc9f3 100644 (file)
@@ -39,7 +39,9 @@
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
 #include <linux/socket.h>
+#include <linux/if_vlan.h>
 #include <rdma/ib_verbs.h>
+#include <rdma/ib_pack.h>
 
 struct rdma_addr_client {
        atomic_t refcount;
@@ -63,6 +65,7 @@ struct rdma_dev_addr {
        unsigned char broadcast[MAX_ADDR_LEN];
        unsigned short dev_type;
        int bound_dev_if;
+       enum rdma_transport_type transport;
 };
 
 /**
@@ -127,9 +130,51 @@ static inline int rdma_addr_gid_offset(struct rdma_dev_addr *dev_addr)
        return dev_addr->dev_type == ARPHRD_INFINIBAND ? 4 : 0;
 }
 
+static inline void iboe_mac_vlan_to_ll(union ib_gid *gid, u8 *mac, u16 vid)
+{
+       memset(gid->raw, 0, 16);
+       *((__be32 *) gid->raw) = cpu_to_be32(0xfe800000);
+       if (vid < 0x1000) {
+               gid->raw[12] = vid & 0xff;
+               gid->raw[11] = vid >> 8;
+       } else {
+               gid->raw[12] = 0xfe;
+               gid->raw[11] = 0xff;
+       }
+       memcpy(gid->raw + 13, mac + 3, 3);
+       memcpy(gid->raw + 8, mac, 3);
+       gid->raw[8] ^= 2;
+}
+
+static inline u16 rdma_vlan_dev_vlan_id(const struct net_device *dev)
+{
+       return dev->priv_flags & IFF_802_1Q_VLAN ?
+               vlan_dev_vlan_id(dev) : 0xffff;
+}
+
+static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
+                                     union ib_gid *gid)
+{
+       struct net_device *dev;
+       u16 vid = 0xffff;
+
+       dev = dev_get_by_index(&init_net, dev_addr->bound_dev_if);
+       if (dev) {
+               vid = rdma_vlan_dev_vlan_id(dev);
+               dev_put(dev);
+       }
+
+       iboe_mac_vlan_to_ll(gid, dev_addr->src_dev_addr, vid);
+}
+
 static inline void rdma_addr_get_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
 {
-       memcpy(gid, dev_addr->src_dev_addr + rdma_addr_gid_offset(dev_addr), sizeof *gid);
+       if (dev_addr->transport == RDMA_TRANSPORT_IB &&
+           dev_addr->dev_type != ARPHRD_INFINIBAND)
+               iboe_addr_get_sgid(dev_addr, gid);
+       else
+               memcpy(gid, dev_addr->src_dev_addr +
+                      rdma_addr_gid_offset(dev_addr), sizeof *gid);
 }
 
 static inline void rdma_addr_set_sgid(struct rdma_dev_addr *dev_addr, union ib_gid *gid)
@@ -147,4 +192,91 @@ static inline void rdma_addr_set_dgid(struct rdma_dev_addr *dev_addr, union ib_g
        memcpy(dev_addr->dst_dev_addr + rdma_addr_gid_offset(dev_addr), gid, sizeof *gid);
 }
 
+static inline enum ib_mtu iboe_get_mtu(int mtu)
+{
+       /*
+        * reduce IB headers from effective IBoE MTU. 28 stands for
+        * atomic header which is the biggest possible header after BTH
+        */
+       mtu = mtu - IB_GRH_BYTES - IB_BTH_BYTES - 28;
+
+       if (mtu >= ib_mtu_enum_to_int(IB_MTU_4096))
+               return IB_MTU_4096;
+       else if (mtu >= ib_mtu_enum_to_int(IB_MTU_2048))
+               return IB_MTU_2048;
+       else if (mtu >= ib_mtu_enum_to_int(IB_MTU_1024))
+               return IB_MTU_1024;
+       else if (mtu >= ib_mtu_enum_to_int(IB_MTU_512))
+               return IB_MTU_512;
+       else if (mtu >= ib_mtu_enum_to_int(IB_MTU_256))
+               return IB_MTU_256;
+       else
+               return 0;
+}
+
+static inline int iboe_get_rate(struct net_device *dev)
+{
+       struct ethtool_cmd cmd;
+
+       if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings ||
+           dev->ethtool_ops->get_settings(dev, &cmd))
+               return IB_RATE_PORT_CURRENT;
+
+       if (cmd.speed >= 40000)
+               return IB_RATE_40_GBPS;
+       else if (cmd.speed >= 30000)
+               return IB_RATE_30_GBPS;
+       else if (cmd.speed >= 20000)
+               return IB_RATE_20_GBPS;
+       else if (cmd.speed >= 10000)
+               return IB_RATE_10_GBPS;
+       else
+               return IB_RATE_PORT_CURRENT;
+}
+
+static inline int rdma_link_local_addr(struct in6_addr *addr)
+{
+       if (addr->s6_addr32[0] == htonl(0xfe800000) &&
+           addr->s6_addr32[1] == 0)
+               return 1;
+
+       return 0;
+}
+
+static inline void rdma_get_ll_mac(struct in6_addr *addr, u8 *mac)
+{
+       memcpy(mac, &addr->s6_addr[8], 3);
+       memcpy(mac + 3, &addr->s6_addr[13], 3);
+       mac[0] ^= 2;
+}
+
+static inline int rdma_is_multicast_addr(struct in6_addr *addr)
+{
+       return addr->s6_addr[0] == 0xff;
+}
+
+static inline void rdma_get_mcast_mac(struct in6_addr *addr, u8 *mac)
+{
+       int i;
+
+       mac[0] = 0x33;
+       mac[1] = 0x33;
+       for (i = 2; i < 6; ++i)
+               mac[i] = addr->s6_addr[i + 10];
+}
+
+static inline u16 rdma_get_vlan_id(union ib_gid *dgid)
+{
+       u16 vid;
+
+       vid = dgid->raw[11] << 8 | dgid->raw[12];
+       return vid < 0x1000 ? vid : 0xffff;
+}
+
+static inline struct net_device *rdma_vlan_dev_real_dev(const struct net_device *dev)
+{
+       return dev->priv_flags & IFF_802_1Q_VLAN ?
+               vlan_dev_real_dev(dev) : 0;
+}
+
 #endif /* IB_ADDR_H */
index cbb50f4..b37fe3b 100644 (file)
@@ -37,6 +37,8 @@
 
 enum {
        IB_LRH_BYTES  = 8,
+       IB_ETH_BYTES  = 14,
+       IB_VLAN_BYTES = 4,
        IB_GRH_BYTES  = 40,
        IB_BTH_BYTES  = 12,
        IB_DETH_BYTES = 8
@@ -210,14 +212,32 @@ struct ib_unpacked_deth {
        __be32       source_qpn;
 };
 
+struct ib_unpacked_eth {
+       u8      dmac_h[4];
+       u8      dmac_l[2];
+       u8      smac_h[2];
+       u8      smac_l[4];
+       __be16  type;
+};
+
+struct ib_unpacked_vlan {
+       __be16  tag;
+       __be16  type;
+};
+
 struct ib_ud_header {
+       int                     lrh_present;
        struct ib_unpacked_lrh  lrh;
-       int                     grh_present;
-       struct ib_unpacked_grh  grh;
-       struct ib_unpacked_bth  bth;
+       int                     eth_present;
+       struct ib_unpacked_eth  eth;
+       int                     vlan_present;
+       struct ib_unpacked_vlan vlan;
+       int                     grh_present;
+       struct ib_unpacked_grh  grh;
+       struct ib_unpacked_bth  bth;
        struct ib_unpacked_deth deth;
-       int                     immediate_present;
-       __be32                  immediate_data;
+       int                     immediate_present;
+       __be32                  immediate_data;
 };
 
 void ib_pack(const struct ib_field        *desc,
@@ -230,9 +250,12 @@ void ib_unpack(const struct ib_field        *desc,
               void                         *buf,
               void                         *structure);
 
-void ib_ud_header_init(int                        payload_bytes,
-                      int                 grh_present,
-                      int                 immediate_present,
+void ib_ud_header_init(int                 payload_bytes,
+                      int                  lrh_present,
+                      int                  eth_present,
+                      int                  vlan_present,
+                      int                  grh_present,
+                      int                  immediate_present,
                       struct ib_ud_header *header);
 
 int ib_ud_header_pack(struct ib_ud_header *header,
index a17f771..fe5b051 100644 (file)
@@ -205,7 +205,8 @@ struct ib_uverbs_query_port_resp {
        __u8  active_width;
        __u8  active_speed;
        __u8  phys_state;
-       __u8  reserved[3];
+       __u8  link_layer;
+       __u8  reserved[2];
 };
 
 struct ib_uverbs_alloc_pd {
index 857b3b9..e04c488 100644 (file)
@@ -75,6 +75,12 @@ enum rdma_transport_type {
 enum rdma_transport_type
 rdma_node_get_transport(enum rdma_node_type node_type) __attribute_const__;
 
+enum rdma_link_layer {
+       IB_LINK_LAYER_UNSPECIFIED,
+       IB_LINK_LAYER_INFINIBAND,
+       IB_LINK_LAYER_ETHERNET,
+};
+
 enum ib_device_cap_flags {
        IB_DEVICE_RESIZE_MAX_WR         = 1,
        IB_DEVICE_BAD_PKEY_CNTR         = (1<<1),
@@ -1010,6 +1016,8 @@ struct ib_device {
        int                        (*query_port)(struct ib_device *device,
                                                 u8 port_num,
                                                 struct ib_port_attr *port_attr);
+       enum rdma_link_layer       (*get_link_layer)(struct ib_device *device,
+                                                    u8 port_num);
        int                        (*query_gid)(struct ib_device *device,
                                                u8 port_num, int index,
                                                union ib_gid *gid);
@@ -1222,6 +1230,9 @@ int ib_query_device(struct ib_device *device,
 int ib_query_port(struct ib_device *device,
                  u8 port_num, struct ib_port_attr *port_attr);
 
+enum rdma_link_layer rdma_port_get_link_layer(struct ib_device *device,
+                                              u8 port_num);
+
 int ib_query_gid(struct ib_device *device,
                 u8 port_num, int index, union ib_gid *gid);
 
index ad178fa..1ae84db 100644 (file)
@@ -239,4 +239,42 @@ struct srp_rsp {
        u8      data[0];
 } __attribute__((packed));
 
+struct srp_cred_req {
+       u8      opcode;
+       u8      sol_not;
+       u8      reserved[2];
+       __be32  req_lim_delta;
+       u64     tag;
+};
+
+struct srp_cred_rsp {
+       u8      opcode;
+       u8      reserved[7];
+       u64     tag;
+};
+
+/*
+ * The SRP spec defines the fixed portion of the AER_REQ structure to be
+ * 36 bytes, so it needs to be packed to avoid having it padded to 40 bytes
+ * on 64-bit architectures.
+ */
+struct srp_aer_req {
+       u8      opcode;
+       u8      sol_not;
+       u8      reserved[2];
+       __be32  req_lim_delta;
+       u64     tag;
+       u32     reserved2;
+       __be64  lun;
+       __be32  sense_data_len;
+       u32     reserved3;
+       u8      sense_data[0];
+} __attribute__((packed));
+
+struct srp_aer_rsp {
+       u8      opcode;
+       u8      reserved[7];
+       u64     tag;
+};
+
 #endif /* SCSI_SRP_H */
index 01e9e00..6bcb006 100644 (file)
@@ -242,18 +242,20 @@ TRACE_EVENT(ext4_da_writepages,
                __entry->pages_skipped  = wbc->pages_skipped;
                __entry->range_start    = wbc->range_start;
                __entry->range_end      = wbc->range_end;
-               __entry->nonblocking    = wbc->nonblocking;
                __entry->for_kupdate    = wbc->for_kupdate;
                __entry->for_reclaim    = wbc->for_reclaim;
                __entry->range_cyclic   = wbc->range_cyclic;
                __entry->writeback_index = inode->i_mapping->writeback_index;
        ),
 
-       TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld range_start %llu range_end %llu nonblocking %d for_kupdate %d for_reclaim %d range_cyclic %d writeback_index %lu",
+       TP_printk("dev %s ino %lu nr_to_write %ld pages_skipped %ld "
+                 "range_start %llu range_end %llu "
+                 "for_kupdate %d for_reclaim %d "
+                 "range_cyclic %d writeback_index %lu",
                  jbd2_dev_to_name(__entry->dev),
                  (unsigned long) __entry->ino, __entry->nr_to_write,
                  __entry->pages_skipped, __entry->range_start,
-                 __entry->range_end, __entry->nonblocking,
+                 __entry->range_end,
                  __entry->for_kupdate, __entry->for_reclaim,
                  __entry->range_cyclic,
                  (unsigned long) __entry->writeback_index)
index 370aa5a..c255fcc 100644 (file)
@@ -10,6 +10,7 @@
 
 #define RECLAIM_WB_ANON                0x0001u
 #define RECLAIM_WB_FILE                0x0002u
+#define RECLAIM_WB_MIXED       0x0010u
 #define RECLAIM_WB_SYNC                0x0004u
 #define RECLAIM_WB_ASYNC       0x0008u
 
        (flags) ? __print_flags(flags, "|",                     \
                {RECLAIM_WB_ANON,       "RECLAIM_WB_ANON"},     \
                {RECLAIM_WB_FILE,       "RECLAIM_WB_FILE"},     \
+               {RECLAIM_WB_MIXED,      "RECLAIM_WB_MIXED"},    \
                {RECLAIM_WB_SYNC,       "RECLAIM_WB_SYNC"},     \
                {RECLAIM_WB_ASYNC,      "RECLAIM_WB_ASYNC"}     \
                ) : "RECLAIM_WB_NONE"
 
 #define trace_reclaim_flags(page, sync) ( \
        (page_is_file_cache(page) ? RECLAIM_WB_FILE : RECLAIM_WB_ANON) | \
-       (sync == PAGEOUT_IO_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC)   \
+       (sync == LUMPY_MODE_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC)   \
+       )
+
+#define trace_shrink_flags(file, sync) ( \
+       (sync == LUMPY_MODE_SYNC ? RECLAIM_WB_MIXED : \
+                       (file ? RECLAIM_WB_FILE : RECLAIM_WB_ANON)) |  \
+       (sync == LUMPY_MODE_SYNC ? RECLAIM_WB_SYNC : RECLAIM_WB_ASYNC) \
        )
 
 TRACE_EVENT(mm_vmscan_kswapd_sleep,
@@ -269,6 +277,40 @@ TRACE_EVENT(mm_vmscan_writepage,
                show_reclaim_flags(__entry->reclaim_flags))
 );
 
+TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
+
+       TP_PROTO(int nid, int zid,
+                       unsigned long nr_scanned, unsigned long nr_reclaimed,
+                       int priority, int reclaim_flags),
+
+       TP_ARGS(nid, zid, nr_scanned, nr_reclaimed, priority, reclaim_flags),
+
+       TP_STRUCT__entry(
+               __field(int, nid)
+               __field(int, zid)
+               __field(unsigned long, nr_scanned)
+               __field(unsigned long, nr_reclaimed)
+               __field(int, priority)
+               __field(int, reclaim_flags)
+       ),
+
+       TP_fast_assign(
+               __entry->nid = nid;
+               __entry->zid = zid;
+               __entry->nr_scanned = nr_scanned;
+               __entry->nr_reclaimed = nr_reclaimed;
+               __entry->priority = priority;
+               __entry->reclaim_flags = reclaim_flags;
+       ),
+
+       TP_printk("nid=%d zid=%d nr_scanned=%ld nr_reclaimed=%ld priority=%d flags=%s",
+               __entry->nid, __entry->zid,
+               __entry->nr_scanned, __entry->nr_reclaimed,
+               __entry->priority,
+               show_reclaim_flags(__entry->reclaim_flags))
+);
+
+
 #endif /* _TRACE_VMSCAN_H */
 
 /* This part must be outside protection */
index f345f66..89a2b2d 100644 (file)
@@ -96,8 +96,6 @@ DECLARE_EVENT_CLASS(wbc_class,
                __field(long, nr_to_write)
                __field(long, pages_skipped)
                __field(int, sync_mode)
-               __field(int, nonblocking)
-               __field(int, encountered_congestion)
                __field(int, for_kupdate)
                __field(int, for_background)
                __field(int, for_reclaim)
@@ -153,6 +151,41 @@ DEFINE_WBC_EVENT(wbc_balance_dirty_written);
 DEFINE_WBC_EVENT(wbc_balance_dirty_wait);
 DEFINE_WBC_EVENT(wbc_writepage);
 
+DECLARE_EVENT_CLASS(writeback_congest_waited_template,
+
+       TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
+
+       TP_ARGS(usec_timeout, usec_delayed),
+
+       TP_STRUCT__entry(
+               __field(        unsigned int,   usec_timeout    )
+               __field(        unsigned int,   usec_delayed    )
+       ),
+
+       TP_fast_assign(
+               __entry->usec_timeout   = usec_timeout;
+               __entry->usec_delayed   = usec_delayed;
+       ),
+
+       TP_printk("usec_timeout=%u usec_delayed=%u",
+                       __entry->usec_timeout,
+                       __entry->usec_delayed)
+);
+
+DEFINE_EVENT(writeback_congest_waited_template, writeback_congestion_wait,
+
+       TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
+
+       TP_ARGS(usec_timeout, usec_delayed)
+);
+
+DEFINE_EVENT(writeback_congest_waited_template, writeback_wait_iff_congested,
+
+       TP_PROTO(unsigned int usec_timeout, unsigned int usec_delayed),
+
+       TP_ARGS(usec_timeout, usec_delayed)
+);
+
 #endif /* _TRACE_WRITEBACK_H */
 
 /* This part must be outside protection */
index 42db055..830aaec 100644 (file)
@@ -291,7 +291,7 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
        if (err)
                return err;
 
-       sys_chdir("/root");
+       sys_chdir((const char __user __force *)"/root");
        ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;
        printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
               current->fs->pwd.mnt->mnt_sb->s_type->name,
@@ -361,13 +361,13 @@ out:
 #ifdef CONFIG_ROOT_NFS
 static int __init mount_nfs_root(void)
 {
-       void *data = nfs_root_data();
+       char *root_dev, *root_data;
 
-       create_dev("/dev/root", ROOT_DEV);
-       if (data &&
-           do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0)
-               return 1;
-       return 0;
+       if (nfs_root_data(&root_dev, &root_data) != 0)
+               return 0;
+       if (do_mount_root(root_dev, "nfs", root_mountflags, root_data) != 0)
+               return 0;
+       return 1;
 }
 #endif
 
@@ -488,5 +488,5 @@ void __init prepare_namespace(void)
 out:
        devtmpfs_mount("dev");
        sys_mount(".", "/", NULL, MS_MOVE, NULL);
-       sys_chroot(".");
+       sys_chroot((const char __user __force *)".");
 }
index 69aebbf..32c4799 100644 (file)
@@ -283,7 +283,7 @@ static void __init autodetect_raid(void)
 
        wait_for_device_probe();
 
-       fd = sys_open("/dev/md0", 0, 0);
+       fd = sys_open((const char __user __force *) "/dev/md0", 0, 0);
        if (fd >= 0) {
                sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
                sys_close(fd);
index bf3ef66..6e1ee69 100644 (file)
@@ -168,7 +168,7 @@ int __init rd_load_image(char *from)
        char rotator[4] = { '|' , '/' , '-' , '\\' };
 #endif
 
-       out_fd = sys_open("/dev/ram", O_RDWR, 0);
+       out_fd = sys_open((const char __user __force *) "/dev/ram", O_RDWR, 0);
        if (out_fd < 0)
                goto out;
 
@@ -267,7 +267,7 @@ noclose_input:
        sys_close(out_fd);
 out:
        kfree(buf);
-       sys_unlink("/dev/ram");
+       sys_unlink((const char __user __force *) "/dev/ram");
        return res;
 }
 
index 4b9c202..d9c6e78 100644 (file)
@@ -528,7 +528,7 @@ static void __init clean_rootfs(void)
        struct linux_dirent64 *dirp;
        int num;
 
-       fd = sys_open("/", O_RDONLY, 0);
+       fd = sys_open((const char __user __force *) "/", O_RDONLY, 0);
        WARN_ON(fd < 0);
        if (fd < 0)
                return;
@@ -590,7 +590,8 @@ static int __init populate_rootfs(void)
                }
                printk(KERN_INFO "rootfs image is not initramfs (%s)"
                                "; looks like an initrd\n", err);
-               fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
+               fd = sys_open((const char __user __force *) "/initrd.image",
+                             O_WRONLY|O_CREAT, 0700);
                if (fd >= 0) {
                        sys_write(fd, (char *)initrd_start,
                                        initrd_end - initrd_start);
index f4c1a3a..267739d 100644 (file)
@@ -29,17 +29,17 @@ static int __init default_rootfs(void)
 {
        int err;
 
-       err = sys_mkdir("/dev", 0755);
+       err = sys_mkdir((const char __user __force *) "/dev", 0755);
        if (err < 0)
                goto out;
 
-       err = sys_mknod((const char __user *) "/dev/console",
+       err = sys_mknod((const char __user __force *) "/dev/console",
                        S_IFCHR | S_IRUSR | S_IWUSR,
                        new_encode_dev(MKDEV(5, 1)));
        if (err < 0)
                goto out;
 
-       err = sys_mkdir("/root", 0700);
+       err = sys_mkdir((const char __user __force *) "/root", 0700);
        if (err < 0)
                goto out;
 
index e2bdf37..894179a 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/perf_event.h>
 #include <trace/events/sched.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/oom.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -687,6 +688,8 @@ static void exit_mm(struct task_struct * tsk)
        enter_lazy_tlb(mm, current);
        /* We don't want this task to be frozen prematurely */
        clear_freeze_flag(tsk);
+       if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+               atomic_dec(&mm->oom_disable_count);
        task_unlock(tsk);
        mm_update_next_owner(mm);
        mmput(mm);
index c445f8c..e87aaaa 100644 (file)
@@ -65,6 +65,7 @@
 #include <linux/perf_event.h>
 #include <linux/posix-timers.h>
 #include <linux/user-return-notifier.h>
+#include <linux/oom.h>
 
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
@@ -488,6 +489,7 @@ static struct mm_struct * mm_init(struct mm_struct * mm, struct task_struct *p)
        mm->cached_hole_size = ~0UL;
        mm_init_aio(mm);
        mm_init_owner(mm, p);
+       atomic_set(&mm->oom_disable_count, 0);
 
        if (likely(!mm_alloc_pgd(mm))) {
                mm->def_flags = 0;
@@ -741,6 +743,8 @@ good_mm:
        /* Initializing for Swap token stuff */
        mm->token_priority = 0;
        mm->last_interval = 0;
+       if (tsk->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+               atomic_inc(&mm->oom_disable_count);
 
        tsk->mm = mm;
        tsk->active_mm = mm;
@@ -1299,8 +1303,13 @@ bad_fork_cleanup_io:
 bad_fork_cleanup_namespaces:
        exit_task_namespaces(p);
 bad_fork_cleanup_mm:
-       if (p->mm)
+       if (p->mm) {
+               task_lock(p);
+               if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN)
+                       atomic_dec(&p->mm->oom_disable_count);
+               task_unlock(p);
                mmput(p->mm);
+       }
 bad_fork_cleanup_signal:
        if (!(clone_flags & CLONE_THREAD))
                free_signal_struct(p->signal);
@@ -1693,6 +1702,10 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
                        active_mm = current->active_mm;
                        current->mm = new_mm;
                        current->active_mm = new_mm;
+                       if (current->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+                               atomic_dec(&mm->oom_disable_count);
+                               atomic_inc(&new_mm->oom_disable_count);
+                       }
                        activate_mm(active_mm, new_mm);
                        new_mm = mm;
                }
index c0613f7..b55045b 100644 (file)
@@ -816,7 +816,7 @@ static int kimage_load_normal_segment(struct kimage *image,
 
                ptr = kmap(page);
                /* Start with a clear page */
-               memset(ptr, 0, PAGE_SIZE);
+               clear_page(ptr);
                ptr += maddr & ~PAGE_MASK;
                mchunk = PAGE_SIZE - (maddr & ~PAGE_MASK);
                if (mchunk > mbytes)
index ac7eb10..0dac75e 100644 (file)
@@ -984,8 +984,8 @@ static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
                src = kmap_atomic(s_page, KM_USER0);
                dst = kmap_atomic(d_page, KM_USER1);
                do_copy_page(dst, src);
-               kunmap_atomic(src, KM_USER0);
                kunmap_atomic(dst, KM_USER1);
+               kunmap_atomic(src, KM_USER0);
        } else {
                if (PageHighMem(d_page)) {
                        /* Page pointed to by src may contain some kernel
@@ -993,7 +993,7 @@ static void copy_data_page(unsigned long dst_pfn, unsigned long src_pfn)
                         */
                        safe_copy_page(buffer, s_page);
                        dst = kmap_atomic(d_page, KM_USER0);
-                       memcpy(dst, buffer, PAGE_SIZE);
+                       copy_page(dst, buffer);
                        kunmap_atomic(dst, KM_USER0);
                } else {
                        safe_copy_page(page_address(d_page), s_page);
@@ -1687,7 +1687,7 @@ int snapshot_read_next(struct snapshot_handle *handle)
                memory_bm_position_reset(&orig_bm);
                memory_bm_position_reset(&copy_bm);
        } else if (handle->cur <= nr_meta_pages) {
-               memset(buffer, 0, PAGE_SIZE);
+               clear_page(buffer);
                pack_pfns(buffer, &orig_bm);
        } else {
                struct page *page;
@@ -1701,7 +1701,7 @@ int snapshot_read_next(struct snapshot_handle *handle)
                        void *kaddr;
 
                        kaddr = kmap_atomic(page, KM_USER0);
-                       memcpy(buffer, kaddr, PAGE_SIZE);
+                       copy_page(buffer, kaddr);
                        kunmap_atomic(kaddr, KM_USER0);
                        handle->buffer = buffer;
                } else {
@@ -1984,7 +1984,7 @@ static void copy_last_highmem_page(void)
                void *dst;
 
                dst = kmap_atomic(last_highmem_page, KM_USER0);
-               memcpy(dst, buffer, PAGE_SIZE);
+               copy_page(dst, buffer);
                kunmap_atomic(dst, KM_USER0);
                last_highmem_page = NULL;
        }
@@ -2270,11 +2270,11 @@ swap_two_pages_data(struct page *p1, struct page *p2, void *buf)
 
        kaddr1 = kmap_atomic(p1, KM_USER0);
        kaddr2 = kmap_atomic(p2, KM_USER1);
-       memcpy(buf, kaddr1, PAGE_SIZE);
-       memcpy(kaddr1, kaddr2, PAGE_SIZE);
-       memcpy(kaddr2, buf, PAGE_SIZE);
-       kunmap_atomic(kaddr1, KM_USER0);
+       copy_page(buf, kaddr1);
+       copy_page(kaddr1, kaddr2);
+       copy_page(kaddr2, buf);
        kunmap_atomic(kaddr2, KM_USER1);
+       kunmap_atomic(kaddr1, KM_USER0);
 }
 
 /**
index 916eaa7..a0e4a86 100644 (file)
@@ -251,7 +251,7 @@ static int write_page(void *buf, sector_t offset, struct bio **bio_chain)
        if (bio_chain) {
                src = (void *)__get_free_page(__GFP_WAIT | __GFP_HIGH);
                if (src) {
-                       memcpy(src, buf, PAGE_SIZE);
+                       copy_page(src, buf);
                } else {
                        WARN_ON_ONCE(1);
                        bio_chain = NULL;       /* Go synchronous */
@@ -325,7 +325,7 @@ static int swap_write_page(struct swap_map_handle *handle, void *buf,
                error = write_page(handle->cur, handle->cur_swap, NULL);
                if (error)
                        goto out;
-               memset(handle->cur, 0, PAGE_SIZE);
+               clear_page(handle->cur);
                handle->cur_swap = offset;
                handle->k = 0;
        }
@@ -910,7 +910,7 @@ int swsusp_check(void)
        hib_resume_bdev = open_by_devnum(swsusp_resume_device, FMODE_READ);
        if (!IS_ERR(hib_resume_bdev)) {
                set_blocksize(hib_resume_bdev, PAGE_SIZE);
-               memset(swsusp_header, 0, PAGE_SIZE);
+               clear_page(swsusp_header);
                error = hib_bio_read_page(swsusp_resume_block,
                                        swsusp_header, NULL);
                if (error)
index 2531017..b2ebaee 100644 (file)
@@ -210,7 +210,7 @@ __setup("log_buf_len=", log_buf_len_setup);
 
 #ifdef CONFIG_BOOT_PRINTK_DELAY
 
-static unsigned int boot_delay; /* msecs delay after each printk during bootup */
+static int boot_delay; /* msecs delay after each printk during bootup */
 static unsigned long long loops_per_msec;      /* based on boot_delay */
 
 static int __init boot_delay_setup(char *str)
@@ -647,6 +647,7 @@ static inline int can_use_console(unsigned int cpu)
  * released but interrupts still disabled.
  */
 static int acquire_console_semaphore_for_printk(unsigned int cpu)
+       __releases(&logbuf_lock)
 {
        int retval = 0;
 
@@ -1511,7 +1512,7 @@ int kmsg_dump_unregister(struct kmsg_dumper *dumper)
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_unregister);
 
-static const char const *kmsg_reasons[] = {
+static const char * const kmsg_reasons[] = {
        [KMSG_DUMP_OOPS]        = "oops",
        [KMSG_DUMP_PANIC]       = "panic",
        [KMSG_DUMP_KEXEC]       = "kexec",
index 090c288..2df820b 100644 (file)
@@ -262,7 +262,7 @@ repeat:
                cpu_stop_fn_t fn = work->fn;
                void *arg = work->arg;
                struct cpu_stop_done *done = work->done;
-               char ksym_buf[KSYM_NAME_LEN];
+               char ksym_buf[KSYM_NAME_LEN] __maybe_unused;
 
                __set_current_state(TASK_RUNNING);
 
@@ -304,7 +304,7 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb,
                p = kthread_create(cpu_stopper_thread, stopper, "migration/%d",
                                   cpu);
                if (IS_ERR(p))
-                       return NOTIFY_BAD;
+                       return notifier_from_errno(PTR_ERR(p));
                get_task_struct(p);
                kthread_bind(p, cpu);
                sched_set_stop_task(cpu, p);
@@ -372,7 +372,7 @@ static int __init cpu_stop_init(void)
        /* start one for the boot cpu */
        err = cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_UP_PREPARE,
                                    bcpu);
-       BUG_ON(err == NOTIFY_BAD);
+       BUG_ON(err != NOTIFY_OK);
        cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_ONLINE, bcpu);
        register_cpu_notifier(&cpu_stop_cpu_notifier);
 
index 8b77ff5..c33a1ed 100644 (file)
@@ -161,8 +161,6 @@ extern int no_unaligned_warning;
 extern int unaligned_dump_stack;
 #endif
 
-extern struct ratelimit_state printk_ratelimit_state;
-
 #ifdef CONFIG_PROC_SYSCTL
 static int proc_do_cad_pid(struct ctl_table *table, int write,
                  void __user *buffer, size_t *lenp, loff_t *ppos);
index 7e72614..2c7d8d5 100644 (file)
@@ -91,6 +91,7 @@ static struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent)
  * upon function exit.
  */
 static void free_user(struct user_struct *up, unsigned long flags)
+       __releases(&uidhash_lock)
 {
        uid_hash_remove(up);
        spin_unlock_irqrestore(&uidhash_lock, flags);
index c4bd3d8..b0310eb 100644 (file)
@@ -92,7 +92,7 @@ prepare_to_wait_exclusive(wait_queue_head_t *q, wait_queue_t *wait, int state)
 }
 EXPORT_SYMBOL(prepare_to_wait_exclusive);
 
-/*
+/**
  * finish_wait - clean up after waiting in a queue
  * @q: waitqueue waited on
  * @wait: wait descriptor
@@ -127,11 +127,11 @@ void finish_wait(wait_queue_head_t *q, wait_queue_t *wait)
 }
 EXPORT_SYMBOL(finish_wait);
 
-/*
+/**
  * abort_exclusive_wait - abort exclusive waiting in a queue
  * @q: waitqueue waited on
  * @wait: wait descriptor
- * @state: runstate of the waiter to be woken
+ * @mode: runstate of the waiter to be woken
  * @key: key to identify a wait bit queue or %NULL
  *
  * Sets current thread back to running state and removes
index 30acdb7..90db1bd 100644 (file)
@@ -2064,7 +2064,7 @@ static void insert_wq_barrier(struct cpu_workqueue_struct *cwq,
         * checks and call back into the fixup functions where we
         * might deadlock.
         */
-       INIT_WORK_ON_STACK(&barr->work, wq_barrier_func);
+       INIT_WORK_ONSTACK(&barr->work, wq_barrier_func);
        __set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(&barr->work));
        init_completion(&barr->done);
 
@@ -2791,7 +2791,9 @@ static int alloc_cwqs(struct workqueue_struct *wq)
                }
        }
 
-       /* just in case, make sure it's actually aligned */
+       /* just in case, make sure it's actually aligned
+        * - this is affected by PERCPU() alignment in vmlinux.lds.S
+        */
        BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align));
        return wq->cpu_wq.v ? 0 : -ENOMEM;
 }
index 69a3266..9958406 100644 (file)
@@ -317,6 +317,14 @@ config DEBUG_OBJECTS_RCU_HEAD
        help
          Enable this to turn on debugging of RCU list heads (call_rcu() usage).
 
+config DEBUG_OBJECTS_PERCPU_COUNTER
+       bool "Debug percpu counter objects"
+       depends on DEBUG_OBJECTS
+       help
+         If you say Y here, additional code will be inserted into the
+         percpu counter routines to track the life time of percpu counter
+         objects and validate the percpu counter operations.
+
 config DEBUG_OBJECTS_ENABLE_DEFAULT
        int "debug_objects bootup default value (0-1)"
         range 0 1
@@ -366,7 +374,7 @@ config SLUB_STATS
 config DEBUG_KMEMLEAK
        bool "Kernel memory leak detector"
        depends on DEBUG_KERNEL && EXPERIMENTAL && !MEMORY_HOTPLUG && \
-               (X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE)
+               (X86 || ARM || PPC || S390 || SPARC64 || SUPERH || MICROBLAZE || TILE)
 
        select DEBUG_FS if SYSFS
        select STACKTRACE if STACKTRACE_SUPPORT
@@ -740,6 +748,15 @@ config DEBUG_LIST
 
          If unsure, say N.
 
+config TEST_LIST_SORT
+       bool "Linked list sorting test"
+       depends on DEBUG_KERNEL
+       help
+         Enable this to turn on 'list_sort()' function test. This test is
+         executed only once during system boot, so affects only boot time.
+
+         If unsure, say N.
+
 config DEBUG_SG
        bool "Debug SG table operations"
        depends on DEBUG_KERNEL
index ffb78c9..741fae9 100644 (file)
@@ -359,7 +359,6 @@ EXPORT_SYMBOL(bitmap_find_next_zero_area);
 
 #define CHUNKSZ                                32
 #define nbits_to_hold_value(val)       fls(val)
-#define unhex(c)                       (isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
 #define BASEDEC 10             /* fancier cpuset lists input in decimal */
 
 /**
@@ -466,7 +465,7 @@ int __bitmap_parse(const char *buf, unsigned int buflen,
                        if (chunk & ~((1UL << (CHUNKSZ - 4)) - 1))
                                return -EOVERFLOW;
 
-                       chunk = (chunk << 4) | unhex(c);
+                       chunk = (chunk << 4) | hex_to_bin(c);
                        ndigits++; totaldigits++;
                }
                if (ndigits == 0)
index a111eb8..5b49191 100644 (file)
@@ -77,26 +77,58 @@ s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
 EXPORT_SYMBOL(div_s64_rem);
 #endif
 
-/* 64bit divisor, dividend and result. dynamic precision */
+/**
+ * div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend:  64bit dividend
+ * @divisor:   64bit divisor
+ *
+ * This implementation is a modified version of the algorithm proposed
+ * by the book 'Hacker's Delight'.  The original source and full proof
+ * can be found here and is available for use without restriction.
+ *
+ * 'http://www.hackersdelight.org/HDcode/newCode/divDouble.c'
+ */
 #ifndef div64_u64
 u64 div64_u64(u64 dividend, u64 divisor)
 {
-       u32 high, d;
+       u32 high = divisor >> 32;
+       u64 quot;
 
-       high = divisor >> 32;
-       if (high) {
-               unsigned int shift = fls(high);
+       if (high == 0) {
+               quot = div_u64(dividend, divisor);
+       } else {
+               int n = 1 + fls(high);
+               quot = div_u64(dividend >> n, divisor >> n);
 
-               d = divisor >> shift;
-               dividend >>= shift;
-       } else
-               d = divisor;
+               if (quot != 0)
+                       quot--;
+               if ((dividend - quot * divisor) >= divisor)
+                       quot++;
+       }
 
-       return div_u64(dividend, d);
+       return quot;
 }
 EXPORT_SYMBOL(div64_u64);
 #endif
 
+/**
+ * div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend:  64bit dividend
+ * @divisor:   64bit divisor
+ */
+#ifndef div64_s64
+s64 div64_s64(s64 dividend, s64 divisor)
+{
+       s64 quot, t;
+
+       quot = div64_u64(abs64(dividend), abs64(divisor));
+       t = (dividend ^ divisor) >> 63;
+
+       return (quot ^ t) - t;
+}
+EXPORT_SYMBOL(div64_s64);
+#endif
+
 #endif /* BITS_PER_LONG == 32 */
 
 /*
index 5e0966b..e15502e 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -106,16 +106,17 @@ static void idr_mark_full(struct idr_layer **pa, int id)
 }
 
 /**
- * idr_pre_get - reserver resources for idr allocation
+ * idr_pre_get - reserve resources for idr allocation
  * @idp:       idr handle
  * @gfp_mask:  memory allocation flags
  *
- * This function should be called prior to locking and calling the
- * idr_get_new* functions. It preallocates enough memory to satisfy
- * the worst possible allocation.
+ * This function should be called prior to calling the idr_get_new* functions.
+ * It preallocates enough memory to satisfy the worst possible allocation. The
+ * caller should pass in GFP_KERNEL if possible.  This of course requires that
+ * no spinning locks be held.
  *
- * If the system is REALLY out of memory this function returns 0,
- * otherwise 1.
+ * If the system is REALLY out of memory this function returns %0,
+ * otherwise %1.
  */
 int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 {
@@ -290,11 +291,13 @@ static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
  * This is the allocate id function.  It should be called with any
  * required locks.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
- * and go back to the idr_pre_get() call.  If the idr is full, it will
- * return -ENOSPC.
+ * If allocation from IDR's private freelist fails, idr_get_new_above() will
+ * return %-EAGAIN.  The caller should retry the idr_pre_get() call to refill
+ * IDR's preallocation and then retry the idr_get_new_above() call.
  *
- * @id returns a value in the range @starting_id ... 0x7fffffff
+ * If the idr is full idr_get_new_above() will return %-ENOSPC.
+ *
+ * @id returns a value in the range @starting_id ... %0x7fffffff
  */
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 {
@@ -318,14 +321,13 @@ EXPORT_SYMBOL(idr_get_new_above);
  * @ptr: pointer you want associated with the id
  * @id: pointer to the allocated handle
  *
- * This is the allocate id function.  It should be called with any
- * required locks.
+ * If allocation from IDR's private freelist fails, idr_get_new_above() will
+ * return %-EAGAIN.  The caller should retry the idr_pre_get() call to refill
+ * IDR's preallocation and then retry the idr_get_new_above() call.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
- * and go back to the idr_pre_get() call.  If the idr is full, it will
- * return -ENOSPC.
+ * If the idr is full idr_get_new_above() will return %-ENOSPC.
  *
- * @id returns a value in the range 0 ... 0x7fffffff
+ * @id returns a value in the range %0 ... %0x7fffffff
  */
 int idr_get_new(struct idr *idp, void *ptr, int *id)
 {
@@ -388,7 +390,7 @@ static void sub_remove(struct idr *idp, int shift, int id)
 }
 
 /**
- * idr_remove - remove the given id and free it's slot
+ * idr_remove - remove the given id and free its slot
  * @idp: idr handle
  * @id: unique key
  */
@@ -437,7 +439,7 @@ EXPORT_SYMBOL(idr_remove);
  * function will remove all id mappings and leave all idp_layers
  * unused.
  *
- * A typical clean-up sequence for objects stored in an idr tree, will
+ * A typical clean-up sequence for objects stored in an idr tree will
  * use idr_for_each() to free all objects, if necessay, then
  * idr_remove_all() to remove all ids, and idr_destroy() to free
  * up the cached idr_layers.
@@ -542,7 +544,7 @@ EXPORT_SYMBOL(idr_find);
  * not allowed.
  *
  * We check the return of @fn each time. If it returns anything other
- * than 0, we break out and return that value.
+ * than %0, we break out and return that value.
  *
  * The caller must serialize idr_for_each() vs idr_get_new() and idr_remove().
  */
@@ -637,8 +639,8 @@ EXPORT_SYMBOL(idr_get_next);
  * @id: lookup key
  *
  * Replace the pointer registered with an id and return the old value.
- * A -ENOENT return indicates that @id was not found.
- * A -EINVAL return indicates that @id was not within valid constraints.
+ * A %-ENOENT return indicates that @id was not found.
+ * A %-EINVAL return indicates that @id was not within valid constraints.
  *
  * The caller must serialize with writers.
  */
@@ -696,10 +698,11 @@ void idr_init(struct idr *idp)
 EXPORT_SYMBOL(idr_init);
 
 
-/*
+/**
+ * DOC: IDA description
  * IDA - IDR based ID allocator
  *
- * this is id allocator without id -> pointer translation.  Memory
+ * This is id allocator without id -> pointer translation.  Memory
  * usage is much lower than full blown idr because each id only
  * occupies a bit.  ida uses a custom leaf node which contains
  * IDA_BITMAP_BITS slots.
@@ -732,8 +735,8 @@ static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
  * following function.  It preallocates enough memory to satisfy the
  * worst possible allocation.
  *
- * If the system is REALLY out of memory this function returns 0,
- * otherwise 1.
+ * If the system is REALLY out of memory this function returns %0,
+ * otherwise %1.
  */
 int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
 {
@@ -765,11 +768,11 @@ EXPORT_SYMBOL(ida_pre_get);
  * Allocate new ID above or equal to @ida.  It should be called with
  * any required locks.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
+ * If memory is required, it will return %-EAGAIN, you should unlock
  * and go back to the ida_pre_get() call.  If the ida is full, it will
- * return -ENOSPC.
+ * return %-ENOSPC.
  *
- * @p_id returns a value in the range @starting_id ... 0x7fffffff.
+ * @p_id returns a value in the range @starting_id ... %0x7fffffff.
  */
 int ida_get_new_above(struct ida *ida, int starting_id, int *p_id)
 {
@@ -851,11 +854,11 @@ EXPORT_SYMBOL(ida_get_new_above);
  *
  * Allocate new ID.  It should be called with any required locks.
  *
- * If memory is required, it will return -EAGAIN, you should unlock
+ * If memory is required, it will return %-EAGAIN, you should unlock
  * and go back to the idr_pre_get() call.  If the idr is full, it will
- * return -ENOSPC.
+ * return %-ENOSPC.
  *
- * @id returns a value in the range 0 ... 0x7fffffff.
+ * @id returns a value in the range %0 ... %0x7fffffff.
  */
 int ida_get_new(struct ida *ida, int *p_id)
 {
index a7616fa..d7325c6 100644 (file)
@@ -141,77 +141,151 @@ void list_sort(void *priv, struct list_head *head,
 }
 EXPORT_SYMBOL(list_sort);
 
-#ifdef DEBUG_LIST_SORT
+#ifdef CONFIG_TEST_LIST_SORT
+
+#include <linux/random.h>
+
+/*
+ * The pattern of set bits in the list length determines which cases
+ * are hit in list_sort().
+ */
+#define TEST_LIST_LEN (512+128+2) /* not including head */
+
+#define TEST_POISON1 0xDEADBEEF
+#define TEST_POISON2 0xA324354C
+
 struct debug_el {
-       struct list_head l_h;
+       unsigned int poison1;
+       struct list_head list;
+       unsigned int poison2;
        int value;
        unsigned serial;
 };
 
-static int cmp(void *priv, struct list_head *a, struct list_head *b)
+/* Array, containing pointers to all elements in the test list */
+static struct debug_el **elts __initdata;
+
+static int __init check(struct debug_el *ela, struct debug_el *elb)
 {
-       return container_of(a, struct debug_el, l_h)->value
-            - container_of(b, struct debug_el, l_h)->value;
+       if (ela->serial >= TEST_LIST_LEN) {
+               printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
+                               ela->serial);
+               return -EINVAL;
+       }
+       if (elb->serial >= TEST_LIST_LEN) {
+               printk(KERN_ERR "list_sort_test: error: incorrect serial %d\n",
+                               elb->serial);
+               return -EINVAL;
+       }
+       if (elts[ela->serial] != ela || elts[elb->serial] != elb) {
+               printk(KERN_ERR "list_sort_test: error: phantom element\n");
+               return -EINVAL;
+       }
+       if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) {
+               printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
+                               ela->poison1, ela->poison2);
+               return -EINVAL;
+       }
+       if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) {
+               printk(KERN_ERR "list_sort_test: error: bad poison: %#x/%#x\n",
+                               elb->poison1, elb->poison2);
+               return -EINVAL;
+       }
+       return 0;
 }
 
-/*
- * The pattern of set bits in the list length determines which cases
- * are hit in list_sort().
- */
-#define LIST_SORT_TEST_LENGTH (512+128+2) /* not including head */
+static int __init cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+       struct debug_el *ela, *elb;
+
+       ela = container_of(a, struct debug_el, list);
+       elb = container_of(b, struct debug_el, list);
+
+       check(ela, elb);
+       return ela->value - elb->value;
+}
 
 static int __init list_sort_test(void)
 {
-       int i, r = 1, count;
-       struct list_head *head = kmalloc(sizeof(*head), GFP_KERNEL);
-       struct list_head *cur;
+       int i, count = 1, err = -EINVAL;
+       struct debug_el *el;
+       struct list_head *cur, *tmp;
+       LIST_HEAD(head);
+
+       printk(KERN_DEBUG "list_sort_test: start testing list_sort()\n");
 
-       printk(KERN_WARNING "testing list_sort()\n");
+       elts = kmalloc(sizeof(void *) * TEST_LIST_LEN, GFP_KERNEL);
+       if (!elts) {
+               printk(KERN_ERR "list_sort_test: error: cannot allocate "
+                               "memory\n");
+               goto exit;
+       }
 
-       cur = head;
-       for (i = 0; i < LIST_SORT_TEST_LENGTH; i++) {
-               struct debug_el *el = kmalloc(sizeof(*el), GFP_KERNEL);
-               BUG_ON(!el);
+       for (i = 0; i < TEST_LIST_LEN; i++) {
+               el = kmalloc(sizeof(*el), GFP_KERNEL);
+               if (!el) {
+                       printk(KERN_ERR "list_sort_test: error: cannot "
+                                       "allocate memory\n");
+                       goto exit;
+               }
                 /* force some equivalencies */
-               el->value = (r = (r * 725861) % 6599) % (LIST_SORT_TEST_LENGTH/3);
+               el->value = random32() % (TEST_LIST_LEN/3);
                el->serial = i;
-
-               el->l_h.prev = cur;
-               cur->next = &el->l_h;
-               cur = cur->next;
+               el->poison1 = TEST_POISON1;
+               el->poison2 = TEST_POISON2;
+               elts[i] = el;
+               list_add_tail(&el->list, &head);
        }
-       head->prev = cur;
 
-       list_sort(NULL, head, cmp);
+       list_sort(NULL, &head, cmp);
+
+       for (cur = head.next; cur->next != &head; cur = cur->next) {
+               struct debug_el *el1;
+               int cmp_result;
 
-       count = 1;
-       for (cur = head->next; cur->next != head; cur = cur->next) {
-               struct debug_el *el = container_of(cur, struct debug_el, l_h);
-               int cmp_result = cmp(NULL, cur, cur->next);
                if (cur->next->prev != cur) {
-                       printk(KERN_EMERG "list_sort() returned "
-                                               "a corrupted list!\n");
-                       return 1;
-               } else if (cmp_result > 0) {
-                       printk(KERN_EMERG "list_sort() failed to sort!\n");
-                       return 1;
-               } else if (cmp_result == 0 &&
-                               el->serial >= container_of(cur->next,
-                                       struct debug_el, l_h)->serial) {
-                       printk(KERN_EMERG "list_sort() failed to preserve order"
-                                                " of equivalent elements!\n");
-                       return 1;
+                       printk(KERN_ERR "list_sort_test: error: list is "
+                                       "corrupted\n");
+                       goto exit;
+               }
+
+               cmp_result = cmp(NULL, cur, cur->next);
+               if (cmp_result > 0) {
+                       printk(KERN_ERR "list_sort_test: error: list is not "
+                                       "sorted\n");
+                       goto exit;
+               }
+
+               el = container_of(cur, struct debug_el, list);
+               el1 = container_of(cur->next, struct debug_el, list);
+               if (cmp_result == 0 && el->serial >= el1->serial) {
+                       printk(KERN_ERR "list_sort_test: error: order of "
+                                       "equivalent elements not preserved\n");
+                       goto exit;
+               }
+
+               if (check(el, el1)) {
+                       printk(KERN_ERR "list_sort_test: error: element check "
+                                       "failed\n");
+                       goto exit;
                }
-               kfree(cur->prev);
                count++;
        }
-       kfree(cur);
-       if (count != LIST_SORT_TEST_LENGTH) {
-               printk(KERN_EMERG "list_sort() returned list of"
-                                               "different length!\n");
-               return 1;
+
+       if (count != TEST_LIST_LEN) {
+               printk(KERN_ERR "list_sort_test: error: bad list length %d",
+                               count);
+               goto exit;
        }
-       return 0;
+
+       err = 0;
+exit:
+       kfree(elts);
+       list_for_each_safe(cur, tmp, &head) {
+               list_del(cur);
+               kfree(container_of(cur, struct debug_el, list));
+       }
+       return err;
 }
 module_init(list_sort_test);
-#endif
+#endif /* CONFIG_TEST_LIST_SORT */
index fb34977..6e89eca 100644 (file)
@@ -128,12 +128,13 @@ static int match_number(substring_t *s, int *result, int base)
        char *endp;
        char *buf;
        int ret;
+       size_t len = s->to - s->from;
 
-       buf = kmalloc(s->to - s->from + 1, GFP_KERNEL);
+       buf = kmalloc(len + 1, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
-       memcpy(buf, s->from, s->to - s->from);
-       buf[s->to - s->from] = '\0';
+       memcpy(buf, s->from, len);
+       buf[len] = '\0';
        *result = simple_strtol(buf, &endp, base);
        ret = 0;
        if (endp == buf)
index ec9048e..604678d 100644 (file)
@@ -8,10 +8,53 @@
 #include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
+#include <linux/debugobjects.h>
 
 static LIST_HEAD(percpu_counters);
 static DEFINE_MUTEX(percpu_counters_lock);
 
+#ifdef CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER
+
+static struct debug_obj_descr percpu_counter_debug_descr;
+
+static int percpu_counter_fixup_free(void *addr, enum debug_obj_state state)
+{
+       struct percpu_counter *fbc = addr;
+
+       switch (state) {
+       case ODEBUG_STATE_ACTIVE:
+               percpu_counter_destroy(fbc);
+               debug_object_free(fbc, &percpu_counter_debug_descr);
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+static struct debug_obj_descr percpu_counter_debug_descr = {
+       .name           = "percpu_counter",
+       .fixup_free     = percpu_counter_fixup_free,
+};
+
+static inline void debug_percpu_counter_activate(struct percpu_counter *fbc)
+{
+       debug_object_init(fbc, &percpu_counter_debug_descr);
+       debug_object_activate(fbc, &percpu_counter_debug_descr);
+}
+
+static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc)
+{
+       debug_object_deactivate(fbc, &percpu_counter_debug_descr);
+       debug_object_free(fbc, &percpu_counter_debug_descr);
+}
+
+#else  /* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */
+static inline void debug_percpu_counter_activate(struct percpu_counter *fbc)
+{ }
+static inline void debug_percpu_counter_deactivate(struct percpu_counter *fbc)
+{ }
+#endif /* CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER */
+
 void percpu_counter_set(struct percpu_counter *fbc, s64 amount)
 {
        int cpu;
@@ -30,9 +73,9 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
 {
        s64 count;
        s32 *pcount;
-       int cpu = get_cpu();
 
-       pcount = per_cpu_ptr(fbc->counters, cpu);
+       preempt_disable();
+       pcount = this_cpu_ptr(fbc->counters);
        count = *pcount + amount;
        if (count >= batch || count <= -batch) {
                spin_lock(&fbc->lock);
@@ -42,7 +85,7 @@ void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch)
        } else {
                *pcount = count;
        }
-       put_cpu();
+       preempt_enable();
 }
 EXPORT_SYMBOL(__percpu_counter_add);
 
@@ -75,7 +118,11 @@ int __percpu_counter_init(struct percpu_counter *fbc, s64 amount,
        fbc->counters = alloc_percpu(s32);
        if (!fbc->counters)
                return -ENOMEM;
+
+       debug_percpu_counter_activate(fbc);
+
 #ifdef CONFIG_HOTPLUG_CPU
+       INIT_LIST_HEAD(&fbc->list);
        mutex_lock(&percpu_counters_lock);
        list_add(&fbc->list, &percpu_counters);
        mutex_unlock(&percpu_counters_lock);
@@ -89,6 +136,8 @@ void percpu_counter_destroy(struct percpu_counter *fbc)
        if (!fbc->counters)
                return;
 
+       debug_percpu_counter_deactivate(fbc);
+
 #ifdef CONFIG_HOTPLUG_CPU
        mutex_lock(&percpu_counters_lock);
        list_del(&fbc->list);
index 7af9d84..c150d3d 100644 (file)
@@ -988,8 +988,15 @@ static noinline_for_stack
 char *pointer(const char *fmt, char *buf, char *end, void *ptr,
              struct printf_spec spec)
 {
-       if (!ptr)
+       if (!ptr) {
+               /*
+                * Print (null) with the same width as a pointer so it makes
+                * tabular output look nice.
+                */
+               if (spec.field_width == -1)
+                       spec.field_width = 2 * sizeof(void *);
                return string(buf, end, "(null)", spec);
+       }
 
        switch (*fmt) {
        case 'F':
@@ -1031,7 +1038,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
        }
        spec.flags |= SMALL;
        if (spec.field_width == -1) {
-               spec.field_width = 2*sizeof(void *);
+               spec.field_width = 2 * sizeof(void *);
                spec.flags |= ZEROPAD;
        }
        spec.base = 16;
@@ -1497,7 +1504,7 @@ EXPORT_SYMBOL(snprintf);
  * @...: Arguments for the format string
  *
  * The return value is the number of characters written into @buf not including
- * the trailing '\0'. If @size is <= 0 the function returns 0.
+ * the trailing '\0'. If @size is == 0 the function returns 0.
  */
 
 int scnprintf(char *buf, size_t size, const char *fmt, ...)
@@ -1509,7 +1516,11 @@ int scnprintf(char *buf, size_t size, const char *fmt, ...)
        i = vsnprintf(buf, size, fmt, args);
        va_end(args);
 
-       return (i >= size) ? (size - 1) : i;
+       if (likely(i < size))
+               return i;
+       if (size != 0)
+               return size - 1;
+       return 0;
 }
 EXPORT_SYMBOL(scnprintf);
 
index 15d5097..027100d 100644 (file)
@@ -362,7 +362,7 @@ static int bdi_forker_thread(void *ptr)
 {
        struct bdi_writeback *me = ptr;
 
-       current->flags |= PF_FLUSHER | PF_SWAPWRITE;
+       current->flags |= PF_SWAPWRITE;
        set_freezable();
 
        /*
@@ -729,6 +729,7 @@ static wait_queue_head_t congestion_wqh[2] = {
                __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[0]),
                __WAIT_QUEUE_HEAD_INITIALIZER(congestion_wqh[1])
        };
+static atomic_t nr_bdi_congested[2];
 
 void clear_bdi_congested(struct backing_dev_info *bdi, int sync)
 {
@@ -736,7 +737,8 @@ void clear_bdi_congested(struct backing_dev_info *bdi, int sync)
        wait_queue_head_t *wqh = &congestion_wqh[sync];
 
        bit = sync ? BDI_sync_congested : BDI_async_congested;
-       clear_bit(bit, &bdi->state);
+       if (test_and_clear_bit(bit, &bdi->state))
+               atomic_dec(&nr_bdi_congested[sync]);
        smp_mb__after_clear_bit();
        if (waitqueue_active(wqh))
                wake_up(wqh);
@@ -748,7 +750,8 @@ void set_bdi_congested(struct backing_dev_info *bdi, int sync)
        enum bdi_state bit;
 
        bit = sync ? BDI_sync_congested : BDI_async_congested;
-       set_bit(bit, &bdi->state);
+       if (!test_and_set_bit(bit, &bdi->state))
+               atomic_inc(&nr_bdi_congested[sync]);
 }
 EXPORT_SYMBOL(set_bdi_congested);
 
@@ -764,13 +767,72 @@ EXPORT_SYMBOL(set_bdi_congested);
 long congestion_wait(int sync, long timeout)
 {
        long ret;
+       unsigned long start = jiffies;
        DEFINE_WAIT(wait);
        wait_queue_head_t *wqh = &congestion_wqh[sync];
 
        prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
        ret = io_schedule_timeout(timeout);
        finish_wait(wqh, &wait);
+
+       trace_writeback_congestion_wait(jiffies_to_usecs(timeout),
+                                       jiffies_to_usecs(jiffies - start));
+
        return ret;
 }
 EXPORT_SYMBOL(congestion_wait);
 
+/**
+ * wait_iff_congested - Conditionally wait for a backing_dev to become uncongested or a zone to complete writes
+ * @zone: A zone to check if it is heavily congested
+ * @sync: SYNC or ASYNC IO
+ * @timeout: timeout in jiffies
+ *
+ * In the event of a congested backing_dev (any backing_dev) and the given
+ * @zone has experienced recent congestion, this waits for up to @timeout
+ * jiffies for either a BDI to exit congestion of the given @sync queue
+ * or a write to complete.
+ *
+ * In the absense of zone congestion, cond_resched() is called to yield
+ * the processor if necessary but otherwise does not sleep.
+ *
+ * The return value is 0 if the sleep is for the full timeout. Otherwise,
+ * it is the number of jiffies that were still remaining when the function
+ * returned. return_value == timeout implies the function did not sleep.
+ */
+long wait_iff_congested(struct zone *zone, int sync, long timeout)
+{
+       long ret;
+       unsigned long start = jiffies;
+       DEFINE_WAIT(wait);
+       wait_queue_head_t *wqh = &congestion_wqh[sync];
+
+       /*
+        * If there is no congestion, or heavy congestion is not being
+        * encountered in the current zone, yield if necessary instead
+        * of sleeping on the congestion queue
+        */
+       if (atomic_read(&nr_bdi_congested[sync]) == 0 ||
+                       !zone_is_reclaim_congested(zone)) {
+               cond_resched();
+
+               /* In case we scheduled, work out time remaining */
+               ret = timeout - (jiffies - start);
+               if (ret < 0)
+                       ret = 0;
+
+               goto out;
+       }
+
+       /* Sleep until uncongested or a write happens */
+       prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
+       ret = io_schedule_timeout(timeout);
+       finish_wait(wqh, &wait);
+
+out:
+       trace_writeback_wait_iff_congested(jiffies_to_usecs(timeout),
+                                       jiffies_to_usecs(jiffies - start));
+
+       return ret;
+}
+EXPORT_SYMBOL(wait_iff_congested);
index 3df0637..4df2de7 100644 (file)
@@ -311,6 +311,8 @@ void *dma_pool_alloc(struct dma_pool *pool, gfp_t mem_flags,
        size_t offset;
        void *retval;
 
+       might_sleep_if(mem_flags & __GFP_WAIT);
+
        spin_lock_irqsave(&pool->lock, flags);
  restart:
        list_for_each_entry(page, &pool->page_list, page_list) {
index 3d4df44..75572b5 100644 (file)
@@ -612,6 +612,19 @@ void __lock_page_nosync(struct page *page)
                                                        TASK_UNINTERRUPTIBLE);
 }
 
+int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
+                        unsigned int flags)
+{
+       if (!(flags & FAULT_FLAG_ALLOW_RETRY)) {
+               __lock_page(page);
+               return 1;
+       } else {
+               up_read(&mm->mmap_sem);
+               wait_on_page_locked(page);
+               return 0;
+       }
+}
+
 /**
  * find_get_page - find and get a page reference
  * @mapping: the address_space to search
@@ -1539,25 +1552,28 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                 * waiting for the lock.
                 */
                do_async_mmap_readahead(vma, ra, file, page, offset);
-               lock_page(page);
-
-               /* Did it get truncated? */
-               if (unlikely(page->mapping != mapping)) {
-                       unlock_page(page);
-                       put_page(page);
-                       goto no_cached_page;
-               }
        } else {
                /* No page in the page cache at all */
                do_sync_mmap_readahead(vma, ra, file, offset);
                count_vm_event(PGMAJFAULT);
                ret = VM_FAULT_MAJOR;
 retry_find:
-               page = find_lock_page(mapping, offset);
+               page = find_get_page(mapping, offset);
                if (!page)
                        goto no_cached_page;
        }
 
+       if (!lock_page_or_retry(page, vma->vm_mm, vmf->flags))
+               return ret | VM_FAULT_RETRY;
+
+       /* Did it get truncated? */
+       if (unlikely(page->mapping != mapping)) {
+               unlock_page(page);
+               put_page(page);
+               goto retry_find;
+       }
+       VM_BUG_ON(page->index != offset);
+
        /*
         * We have a locked page in the page cache, now we need to check
         * that it's up-to-date. If not, it is going to be due to an error.
@@ -2177,12 +2193,12 @@ generic_file_direct_write(struct kiocb *iocb, const struct iovec *iov,
        }
 
        if (written > 0) {
-               loff_t end = pos + written;
-               if (end > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
-                       i_size_write(inode,  end);
+               pos += written;
+               if (pos > i_size_read(inode) && !S_ISBLK(inode->i_mode)) {
+                       i_size_write(inode, pos);
                        mark_inode_dirty(inode);
                }
-               *ppos = end;
+               *ppos = pos;
        }
 out:
        return written;
index 7a0aa1b..781e754 100644 (file)
 unsigned long totalhigh_pages __read_mostly;
 EXPORT_SYMBOL(totalhigh_pages);
 
+
+DEFINE_PER_CPU(int, __kmap_atomic_idx);
+EXPORT_PER_CPU_SYMBOL(__kmap_atomic_idx);
+
 unsigned int nr_free_highpages (void)
 {
        pg_data_t *pgdat;
@@ -422,61 +426,3 @@ void __init page_address_init(void)
 }
 
 #endif /* defined(CONFIG_HIGHMEM) && !defined(WANT_PAGE_VIRTUAL) */
-
-#ifdef CONFIG_DEBUG_HIGHMEM
-
-void debug_kmap_atomic(enum km_type type)
-{
-       static int warn_count = 10;
-
-       if (unlikely(warn_count < 0))
-               return;
-
-       if (unlikely(in_interrupt())) {
-               if (in_nmi()) {
-                       if (type != KM_NMI && type != KM_NMI_PTE) {
-                               WARN_ON(1);
-                               warn_count--;
-                       }
-               } else if (in_irq()) {
-                       if (type != KM_IRQ0 && type != KM_IRQ1 &&
-                           type != KM_BIO_SRC_IRQ && type != KM_BIO_DST_IRQ &&
-                           type != KM_BOUNCE_READ && type != KM_IRQ_PTE) {
-                               WARN_ON(1);
-                               warn_count--;
-                       }
-               } else if (!irqs_disabled()) {  /* softirq */
-                       if (type != KM_IRQ0 && type != KM_IRQ1 &&
-                           type != KM_SOFTIRQ0 && type != KM_SOFTIRQ1 &&
-                           type != KM_SKB_SUNRPC_DATA &&
-                           type != KM_SKB_DATA_SOFTIRQ &&
-                           type != KM_BOUNCE_READ) {
-                               WARN_ON(1);
-                               warn_count--;
-                       }
-               }
-       }
-
-       if (type == KM_IRQ0 || type == KM_IRQ1 || type == KM_BOUNCE_READ ||
-                       type == KM_BIO_SRC_IRQ || type == KM_BIO_DST_IRQ ||
-                       type == KM_IRQ_PTE || type == KM_NMI ||
-                       type == KM_NMI_PTE ) {
-               if (!irqs_disabled()) {
-                       WARN_ON(1);
-                       warn_count--;
-               }
-       } else if (type == KM_SOFTIRQ0 || type == KM_SOFTIRQ1) {
-               if (irq_count() == 0 && !irqs_disabled()) {
-                       WARN_ON(1);
-                       warn_count--;
-               }
-       }
-#ifdef CONFIG_KGDB_KDB
-       if (unlikely(type == KM_KDB && atomic_read(&kgdb_active) == -1)) {
-               WARN_ON(1);
-               warn_count--;
-       }
-#endif /* CONFIG_KGDB_KDB */
-}
-
-#endif
index c032738..c4a3558 100644 (file)
@@ -423,14 +423,14 @@ static void clear_huge_page(struct page *page,
        }
 }
 
-static void copy_gigantic_page(struct page *dst, struct page *src,
+static void copy_user_gigantic_page(struct page *dst, struct page *src,
                           unsigned long addr, struct vm_area_struct *vma)
 {
        int i;
        struct hstate *h = hstate_vma(vma);
        struct page *dst_base = dst;
        struct page *src_base = src;
-       might_sleep();
+
        for (i = 0; i < pages_per_huge_page(h); ) {
                cond_resched();
                copy_user_highpage(dst, src, addr + i*PAGE_SIZE, vma);
@@ -440,14 +440,15 @@ static void copy_gigantic_page(struct page *dst, struct page *src,
                src = mem_map_next(src, src_base, i);
        }
 }
-static void copy_huge_page(struct page *dst, struct page *src,
+
+static void copy_user_huge_page(struct page *dst, struct page *src,
                           unsigned long addr, struct vm_area_struct *vma)
 {
        int i;
        struct hstate *h = hstate_vma(vma);
 
        if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) {
-               copy_gigantic_page(dst, src, addr, vma);
+               copy_user_gigantic_page(dst, src, addr, vma);
                return;
        }
 
@@ -458,6 +459,40 @@ static void copy_huge_page(struct page *dst, struct page *src,
        }
 }
 
+static void copy_gigantic_page(struct page *dst, struct page *src)
+{
+       int i;
+       struct hstate *h = page_hstate(src);
+       struct page *dst_base = dst;
+       struct page *src_base = src;
+
+       for (i = 0; i < pages_per_huge_page(h); ) {
+               cond_resched();
+               copy_highpage(dst, src);
+
+               i++;
+               dst = mem_map_next(dst, dst_base, i);
+               src = mem_map_next(src, src_base, i);
+       }
+}
+
+void copy_huge_page(struct page *dst, struct page *src)
+{
+       int i;
+       struct hstate *h = page_hstate(src);
+
+       if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) {
+               copy_gigantic_page(dst, src);
+               return;
+       }
+
+       might_sleep();
+       for (i = 0; i < pages_per_huge_page(h); i++) {
+               cond_resched();
+               copy_highpage(dst + i, src + i);
+       }
+}
+
 static void enqueue_huge_page(struct hstate *h, struct page *page)
 {
        int nid = page_to_nid(page);
@@ -466,11 +501,24 @@ static void enqueue_huge_page(struct hstate *h, struct page *page)
        h->free_huge_pages_node[nid]++;
 }
 
+static struct page *dequeue_huge_page_node(struct hstate *h, int nid)
+{
+       struct page *page;
+
+       if (list_empty(&h->hugepage_freelists[nid]))
+               return NULL;
+       page = list_entry(h->hugepage_freelists[nid].next, struct page, lru);
+       list_del(&page->lru);
+       set_page_refcounted(page);
+       h->free_huge_pages--;
+       h->free_huge_pages_node[nid]--;
+       return page;
+}
+
 static struct page *dequeue_huge_page_vma(struct hstate *h,
                                struct vm_area_struct *vma,
                                unsigned long address, int avoid_reserve)
 {
-       int nid;
        struct page *page = NULL;
        struct mempolicy *mpol;
        nodemask_t *nodemask;
@@ -496,19 +544,13 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
 
        for_each_zone_zonelist_nodemask(zone, z, zonelist,
                                                MAX_NR_ZONES - 1, nodemask) {
-               nid = zone_to_nid(zone);
-               if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask) &&
-                   !list_empty(&h->hugepage_freelists[nid])) {
-                       page = list_entry(h->hugepage_freelists[nid].next,
-                                         struct page, lru);
-                       list_del(&page->lru);
-                       h->free_huge_pages--;
-                       h->free_huge_pages_node[nid]--;
-
-                       if (!avoid_reserve)
-                               decrement_hugepage_resv_vma(h, vma);
-
-                       break;
+               if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask)) {
+                       page = dequeue_huge_page_node(h, zone_to_nid(zone));
+                       if (page) {
+                               if (!avoid_reserve)
+                                       decrement_hugepage_resv_vma(h, vma);
+                               break;
+                       }
                }
        }
 err:
@@ -770,11 +812,10 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
        return ret;
 }
 
-static struct page *alloc_buddy_huge_page(struct hstate *h,
-                       struct vm_area_struct *vma, unsigned long address)
+static struct page *alloc_buddy_huge_page(struct hstate *h, int nid)
 {
        struct page *page;
-       unsigned int nid;
+       unsigned int r_nid;
 
        if (h->order >= MAX_ORDER)
                return NULL;
@@ -812,9 +853,14 @@ static struct page *alloc_buddy_huge_page(struct hstate *h,
        }
        spin_unlock(&hugetlb_lock);
 
-       page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
-                                       __GFP_REPEAT|__GFP_NOWARN,
-                                       huge_page_order(h));
+       if (nid == NUMA_NO_NODE)
+               page = alloc_pages(htlb_alloc_mask|__GFP_COMP|
+                                  __GFP_REPEAT|__GFP_NOWARN,
+                                  huge_page_order(h));
+       else
+               page = alloc_pages_exact_node(nid,
+                       htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|
+                       __GFP_REPEAT|__GFP_NOWARN, huge_page_order(h));
 
        if (page && arch_prepare_hugepage(page)) {
                __free_pages(page, huge_page_order(h));
@@ -823,19 +869,13 @@ static struct page *alloc_buddy_huge_page(struct hstate *h,
 
        spin_lock(&hugetlb_lock);
        if (page) {
-               /*
-                * This page is now managed by the hugetlb allocator and has
-                * no users -- drop the buddy allocator's reference.
-                */
-               put_page_testzero(page);
-               VM_BUG_ON(page_count(page));
-               nid = page_to_nid(page);
+               r_nid = page_to_nid(page);
                set_compound_page_dtor(page, free_huge_page);
                /*
                 * We incremented the global counters already
                 */
-               h->nr_huge_pages_node[nid]++;
-               h->surplus_huge_pages_node[nid]++;
+               h->nr_huge_pages_node[r_nid]++;
+               h->surplus_huge_pages_node[r_nid]++;
                __count_vm_event(HTLB_BUDDY_PGALLOC);
        } else {
                h->nr_huge_pages--;
@@ -848,6 +888,25 @@ static struct page *alloc_buddy_huge_page(struct hstate *h,
 }
 
 /*
+ * This allocation function is useful in the context where vma is irrelevant.
+ * E.g. soft-offlining uses this function because it only cares physical
+ * address of error page.
+ */
+struct page *alloc_huge_page_node(struct hstate *h, int nid)
+{
+       struct page *page;
+
+       spin_lock(&hugetlb_lock);
+       page = dequeue_huge_page_node(h, nid);
+       spin_unlock(&hugetlb_lock);
+
+       if (!page)
+               page = alloc_buddy_huge_page(h, nid);
+
+       return page;
+}
+
+/*
  * Increase the hugetlb pool such that it can accomodate a reservation
  * of size 'delta'.
  */
@@ -871,17 +930,14 @@ static int gather_surplus_pages(struct hstate *h, int delta)
 retry:
        spin_unlock(&hugetlb_lock);
        for (i = 0; i < needed; i++) {
-               page = alloc_buddy_huge_page(h, NULL, 0);
-               if (!page) {
+               page = alloc_buddy_huge_page(h, NUMA_NO_NODE);
+               if (!page)
                        /*
                         * We were not able to allocate enough pages to
                         * satisfy the entire reservation so we free what
                         * we've allocated so far.
                         */
-                       spin_lock(&hugetlb_lock);
-                       needed = 0;
                        goto free;
-               }
 
                list_add(&page->lru, &surplus_list);
        }
@@ -908,31 +964,31 @@ retry:
        needed += allocated;
        h->resv_huge_pages += delta;
        ret = 0;
-free:
+
+       spin_unlock(&hugetlb_lock);
        /* Free the needed pages to the hugetlb pool */
        list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
                if ((--needed) < 0)
                        break;
                list_del(&page->lru);
+               /*
+                * This page is now managed by the hugetlb allocator and has
+                * no users -- drop the buddy allocator's reference.
+                */
+               put_page_testzero(page);
+               VM_BUG_ON(page_count(page));
                enqueue_huge_page(h, page);
        }
 
        /* Free unnecessary surplus pages to the buddy allocator */
+free:
        if (!list_empty(&surplus_list)) {
-               spin_unlock(&hugetlb_lock);
                list_for_each_entry_safe(page, tmp, &surplus_list, lru) {
                        list_del(&page->lru);
-                       /*
-                        * The page has a reference count of zero already, so
-                        * call free_huge_page directly instead of using
-                        * put_page.  This must be done with hugetlb_lock
-                        * unlocked which is safe because free_huge_page takes
-                        * hugetlb_lock before deciding how to free the page.
-                        */
-                       free_huge_page(page);
+                       put_page(page);
                }
-               spin_lock(&hugetlb_lock);
        }
+       spin_lock(&hugetlb_lock);
 
        return ret;
 }
@@ -1052,14 +1108,13 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
        spin_unlock(&hugetlb_lock);
 
        if (!page) {
-               page = alloc_buddy_huge_page(h, vma, addr);
+               page = alloc_buddy_huge_page(h, NUMA_NO_NODE);
                if (!page) {
                        hugetlb_put_quota(inode->i_mapping, chg);
                        return ERR_PTR(-VM_FAULT_SIGBUS);
                }
        }
 
-       set_page_refcounted(page);
        set_page_private(page, (unsigned long) mapping);
 
        vma_commit_reservation(h, vma, addr);
@@ -2153,6 +2208,19 @@ nomem:
        return -ENOMEM;
 }
 
+static int is_hugetlb_entry_migration(pte_t pte)
+{
+       swp_entry_t swp;
+
+       if (huge_pte_none(pte) || pte_present(pte))
+               return 0;
+       swp = pte_to_swp_entry(pte);
+       if (non_swap_entry(swp) && is_migration_entry(swp)) {
+               return 1;
+       } else
+               return 0;
+}
+
 static int is_hugetlb_entry_hwpoisoned(pte_t pte)
 {
        swp_entry_t swp;
@@ -2380,10 +2448,13 @@ retry_avoidcopy:
         * When the original hugepage is shared one, it does not have
         * anon_vma prepared.
         */
-       if (unlikely(anon_vma_prepare(vma)))
+       if (unlikely(anon_vma_prepare(vma))) {
+               /* Caller expects lock to be held */
+               spin_lock(&mm->page_table_lock);
                return VM_FAULT_OOM;
+       }
 
-       copy_huge_page(new_page, old_page, address, vma);
+       copy_user_huge_page(new_page, old_page, address, vma);
        __SetPageUptodate(new_page);
 
        /*
@@ -2515,22 +2586,20 @@ retry:
                        hugepage_add_new_anon_rmap(page, vma, address);
                }
        } else {
+               /*
+                * If memory error occurs between mmap() and fault, some process
+                * don't have hwpoisoned swap entry for errored virtual address.
+                * So we need to block hugepage fault by PG_hwpoison bit check.
+                */
+               if (unlikely(PageHWPoison(page))) {
+                       ret = VM_FAULT_HWPOISON | 
+                             VM_FAULT_SET_HINDEX(h - hstates);
+                       goto backout_unlocked;
+               }
                page_dup_rmap(page);
        }
 
        /*
-        * Since memory error handler replaces pte into hwpoison swap entry
-        * at the time of error handling, a process which reserved but not have
-        * the mapping to the error hugepage does not have hwpoison swap entry.
-        * So we need to block accesses from such a process by checking
-        * PG_hwpoison bit here.
-        */
-       if (unlikely(PageHWPoison(page))) {
-               ret = VM_FAULT_HWPOISON;
-               goto backout_unlocked;
-       }
-
-       /*
         * If we are going to COW a private mapping later, we examine the
         * pending reservations for this page now. This will ensure that
         * any allocations necessary to record that reservation occur outside
@@ -2587,8 +2656,12 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        ptep = huge_pte_offset(mm, address);
        if (ptep) {
                entry = huge_ptep_get(ptep);
-               if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
-                       return VM_FAULT_HWPOISON;
+               if (unlikely(is_hugetlb_entry_migration(entry))) {
+                       migration_entry_wait(mm, (pmd_t *)ptep, address);
+                       return 0;
+               } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
+                       return VM_FAULT_HWPOISON_LARGE | 
+                              VM_FAULT_SET_HINDEX(h - hstates);
        }
 
        ptep = huge_pte_alloc(mm, address, huge_page_size(h));
@@ -2878,18 +2951,41 @@ void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed)
        hugetlb_acct_memory(h, -(chg - freed));
 }
 
+#ifdef CONFIG_MEMORY_FAILURE
+
+/* Should be called in hugetlb_lock */
+static int is_hugepage_on_freelist(struct page *hpage)
+{
+       struct page *page;
+       struct page *tmp;
+       struct hstate *h = page_hstate(hpage);
+       int nid = page_to_nid(hpage);
+
+       list_for_each_entry_safe(page, tmp, &h->hugepage_freelists[nid], lru)
+               if (page == hpage)
+                       return 1;
+       return 0;
+}
+
 /*
  * This function is called from memory failure code.
  * Assume the caller holds page lock of the head page.
  */
-void __isolate_hwpoisoned_huge_page(struct page *hpage)
+int dequeue_hwpoisoned_huge_page(struct page *hpage)
 {
        struct hstate *h = page_hstate(hpage);
        int nid = page_to_nid(hpage);
+       int ret = -EBUSY;
 
        spin_lock(&hugetlb_lock);
-       list_del(&hpage->lru);
-       h->free_huge_pages--;
-       h->free_huge_pages_node[nid]--;
+       if (is_hugepage_on_freelist(hpage)) {
+               list_del(&hpage->lru);
+               set_page_refcounted(hpage);
+               h->free_huge_pages--;
+               h->free_huge_pages_node[nid]--;
+               ret = 0;
+       }
        spin_unlock(&hugetlb_lock);
+       return ret;
 }
+#endif
index 6a697bb..dedb0af 100644 (file)
@@ -62,7 +62,7 @@ extern bool is_free_buddy_page(struct page *page);
  */
 static inline unsigned long page_order(struct page *page)
 {
-       VM_BUG_ON(!PageBuddy(page));
+       /* PageBuddy() must be checked by the caller */
        return page_private(page);
 }
 
index 757f6b0..1243241 100644 (file)
@@ -7,21 +7,26 @@
  * Free Software Foundation.
  *
  * High level machine check handler. Handles pages reported by the
- * hardware as being corrupted usually due to a 2bit ECC memory or cache
+ * hardware as being corrupted usually due to a multi-bit ECC memory or cache
  * failure.
+ * 
+ * In addition there is a "soft offline" entry point that allows stop using
+ * not-yet-corrupted-by-suspicious pages without killing anything.
  *
  * Handles page cache pages in various states. The tricky part
- * here is that we can access any page asynchronous to other VM
- * users, because memory failures could happen anytime and anywhere,
- * possibly violating some of their assumptions. This is why this code
- * has to be extremely careful. Generally it tries to use normal locking
- * rules, as in get the standard locks, even if that means the
- * error handling takes potentially a long time.
- *
- * The operation to map back from RMAP chains to processes has to walk
- * the complete process list and has non linear complexity with the number
- * mappings. In short it can be quite slow. But since memory corruptions
- * are rare we hope to get away with this.
+ * here is that we can access any page asynchronously in respect to 
+ * other VM users, because memory failures could happen anytime and 
+ * anywhere. This could violate some of their assumptions. This is why 
+ * this code has to be extremely careful. Generally it tries to use 
+ * normal locking rules, as in get the standard locks, even if that means 
+ * the error handling takes potentially a long time.
+ * 
+ * There are several operations here with exponential complexity because
+ * of unsuitable VM data structures. For example the operation to map back 
+ * from RMAP chains to processes has to walk the complete process list and 
+ * has non linear complexity with the number. But since memory corruptions
+ * are rare we hope to get away with this. This avoids impacting the core 
+ * VM.
  */
 
 /*
@@ -30,7 +35,6 @@
  * - kcore/oldmem/vmcore/mem/kmem check for hwpoison pages
  * - pass bad pages to kdump next kernel
  */
-#define DEBUG 1                /* remove me in 2.6.34 */
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/page-flags.h>
@@ -78,7 +82,7 @@ static int hwpoison_filter_dev(struct page *p)
                return 0;
 
        /*
-        * page_mapping() does not accept slab page
+        * page_mapping() does not accept slab pages.
         */
        if (PageSlab(p))
                return -EINVAL;
@@ -268,7 +272,7 @@ struct to_kill {
        struct list_head nd;
        struct task_struct *tsk;
        unsigned long addr;
-       unsigned addr_valid:1;
+       char addr_valid;
 };
 
 /*
@@ -309,7 +313,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
         * a SIGKILL because the error is not contained anymore.
         */
        if (tk->addr == -EFAULT) {
-               pr_debug("MCE: Unable to find user space address %lx in %s\n",
+               pr_info("MCE: Unable to find user space address %lx in %s\n",
                        page_to_pfn(p), tsk->comm);
                tk->addr_valid = 0;
        }
@@ -577,7 +581,7 @@ static int me_pagecache_clean(struct page *p, unsigned long pfn)
                                        pfn, err);
                } else if (page_has_private(p) &&
                                !try_to_release_page(p, GFP_NOIO)) {
-                       pr_debug("MCE %#lx: failed to release buffers\n", pfn);
+                       pr_info("MCE %#lx: failed to release buffers\n", pfn);
                } else {
                        ret = RECOVERED;
                }
@@ -693,11 +697,10 @@ static int me_swapcache_clean(struct page *p, unsigned long pfn)
  * Issues:
  * - Error on hugepage is contained in hugepage unit (not in raw page unit.)
  *   To narrow down kill region to one page, we need to break up pmd.
- * - To support soft-offlining for hugepage, we need to support hugepage
- *   migration.
  */
 static int me_huge_page(struct page *p, unsigned long pfn)
 {
+       int res = 0;
        struct page *hpage = compound_head(p);
        /*
         * We can safely recover from error on free or reserved (i.e.
@@ -710,8 +713,9 @@ static int me_huge_page(struct page *p, unsigned long pfn)
         * so there is no race between isolation and mapping/unmapping.
         */
        if (!(page_mapping(hpage) || PageAnon(hpage))) {
-               __isolate_hwpoisoned_huge_page(hpage);
-               return RECOVERED;
+               res = dequeue_hwpoisoned_huge_page(hpage);
+               if (!res)
+                       return RECOVERED;
        }
        return DELAYED;
 }
@@ -836,8 +840,6 @@ static int page_action(struct page_state *ps, struct page *p,
        return (result == RECOVERED || result == DELAYED) ? 0 : -EBUSY;
 }
 
-#define N_UNMAP_TRIES 5
-
 /*
  * Do all that is necessary to remove user space mappings. Unmap
  * the pages and send SIGBUS to the processes if the data was dirty.
@@ -849,7 +851,6 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
        struct address_space *mapping;
        LIST_HEAD(tokill);
        int ret;
-       int i;
        int kill = 1;
        struct page *hpage = compound_head(p);
 
@@ -903,17 +904,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
        if (kill)
                collect_procs(hpage, &tokill);
 
-       /*
-        * try_to_unmap can fail temporarily due to races.
-        * Try a few times (RED-PEN better strategy?)
-        */
-       for (i = 0; i < N_UNMAP_TRIES; i++) {
-               ret = try_to_unmap(hpage, ttu);
-               if (ret == SWAP_SUCCESS)
-                       break;
-               pr_debug("MCE %#lx: try_to_unmap retry needed %d\n", pfn,  ret);
-       }
-
+       ret = try_to_unmap(hpage, ttu);
        if (ret != SWAP_SUCCESS)
                printk(KERN_ERR "MCE %#lx: failed to unmap page (mapcount=%d)\n",
                                pfn, page_mapcount(hpage));
@@ -981,7 +972,10 @@ int __memory_failure(unsigned long pfn, int trapno, int flags)
         * We need/can do nothing about count=0 pages.
         * 1) it's a free page, and therefore in safe hand:
         *    prep_new_page() will be the gate keeper.
-        * 2) it's part of a non-compound high order page.
+        * 2) it's a free hugepage, which is also safe:
+        *    an affected hugepage will be dequeued from hugepage freelist,
+        *    so there's no concern about reusing it ever after.
+        * 3) it's part of a non-compound high order page.
         *    Implies some kernel user: cannot stop them from
         *    R/W the page; let's pray that the page has been
         *    used and will be freed some time later.
@@ -993,6 +987,24 @@ int __memory_failure(unsigned long pfn, int trapno, int flags)
                if (is_free_buddy_page(p)) {
                        action_result(pfn, "free buddy", DELAYED);
                        return 0;
+               } else if (PageHuge(hpage)) {
+                       /*
+                        * Check "just unpoisoned", "filter hit", and
+                        * "race with other subpage."
+                        */
+                       lock_page_nosync(hpage);
+                       if (!PageHWPoison(hpage)
+                           || (hwpoison_filter(p) && TestClearPageHWPoison(p))
+                           || (p != hpage && TestSetPageHWPoison(hpage))) {
+                               atomic_long_sub(nr_pages, &mce_bad_pages);
+                               return 0;
+                       }
+                       set_page_hwpoison_huge_page(hpage);
+                       res = dequeue_hwpoisoned_huge_page(hpage);
+                       action_result(pfn, "free huge",
+                                     res ? IGNORED : DELAYED);
+                       unlock_page(hpage);
+                       return res;
                } else {
                        action_result(pfn, "high order kernel", IGNORED);
                        return -EBUSY;
@@ -1147,16 +1159,26 @@ int unpoison_memory(unsigned long pfn)
        page = compound_head(p);
 
        if (!PageHWPoison(p)) {
-               pr_debug("MCE: Page was already unpoisoned %#lx\n", pfn);
+               pr_info("MCE: Page was already unpoisoned %#lx\n", pfn);
                return 0;
        }
 
        nr_pages = 1 << compound_order(page);
 
        if (!get_page_unless_zero(page)) {
+               /*
+                * Since HWPoisoned hugepage should have non-zero refcount,
+                * race between memory failure and unpoison seems to happen.
+                * In such case unpoison fails and memory failure runs
+                * to the end.
+                */
+               if (PageHuge(page)) {
+                       pr_debug("MCE: Memory failure is now running on free hugepage %#lx\n", pfn);
+                       return 0;
+               }
                if (TestClearPageHWPoison(p))
                        atomic_long_sub(nr_pages, &mce_bad_pages);
-               pr_debug("MCE: Software-unpoisoned free page %#lx\n", pfn);
+               pr_info("MCE: Software-unpoisoned free page %#lx\n", pfn);
                return 0;
        }
 
@@ -1168,12 +1190,12 @@ int unpoison_memory(unsigned long pfn)
         * the free buddy page pool.
         */
        if (TestClearPageHWPoison(page)) {
-               pr_debug("MCE: Software-unpoisoned page %#lx\n", pfn);
+               pr_info("MCE: Software-unpoisoned page %#lx\n", pfn);
                atomic_long_sub(nr_pages, &mce_bad_pages);
                freeit = 1;
+               if (PageHuge(page))
+                       clear_page_hwpoison_huge_page(page);
        }
-       if (PageHuge(p))
-               clear_page_hwpoison_huge_page(page);
        unlock_page(page);
 
        put_page(page);
@@ -1187,7 +1209,11 @@ EXPORT_SYMBOL(unpoison_memory);
 static struct page *new_page(struct page *p, unsigned long private, int **x)
 {
        int nid = page_to_nid(p);
-       return alloc_pages_exact_node(nid, GFP_HIGHUSER_MOVABLE, 0);
+       if (PageHuge(p))
+               return alloc_huge_page_node(page_hstate(compound_head(p)),
+                                                  nid);
+       else
+               return alloc_pages_exact_node(nid, GFP_HIGHUSER_MOVABLE, 0);
 }
 
 /*
@@ -1215,14 +1241,21 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
         * was free.
         */
        set_migratetype_isolate(p);
+       /*
+        * When the target page is a free hugepage, just remove it
+        * from free hugepage list.
+        */
        if (!get_page_unless_zero(compound_head(p))) {
-               if (is_free_buddy_page(p)) {
-                       pr_debug("get_any_page: %#lx free buddy page\n", pfn);
+               if (PageHuge(p)) {
+                       pr_info("get_any_page: %#lx free huge page\n", pfn);
+                       ret = dequeue_hwpoisoned_huge_page(compound_head(p));
+               } else if (is_free_buddy_page(p)) {
+                       pr_info("get_any_page: %#lx free buddy page\n", pfn);
                        /* Set hwpoison bit while page is still isolated */
                        SetPageHWPoison(p);
                        ret = 0;
                } else {
-                       pr_debug("get_any_page: %#lx: unknown zero refcount page type %lx\n",
+                       pr_info("get_any_page: %#lx: unknown zero refcount page type %lx\n",
                                pfn, p->flags);
                        ret = -EIO;
                }
@@ -1235,6 +1268,46 @@ static int get_any_page(struct page *p, unsigned long pfn, int flags)
        return ret;
 }
 
+static int soft_offline_huge_page(struct page *page, int flags)
+{
+       int ret;
+       unsigned long pfn = page_to_pfn(page);
+       struct page *hpage = compound_head(page);
+       LIST_HEAD(pagelist);
+
+       ret = get_any_page(page, pfn, flags);
+       if (ret < 0)
+               return ret;
+       if (ret == 0)
+               goto done;
+
+       if (PageHWPoison(hpage)) {
+               put_page(hpage);
+               pr_debug("soft offline: %#lx hugepage already poisoned\n", pfn);
+               return -EBUSY;
+       }
+
+       /* Keep page count to indicate a given hugepage is isolated. */
+
+       list_add(&hpage->lru, &pagelist);
+       ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0);
+       if (ret) {
+                       putback_lru_pages(&pagelist);
+               pr_debug("soft offline: %#lx: migration failed %d, type %lx\n",
+                        pfn, ret, page->flags);
+               if (ret > 0)
+                       ret = -EIO;
+               return ret;
+       }
+done:
+       if (!PageHWPoison(hpage))
+               atomic_long_add(1 << compound_order(hpage), &mce_bad_pages);
+       set_page_hwpoison_huge_page(hpage);
+       dequeue_hwpoisoned_huge_page(hpage);
+       /* keep elevated page count for bad page */
+       return ret;
+}
+
 /**
  * soft_offline_page - Soft offline a page.
  * @page: page to offline
@@ -1262,6 +1335,9 @@ int soft_offline_page(struct page *page, int flags)
        int ret;
        unsigned long pfn = page_to_pfn(page);
 
+       if (PageHuge(page))
+               return soft_offline_huge_page(page, flags);
+
        ret = get_any_page(page, pfn, flags);
        if (ret < 0)
                return ret;
@@ -1288,7 +1364,7 @@ int soft_offline_page(struct page *page, int flags)
                        goto done;
        }
        if (!PageLRU(page)) {
-               pr_debug("soft_offline: %#lx: unknown non LRU page type %lx\n",
+               pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n",
                                pfn, page->flags);
                return -EIO;
        }
@@ -1302,7 +1378,7 @@ int soft_offline_page(struct page *page, int flags)
        if (PageHWPoison(page)) {
                unlock_page(page);
                put_page(page);
-               pr_debug("soft offline: %#lx page already poisoned\n", pfn);
+               pr_info("soft offline: %#lx page already poisoned\n", pfn);
                return -EBUSY;
        }
 
@@ -1323,7 +1399,7 @@ int soft_offline_page(struct page *page, int flags)
        put_page(page);
        if (ret == 1) {
                ret = 0;
-               pr_debug("soft_offline: %#lx: invalidated\n", pfn);
+               pr_info("soft_offline: %#lx: invalidated\n", pfn);
                goto done;
        }
 
@@ -1339,13 +1415,13 @@ int soft_offline_page(struct page *page, int flags)
                list_add(&page->lru, &pagelist);
                ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0);
                if (ret) {
-                       pr_debug("soft offline: %#lx: migration failed %d, type %lx\n",
+                       pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
                                pfn, ret, page->flags);
                        if (ret > 0)
                                ret = -EIO;
                }
        } else {
-               pr_debug("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
+               pr_info("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
                                pfn, ret, page_count(page), page->flags);
        }
        if (ret)
index 98b58fe..02e48aa 100644 (file)
@@ -736,7 +736,7 @@ again:
        dst_pte = pte_alloc_map_lock(dst_mm, dst_pmd, addr, &dst_ptl);
        if (!dst_pte)
                return -ENOMEM;
-       src_pte = pte_offset_map_nested(src_pmd, addr);
+       src_pte = pte_offset_map(src_pmd, addr);
        src_ptl = pte_lockptr(src_mm, src_pmd);
        spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING);
        orig_src_pte = src_pte;
@@ -767,7 +767,7 @@ again:
 
        arch_leave_lazy_mmu_mode();
        spin_unlock(src_ptl);
-       pte_unmap_nested(orig_src_pte);
+       pte_unmap(orig_src_pte);
        add_mm_rss_vec(dst_mm, rss);
        pte_unmap_unlock(orig_dst_pte, dst_ptl);
        cond_resched();
@@ -1450,7 +1450,8 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                        if (ret & VM_FAULT_OOM)
                                                return i ? i : -ENOMEM;
                                        if (ret &
-                                           (VM_FAULT_HWPOISON|VM_FAULT_SIGBUS))
+                                           (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE|
+                                            VM_FAULT_SIGBUS))
                                                return i ? i : -EFAULT;
                                        BUG();
                                }
@@ -1590,7 +1591,7 @@ struct page *get_dump_page(unsigned long addr)
 }
 #endif /* CONFIG_ELF_CORE */
 
-pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
+pte_t *__get_locked_pte(struct mm_struct *mm, unsigned long addr,
                        spinlock_t **ptl)
 {
        pgd_t * pgd = pgd_offset(mm, addr);
@@ -2079,7 +2080,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
                 * zeroes.
                 */
                if (__copy_from_user_inatomic(kaddr, uaddr, PAGE_SIZE))
-                       memset(kaddr, 0, PAGE_SIZE);
+                       clear_page(kaddr);
                kunmap_atomic(kaddr, KM_USER0);
                flush_dcache_page(dst);
        } else
@@ -2107,6 +2108,7 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
 static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
                unsigned long address, pte_t *page_table, pmd_t *pmd,
                spinlock_t *ptl, pte_t orig_pte)
+       __releases(ptl)
 {
        struct page *old_page, *new_page;
        pte_t entry;
@@ -2626,6 +2628,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
        struct page *page, *swapcache = NULL;
        swp_entry_t entry;
        pte_t pte;
+       int locked;
        struct mem_cgroup *ptr = NULL;
        int exclusive = 0;
        int ret = 0;
@@ -2676,8 +2679,12 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                goto out_release;
        }
 
-       lock_page(page);
+       locked = lock_page_or_retry(page, mm, flags);
        delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
+       if (!locked) {
+               ret |= VM_FAULT_RETRY;
+               goto out_release;
+       }
 
        /*
         * Make sure try_to_free_swap or reuse_swap_page or swapoff did not
@@ -2926,7 +2933,8 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        vmf.page = NULL;
 
        ret = vma->vm_ops->fault(vma, &vmf);
-       if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))
+       if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE |
+                           VM_FAULT_RETRY)))
                return ret;
 
        if (unlikely(PageHWPoison(vmf.page))) {
@@ -3343,7 +3351,7 @@ int in_gate_area_no_task(unsigned long addr)
 
 #endif /* __HAVE_ARCH_GATE_AREA */
 
-static int follow_pte(struct mm_struct *mm, unsigned long address,
+static int __follow_pte(struct mm_struct *mm, unsigned long address,
                pte_t **ptepp, spinlock_t **ptlp)
 {
        pgd_t *pgd;
@@ -3380,6 +3388,17 @@ out:
        return -EINVAL;
 }
 
+static inline int follow_pte(struct mm_struct *mm, unsigned long address,
+                            pte_t **ptepp, spinlock_t **ptlp)
+{
+       int res;
+
+       /* (void) is needed to make gcc happy */
+       (void) __cond_lock(*ptlp,
+                          !(res = __follow_pte(mm, address, ptepp, ptlp)));
+       return res;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
index d4e940a..9260314 100644 (file)
@@ -602,27 +602,14 @@ static struct page *next_active_pageblock(struct page *page)
 /* Checks if this range of memory is likely to be hot-removable. */
 int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
 {
-       int type;
        struct page *page = pfn_to_page(start_pfn);
        struct page *end_page = page + nr_pages;
 
        /* Check the starting page of each pageblock within the range */
        for (; page < end_page; page = next_active_pageblock(page)) {
-               type = get_pageblock_migratetype(page);
-
-               /*
-                * A pageblock containing MOVABLE or free pages is considered
-                * removable
-                */
-               if (type != MIGRATE_MOVABLE && !pageblock_free(page))
-                       return 0;
-
-               /*
-                * A pageblock starting with a PageReserved page is not
-                * considered removable.
-                */
-               if (PageReserved(page))
+               if (!is_pageblock_removable_nolock(page))
                        return 0;
+               cond_resched();
        }
 
        /* All pageblocks in the memory block are likely to be hot-removable */
@@ -659,7 +646,7 @@ static int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
  * Scanning pfn is much easier than scanning lru list.
  * Scan pfn from start to end and Find LRU page.
  */
-int scan_lru_pages(unsigned long start, unsigned long end)
+static unsigned long scan_lru_pages(unsigned long start, unsigned long end)
 {
        unsigned long pfn;
        struct page *page;
@@ -709,29 +696,30 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                                            page_is_file_cache(page));
 
                } else {
-                       /* Becasue we don't have big zone->lock. we should
-                          check this again here. */
-                       if (page_count(page))
-                               not_managed++;
 #ifdef CONFIG_DEBUG_VM
                        printk(KERN_ALERT "removing pfn %lx from LRU failed\n",
                               pfn);
                        dump_page(page);
 #endif
+                       /* Becasue we don't have big zone->lock. we should
+                          check this again here. */
+                       if (page_count(page)) {
+                               not_managed++;
+                               ret = -EBUSY;
+                               break;
+                       }
                }
        }
-       ret = -EBUSY;
-       if (not_managed) {
-               if (!list_empty(&source))
+       if (!list_empty(&source)) {
+               if (not_managed) {
+                       putback_lru_pages(&source);
+                       goto out;
+               }
+               /* this function returns # of failed pages */
+               ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1);
+               if (ret)
                        putback_lru_pages(&source);
-               goto out;
        }
-       ret = 0;
-       if (list_empty(&source))
-               goto out;
-       /* this function returns # of failed pages */
-       ret = migrate_pages(&source, hotremove_migrate_alloc, 0, 1);
-
 out:
        return ret;
 }
index f969da5..81a1276 100644 (file)
@@ -924,15 +924,21 @@ static int migrate_to_node(struct mm_struct *mm, int source, int dest,
        nodemask_t nmask;
        LIST_HEAD(pagelist);
        int err = 0;
+       struct vm_area_struct *vma;
 
        nodes_clear(nmask);
        node_set(source, nmask);
 
-       check_range(mm, mm->mmap->vm_start, mm->task_size, &nmask,
+       vma = check_range(mm, mm->mmap->vm_start, mm->task_size, &nmask,
                        flags | MPOL_MF_DISCONTIG_OK, &pagelist);
+       if (IS_ERR(vma))
+               return PTR_ERR(vma);
 
-       if (!list_empty(&pagelist))
+       if (!list_empty(&pagelist)) {
                err = migrate_pages(&pagelist, new_node_page, dest, 0);
+               if (err)
+                       putback_lru_pages(&pagelist);
+       }
 
        return err;
 }
@@ -1147,9 +1153,12 @@ static long do_mbind(unsigned long start, unsigned long len,
 
                err = mbind_range(mm, start, end, new);
 
-               if (!list_empty(&pagelist))
+               if (!list_empty(&pagelist)) {
                        nr_failed = migrate_pages(&pagelist, new_vma_page,
                                                (unsigned long)vma, 0);
+                       if (nr_failed)
+                               putback_lru_pages(&pagelist);
+               }
 
                if (!err && nr_failed && (flags & MPOL_MF_STRICT))
                        err = -EIO;
index 38e7cad..fe5a3c6 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/security.h>
 #include <linux/memcontrol.h>
 #include <linux/syscalls.h>
+#include <linux/hugetlb.h>
 #include <linux/gfp.h>
 
 #include "internal.h"
@@ -95,26 +96,34 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
        pte_t *ptep, pte;
        spinlock_t *ptl;
 
-       pgd = pgd_offset(mm, addr);
-       if (!pgd_present(*pgd))
-               goto out;
+       if (unlikely(PageHuge(new))) {
+               ptep = huge_pte_offset(mm, addr);
+               if (!ptep)
+                       goto out;
+               ptl = &mm->page_table_lock;
+       } else {
+               pgd = pgd_offset(mm, addr);
+               if (!pgd_present(*pgd))
+                       goto out;
 
-       pud = pud_offset(pgd, addr);
-       if (!pud_present(*pud))
-               goto out;
+               pud = pud_offset(pgd, addr);
+               if (!pud_present(*pud))
+                       goto out;
 
-       pmd = pmd_offset(pud, addr);
-       if (!pmd_present(*pmd))
-               goto out;
+               pmd = pmd_offset(pud, addr);
+               if (!pmd_present(*pmd))
+                       goto out;
 
-       ptep = pte_offset_map(pmd, addr);
+               ptep = pte_offset_map(pmd, addr);
 
-       if (!is_swap_pte(*ptep)) {
-               pte_unmap(ptep);
-               goto out;
-       }
+               if (!is_swap_pte(*ptep)) {
+                       pte_unmap(ptep);
+                       goto out;
+               }
+
+               ptl = pte_lockptr(mm, pmd);
+       }
 
-       ptl = pte_lockptr(mm, pmd);
        spin_lock(ptl);
        pte = *ptep;
        if (!is_swap_pte(pte))
@@ -130,10 +139,19 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma,
        pte = pte_mkold(mk_pte(new, vma->vm_page_prot));
        if (is_write_migration_entry(entry))
                pte = pte_mkwrite(pte);
+#ifdef CONFIG_HUGETLB_PAGE
+       if (PageHuge(new))
+               pte = pte_mkhuge(pte);
+#endif
        flush_cache_page(vma, addr, pte_pfn(pte));
        set_pte_at(mm, addr, ptep, pte);
 
-       if (PageAnon(new))
+       if (PageHuge(new)) {
+               if (PageAnon(new))
+                       hugepage_add_anon_rmap(new, vma, addr);
+               else
+                       page_dup_rmap(new);
+       } else if (PageAnon(new))
                page_add_anon_rmap(new, vma, addr);
        else
                page_add_file_rmap(new);
@@ -276,11 +294,59 @@ static int migrate_page_move_mapping(struct address_space *mapping,
 }
 
 /*
+ * The expected number of remaining references is the same as that
+ * of migrate_page_move_mapping().
+ */
+int migrate_huge_page_move_mapping(struct address_space *mapping,
+                                  struct page *newpage, struct page *page)
+{
+       int expected_count;
+       void **pslot;
+
+       if (!mapping) {
+               if (page_count(page) != 1)
+                       return -EAGAIN;
+               return 0;
+       }
+
+       spin_lock_irq(&mapping->tree_lock);
+
+       pslot = radix_tree_lookup_slot(&mapping->page_tree,
+                                       page_index(page));
+
+       expected_count = 2 + page_has_private(page);
+       if (page_count(page) != expected_count ||
+           (struct page *)radix_tree_deref_slot(pslot) != page) {
+               spin_unlock_irq(&mapping->tree_lock);
+               return -EAGAIN;
+       }
+
+       if (!page_freeze_refs(page, expected_count)) {
+               spin_unlock_irq(&mapping->tree_lock);
+               return -EAGAIN;
+       }
+
+       get_page(newpage);
+
+       radix_tree_replace_slot(pslot, newpage);
+
+       page_unfreeze_refs(page, expected_count);
+
+       __put_page(page);
+
+       spin_unlock_irq(&mapping->tree_lock);
+       return 0;
+}
+
+/*
  * Copy the page to its new location
  */
-static void migrate_page_copy(struct page *newpage, struct page *page)
+void migrate_page_copy(struct page *newpage, struct page *page)
 {
-       copy_highpage(newpage, page);
+       if (PageHuge(page))
+               copy_huge_page(newpage, page);
+       else
+               copy_highpage(newpage, page);
 
        if (PageError(page))
                SetPageError(newpage);
@@ -431,7 +497,6 @@ static int writeout(struct address_space *mapping, struct page *page)
                .nr_to_write = 1,
                .range_start = 0,
                .range_end = LLONG_MAX,
-               .nonblocking = 1,
                .for_reclaim = 1
        };
        int rc;
@@ -724,6 +789,92 @@ move_newpage:
 }
 
 /*
+ * Counterpart of unmap_and_move_page() for hugepage migration.
+ *
+ * This function doesn't wait the completion of hugepage I/O
+ * because there is no race between I/O and migration for hugepage.
+ * Note that currently hugepage I/O occurs only in direct I/O
+ * where no lock is held and PG_writeback is irrelevant,
+ * and writeback status of all subpages are counted in the reference
+ * count of the head page (i.e. if all subpages of a 2MB hugepage are
+ * under direct I/O, the reference of the head page is 512 and a bit more.)
+ * This means that when we try to migrate hugepage whose subpages are
+ * doing direct I/O, some references remain after try_to_unmap() and
+ * hugepage migration fails without data corruption.
+ *
+ * There is also no race when direct I/O is issued on the page under migration,
+ * because then pte is replaced with migration swap entry and direct I/O code
+ * will wait in the page fault for migration to complete.
+ */
+static int unmap_and_move_huge_page(new_page_t get_new_page,
+                               unsigned long private, struct page *hpage,
+                               int force, int offlining)
+{
+       int rc = 0;
+       int *result = NULL;
+       struct page *new_hpage = get_new_page(hpage, private, &result);
+       int rcu_locked = 0;
+       struct anon_vma *anon_vma = NULL;
+
+       if (!new_hpage)
+               return -ENOMEM;
+
+       rc = -EAGAIN;
+
+       if (!trylock_page(hpage)) {
+               if (!force)
+                       goto out;
+               lock_page(hpage);
+       }
+
+       if (PageAnon(hpage)) {
+               rcu_read_lock();
+               rcu_locked = 1;
+
+               if (page_mapped(hpage)) {
+                       anon_vma = page_anon_vma(hpage);
+                       atomic_inc(&anon_vma->external_refcount);
+               }
+       }
+
+       try_to_unmap(hpage, TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
+
+       if (!page_mapped(hpage))
+               rc = move_to_new_page(new_hpage, hpage, 1);
+
+       if (rc)
+               remove_migration_ptes(hpage, hpage);
+
+       if (anon_vma && atomic_dec_and_lock(&anon_vma->external_refcount,
+                                           &anon_vma->lock)) {
+               int empty = list_empty(&anon_vma->head);
+               spin_unlock(&anon_vma->lock);
+               if (empty)
+                       anon_vma_free(anon_vma);
+       }
+
+       if (rcu_locked)
+               rcu_read_unlock();
+out:
+       unlock_page(hpage);
+
+       if (rc != -EAGAIN) {
+               list_del(&hpage->lru);
+               put_page(hpage);
+       }
+
+       put_page(new_hpage);
+
+       if (result) {
+               if (rc)
+                       *result = rc;
+               else
+                       *result = page_to_nid(new_hpage);
+       }
+       return rc;
+}
+
+/*
  * migrate_pages
  *
  * The function takes one list of pages to migrate and a function
@@ -732,8 +883,9 @@ move_newpage:
  *
  * The function returns after 10 attempts or if no pages
  * are movable anymore because to has become empty
- * or no retryable pages exist anymore. All pages will be
- * returned to the LRU or freed.
+ * or no retryable pages exist anymore.
+ * Caller should call putback_lru_pages to return pages to the LRU
+ * or free list.
  *
  * Return: Number of pages not migrated or error code.
  */
@@ -780,7 +932,51 @@ out:
        if (!swapwrite)
                current->flags &= ~PF_SWAPWRITE;
 
-       putback_lru_pages(from);
+       if (rc)
+               return rc;
+
+       return nr_failed + retry;
+}
+
+int migrate_huge_pages(struct list_head *from,
+               new_page_t get_new_page, unsigned long private, int offlining)
+{
+       int retry = 1;
+       int nr_failed = 0;
+       int pass = 0;
+       struct page *page;
+       struct page *page2;
+       int rc;
+
+       for (pass = 0; pass < 10 && retry; pass++) {
+               retry = 0;
+
+               list_for_each_entry_safe(page, page2, from, lru) {
+                       cond_resched();
+
+                       rc = unmap_and_move_huge_page(get_new_page,
+                                       private, page, pass > 2, offlining);
+
+                       switch(rc) {
+                       case -ENOMEM:
+                               goto out;
+                       case -EAGAIN:
+                               retry++;
+                               break;
+                       case 0:
+                               break;
+                       default:
+                               /* Permanent failure */
+                               nr_failed++;
+                               break;
+                       }
+               }
+       }
+       rc = 0;
+out:
+
+       list_for_each_entry_safe(page, page2, from, lru)
+               put_page(page);
 
        if (rc)
                return rc;
@@ -841,7 +1037,7 @@ static int do_move_page_to_node_array(struct mm_struct *mm,
 
                err = -EFAULT;
                vma = find_vma(mm, pp->addr);
-               if (!vma || !vma_migratable(vma))
+               if (!vma || pp->addr < vma->vm_start || !vma_migratable(vma))
                        goto set_status;
 
                page = follow_page(vma, pp->addr, FOLL_GET);
@@ -890,9 +1086,12 @@ set_status:
        }
 
        err = 0;
-       if (!list_empty(&pagelist))
+       if (!list_empty(&pagelist)) {
                err = migrate_pages(&pagelist, new_page_node,
                                (unsigned long)pm, 0);
+               if (err)
+                       putback_lru_pages(&pagelist);
+       }
 
        up_read(&mm->mmap_sem);
        return err;
@@ -1005,7 +1204,7 @@ static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages,
                int err = -EFAULT;
 
                vma = find_vma(mm, addr);
-               if (!vma)
+               if (!vma || addr < vma->vm_start)
                        goto set_status;
 
                page = follow_page(vma, addr, 0);
index cde56ee..563fbdd 100644 (file)
@@ -101,7 +101,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
         * pte locks because exclusive mmap_sem prevents deadlock.
         */
        old_pte = pte_offset_map_lock(mm, old_pmd, old_addr, &old_ptl);
-       new_pte = pte_offset_map_nested(new_pmd, new_addr);
+       new_pte = pte_offset_map(new_pmd, new_addr);
        new_ptl = pte_lockptr(mm, new_pmd);
        if (new_ptl != old_ptl)
                spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
@@ -119,7 +119,7 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
        arch_leave_lazy_mmu_mode();
        if (new_ptl != old_ptl)
                spin_unlock(new_ptl);
-       pte_unmap_nested(new_pte - 1);
+       pte_unmap(new_pte - 1);
        pte_unmap_unlock(old_pte - 1, old_ptl);
        if (mapping)
                spin_unlock(&mapping->i_mmap_lock);
index 88ff091..30b5c20 100644 (file)
@@ -293,11 +293,58 @@ void *vmalloc(unsigned long size)
 }
 EXPORT_SYMBOL(vmalloc);
 
+/*
+ *     vzalloc - allocate virtually continguos memory with zero fill
+ *
+ *     @size:          allocation size
+ *
+ *     Allocate enough pages to cover @size from the page level
+ *     allocator and map them into continguos kernel virtual space.
+ *     The memory allocated is set to zero.
+ *
+ *     For tight control over page level allocator and protection flags
+ *     use __vmalloc() instead.
+ */
+void *vzalloc(unsigned long size)
+{
+       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
+                       PAGE_KERNEL);
+}
+EXPORT_SYMBOL(vzalloc);
+
+/**
+ * vmalloc_node - allocate memory on a specific node
+ * @size:      allocation size
+ * @node:      numa node
+ *
+ * Allocate enough pages to cover @size from the page level
+ * allocator and map them into contiguous kernel virtual space.
+ *
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
 void *vmalloc_node(unsigned long size, int node)
 {
        return vmalloc(size);
 }
-EXPORT_SYMBOL(vmalloc_node);
+
+/**
+ * vzalloc_node - allocate memory on a specific node with zero fill
+ * @size:      allocation size
+ * @node:      numa node
+ *
+ * Allocate enough pages to cover @size from the page level
+ * allocator and map them into contiguous kernel virtual space.
+ * The memory allocated is set to zero.
+ *
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc() instead.
+ */
+void *vzalloc_node(unsigned long size, int node)
+{
+       return vzalloc(size);
+}
+EXPORT_SYMBOL(vzalloc_node);
 
 #ifndef PAGE_KERNEL_EXEC
 # define PAGE_KERNEL_EXEC PAGE_KERNEL
index 4029583..7dcca55 100644 (file)
@@ -162,10 +162,11 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
                return 0;
 
        /*
-        * Shortcut check for OOM_SCORE_ADJ_MIN so the entire heuristic doesn't
-        * need to be executed for something that cannot be killed.
+        * Shortcut check for a thread sharing p->mm that is OOM_SCORE_ADJ_MIN
+        * so the entire heuristic doesn't need to be executed for something
+        * that cannot be killed.
         */
-       if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+       if (atomic_read(&p->mm->oom_disable_count)) {
                task_unlock(p);
                return 0;
        }
@@ -403,16 +404,40 @@ static void dump_header(struct task_struct *p, gfp_t gfp_mask, int order,
 #define K(x) ((x) << (PAGE_SHIFT-10))
 static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
 {
+       struct task_struct *q;
+       struct mm_struct *mm;
+
        p = find_lock_task_mm(p);
        if (!p)
                return 1;
 
+       /* mm cannot be safely dereferenced after task_unlock(p) */
+       mm = p->mm;
+
        pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB\n",
                task_pid_nr(p), p->comm, K(p->mm->total_vm),
                K(get_mm_counter(p->mm, MM_ANONPAGES)),
                K(get_mm_counter(p->mm, MM_FILEPAGES)));
        task_unlock(p);
 
+       /*
+        * Kill all processes sharing p->mm in other thread groups, if any.
+        * They don't get access to memory reserves or a higher scheduler
+        * priority, though, to avoid depletion of all memory or task
+        * starvation.  This prevents mm->mmap_sem livelock when an oom killed
+        * task cannot exit because it requires the semaphore and its contended
+        * by another thread trying to allocate memory itself.  That thread will
+        * now get access to memory reserves since it has a pending fatal
+        * signal.
+        */
+       for_each_process(q)
+               if (q->mm == mm && !same_thread_group(q, p)) {
+                       task_lock(q);   /* Protect ->comm from prctl() */
+                       pr_err("Kill process %d (%s) sharing same memory\n",
+                               task_pid_nr(q), q->comm);
+                       task_unlock(q);
+                       force_sig(SIGKILL, q);
+               }
 
        set_tsk_thread_flag(p, TIF_MEMDIE);
        force_sig(SIGKILL, p);
@@ -680,7 +705,7 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
        read_lock(&tasklist_lock);
        if (sysctl_oom_kill_allocating_task &&
            !oom_unkillable_task(current, NULL, nodemask) &&
-           (current->signal->oom_adj != OOM_DISABLE)) {
+           current->mm && !atomic_read(&current->mm->oom_disable_count)) {
                /*
                 * oom_kill_process() needs tasklist_lock held.  If it returns
                 * non-zero, current could not be killed so we must fallback to
index e3bccac..b840afa 100644 (file)
@@ -415,14 +415,8 @@ void global_dirty_limits(unsigned long *pbackground, unsigned long *pdirty)
 
        if (vm_dirty_bytes)
                dirty = DIV_ROUND_UP(vm_dirty_bytes, PAGE_SIZE);
-       else {
-               int dirty_ratio;
-
-               dirty_ratio = vm_dirty_ratio;
-               if (dirty_ratio < 5)
-                       dirty_ratio = 5;
-               dirty = (dirty_ratio * available_memory) / 100;
-       }
+       else
+               dirty = (vm_dirty_ratio * available_memory) / 100;
 
        if (dirty_background_bytes)
                background = DIV_ROUND_UP(dirty_background_bytes, PAGE_SIZE);
@@ -510,7 +504,7 @@ static void balance_dirty_pages(struct address_space *mapping,
                 * catch-up. This avoids (excessively) small writeouts
                 * when the bdi limits are ramping up.
                 */
-               if (nr_reclaimable + nr_writeback <
+               if (nr_reclaimable + nr_writeback <=
                                (background_thresh + dirty_thresh) / 2)
                        break;
 
@@ -542,8 +536,8 @@ static void balance_dirty_pages(struct address_space *mapping,
                 * the last resort safeguard.
                 */
                dirty_exceeded =
-                       (bdi_nr_reclaimable + bdi_nr_writeback >= bdi_thresh)
-                       || (nr_reclaimable + nr_writeback >= dirty_thresh);
+                       (bdi_nr_reclaimable + bdi_nr_writeback > bdi_thresh)
+                       || (nr_reclaimable + nr_writeback > dirty_thresh);
 
                if (!dirty_exceeded)
                        break;
@@ -1121,6 +1115,7 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
 {
        if (mapping_cap_account_dirty(mapping)) {
                __inc_zone_page_state(page, NR_FILE_DIRTY);
+               __inc_zone_page_state(page, NR_DIRTIED);
                __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE);
                task_dirty_inc(current);
                task_io_account_write(PAGE_CACHE_SIZE);
@@ -1129,6 +1124,18 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
 EXPORT_SYMBOL(account_page_dirtied);
 
 /*
+ * Helper function for set_page_writeback family.
+ * NOTE: Unlike account_page_dirtied this does not rely on being atomic
+ * wrt interrupts.
+ */
+void account_page_writeback(struct page *page)
+{
+       inc_zone_page_state(page, NR_WRITEBACK);
+       inc_zone_page_state(page, NR_WRITTEN);
+}
+EXPORT_SYMBOL(account_page_writeback);
+
+/*
  * For address_spaces which do not use buffers.  Just tag the page as dirty in
  * its radix tree.
  *
@@ -1366,7 +1373,7 @@ int test_set_page_writeback(struct page *page)
                ret = TestSetPageWriteback(page);
        }
        if (!ret)
-               inc_zone_page_state(page, NR_WRITEBACK);
+               account_page_writeback(page);
        return ret;
 
 }
index 2a362c5..07a6544 100644 (file)
@@ -531,7 +531,7 @@ static inline void __free_one_page(struct page *page,
         * so it's less likely to be used soon and more likely to be merged
         * as a higher order page
         */
-       if ((order < MAX_ORDER-1) && pfn_valid_within(page_to_pfn(buddy))) {
+       if ((order < MAX_ORDER-2) && pfn_valid_within(page_to_pfn(buddy))) {
                struct page *higher_page, *higher_buddy;
                combined_idx = __find_combined_index(page_idx, order);
                higher_page = page + combined_idx - page_idx;
@@ -1907,7 +1907,7 @@ __alloc_pages_high_priority(gfp_t gfp_mask, unsigned int order,
                        preferred_zone, migratetype);
 
                if (!page && gfp_mask & __GFP_NOFAIL)
-                       congestion_wait(BLK_RW_ASYNC, HZ/50);
+                       wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50);
        } while (!page && (gfp_mask & __GFP_NOFAIL));
 
        return page;
@@ -1932,7 +1932,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask)
        const gfp_t wait = gfp_mask & __GFP_WAIT;
 
        /* __GFP_HIGH is assumed to be the same as ALLOC_HIGH to save a branch. */
-       BUILD_BUG_ON(__GFP_HIGH != ALLOC_HIGH);
+       BUILD_BUG_ON(__GFP_HIGH != (__force gfp_t) ALLOC_HIGH);
 
        /*
         * The caller may dip into page reserves a bit more if the caller
@@ -1940,7 +1940,7 @@ gfp_to_alloc_flags(gfp_t gfp_mask)
         * policy or is asking for __GFP_HIGH memory.  GFP_ATOMIC requests will
         * set both ALLOC_HARDER (!wait) and ALLOC_HIGH (__GFP_HIGH).
         */
-       alloc_flags |= (gfp_mask & __GFP_HIGH);
+       alloc_flags |= (__force int) (gfp_mask & __GFP_HIGH);
 
        if (!wait) {
                alloc_flags |= ALLOC_HARDER;
@@ -2095,7 +2095,7 @@ rebalance:
        pages_reclaimed += did_some_progress;
        if (should_alloc_retry(gfp_mask, order, pages_reclaimed)) {
                /* Wait for some write requests to complete then retry */
-               congestion_wait(BLK_RW_ASYNC, HZ/50);
+               wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/50);
                goto rebalance;
        }
 
@@ -5297,12 +5297,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
  * page allocater never alloc memory from ISOLATE block.
  */
 
+static int
+__count_immobile_pages(struct zone *zone, struct page *page, int count)
+{
+       unsigned long pfn, iter, found;
+       /*
+        * For avoiding noise data, lru_add_drain_all() should be called
+        * If ZONE_MOVABLE, the zone never contains immobile pages
+        */
+       if (zone_idx(zone) == ZONE_MOVABLE)
+               return true;
+
+       if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE)
+               return true;
+
+       pfn = page_to_pfn(page);
+       for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) {
+               unsigned long check = pfn + iter;
+
+               if (!pfn_valid_within(check)) {
+                       iter++;
+                       continue;
+               }
+               page = pfn_to_page(check);
+               if (!page_count(page)) {
+                       if (PageBuddy(page))
+                               iter += (1 << page_order(page)) - 1;
+                       continue;
+               }
+               if (!PageLRU(page))
+                       found++;
+               /*
+                * If there are RECLAIMABLE pages, we need to check it.
+                * But now, memory offline itself doesn't call shrink_slab()
+                * and it still to be fixed.
+                */
+               /*
+                * If the page is not RAM, page_count()should be 0.
+                * we don't need more check. This is an _used_ not-movable page.
+                *
+                * The problematic thing here is PG_reserved pages. PG_reserved
+                * is set to both of a memory hole page and a _used_ kernel
+                * page at boot.
+                */
+               if (found > count)
+                       return false;
+       }
+       return true;
+}
+
+bool is_pageblock_removable_nolock(struct page *page)
+{
+       struct zone *zone = page_zone(page);
+       return __count_immobile_pages(zone, page, 0);
+}
+
 int set_migratetype_isolate(struct page *page)
 {
        struct zone *zone;
-       struct page *curr_page;
-       unsigned long flags, pfn, iter;
-       unsigned long immobile = 0;
+       unsigned long flags, pfn;
        struct memory_isolate_notify arg;
        int notifier_ret;
        int ret = -EBUSY;
@@ -5312,11 +5365,6 @@ int set_migratetype_isolate(struct page *page)
        zone_idx = zone_idx(zone);
 
        spin_lock_irqsave(&zone->lock, flags);
-       if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE ||
-           zone_idx == ZONE_MOVABLE) {
-               ret = 0;
-               goto out;
-       }
 
        pfn = page_to_pfn(page);
        arg.start_pfn = pfn;
@@ -5336,23 +5384,20 @@ int set_migratetype_isolate(struct page *page)
         */
        notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg);
        notifier_ret = notifier_to_errno(notifier_ret);
-       if (notifier_ret || !arg.pages_found)
+       if (notifier_ret)
                goto out;
-
-       for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) {
-               if (!pfn_valid_within(pfn))
-                       continue;
-
-               curr_page = pfn_to_page(iter);
-               if (!page_count(curr_page) || PageLRU(curr_page))
-                       continue;
-
-               immobile++;
-       }
-
-       if (arg.pages_found == immobile)
+       /*
+        * FIXME: Now, memory hotplug doesn't call shrink_slab() by itself.
+        * We just check MOVABLE pages.
+        */
+       if (__count_immobile_pages(zone, page, arg.pages_found))
                ret = 0;
 
+       /*
+        * immobile means "not-on-lru" paes. If immobile is larger than
+        * removable-by-driver pages reported by notifier, we'll fail.
+        */
+
 out:
        if (!ret) {
                set_pageblock_migratetype(page, MIGRATE_ISOLATE);
index 5e0ffd9..4ae42bb 100644 (file)
@@ -86,7 +86,7 @@ undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn)
  * all pages in [start_pfn...end_pfn) must be in the same zone.
  * zone->lock must be held before call this.
  *
- * Returns 0 if all pages in the range is isolated.
+ * Returns 1 if all pages in the range is isolated.
  */
 static int
 __test_page_isolated_in_pageblock(unsigned long pfn, unsigned long end_pfn)
@@ -119,7 +119,6 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn)
        struct zone *zone;
        int ret;
 
-       pfn = start_pfn;
        /*
         * Note: pageblock_nr_page != MAX_ORDER. Then, chunks of free page
         * is not aligned to pageblock_nr_pages.
index 5f17fad..1a8bf76 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -80,7 +80,7 @@ static inline struct anon_vma_chain *anon_vma_chain_alloc(void)
        return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL);
 }
 
-void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
+static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
 {
        kmem_cache_free(anon_vma_chain_cachep, anon_vma_chain);
 }
@@ -314,7 +314,7 @@ void __init anon_vma_init(void)
  * Getting a lock on a stable anon_vma from a page off the LRU is
  * tricky: page_lock_anon_vma rely on RCU to guard against the races.
  */
-struct anon_vma *page_lock_anon_vma(struct page *page)
+struct anon_vma *__page_lock_anon_vma(struct page *page)
 {
        struct anon_vma *anon_vma, *root_anon_vma;
        unsigned long anon_mapping;
@@ -348,6 +348,8 @@ out:
 }
 
 void page_unlock_anon_vma(struct anon_vma *anon_vma)
+       __releases(&anon_vma->root->lock)
+       __releases(RCU)
 {
        anon_vma_unlock(anon_vma);
        rcu_read_unlock();
@@ -407,7 +409,7 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma)
  *
  * On success returns with pte mapped and locked.
  */
-pte_t *page_check_address(struct page *page, struct mm_struct *mm,
+pte_t *__page_check_address(struct page *page, struct mm_struct *mm,
                          unsigned long address, spinlock_t **ptlp, int sync)
 {
        pgd_t *pgd;
@@ -780,10 +782,10 @@ void page_move_anon_rmap(struct page *page,
 }
 
 /**
- * __page_set_anon_rmap - setup new anonymous rmap
- * @page:      the page to add the mapping to
- * @vma:       the vm area in which the mapping is added
- * @address:   the user virtual address mapped
+ * __page_set_anon_rmap - set up new anonymous rmap
+ * @page:      Page to add to rmap     
+ * @vma:       VM area to add page to.
+ * @address:   User virtual address of the mapping     
  * @exclusive: the page is exclusively owned by the current process
  */
 static void __page_set_anon_rmap(struct page *page,
@@ -793,25 +795,16 @@ static void __page_set_anon_rmap(struct page *page,
 
        BUG_ON(!anon_vma);
 
+       if (PageAnon(page))
+               return;
+
        /*
         * If the page isn't exclusively mapped into this vma,
         * we must use the _oldest_ possible anon_vma for the
         * page mapping!
         */
-       if (!exclusive) {
-               if (PageAnon(page))
-                       return;
+       if (!exclusive)
                anon_vma = anon_vma->root;
-       } else {
-               /*
-                * In this case, swapped-out-but-not-discarded swap-cache
-                * is remapped. So, no need to update page->mapping here.
-                * We convice anon_vma poitned by page->mapping is not obsolete
-                * because vma->anon_vma is necessary to be a family of it.
-                */
-               if (PageAnon(page))
-                       return;
-       }
 
        anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON;
        page->mapping = (struct address_space *) anon_vma;
index fcae981..b1e40da 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -901,7 +901,7 @@ static int transfer_objects(struct array_cache *to,
                struct array_cache *from, unsigned int max)
 {
        /* Figure out how many entries to transfer */
-       int nr = min(min(from->avail, max), to->limit - to->avail);
+       int nr = min3(from->avail, max, to->limit - to->avail);
 
        if (!nr)
                return 0;
index 9fc7bac..67ddaaf 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/capability.h>
 #include <linux/syscalls.h>
 #include <linux/memcontrol.h>
+#include <linux/poll.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -58,6 +59,10 @@ static struct swap_info_struct *swap_info[MAX_SWAPFILES];
 
 static DEFINE_MUTEX(swapon_mutex);
 
+static DECLARE_WAIT_QUEUE_HEAD(proc_poll_wait);
+/* Activity counter to indicate that a swapon or swapoff has occurred */
+static atomic_t proc_poll_event = ATOMIC_INIT(0);
+
 static inline unsigned char swap_count(unsigned char ent)
 {
        return ent & ~SWAP_HAS_CACHE;   /* may include SWAP_HAS_CONT flag */
@@ -1680,6 +1685,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        }
        filp_close(swap_file, NULL);
        err = 0;
+       atomic_inc(&proc_poll_event);
+       wake_up_interruptible(&proc_poll_wait);
 
 out_dput:
        filp_close(victim, NULL);
@@ -1688,6 +1695,25 @@ out:
 }
 
 #ifdef CONFIG_PROC_FS
+struct proc_swaps {
+       struct seq_file seq;
+       int event;
+};
+
+static unsigned swaps_poll(struct file *file, poll_table *wait)
+{
+       struct proc_swaps *s = file->private_data;
+
+       poll_wait(file, &proc_poll_wait, wait);
+
+       if (s->event != atomic_read(&proc_poll_event)) {
+               s->event = atomic_read(&proc_poll_event);
+               return POLLIN | POLLRDNORM | POLLERR | POLLPRI;
+       }
+
+       return POLLIN | POLLRDNORM;
+}
+
 /* iterator */
 static void *swap_start(struct seq_file *swap, loff_t *pos)
 {
@@ -1771,7 +1797,24 @@ static const struct seq_operations swaps_op = {
 
 static int swaps_open(struct inode *inode, struct file *file)
 {
-       return seq_open(file, &swaps_op);
+       struct proc_swaps *s;
+       int ret;
+
+       s = kmalloc(sizeof(struct proc_swaps), GFP_KERNEL);
+       if (!s)
+               return -ENOMEM;
+
+       file->private_data = s;
+
+       ret = seq_open(file, &swaps_op);
+       if (ret) {
+               kfree(s);
+               return ret;
+       }
+
+       s->seq.private = s;
+       s->event = atomic_read(&proc_poll_event);
+       return ret;
 }
 
 static const struct file_operations proc_swaps_operations = {
@@ -1779,6 +1822,7 @@ static const struct file_operations proc_swaps_operations = {
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release,
+       .poll           = swaps_poll,
 };
 
 static int __init procswaps_init(void)
@@ -2084,6 +2128,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                swap_info[prev]->next = type;
        spin_unlock(&swap_lock);
        mutex_unlock(&swapon_mutex);
+       atomic_inc(&proc_poll_event);
+       wake_up_interruptible(&proc_poll_wait);
+
        error = 0;
        goto out;
 bad_swap:
index 9f90962..a3d66b3 100644 (file)
@@ -293,13 +293,13 @@ static void __insert_vmap_area(struct vmap_area *va)
        struct rb_node *tmp;
 
        while (*p) {
-               struct vmap_area *tmp;
+               struct vmap_area *tmp_va;
 
                parent = *p;
-               tmp = rb_entry(parent, struct vmap_area, rb_node);
-               if (va->va_start < tmp->va_end)
+               tmp_va = rb_entry(parent, struct vmap_area, rb_node);
+               if (va->va_start < tmp_va->va_end)
                        p = &(*p)->rb_left;
-               else if (va->va_end > tmp->va_start)
+               else if (va->va_end > tmp_va->va_start)
                        p = &(*p)->rb_right;
                else
                        BUG();
@@ -1596,6 +1596,13 @@ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
 }
 EXPORT_SYMBOL(__vmalloc);
 
+static inline void *__vmalloc_node_flags(unsigned long size,
+                                       int node, gfp_t flags)
+{
+       return __vmalloc_node(size, 1, flags, PAGE_KERNEL,
+                                       node, __builtin_return_address(0));
+}
+
 /**
  *     vmalloc  -  allocate virtually contiguous memory
  *     @size:          allocation size
@@ -1607,12 +1614,28 @@ EXPORT_SYMBOL(__vmalloc);
  */
 void *vmalloc(unsigned long size)
 {
-       return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
-                                       -1, __builtin_return_address(0));
+       return __vmalloc_node_flags(size, -1, GFP_KERNEL | __GFP_HIGHMEM);
 }
 EXPORT_SYMBOL(vmalloc);
 
 /**
+ *     vzalloc - allocate virtually contiguous memory with zero fill
+ *     @size:  allocation size
+ *     Allocate enough pages to cover @size from the page level
+ *     allocator and map them into contiguous kernel virtual space.
+ *     The memory allocated is set to zero.
+ *
+ *     For tight control over page level allocator and protection flags
+ *     use __vmalloc() instead.
+ */
+void *vzalloc(unsigned long size)
+{
+       return __vmalloc_node_flags(size, -1,
+                               GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
+}
+EXPORT_SYMBOL(vzalloc);
+
+/**
  * vmalloc_user - allocate zeroed virtually contiguous memory for userspace
  * @size: allocation size
  *
@@ -1653,6 +1676,25 @@ void *vmalloc_node(unsigned long size, int node)
 }
 EXPORT_SYMBOL(vmalloc_node);
 
+/**
+ * vzalloc_node - allocate memory on a specific node with zero fill
+ * @size:      allocation size
+ * @node:      numa node
+ *
+ * Allocate enough pages to cover @size from the page level
+ * allocator and map them into contiguous kernel virtual space.
+ * The memory allocated is set to zero.
+ *
+ * For tight control over page level allocator and protection flags
+ * use __vmalloc_node() instead.
+ */
+void *vzalloc_node(unsigned long size, int node)
+{
+       return __vmalloc_node_flags(size, node,
+                        GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
+}
+EXPORT_SYMBOL(vzalloc_node);
+
 #ifndef PAGE_KERNEL_EXEC
 # define PAGE_KERNEL_EXEC PAGE_KERNEL
 #endif
@@ -2350,6 +2392,7 @@ void pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms)
 
 #ifdef CONFIG_PROC_FS
 static void *s_start(struct seq_file *m, loff_t *pos)
+       __acquires(&vmlist_lock)
 {
        loff_t n = *pos;
        struct vm_struct *v;
@@ -2376,6 +2419,7 @@ static void *s_next(struct seq_file *m, void *p, loff_t *pos)
 }
 
 static void s_stop(struct seq_file *m, void *p)
+       __releases(&vmlist_lock)
 {
        read_unlock(&vmlist_lock);
 }
index b94c946..b8a6fdc 100644 (file)
 #define CREATE_TRACE_POINTS
 #include <trace/events/vmscan.h>
 
+enum lumpy_mode {
+       LUMPY_MODE_NONE,
+       LUMPY_MODE_ASYNC,
+       LUMPY_MODE_SYNC,
+};
+
 struct scan_control {
        /* Incremented by the number of inactive pages that were scanned */
        unsigned long nr_scanned;
@@ -82,7 +88,7 @@ struct scan_control {
         * Intend to reclaim enough continuous memory rather than reclaim
         * enough amount of memory. i.e, mode for high order allocation.
         */
-       bool lumpy_reclaim_mode;
+       enum lumpy_mode lumpy_reclaim_mode;
 
        /* Which cgroup do we reclaim from */
        struct mem_cgroup *mem_cgroup;
@@ -265,6 +271,36 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
        return ret;
 }
 
+static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc,
+                                  bool sync)
+{
+       enum lumpy_mode mode = sync ? LUMPY_MODE_SYNC : LUMPY_MODE_ASYNC;
+
+       /*
+        * Some reclaim have alredy been failed. No worth to try synchronous
+        * lumpy reclaim.
+        */
+       if (sync && sc->lumpy_reclaim_mode == LUMPY_MODE_NONE)
+               return;
+
+       /*
+        * If we need a large contiguous chunk of memory, or have
+        * trouble getting a small set of contiguous pages, we
+        * will reclaim both active and inactive pages.
+        */
+       if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+               sc->lumpy_reclaim_mode = mode;
+       else if (sc->order && priority < DEF_PRIORITY - 2)
+               sc->lumpy_reclaim_mode = mode;
+       else
+               sc->lumpy_reclaim_mode = LUMPY_MODE_NONE;
+}
+
+static void disable_lumpy_reclaim_mode(struct scan_control *sc)
+{
+       sc->lumpy_reclaim_mode = LUMPY_MODE_NONE;
+}
+
 static inline int is_page_cache_freeable(struct page *page)
 {
        /*
@@ -275,7 +311,8 @@ static inline int is_page_cache_freeable(struct page *page)
        return page_count(page) - page_has_private(page) == 2;
 }
 
-static int may_write_to_queue(struct backing_dev_info *bdi)
+static int may_write_to_queue(struct backing_dev_info *bdi,
+                             struct scan_control *sc)
 {
        if (current->flags & PF_SWAPWRITE)
                return 1;
@@ -283,6 +320,10 @@ static int may_write_to_queue(struct backing_dev_info *bdi)
                return 1;
        if (bdi == current->backing_dev_info)
                return 1;
+
+       /* lumpy reclaim for hugepage often need a lot of write */
+       if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+               return 1;
        return 0;
 }
 
@@ -307,12 +348,6 @@ static void handle_write_error(struct address_space *mapping,
        unlock_page(page);
 }
 
-/* Request for sync pageout. */
-enum pageout_io {
-       PAGEOUT_IO_ASYNC,
-       PAGEOUT_IO_SYNC,
-};
-
 /* possible outcome of pageout() */
 typedef enum {
        /* failed to write page out, page is locked */
@@ -330,7 +365,7 @@ typedef enum {
  * Calls ->writepage().
  */
 static pageout_t pageout(struct page *page, struct address_space *mapping,
-                                               enum pageout_io sync_writeback)
+                        struct scan_control *sc)
 {
        /*
         * If the page is dirty, only perform writeback if that write
@@ -366,7 +401,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
        }
        if (mapping->a_ops->writepage == NULL)
                return PAGE_ACTIVATE;
-       if (!may_write_to_queue(mapping->backing_dev_info))
+       if (!may_write_to_queue(mapping->backing_dev_info, sc))
                return PAGE_KEEP;
 
        if (clear_page_dirty_for_io(page)) {
@@ -376,7 +411,6 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
                        .nr_to_write = SWAP_CLUSTER_MAX,
                        .range_start = 0,
                        .range_end = LLONG_MAX,
-                       .nonblocking = 1,
                        .for_reclaim = 1,
                };
 
@@ -394,7 +428,8 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
                 * direct reclaiming a large contiguous area and the
                 * first attempt to free a range of pages fails.
                 */
-               if (PageWriteback(page) && sync_writeback == PAGEOUT_IO_SYNC)
+               if (PageWriteback(page) &&
+                   sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC)
                        wait_on_page_writeback(page);
 
                if (!PageWriteback(page)) {
@@ -402,7 +437,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping,
                        ClearPageReclaim(page);
                }
                trace_mm_vmscan_writepage(page,
-                       trace_reclaim_flags(page, sync_writeback));
+                       trace_reclaim_flags(page, sc->lumpy_reclaim_mode));
                inc_zone_page_state(page, NR_VMSCAN_WRITE);
                return PAGE_SUCCESS;
        }
@@ -580,7 +615,7 @@ static enum page_references page_check_references(struct page *page,
        referenced_page = TestClearPageReferenced(page);
 
        /* Lumpy reclaim - ignore references */
-       if (sc->lumpy_reclaim_mode)
+       if (sc->lumpy_reclaim_mode != LUMPY_MODE_NONE)
                return PAGEREF_RECLAIM;
 
        /*
@@ -616,7 +651,7 @@ static enum page_references page_check_references(struct page *page,
        }
 
        /* Reclaim if clean, defer dirty pages to writeback */
-       if (referenced_page)
+       if (referenced_page && !PageSwapBacked(page))
                return PAGEREF_RECLAIM_CLEAN;
 
        return PAGEREF_RECLAIM;
@@ -644,12 +679,14 @@ static noinline_for_stack void free_page_list(struct list_head *free_pages)
  * shrink_page_list() returns the number of reclaimed pages
  */
 static unsigned long shrink_page_list(struct list_head *page_list,
-                                       struct scan_control *sc,
-                                       enum pageout_io sync_writeback)
+                                     struct zone *zone,
+                                     struct scan_control *sc)
 {
        LIST_HEAD(ret_pages);
        LIST_HEAD(free_pages);
        int pgactivate = 0;
+       unsigned long nr_dirty = 0;
+       unsigned long nr_congested = 0;
        unsigned long nr_reclaimed = 0;
 
        cond_resched();
@@ -669,6 +706,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                        goto keep;
 
                VM_BUG_ON(PageActive(page));
+               VM_BUG_ON(page_zone(page) != zone);
 
                sc->nr_scanned++;
 
@@ -694,10 +732,13 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                         * for any page for which writeback has already
                         * started.
                         */
-                       if (sync_writeback == PAGEOUT_IO_SYNC && may_enter_fs)
+                       if (sc->lumpy_reclaim_mode == LUMPY_MODE_SYNC &&
+                           may_enter_fs)
                                wait_on_page_writeback(page);
-                       else
-                               goto keep_locked;
+                       else {
+                               unlock_page(page);
+                               goto keep_lumpy;
+                       }
                }
 
                references = page_check_references(page, sc);
@@ -743,6 +784,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                }
 
                if (PageDirty(page)) {
+                       nr_dirty++;
+
                        if (references == PAGEREF_RECLAIM_CLEAN)
                                goto keep_locked;
                        if (!may_enter_fs)
@@ -751,14 +794,18 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                                goto keep_locked;
 
                        /* Page is dirty, try to write it out here */
-                       switch (pageout(page, mapping, sync_writeback)) {
+                       switch (pageout(page, mapping, sc)) {
                        case PAGE_KEEP:
+                               nr_congested++;
                                goto keep_locked;
                        case PAGE_ACTIVATE:
                                goto activate_locked;
                        case PAGE_SUCCESS:
-                               if (PageWriteback(page) || PageDirty(page))
+                               if (PageWriteback(page))
+                                       goto keep_lumpy;
+                               if (PageDirty(page))
                                        goto keep;
+
                                /*
                                 * A synchronous write - probably a ramdisk.  Go
                                 * ahead and try to reclaim the page.
@@ -841,6 +888,7 @@ cull_mlocked:
                        try_to_free_swap(page);
                unlock_page(page);
                putback_lru_page(page);
+               disable_lumpy_reclaim_mode(sc);
                continue;
 
 activate_locked:
@@ -853,10 +901,21 @@ activate_locked:
 keep_locked:
                unlock_page(page);
 keep:
+               disable_lumpy_reclaim_mode(sc);
+keep_lumpy:
                list_add(&page->lru, &ret_pages);
                VM_BUG_ON(PageLRU(page) || PageUnevictable(page));
        }
 
+       /*
+        * Tag a zone as congested if all the dirty pages encountered were
+        * backed by a congested BDI. In this case, reclaimers should just
+        * back off and wait for congestion to clear because further reclaim
+        * will encounter the same problem
+        */
+       if (nr_dirty == nr_congested)
+               zone_set_flag(zone, ZONE_CONGESTED);
+
        free_page_list(&free_pages);
 
        list_splice(&ret_pages, page_list);
@@ -1006,7 +1065,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
 
                        /* Check that we have not crossed a zone boundary. */
                        if (unlikely(page_zone_id(cursor_page) != zone_id))
-                               continue;
+                               break;
 
                        /*
                         * If we don't have enough swap space, reclaiming of
@@ -1014,8 +1073,8 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                         * pointless.
                         */
                        if (nr_swap_pages <= 0 && PageAnon(cursor_page) &&
-                                       !PageSwapCache(cursor_page))
-                               continue;
+                           !PageSwapCache(cursor_page))
+                               break;
 
                        if (__isolate_lru_page(cursor_page, mode, file) == 0) {
                                list_move(&cursor_page->lru, dst);
@@ -1026,11 +1085,16 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                                        nr_lumpy_dirty++;
                                scan++;
                        } else {
-                               if (mode == ISOLATE_BOTH &&
-                                               page_count(cursor_page))
-                                       nr_lumpy_failed++;
+                               /* the page is freed already. */
+                               if (!page_count(cursor_page))
+                                       continue;
+                               break;
                        }
                }
+
+               /* If we break out of the loop above, lumpy reclaim failed */
+               if (pfn < end_pfn)
+                       nr_lumpy_failed++;
        }
 
        *scanned = scan;
@@ -1253,7 +1317,7 @@ static inline bool should_reclaim_stall(unsigned long nr_taken,
                return false;
 
        /* Only stall on lumpy reclaim */
-       if (!sc->lumpy_reclaim_mode)
+       if (sc->lumpy_reclaim_mode == LUMPY_MODE_NONE)
                return false;
 
        /* If we have relaimed everything on the isolated list, no stall */
@@ -1286,7 +1350,6 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
        unsigned long nr_scanned;
        unsigned long nr_reclaimed = 0;
        unsigned long nr_taken;
-       unsigned long nr_active;
        unsigned long nr_anon;
        unsigned long nr_file;
 
@@ -1298,15 +1361,15 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
                        return SWAP_CLUSTER_MAX;
        }
 
-
+       set_lumpy_reclaim_mode(priority, sc, false);
        lru_add_drain();
        spin_lock_irq(&zone->lru_lock);
 
        if (scanning_global_lru(sc)) {
                nr_taken = isolate_pages_global(nr_to_scan,
                        &page_list, &nr_scanned, sc->order,
-                       sc->lumpy_reclaim_mode ?
-                               ISOLATE_BOTH : ISOLATE_INACTIVE,
+                       sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ?
+                                       ISOLATE_INACTIVE : ISOLATE_BOTH,
                        zone, 0, file);
                zone->pages_scanned += nr_scanned;
                if (current_is_kswapd())
@@ -1318,8 +1381,8 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
        } else {
                nr_taken = mem_cgroup_isolate_pages(nr_to_scan,
                        &page_list, &nr_scanned, sc->order,
-                       sc->lumpy_reclaim_mode ?
-                               ISOLATE_BOTH : ISOLATE_INACTIVE,
+                       sc->lumpy_reclaim_mode == LUMPY_MODE_NONE ?
+                                       ISOLATE_INACTIVE : ISOLATE_BOTH,
                        zone, sc->mem_cgroup,
                        0, file);
                /*
@@ -1337,20 +1400,12 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
 
        spin_unlock_irq(&zone->lru_lock);
 
-       nr_reclaimed = shrink_page_list(&page_list, sc, PAGEOUT_IO_ASYNC);
+       nr_reclaimed = shrink_page_list(&page_list, zone, sc);
 
        /* Check if we should syncronously wait for writeback */
        if (should_reclaim_stall(nr_taken, nr_reclaimed, priority, sc)) {
-               congestion_wait(BLK_RW_ASYNC, HZ/10);
-
-               /*
-                * The attempt at page out may have made some
-                * of the pages active, mark them inactive again.
-                */
-               nr_active = clear_active_flags(&page_list, NULL);
-               count_vm_events(PGDEACTIVATE, nr_active);
-
-               nr_reclaimed += shrink_page_list(&page_list, sc, PAGEOUT_IO_SYNC);
+               set_lumpy_reclaim_mode(priority, sc, true);
+               nr_reclaimed += shrink_page_list(&page_list, zone, sc);
        }
 
        local_irq_disable();
@@ -1359,6 +1414,12 @@ shrink_inactive_list(unsigned long nr_to_scan, struct zone *zone,
        __count_zone_vm_events(PGSTEAL, zone, nr_reclaimed);
 
        putback_lru_pages(zone, sc, nr_anon, nr_file, &page_list);
+
+       trace_mm_vmscan_lru_shrink_inactive(zone->zone_pgdat->node_id,
+               zone_idx(zone),
+               nr_scanned, nr_reclaimed,
+               priority,
+               trace_shrink_flags(file, sc->lumpy_reclaim_mode));
        return nr_reclaimed;
 }
 
@@ -1506,6 +1567,7 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
        spin_unlock_irq(&zone->lru_lock);
 }
 
+#ifdef CONFIG_SWAP
 static int inactive_anon_is_low_global(struct zone *zone)
 {
        unsigned long active, inactive;
@@ -1531,12 +1593,26 @@ static int inactive_anon_is_low(struct zone *zone, struct scan_control *sc)
 {
        int low;
 
+       /*
+        * If we don't have swap space, anonymous page deactivation
+        * is pointless.
+        */
+       if (!total_swap_pages)
+               return 0;
+
        if (scanning_global_lru(sc))
                low = inactive_anon_is_low_global(zone);
        else
                low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup);
        return low;
 }
+#else
+static inline int inactive_anon_is_low(struct zone *zone,
+                                       struct scan_control *sc)
+{
+       return 0;
+}
+#endif
 
 static int inactive_file_is_low_global(struct zone *zone)
 {
@@ -1721,21 +1797,6 @@ out:
        }
 }
 
-static void set_lumpy_reclaim_mode(int priority, struct scan_control *sc)
-{
-       /*
-        * If we need a large contiguous chunk of memory, or have
-        * trouble getting a small set of contiguous pages, we
-        * will reclaim both active and inactive pages.
-        */
-       if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
-               sc->lumpy_reclaim_mode = 1;
-       else if (sc->order && priority < DEF_PRIORITY - 2)
-               sc->lumpy_reclaim_mode = 1;
-       else
-               sc->lumpy_reclaim_mode = 0;
-}
-
 /*
  * This is a basic per-zone page freer.  Used by both kswapd and direct reclaim.
  */
@@ -1750,8 +1811,6 @@ static void shrink_zone(int priority, struct zone *zone,
 
        get_scan_count(zone, sc, nr, priority);
 
-       set_lumpy_reclaim_mode(priority, sc);
-
        while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
                                        nr[LRU_INACTIVE_FILE]) {
                for_each_evictable_lru(l) {
@@ -1782,7 +1841,7 @@ static void shrink_zone(int priority, struct zone *zone,
         * Even if we did not try to evict anon pages at all, we want to
         * rebalance the anon lru active/inactive ratio.
         */
-       if (inactive_anon_is_low(zone, sc) && nr_swap_pages > 0)
+       if (inactive_anon_is_low(zone, sc))
                shrink_active_list(SWAP_CLUSTER_MAX, zone, sc, priority, 0);
 
        throttle_vm_writeout(sc->gfp_mask);
@@ -1937,21 +1996,16 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
 
                /* Take a nap, wait for some writeback to complete */
                if (!sc->hibernation_mode && sc->nr_scanned &&
-                   priority < DEF_PRIORITY - 2)
-                       congestion_wait(BLK_RW_ASYNC, HZ/10);
+                   priority < DEF_PRIORITY - 2) {
+                       struct zone *preferred_zone;
+
+                       first_zones_zonelist(zonelist, gfp_zone(sc->gfp_mask),
+                                                       NULL, &preferred_zone);
+                       wait_iff_congested(preferred_zone, BLK_RW_ASYNC, HZ/10);
+               }
        }
 
 out:
-       /*
-        * Now that we've scanned all the zones at this priority level, note
-        * that level within the zone so that the next thread which performs
-        * scanning of this zone will immediately start out at this priority
-        * level.  This affects only the decision whether or not to bring
-        * mapped pages onto the inactive list.
-        */
-       if (priority < 0)
-               priority = 0;
-
        delayacct_freepages_end();
        put_mems_allowed();
 
@@ -2247,6 +2301,15 @@ loop_again:
                                if (!zone_watermark_ok(zone, order,
                                            min_wmark_pages(zone), end_zone, 0))
                                        has_under_min_watermark_zone = 1;
+                       } else {
+                               /*
+                                * If a zone reaches its high watermark,
+                                * consider it to be no longer congested. It's
+                                * possible there are dirty pages backed by
+                                * congested BDIs but as pressure is relieved,
+                                * spectulatively avoid congestion waits
+                                */
+                               zone_clear_flag(zone, ZONE_CONGESTED);
                        }
 
                }
@@ -2987,6 +3050,7 @@ int scan_unevictable_handler(struct ctl_table *table, int write,
        return 0;
 }
 
+#ifdef CONFIG_NUMA
 /*
  * per node 'scan_unevictable_pages' attribute.  On demand re-scan of
  * a specified node's per zone unevictable lists for evictable pages.
@@ -3033,4 +3097,4 @@ void scan_unevictable_unregister_node(struct node *node)
 {
        sysdev_remove_file(&node->sysdev, &attr_scan_unevictable_pages);
 }
-
+#endif
index 355a9e6..cd2e42b 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/vmstat.h>
 #include <linux/sched.h>
 #include <linux/math64.h>
+#include <linux/writeback.h>
+#include <linux/compaction.h>
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
 DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
@@ -394,6 +396,7 @@ void zone_statistics(struct zone *preferred_zone, struct zone *z)
 #endif
 
 #ifdef CONFIG_COMPACTION
+
 struct contig_page_info {
        unsigned long free_pages;
        unsigned long free_blocks_total;
@@ -745,6 +748,11 @@ static const char * const vmstat_text[] = {
        "nr_isolated_anon",
        "nr_isolated_file",
        "nr_shmem",
+       "nr_dirtied",
+       "nr_written",
+       "nr_dirty_threshold",
+       "nr_dirty_background_threshold",
+
 #ifdef CONFIG_NUMA
        "numa_hit",
        "numa_miss",
@@ -904,36 +912,44 @@ static const struct file_operations proc_zoneinfo_file_operations = {
        .release        = seq_release,
 };
 
+enum writeback_stat_item {
+       NR_DIRTY_THRESHOLD,
+       NR_DIRTY_BG_THRESHOLD,
+       NR_VM_WRITEBACK_STAT_ITEMS,
+};
+
 static void *vmstat_start(struct seq_file *m, loff_t *pos)
 {
        unsigned long *v;
-#ifdef CONFIG_VM_EVENT_COUNTERS
-       unsigned long *e;
-#endif
-       int i;
+       int i, stat_items_size;
 
        if (*pos >= ARRAY_SIZE(vmstat_text))
                return NULL;
+       stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) +
+                         NR_VM_WRITEBACK_STAT_ITEMS * sizeof(unsigned long);
 
 #ifdef CONFIG_VM_EVENT_COUNTERS
-       v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long)
-                       + sizeof(struct vm_event_state), GFP_KERNEL);
-#else
-       v = kmalloc(NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long),
-                       GFP_KERNEL);
+       stat_items_size += sizeof(struct vm_event_state);
 #endif
+
+       v = kmalloc(stat_items_size, GFP_KERNEL);
        m->private = v;
        if (!v)
                return ERR_PTR(-ENOMEM);
        for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
                v[i] = global_page_state(i);
+       v += NR_VM_ZONE_STAT_ITEMS;
+
+       global_dirty_limits(v + NR_DIRTY_BG_THRESHOLD,
+                           v + NR_DIRTY_THRESHOLD);
+       v += NR_VM_WRITEBACK_STAT_ITEMS;
+
 #ifdef CONFIG_VM_EVENT_COUNTERS
-       e = v + NR_VM_ZONE_STAT_ITEMS;
-       all_vm_events(e);
-       e[PGPGIN] /= 2;         /* sectors -> kbytes */
-       e[PGPGOUT] /= 2;
+       all_vm_events(v);
+       v[PGPGIN] /= 2;         /* sectors -> kbytes */
+       v[PGPGOUT] /= 2;
 #endif
-       return v + *pos;
+       return m->private + *pos;
 }
 
 static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos)
index 5cac1c7..ee3cd28 100644 (file)
@@ -1146,7 +1146,7 @@ call_kill:
 }
 EXPORT_SYMBOL(sock_wake_async);
 
-static int __sock_create(struct net *net, int family, int type, int protocol,
+int __sock_create(struct net *net, int family, int type, int protocol,
                         struct socket **res, int kern)
 {
        int err;
@@ -1258,6 +1258,7 @@ out_release:
        rcu_read_unlock();
        goto out_sock_release;
 }
+EXPORT_SYMBOL(__sock_create);
 
 int sock_create(int family, int type, int protocol, struct socket **res)
 {
index 3376d76..8873fd8 100644 (file)
@@ -36,22 +36,3 @@ config RPCSEC_GSS_KRB5
          Kerberos support should be installed.
 
          If unsure, say Y.
-
-config RPCSEC_GSS_SPKM3
-       tristate "Secure RPC: SPKM3 mechanism (EXPERIMENTAL)"
-       depends on SUNRPC && EXPERIMENTAL
-       select SUNRPC_GSS
-       select CRYPTO
-       select CRYPTO_MD5
-       select CRYPTO_DES
-       select CRYPTO_CAST5
-       select CRYPTO_CBC
-       help
-         Choose Y here to enable Secure RPC using the SPKM3 public key
-         GSS-API mechanism (RFC 2025).
-
-         Secure RPC calls with SPKM3 require an auxiliary userspace
-         daemon which may be found in the Linux nfs-utils package
-         available from http://linux-nfs.org/.
-
-         If unsure, say N.
index e9eaaf7..afe6784 100644 (file)
@@ -595,7 +595,7 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
 int
 rpcauth_refreshcred(struct rpc_task *task)
 {
-       struct rpc_cred *cred = task->tk_rqstp->rq_cred;
+       struct rpc_cred *cred;
        int err;
 
        cred = task->tk_rqstp->rq_cred;
@@ -658,7 +658,7 @@ out1:
        return err;
 }
 
-void __exit rpcauth_remove_module(void)
+void rpcauth_remove_module(void)
 {
        rpc_destroy_authunix();
        rpc_destroy_generic_auth();
index 43162bb..e010a01 100644 (file)
@@ -158,7 +158,7 @@ int __init rpc_init_generic_auth(void)
        return rpcauth_init_credcache(&generic_auth);
 }
 
-void __exit rpc_destroy_generic_auth(void)
+void rpc_destroy_generic_auth(void)
 {
        rpcauth_destroy_credcache(&generic_auth);
 }
index 74a2317..7350d86 100644 (file)
@@ -11,8 +11,3 @@ obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o
 
 rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \
        gss_krb5_seqnum.o gss_krb5_wrap.o gss_krb5_crypto.o gss_krb5_keys.o
-
-obj-$(CONFIG_RPCSEC_GSS_SPKM3) += rpcsec_gss_spkm3.o
-
-rpcsec_gss_spkm3-objs := gss_spkm3_mech.o gss_spkm3_seal.o gss_spkm3_unseal.o \
-       gss_spkm3_token.o
index 778e5df..f375dec 100644 (file)
@@ -427,7 +427,7 @@ static int
 context_derive_keys_rc4(struct krb5_ctx *ctx)
 {
        struct crypto_hash *hmac;
-       char sigkeyconstant[] = "signaturekey";
+       static const char sigkeyconstant[] = "signaturekey";
        int slen = strlen(sigkeyconstant) + 1;  /* include null terminator */
        struct hash_desc desc;
        struct scatterlist sg[1];
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
deleted file mode 100644 (file)
index adade3d..0000000
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_mech.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *  J. Bruce Fields <bfields@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/sunrpc/auth.h>
-#include <linux/in.h>
-#include <linux/sunrpc/svcauth_gss.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/sunrpc/xdr.h>
-#include <linux/crypto.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY       RPCDBG_AUTH
-#endif
-
-static const void *
-simple_get_bytes(const void *p, const void *end, void *res, int len)
-{
-       const void *q = (const void *)((const char *)p + len);
-       if (unlikely(q > end || q < p))
-               return ERR_PTR(-EFAULT);
-       memcpy(res, p, len);
-       return q;
-}
-
-static const void *
-simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
-{
-       const void *q;
-       unsigned int len;
-       p = simple_get_bytes(p, end, &len, sizeof(len));
-       if (IS_ERR(p))
-               return p;
-       res->len = len;
-       if (len == 0) {
-               res->data = NULL;
-               return p;
-       }
-       q = (const void *)((const char *)p + len);
-       if (unlikely(q > end || q < p))
-               return ERR_PTR(-EFAULT);
-       res->data = kmemdup(p, len, GFP_NOFS);
-       if (unlikely(res->data == NULL))
-               return ERR_PTR(-ENOMEM);
-       return q;
-}
-
-static int
-gss_import_sec_context_spkm3(const void *p, size_t len,
-                               struct gss_ctx *ctx_id,
-                               gfp_t gfp_mask)
-{
-       const void *end = (const void *)((const char *)p + len);
-       struct  spkm3_ctx *ctx;
-       int     version;
-
-       if (!(ctx = kzalloc(sizeof(*ctx), gfp_mask)))
-               goto out_err;
-
-       p = simple_get_bytes(p, end, &version, sizeof(version));
-       if (IS_ERR(p))
-               goto out_err_free_ctx;
-       if (version != 1) {
-               dprintk("RPC:       unknown spkm3 token format: "
-                               "obsolete nfs-utils?\n");
-               p = ERR_PTR(-EINVAL);
-               goto out_err_free_ctx;
-       }
-
-       p = simple_get_netobj(p, end, &ctx->ctx_id);
-       if (IS_ERR(p))
-               goto out_err_free_ctx;
-
-       p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
-       if (IS_ERR(p))
-               goto out_err_free_ctx_id;
-
-       p = simple_get_netobj(p, end, &ctx->mech_used);
-       if (IS_ERR(p))
-               goto out_err_free_ctx_id;
-
-       p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
-       if (IS_ERR(p))
-               goto out_err_free_mech;
-
-       p = simple_get_netobj(p, end, &ctx->conf_alg);
-       if (IS_ERR(p))
-               goto out_err_free_mech;
-
-       p = simple_get_netobj(p, end, &ctx->derived_conf_key);
-       if (IS_ERR(p))
-               goto out_err_free_conf_alg;
-
-       p = simple_get_netobj(p, end, &ctx->intg_alg);
-       if (IS_ERR(p))
-               goto out_err_free_conf_key;
-
-       p = simple_get_netobj(p, end, &ctx->derived_integ_key);
-       if (IS_ERR(p))
-               goto out_err_free_intg_alg;
-
-       if (p != end) {
-               p = ERR_PTR(-EFAULT);
-               goto out_err_free_intg_key;
-       }
-
-       ctx_id->internal_ctx_id = ctx;
-
-       dprintk("RPC:       Successfully imported new spkm context.\n");
-       return 0;
-
-out_err_free_intg_key:
-       kfree(ctx->derived_integ_key.data);
-out_err_free_intg_alg:
-       kfree(ctx->intg_alg.data);
-out_err_free_conf_key:
-       kfree(ctx->derived_conf_key.data);
-out_err_free_conf_alg:
-       kfree(ctx->conf_alg.data);
-out_err_free_mech:
-       kfree(ctx->mech_used.data);
-out_err_free_ctx_id:
-       kfree(ctx->ctx_id.data);
-out_err_free_ctx:
-       kfree(ctx);
-out_err:
-       return PTR_ERR(p);
-}
-
-static void
-gss_delete_sec_context_spkm3(void *internal_ctx)
-{
-       struct spkm3_ctx *sctx = internal_ctx;
-
-       kfree(sctx->derived_integ_key.data);
-       kfree(sctx->intg_alg.data);
-       kfree(sctx->derived_conf_key.data);
-       kfree(sctx->conf_alg.data);
-       kfree(sctx->mech_used.data);
-       kfree(sctx->ctx_id.data);
-       kfree(sctx);
-}
-
-static u32
-gss_verify_mic_spkm3(struct gss_ctx            *ctx,
-                       struct xdr_buf          *signbuf,
-                       struct xdr_netobj       *checksum)
-{
-       u32 maj_stat = 0;
-       struct spkm3_ctx *sctx = ctx->internal_ctx_id;
-
-       maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
-
-       dprintk("RPC:       gss_verify_mic_spkm3 returning %d\n", maj_stat);
-       return maj_stat;
-}
-
-static u32
-gss_get_mic_spkm3(struct gss_ctx       *ctx,
-                    struct xdr_buf     *message_buffer,
-                    struct xdr_netobj  *message_token)
-{
-       u32 err = 0;
-       struct spkm3_ctx *sctx = ctx->internal_ctx_id;
-
-       err = spkm3_make_token(sctx, message_buffer,
-                               message_token, SPKM_MIC_TOK);
-       dprintk("RPC:       gss_get_mic_spkm3 returning %d\n", err);
-       return err;
-}
-
-static const struct gss_api_ops gss_spkm3_ops = {
-       .gss_import_sec_context = gss_import_sec_context_spkm3,
-       .gss_get_mic            = gss_get_mic_spkm3,
-       .gss_verify_mic         = gss_verify_mic_spkm3,
-       .gss_delete_sec_context = gss_delete_sec_context_spkm3,
-};
-
-static struct pf_desc gss_spkm3_pfs[] = {
-       {RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
-       {RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
-};
-
-static struct gss_api_mech gss_spkm3_mech = {
-       .gm_name        = "spkm3",
-       .gm_owner       = THIS_MODULE,
-       .gm_oid         = {7, "\053\006\001\005\005\001\003"},
-       .gm_ops         = &gss_spkm3_ops,
-       .gm_pf_num      = ARRAY_SIZE(gss_spkm3_pfs),
-       .gm_pfs         = gss_spkm3_pfs,
-};
-
-static int __init init_spkm3_module(void)
-{
-       int status;
-
-       status = gss_mech_register(&gss_spkm3_mech);
-       if (status)
-               printk("Failed to register spkm3 gss mechanism!\n");
-       return status;
-}
-
-static void __exit cleanup_spkm3_module(void)
-{
-       gss_mech_unregister(&gss_spkm3_mech);
-}
-
-MODULE_LICENSE("GPL");
-module_init(init_spkm3_module);
-module_exit(cleanup_spkm3_module);
diff --git a/net/sunrpc/auth_gss/gss_spkm3_seal.c b/net/sunrpc/auth_gss/gss_spkm3_seal.c
deleted file mode 100644 (file)
index 5a3a65a..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_seal.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/jiffies.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/random.h>
-#include <linux/crypto.h>
-#include <linux/pagemap.h>
-#include <linux/scatterlist.h>
-#include <linux/sunrpc/xdr.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY        RPCDBG_AUTH
-#endif
-
-const struct xdr_netobj hmac_md5_oid = { 8, "\x2B\x06\x01\x05\x05\x08\x01\x01"};
-const struct xdr_netobj cast5_cbc_oid = {9, "\x2A\x86\x48\x86\xF6\x7D\x07\x42\x0A"};
-
-/*
- * spkm3_make_token()
- *
- * Only SPKM_MIC_TOK with md5 intg-alg is supported
- */
-
-u32
-spkm3_make_token(struct spkm3_ctx *ctx,
-                  struct xdr_buf * text, struct xdr_netobj * token,
-                  int toktype)
-{
-       s32                     checksum_type;
-       char                    tokhdrbuf[25];
-       char                    cksumdata[16];
-       struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
-       struct xdr_netobj       mic_hdr = {.len = 0, .data = tokhdrbuf};
-       int                     tokenlen = 0;
-       unsigned char           *ptr;
-       s32                     now;
-       int                     ctxelen = 0, ctxzbit = 0;
-       int                     md5elen = 0, md5zbit = 0;
-
-       now = jiffies;
-
-       if (ctx->ctx_id.len != 16) {
-               dprintk("RPC:       spkm3_make_token BAD ctx_id.len %d\n",
-                               ctx->ctx_id.len);
-               goto out_err;
-       }
-
-       if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
-               dprintk("RPC:       gss_spkm3_seal: unsupported I-ALG "
-                               "algorithm.  only support hmac-md5 I-ALG.\n");
-               goto out_err;
-       } else
-               checksum_type = CKSUMTYPE_HMAC_MD5;
-
-       if (!g_OID_equal(&ctx->conf_alg, &cast5_cbc_oid)) {
-               dprintk("RPC:       gss_spkm3_seal: unsupported C-ALG "
-                               "algorithm\n");
-               goto out_err;
-       }
-
-       if (toktype == SPKM_MIC_TOK) {
-               /* Calculate checksum over the mic-header */
-               asn1_bitstring_len(&ctx->ctx_id, &ctxelen, &ctxzbit);
-               spkm3_mic_header(&mic_hdr.data, &mic_hdr.len, ctx->ctx_id.data,
-                               ctxelen, ctxzbit);
-               if (make_spkm3_checksum(checksum_type, &ctx->derived_integ_key,
-                                       (char *)mic_hdr.data, mic_hdr.len,
-                                       text, 0, &md5cksum))
-                       goto out_err;
-
-               asn1_bitstring_len(&md5cksum, &md5elen, &md5zbit);
-               tokenlen = 10 + ctxelen + 1 + md5elen + 1;
-
-               /* Create token header using generic routines */
-               token->len = g_token_size(&ctx->mech_used, tokenlen + 2);
-
-               ptr = token->data;
-               g_make_token_header(&ctx->mech_used, tokenlen + 2, &ptr);
-
-               spkm3_make_mic_token(&ptr, tokenlen, &mic_hdr, &md5cksum, md5elen, md5zbit);
-       } else if (toktype == SPKM_WRAP_TOK) { /* Not Supported */
-               dprintk("RPC:       gss_spkm3_seal: SPKM_WRAP_TOK "
-                               "not supported\n");
-               goto out_err;
-       }
-
-       /* XXX need to implement sequence numbers, and ctx->expired */
-
-       return  GSS_S_COMPLETE;
-out_err:
-       token->data = NULL;
-       token->len = 0;
-       return GSS_S_FAILURE;
-}
-
-static int
-spkm3_checksummer(struct scatterlist *sg, void *data)
-{
-       struct hash_desc *desc = data;
-
-       return crypto_hash_update(desc, sg, sg->length);
-}
-
-/* checksum the plaintext data and hdrlen bytes of the token header */
-s32
-make_spkm3_checksum(s32 cksumtype, struct xdr_netobj *key, char *header,
-                   unsigned int hdrlen, struct xdr_buf *body,
-                   unsigned int body_offset, struct xdr_netobj *cksum)
-{
-       char                            *cksumname;
-       struct hash_desc                desc; /* XXX add to ctx? */
-       struct scatterlist              sg[1];
-       int err;
-
-       switch (cksumtype) {
-               case CKSUMTYPE_HMAC_MD5:
-                       cksumname = "hmac(md5)";
-                       break;
-               default:
-                       dprintk("RPC:       spkm3_make_checksum:"
-                                       " unsupported checksum %d", cksumtype);
-                       return GSS_S_FAILURE;
-       }
-
-       if (key->data == NULL || key->len <= 0) return GSS_S_FAILURE;
-
-       desc.tfm = crypto_alloc_hash(cksumname, 0, CRYPTO_ALG_ASYNC);
-       if (IS_ERR(desc.tfm))
-               return GSS_S_FAILURE;
-       cksum->len = crypto_hash_digestsize(desc.tfm);
-       desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-
-       err = crypto_hash_setkey(desc.tfm, key->data, key->len);
-       if (err)
-               goto out;
-
-       err = crypto_hash_init(&desc);
-       if (err)
-               goto out;
-
-       sg_init_one(sg, header, hdrlen);
-       crypto_hash_update(&desc, sg, sg->length);
-
-       xdr_process_buf(body, body_offset, body->len - body_offset,
-                       spkm3_checksummer, &desc);
-       crypto_hash_final(&desc, cksum->data);
-
-out:
-       crypto_free_hash(desc.tfm);
-
-       return err ? GSS_S_FAILURE : 0;
-}
diff --git a/net/sunrpc/auth_gss/gss_spkm3_token.c b/net/sunrpc/auth_gss/gss_spkm3_token.c
deleted file mode 100644 (file)
index a99825d..0000000
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_token.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/random.h>
-#include <linux/crypto.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY        RPCDBG_AUTH
-#endif
-
-/*
- * asn1_bitstring_len()
- *
- * calculate the asn1 bitstring length of the xdr_netobject
- */
-void
-asn1_bitstring_len(struct xdr_netobj *in, int *enclen, int *zerobits)
-{
-       int i, zbit = 0,elen = in->len;
-       char *ptr;
-
-       ptr = &in->data[in->len -1];
-
-       /* count trailing 0's */
-       for(i = in->len; i > 0; i--) {
-               if (*ptr == 0) {
-                       ptr--;
-                       elen--;
-               } else
-                       break;
-       }
-
-       /* count number of 0 bits in final octet */
-       ptr = &in->data[elen - 1];
-       for(i = 0; i < 8; i++) {
-               short mask = 0x01;
-
-               if (!((mask << i) & *ptr))
-                       zbit++;
-               else
-                       break;
-       }
-       *enclen = elen;
-       *zerobits = zbit;
-}
-
-/*
- * decode_asn1_bitstring()
- *
- * decode a bitstring into a buffer of the expected length.
- * enclen = bit string length
- * explen = expected length (define in rfc)
- */
-int
-decode_asn1_bitstring(struct xdr_netobj *out, char *in, int enclen, int explen)
-{
-       if (!(out->data = kzalloc(explen,GFP_NOFS)))
-               return 0;
-       out->len = explen;
-       memcpy(out->data, in, enclen);
-       return 1;
-}
-
-/*
- * SPKMInnerContextToken choice SPKM_MIC asn1 token layout
- *
- * contextid is always 16 bytes plain data. max asn1 bitstring len = 17.
- *
- * tokenlen = pos[0] to end of token (max pos[45] with MD5 cksum)
- *
- * pos  value
- * ----------
- * [0] a4  SPKM-MIC tag
- * [1] ??  innertoken length  (max 44)
- *
- *
- * tok_hdr piece of checksum data starts here
- *
- * the maximum mic-header len = 9 + 17 = 26
- *     mic-header
- *     ----------
- * [2] 30      SEQUENCE tag
- * [3] ??      mic-header length: (max 23) = TokenID + ContextID
- *
- *             TokenID  - all fields constant and can be hardcoded
- *             -------
- * [4]   02    Type 2
- * [5]   02    Length 2
- * [6][7] 01 01        TokenID (SPKM_MIC_TOK)
- *
- *             ContextID  - encoded length not constant, calculated
- *             ---------
- * [8] 03      Type 3
- * [9] ??      encoded length
- * [10]        ??      ctxzbit
- * [11]                contextid
- *
- * mic_header piece of checksum data ends here.
- *
- *     int-cksum - encoded length not constant, calculated
- *     ---------
- * [??]        03      Type 3
- * [??]        ??      encoded length
- * [??]        ??      md5zbit
- * [??]                int-cksum (NID_md5 = 16)
- *
- * maximum SPKM-MIC innercontext token length =
- *      10 + encoded contextid_size(17 max) + 2 + encoded
- *       cksum_size (17 maxfor NID_md5) = 46
- */
-
-/*
- * spkm3_mic_header()
- *
- * Prepare the SPKM_MIC_TOK mic-header for check-sum calculation
- * elen: 16 byte context id asn1 bitstring encoded length
- */
-void
-spkm3_mic_header(unsigned char **hdrbuf, unsigned int *hdrlen, unsigned char *ctxdata, int elen, int zbit)
-{
-       char *hptr = *hdrbuf;
-       char *top = *hdrbuf;
-
-       *(u8 *)hptr++ = 0x30;
-       *(u8 *)hptr++ = elen + 7;  /* on the wire header length */
-
-       /* tokenid */
-       *(u8 *)hptr++ = 0x02;
-       *(u8 *)hptr++ = 0x02;
-       *(u8 *)hptr++ = 0x01;
-       *(u8 *)hptr++ = 0x01;
-
-       /* coniextid */
-       *(u8 *)hptr++ = 0x03;
-       *(u8 *)hptr++ = elen + 1; /* add 1 to include zbit */
-       *(u8 *)hptr++ = zbit;
-       memcpy(hptr, ctxdata, elen);
-       hptr += elen;
-       *hdrlen = hptr - top;
-}
-
-/*
- * spkm3_mic_innercontext_token()
- *
- * *tokp points to the beginning of the SPKM_MIC token  described
- * in rfc 2025, section 3.2.1:
- *
- * toklen is the inner token length
- */
-void
-spkm3_make_mic_token(unsigned char **tokp, int toklen, struct xdr_netobj *mic_hdr, struct xdr_netobj *md5cksum, int md5elen, int md5zbit)
-{
-       unsigned char *ict = *tokp;
-
-       *(u8 *)ict++ = 0xa4;
-       *(u8 *)ict++ = toklen;
-       memcpy(ict, mic_hdr->data, mic_hdr->len);
-       ict += mic_hdr->len;
-
-       *(u8 *)ict++ = 0x03;
-       *(u8 *)ict++ = md5elen + 1; /* add 1 to include zbit */
-       *(u8 *)ict++ = md5zbit;
-       memcpy(ict, md5cksum->data, md5elen);
-}
-
-u32
-spkm3_verify_mic_token(unsigned char **tokp, int *mic_hdrlen, unsigned char **cksum)
-{
-       struct xdr_netobj       spkm3_ctx_id = {.len =0, .data = NULL};
-       unsigned char           *ptr = *tokp;
-       int                     ctxelen;
-       u32                     ret = GSS_S_DEFECTIVE_TOKEN;
-
-       /* spkm3 innercontext token preamble */
-       if ((ptr[0] != 0xa4) || (ptr[2] != 0x30)) {
-               dprintk("RPC:       BAD SPKM ictoken preamble\n");
-               goto out;
-       }
-
-       *mic_hdrlen = ptr[3];
-
-       /* token type */
-       if ((ptr[4] != 0x02) || (ptr[5] != 0x02)) {
-               dprintk("RPC:       BAD asn1 SPKM3 token type\n");
-               goto out;
-       }
-
-       /* only support SPKM_MIC_TOK */
-       if((ptr[6] != 0x01) || (ptr[7] != 0x01)) {
-               dprintk("RPC:       ERROR unsupported SPKM3 token\n");
-               goto out;
-       }
-
-       /* contextid */
-       if (ptr[8] != 0x03) {
-               dprintk("RPC:       BAD SPKM3 asn1 context-id type\n");
-               goto out;
-       }
-
-       ctxelen = ptr[9];
-       if (ctxelen > 17) {  /* length includes asn1 zbit octet */
-               dprintk("RPC:       BAD SPKM3 contextid len %d\n", ctxelen);
-               goto out;
-       }
-
-       /* ignore ptr[10] */
-
-       if(!decode_asn1_bitstring(&spkm3_ctx_id, &ptr[11], ctxelen - 1, 16))
-               goto out;
-
-       /*
-       * in the current implementation: the optional int-alg is not present
-       * so the default int-alg (md5) is used the optional snd-seq field is
-       * also not present
-       */
-
-       if (*mic_hdrlen != 6 + ctxelen) {
-               dprintk("RPC:       BAD SPKM_ MIC_TOK header len %d: we only "
-                               "support default int-alg (should be absent) "
-                               "and do not support snd-seq\n", *mic_hdrlen);
-               goto out;
-       }
-       /* checksum */
-       *cksum = (&ptr[10] + ctxelen); /* ctxelen includes ptr[10] */
-
-       ret = GSS_S_COMPLETE;
-out:
-       kfree(spkm3_ctx_id.data);
-       return ret;
-}
-
diff --git a/net/sunrpc/auth_gss/gss_spkm3_unseal.c b/net/sunrpc/auth_gss/gss_spkm3_unseal.c
deleted file mode 100644 (file)
index cc21ee8..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- *  linux/net/sunrpc/gss_spkm3_unseal.c
- *
- *  Copyright (c) 2003 The Regents of the University of Michigan.
- *  All rights reserved.
- *
- *  Andy Adamson <andros@umich.edu>
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the University nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/sunrpc/gss_spkm3.h>
-#include <linux/crypto.h>
-
-#ifdef RPC_DEBUG
-# define RPCDBG_FACILITY        RPCDBG_AUTH
-#endif
-
-/*
- * spkm3_read_token()
- *
- * only SPKM_MIC_TOK with md5 intg-alg is supported
- */
-u32
-spkm3_read_token(struct spkm3_ctx *ctx,
-               struct xdr_netobj *read_token,    /* checksum */
-               struct xdr_buf *message_buffer, /* signbuf */
-               int toktype)
-{
-       s32                     checksum_type;
-       s32                     code;
-       struct xdr_netobj       wire_cksum = {.len =0, .data = NULL};
-       char                    cksumdata[16];
-       struct xdr_netobj       md5cksum = {.len = 0, .data = cksumdata};
-       unsigned char           *ptr = (unsigned char *)read_token->data;
-       unsigned char           *cksum;
-       int                     bodysize, md5elen;
-       int                     mic_hdrlen;
-       u32                     ret = GSS_S_DEFECTIVE_TOKEN;
-
-       if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used,
-                                       &bodysize, &ptr, read_token->len))
-               goto out;
-
-       /* decode the token */
-
-       if (toktype != SPKM_MIC_TOK) {
-               dprintk("RPC:       BAD SPKM3 token type: %d\n", toktype);
-               goto out;
-       }
-
-       if ((ret = spkm3_verify_mic_token(&ptr, &mic_hdrlen, &cksum)))
-               goto out;
-
-       if (*cksum++ != 0x03) {
-               dprintk("RPC:       spkm3_read_token BAD checksum type\n");
-               goto out;
-       }
-       md5elen = *cksum++;
-       cksum++;        /* move past the zbit */
-
-       if (!decode_asn1_bitstring(&wire_cksum, cksum, md5elen - 1, 16))
-               goto out;
-
-       /* HARD CODED FOR MD5 */
-
-       /* compute the checksum of the message.
-        * ptr + 2 = start of header piece of checksum
-        * mic_hdrlen + 2 = length of header piece of checksum
-        */
-       ret = GSS_S_DEFECTIVE_TOKEN;
-       if (!g_OID_equal(&ctx->intg_alg, &hmac_md5_oid)) {
-               dprintk("RPC:       gss_spkm3_seal: unsupported I-ALG "
-                               "algorithm\n");
-               goto out;
-       }
-
-       checksum_type = CKSUMTYPE_HMAC_MD5;
-
-       code = make_spkm3_checksum(checksum_type,
-               &ctx->derived_integ_key, ptr + 2, mic_hdrlen + 2,
-               message_buffer, 0, &md5cksum);
-
-       if (code)
-               goto out;
-
-       ret = GSS_S_BAD_SIG;
-       code = memcmp(md5cksum.data, wire_cksum.data, wire_cksum.len);
-       if (code) {
-               dprintk("RPC:       bad MIC checksum\n");
-               goto out;
-       }
-
-
-       /* XXX: need to add expiration and sequencing */
-       ret = GSS_S_COMPLETE;
-out:
-       kfree(wire_cksum.data);
-       return ret;
-}
index cc385b3..dec2a6f 100644 (file)
@@ -964,7 +964,7 @@ svcauth_gss_set_client(struct svc_rqst *rqstp)
        if (rqstp->rq_gssclient == NULL)
                return SVC_DENIED;
        stat = svcauth_unix_set_client(rqstp);
-       if (stat == SVC_DROP)
+       if (stat == SVC_DROP || stat == SVC_CLOSE)
                return stat;
        return SVC_OK;
 }
@@ -1018,7 +1018,7 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
                return SVC_DENIED;
        memset(&rsikey, 0, sizeof(rsikey));
        if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx))
-               return SVC_DROP;
+               return SVC_CLOSE;
        *authp = rpc_autherr_badverf;
        if (svc_safe_getnetobj(argv, &tmpobj)) {
                kfree(rsikey.in_handle.data);
@@ -1026,38 +1026,35 @@ static int svcauth_gss_handle_init(struct svc_rqst *rqstp,
        }
        if (dup_netobj(&rsikey.in_token, &tmpobj)) {
                kfree(rsikey.in_handle.data);
-               return SVC_DROP;
+               return SVC_CLOSE;
        }
 
        /* Perform upcall, or find upcall result: */
        rsip = rsi_lookup(&rsikey);
        rsi_free(&rsikey);
        if (!rsip)
-               return SVC_DROP;
-       switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
-       case -EAGAIN:
-       case -ETIMEDOUT:
-       case -ENOENT:
+               return SVC_CLOSE;
+       if (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0)
                /* No upcall result: */
-               return SVC_DROP;
-       case 0:
-               ret = SVC_DROP;
-               /* Got an answer to the upcall; use it: */
-               if (gss_write_init_verf(rqstp, rsip))
-                       goto out;
-               if (resv->iov_len + 4 > PAGE_SIZE)
-                       goto out;
-               svc_putnl(resv, RPC_SUCCESS);
-               if (svc_safe_putnetobj(resv, &rsip->out_handle))
-                       goto out;
-               if (resv->iov_len + 3 * 4 > PAGE_SIZE)
-                       goto out;
-               svc_putnl(resv, rsip->major_status);
-               svc_putnl(resv, rsip->minor_status);
-               svc_putnl(resv, GSS_SEQ_WIN);
-               if (svc_safe_putnetobj(resv, &rsip->out_token))
-                       goto out;
-       }
+               return SVC_CLOSE;
+
+       ret = SVC_CLOSE;
+       /* Got an answer to the upcall; use it: */
+       if (gss_write_init_verf(rqstp, rsip))
+               goto out;
+       if (resv->iov_len + 4 > PAGE_SIZE)
+               goto out;
+       svc_putnl(resv, RPC_SUCCESS);
+       if (svc_safe_putnetobj(resv, &rsip->out_handle))
+               goto out;
+       if (resv->iov_len + 3 * 4 > PAGE_SIZE)
+               goto out;
+       svc_putnl(resv, rsip->major_status);
+       svc_putnl(resv, rsip->minor_status);
+       svc_putnl(resv, GSS_SEQ_WIN);
+       if (svc_safe_putnetobj(resv, &rsip->out_token))
+               goto out;
+
        ret = SVC_COMPLETE;
 out:
        cache_put(&rsip->h, &rsi_cache);
index 7dce81a..e433e75 100644 (file)
 #include <linux/sunrpc/cache.h>
 #include <linux/sunrpc/stats.h>
 #include <linux/sunrpc/rpc_pipe_fs.h>
+#include "netns.h"
 
 #define         RPCDBG_FACILITY RPCDBG_CACHE
 
-static int cache_defer_req(struct cache_req *req, struct cache_head *item);
+static void cache_defer_req(struct cache_req *req, struct cache_head *item);
 static void cache_revisit_request(struct cache_head *item);
 
 static void cache_init(struct cache_head *h)
 {
-       time_t now = get_seconds();
+       time_t now = seconds_since_boot();
        h->next = NULL;
        h->flags = 0;
        kref_init(&h->ref);
@@ -51,7 +52,7 @@ static void cache_init(struct cache_head *h)
 
 static inline int cache_is_expired(struct cache_detail *detail, struct cache_head *h)
 {
-       return  (h->expiry_time < get_seconds()) ||
+       return  (h->expiry_time < seconds_since_boot()) ||
                (detail->flush_time > h->last_refresh);
 }
 
@@ -126,7 +127,7 @@ static void cache_dequeue(struct cache_detail *detail, struct cache_head *ch);
 static void cache_fresh_locked(struct cache_head *head, time_t expiry)
 {
        head->expiry_time = expiry;
-       head->last_refresh = get_seconds();
+       head->last_refresh = seconds_since_boot();
        set_bit(CACHE_VALID, &head->flags);
 }
 
@@ -237,7 +238,7 @@ int cache_check(struct cache_detail *detail,
 
        /* now see if we want to start an upcall */
        refresh_age = (h->expiry_time - h->last_refresh);
-       age = get_seconds() - h->last_refresh;
+       age = seconds_since_boot() - h->last_refresh;
 
        if (rqstp == NULL) {
                if (rv == -EAGAIN)
@@ -252,7 +253,7 @@ int cache_check(struct cache_detail *detail,
                                cache_revisit_request(h);
                                if (rv == -EAGAIN) {
                                        set_bit(CACHE_NEGATIVE, &h->flags);
-                                       cache_fresh_locked(h, get_seconds()+CACHE_NEW_EXPIRY);
+                                       cache_fresh_locked(h, seconds_since_boot()+CACHE_NEW_EXPIRY);
                                        cache_fresh_unlocked(h, detail);
                                        rv = -ENOENT;
                                }
@@ -267,7 +268,8 @@ int cache_check(struct cache_detail *detail,
        }
 
        if (rv == -EAGAIN) {
-               if (cache_defer_req(rqstp, h) < 0) {
+               cache_defer_req(rqstp, h);
+               if (!test_bit(CACHE_PENDING, &h->flags)) {
                        /* Request is not deferred */
                        rv = cache_is_valid(detail, h);
                        if (rv == -EAGAIN)
@@ -387,11 +389,11 @@ static int cache_clean(void)
                        return -1;
                }
                current_detail = list_entry(next, struct cache_detail, others);
-               if (current_detail->nextcheck > get_seconds())
+               if (current_detail->nextcheck > seconds_since_boot())
                        current_index = current_detail->hash_size;
                else {
                        current_index = 0;
-                       current_detail->nextcheck = get_seconds()+30*60;
+                       current_detail->nextcheck = seconds_since_boot()+30*60;
                }
        }
 
@@ -476,7 +478,7 @@ EXPORT_SYMBOL_GPL(cache_flush);
 void cache_purge(struct cache_detail *detail)
 {
        detail->flush_time = LONG_MAX;
-       detail->nextcheck = get_seconds();
+       detail->nextcheck = seconds_since_boot();
        cache_flush();
        detail->flush_time = 1;
 }
@@ -505,81 +507,155 @@ EXPORT_SYMBOL_GPL(cache_purge);
 
 static DEFINE_SPINLOCK(cache_defer_lock);
 static LIST_HEAD(cache_defer_list);
-static struct list_head cache_defer_hash[DFR_HASHSIZE];
+static struct hlist_head cache_defer_hash[DFR_HASHSIZE];
 static int cache_defer_cnt;
 
-static int cache_defer_req(struct cache_req *req, struct cache_head *item)
+static void __unhash_deferred_req(struct cache_deferred_req *dreq)
+{
+       hlist_del_init(&dreq->hash);
+       if (!list_empty(&dreq->recent)) {
+               list_del_init(&dreq->recent);
+               cache_defer_cnt--;
+       }
+}
+
+static void __hash_deferred_req(struct cache_deferred_req *dreq, struct cache_head *item)
 {
-       struct cache_deferred_req *dreq, *discard;
        int hash = DFR_HASH(item);
 
-       if (cache_defer_cnt >= DFR_MAX) {
-               /* too much in the cache, randomly drop this one,
-                * or continue and drop the oldest below
-                */
-               if (net_random()&1)
-                       return -ENOMEM;
-       }
-       dreq = req->defer(req);
-       if (dreq == NULL)
-               return -ENOMEM;
+       INIT_LIST_HEAD(&dreq->recent);
+       hlist_add_head(&dreq->hash, &cache_defer_hash[hash]);
+}
+
+static void setup_deferral(struct cache_deferred_req *dreq,
+                          struct cache_head *item,
+                          int count_me)
+{
 
        dreq->item = item;
 
        spin_lock(&cache_defer_lock);
 
-       list_add(&dreq->recent, &cache_defer_list);
-
-       if (cache_defer_hash[hash].next == NULL)
-               INIT_LIST_HEAD(&cache_defer_hash[hash]);
-       list_add(&dreq->hash, &cache_defer_hash[hash]);
+       __hash_deferred_req(dreq, item);
 
-       /* it is in, now maybe clean up */
-       discard = NULL;
-       if (++cache_defer_cnt > DFR_MAX) {
-               discard = list_entry(cache_defer_list.prev,
-                                    struct cache_deferred_req, recent);
-               list_del_init(&discard->recent);
-               list_del_init(&discard->hash);
-               cache_defer_cnt--;
+       if (count_me) {
+               cache_defer_cnt++;
+               list_add(&dreq->recent, &cache_defer_list);
        }
+
        spin_unlock(&cache_defer_lock);
 
+}
+
+struct thread_deferred_req {
+       struct cache_deferred_req handle;
+       struct completion completion;
+};
+
+static void cache_restart_thread(struct cache_deferred_req *dreq, int too_many)
+{
+       struct thread_deferred_req *dr =
+               container_of(dreq, struct thread_deferred_req, handle);
+       complete(&dr->completion);
+}
+
+static void cache_wait_req(struct cache_req *req, struct cache_head *item)
+{
+       struct thread_deferred_req sleeper;
+       struct cache_deferred_req *dreq = &sleeper.handle;
+
+       sleeper.completion = COMPLETION_INITIALIZER_ONSTACK(sleeper.completion);
+       dreq->revisit = cache_restart_thread;
+
+       setup_deferral(dreq, item, 0);
+
+       if (!test_bit(CACHE_PENDING, &item->flags) ||
+           wait_for_completion_interruptible_timeout(
+                   &sleeper.completion, req->thread_wait) <= 0) {
+               /* The completion wasn't completed, so we need
+                * to clean up
+                */
+               spin_lock(&cache_defer_lock);
+               if (!hlist_unhashed(&sleeper.handle.hash)) {
+                       __unhash_deferred_req(&sleeper.handle);
+                       spin_unlock(&cache_defer_lock);
+               } else {
+                       /* cache_revisit_request already removed
+                        * this from the hash table, but hasn't
+                        * called ->revisit yet.  It will very soon
+                        * and we need to wait for it.
+                        */
+                       spin_unlock(&cache_defer_lock);
+                       wait_for_completion(&sleeper.completion);
+               }
+       }
+}
+
+static void cache_limit_defers(void)
+{
+       /* Make sure we haven't exceed the limit of allowed deferred
+        * requests.
+        */
+       struct cache_deferred_req *discard = NULL;
+
+       if (cache_defer_cnt <= DFR_MAX)
+               return;
+
+       spin_lock(&cache_defer_lock);
+
+       /* Consider removing either the first or the last */
+       if (cache_defer_cnt > DFR_MAX) {
+               if (net_random() & 1)
+                       discard = list_entry(cache_defer_list.next,
+                                            struct cache_deferred_req, recent);
+               else
+                       discard = list_entry(cache_defer_list.prev,
+                                            struct cache_deferred_req, recent);
+               __unhash_deferred_req(discard);
+       }
+       spin_unlock(&cache_defer_lock);
        if (discard)
-               /* there was one too many */
                discard->revisit(discard, 1);
+}
 
-       if (!test_bit(CACHE_PENDING, &item->flags)) {
-               /* must have just been validated... */
-               cache_revisit_request(item);
-               return -EAGAIN;
+static void cache_defer_req(struct cache_req *req, struct cache_head *item)
+{
+       struct cache_deferred_req *dreq;
+
+       if (req->thread_wait) {
+               cache_wait_req(req, item);
+               if (!test_bit(CACHE_PENDING, &item->flags))
+                       return;
        }
-       return 0;
+       dreq = req->defer(req);
+       if (dreq == NULL)
+               return;
+       setup_deferral(dreq, item, 1);
+       if (!test_bit(CACHE_PENDING, &item->flags))
+               /* Bit could have been cleared before we managed to
+                * set up the deferral, so need to revisit just in case
+                */
+               cache_revisit_request(item);
+
+       cache_limit_defers();
 }
 
 static void cache_revisit_request(struct cache_head *item)
 {
        struct cache_deferred_req *dreq;
        struct list_head pending;
-
-       struct list_head *lp;
+       struct hlist_node *lp, *tmp;
        int hash = DFR_HASH(item);
 
        INIT_LIST_HEAD(&pending);
        spin_lock(&cache_defer_lock);
 
-       lp = cache_defer_hash[hash].next;
-       if (lp) {
-               while (lp != &cache_defer_hash[hash]) {
-                       dreq = list_entry(lp, struct cache_deferred_req, hash);
-                       lp = lp->next;
-                       if (dreq->item == item) {
-                               list_del_init(&dreq->hash);
-                               list_move(&dreq->recent, &pending);
-                               cache_defer_cnt--;
-                       }
+       hlist_for_each_entry_safe(dreq, lp, tmp, &cache_defer_hash[hash], hash)
+               if (dreq->item == item) {
+                       __unhash_deferred_req(dreq);
+                       list_add(&dreq->recent, &pending);
                }
-       }
+
        spin_unlock(&cache_defer_lock);
 
        while (!list_empty(&pending)) {
@@ -600,9 +676,8 @@ void cache_clean_deferred(void *owner)
 
        list_for_each_entry_safe(dreq, tmp, &cache_defer_list, recent) {
                if (dreq->owner == owner) {
-                       list_del_init(&dreq->hash);
-                       list_move(&dreq->recent, &pending);
-                       cache_defer_cnt--;
+                       __unhash_deferred_req(dreq);
+                       list_add(&dreq->recent, &pending);
                }
        }
        spin_unlock(&cache_defer_lock);
@@ -901,7 +976,7 @@ static int cache_release(struct inode *inode, struct file *filp,
                filp->private_data = NULL;
                kfree(rp);
 
-               cd->last_close = get_seconds();
+               cd->last_close = seconds_since_boot();
                atomic_dec(&cd->readers);
        }
        module_put(cd->owner);
@@ -1014,6 +1089,23 @@ static void warn_no_listener(struct cache_detail *detail)
        }
 }
 
+static bool cache_listeners_exist(struct cache_detail *detail)
+{
+       if (atomic_read(&detail->readers))
+               return true;
+       if (detail->last_close == 0)
+               /* This cache was never opened */
+               return false;
+       if (detail->last_close < seconds_since_boot() - 30)
+               /*
+                * We allow for the possibility that someone might
+                * restart a userspace daemon without restarting the
+                * server; but after 30 seconds, we give up.
+                */
+                return false;
+       return true;
+}
+
 /*
  * register an upcall request to user-space and queue it up for read() by the
  * upcall daemon.
@@ -1032,10 +1124,9 @@ int sunrpc_cache_pipe_upcall(struct cache_detail *detail, struct cache_head *h,
        char *bp;
        int len;
 
-       if (atomic_read(&detail->readers) == 0 &&
-           detail->last_close < get_seconds() - 30) {
-                       warn_no_listener(detail);
-                       return -EINVAL;
+       if (!cache_listeners_exist(detail)) {
+               warn_no_listener(detail);
+               return -EINVAL;
        }
 
        buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -1094,13 +1185,19 @@ int qword_get(char **bpp, char *dest, int bufsize)
        if (bp[0] == '\\' && bp[1] == 'x') {
                /* HEX STRING */
                bp += 2;
-               while (isxdigit(bp[0]) && isxdigit(bp[1]) && len < bufsize) {
-                       int byte = isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
-                       bp++;
-                       byte <<= 4;
-                       byte |= isdigit(*bp) ? *bp-'0' : toupper(*bp)-'A'+10;
-                       *dest++ = byte;
-                       bp++;
+               while (len < bufsize) {
+                       int h, l;
+
+                       h = hex_to_bin(bp[0]);
+                       if (h < 0)
+                               break;
+
+                       l = hex_to_bin(bp[1]);
+                       if (l < 0)
+                               break;
+
+                       *dest++ = (h << 4) | l;
+                       bp += 2;
                        len++;
                }
        } else {
@@ -1218,7 +1315,8 @@ static int c_show(struct seq_file *m, void *p)
 
        ifdebug(CACHE)
                seq_printf(m, "# expiry=%ld refcnt=%d flags=%lx\n",
-                          cp->expiry_time, atomic_read(&cp->ref.refcount), cp->flags);
+                          convert_to_wallclock(cp->expiry_time),
+                          atomic_read(&cp->ref.refcount), cp->flags);
        cache_get(cp);
        if (cache_check(cd, cp, NULL))
                /* cache_check does a cache_put on failure */
@@ -1284,7 +1382,7 @@ static ssize_t read_flush(struct file *file, char __user *buf,
        unsigned long p = *ppos;
        size_t len;
 
-       sprintf(tbuf, "%lu\n", cd->flush_time);
+       sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time));
        len = strlen(tbuf);
        if (p >= len)
                return 0;
@@ -1302,19 +1400,20 @@ static ssize_t write_flush(struct file *file, const char __user *buf,
                           struct cache_detail *cd)
 {
        char tbuf[20];
-       char *ep;
-       long flushtime;
+       char *bp, *ep;
+
        if (*ppos || count > sizeof(tbuf)-1)
                return -EINVAL;
        if (copy_from_user(tbuf, buf, count))
                return -EFAULT;
        tbuf[count] = 0;
-       flushtime = simple_strtoul(tbuf, &ep, 0);
+       simple_strtoul(tbuf, &ep, 0);
        if (*ep && *ep != '\n')
                return -EINVAL;
 
-       cd->flush_time = flushtime;
-       cd->nextcheck = get_seconds();
+       bp = tbuf;
+       cd->flush_time = get_expiry(&bp);
+       cd->nextcheck = seconds_since_boot();
        cache_flush();
 
        *ppos += count;
@@ -1438,8 +1537,10 @@ static const struct file_operations cache_flush_operations_procfs = {
        .llseek         = no_llseek,
 };
 
-static void remove_cache_proc_entries(struct cache_detail *cd)
+static void remove_cache_proc_entries(struct cache_detail *cd, struct net *net)
 {
+       struct sunrpc_net *sn;
+
        if (cd->u.procfs.proc_ent == NULL)
                return;
        if (cd->u.procfs.flush_ent)
@@ -1449,15 +1550,18 @@ static void remove_cache_proc_entries(struct cache_detail *cd)
        if (cd->u.procfs.content_ent)
                remove_proc_entry("content", cd->u.procfs.proc_ent);
        cd->u.procfs.proc_ent = NULL;
-       remove_proc_entry(cd->name, proc_net_rpc);
+       sn = net_generic(net, sunrpc_net_id);
+       remove_proc_entry(cd->name, sn->proc_net_rpc);
 }
 
 #ifdef CONFIG_PROC_FS
-static int create_cache_proc_entries(struct cache_detail *cd)
+static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
 {
        struct proc_dir_entry *p;
+       struct sunrpc_net *sn;
 
-       cd->u.procfs.proc_ent = proc_mkdir(cd->name, proc_net_rpc);
+       sn = net_generic(net, sunrpc_net_id);
+       cd->u.procfs.proc_ent = proc_mkdir(cd->name, sn->proc_net_rpc);
        if (cd->u.procfs.proc_ent == NULL)
                goto out_nomem;
        cd->u.procfs.channel_ent = NULL;
@@ -1488,11 +1592,11 @@ static int create_cache_proc_entries(struct cache_detail *cd)
        }
        return 0;
 out_nomem:
-       remove_cache_proc_entries(cd);
+       remove_cache_proc_entries(cd, net);
        return -ENOMEM;
 }
 #else /* CONFIG_PROC_FS */
-static int create_cache_proc_entries(struct cache_detail *cd)
+static int create_cache_proc_entries(struct cache_detail *cd, struct net *net)
 {
        return 0;
 }
@@ -1503,23 +1607,33 @@ void __init cache_initialize(void)
        INIT_DELAYED_WORK_DEFERRABLE(&cache_cleaner, do_cache_clean);
 }
 
-int cache_register(struct cache_detail *cd)
+int cache_register_net(struct cache_detail *cd, struct net *net)
 {
        int ret;
 
        sunrpc_init_cache_detail(cd);
-       ret = create_cache_proc_entries(cd);
+       ret = create_cache_proc_entries(cd, net);
        if (ret)
                sunrpc_destroy_cache_detail(cd);
        return ret;
 }
+
+int cache_register(struct cache_detail *cd)
+{
+       return cache_register_net(cd, &init_net);
+}
 EXPORT_SYMBOL_GPL(cache_register);
 
-void cache_unregister(struct cache_detail *cd)
+void cache_unregister_net(struct cache_detail *cd, struct net *net)
 {
-       remove_cache_proc_entries(cd);
+       remove_cache_proc_entries(cd, net);
        sunrpc_destroy_cache_detail(cd);
 }
+
+void cache_unregister(struct cache_detail *cd)
+{
+       cache_unregister_net(cd, &init_net);
+}
 EXPORT_SYMBOL_GPL(cache_unregister);
 
 static ssize_t cache_read_pipefs(struct file *filp, char __user *buf,
index fa55490..9dab957 100644 (file)
@@ -284,6 +284,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
        struct rpc_xprt *xprt;
        struct rpc_clnt *clnt;
        struct xprt_create xprtargs = {
+               .net = args->net,
                .ident = args->protocol,
                .srcaddr = args->saddress,
                .dstaddr = args->address,
@@ -1675,7 +1676,7 @@ rpc_verify_header(struct rpc_task *task)
                        rpcauth_invalcred(task);
                        /* Ensure we obtain a new XID! */
                        xprt_release(task);
-                       task->tk_action = call_refresh;
+                       task->tk_action = call_reserve;
                        goto out_retry;
                case RPC_AUTH_BADCRED:
                case RPC_AUTH_BADVERF:
diff --git a/net/sunrpc/netns.h b/net/sunrpc/netns.h
new file mode 100644 (file)
index 0000000..d013bf2
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __SUNRPC_NETNS_H__
+#define __SUNRPC_NETNS_H__
+
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+
+struct cache_detail;
+
+struct sunrpc_net {
+       struct proc_dir_entry *proc_net_rpc;
+       struct cache_detail *ip_map_cache;
+};
+
+extern int sunrpc_net_id;
+
+int ip_map_cache_create(struct net *);
+void ip_map_cache_destroy(struct net *);
+
+#endif
index dac219a..fa6d7ca 100644 (file)
@@ -177,6 +177,7 @@ static DEFINE_MUTEX(rpcb_create_local_mutex);
 static int rpcb_create_local(void)
 {
        struct rpc_create_args args = {
+               .net            = &init_net,
                .protocol       = XPRT_TRANSPORT_TCP,
                .address        = (struct sockaddr *)&rpcb_inaddr_loopback,
                .addrsize       = sizeof(rpcb_inaddr_loopback),
@@ -211,8 +212,9 @@ static int rpcb_create_local(void)
         */
        clnt4 = rpc_bind_new_program(clnt, &rpcb_program, RPCBVERS_4);
        if (IS_ERR(clnt4)) {
-               dprintk("RPC:       failed to create local rpcbind v4 "
-                               "cleint (errno %ld).\n", PTR_ERR(clnt4));
+               dprintk("RPC:       failed to bind second program to "
+                               "rpcbind v4 client (errno %ld).\n",
+                               PTR_ERR(clnt4));
                clnt4 = NULL;
        }
 
@@ -228,6 +230,7 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
                                    size_t salen, int proto, u32 version)
 {
        struct rpc_create_args args = {
+               .net            = &init_net,
                .protocol       = proto,
                .address        = srvaddr,
                .addrsize       = salen,
@@ -247,7 +250,7 @@ static struct rpc_clnt *rpcb_create(char *hostname, struct sockaddr *srvaddr,
                ((struct sockaddr_in6 *)srvaddr)->sin6_port = htons(RPCBIND_PORT);
                break;
        default:
-               return NULL;
+               return ERR_PTR(-EAFNOSUPPORT);
        }
 
        return rpc_create(&args);
@@ -475,57 +478,6 @@ int rpcb_v4_register(const u32 program, const u32 version,
        return -EAFNOSUPPORT;
 }
 
-/**
- * rpcb_getport_sync - obtain the port for an RPC service on a given host
- * @sin: address of remote peer
- * @prog: RPC program number to bind
- * @vers: RPC version number to bind
- * @prot: transport protocol to use to make this request
- *
- * Return value is the requested advertised port number,
- * or a negative errno value.
- *
- * Called from outside the RPC client in a synchronous task context.
- * Uses default timeout parameters specified by underlying transport.
- *
- * XXX: Needs to support IPv6
- */
-int rpcb_getport_sync(struct sockaddr_in *sin, u32 prog, u32 vers, int prot)
-{
-       struct rpcbind_args map = {
-               .r_prog         = prog,
-               .r_vers         = vers,
-               .r_prot         = prot,
-               .r_port         = 0,
-       };
-       struct rpc_message msg = {
-               .rpc_proc       = &rpcb_procedures2[RPCBPROC_GETPORT],
-               .rpc_argp       = &map,
-               .rpc_resp       = &map,
-       };
-       struct rpc_clnt *rpcb_clnt;
-       int status;
-
-       dprintk("RPC:       %s(%pI4, %u, %u, %d)\n",
-               __func__, &sin->sin_addr.s_addr, prog, vers, prot);
-
-       rpcb_clnt = rpcb_create(NULL, (struct sockaddr *)sin,
-                               sizeof(*sin), prot, RPCBVERS_2);
-       if (IS_ERR(rpcb_clnt))
-               return PTR_ERR(rpcb_clnt);
-
-       status = rpc_call_sync(rpcb_clnt, &msg, 0);
-       rpc_shutdown_client(rpcb_clnt);
-
-       if (status >= 0) {
-               if (map.r_port != 0)
-                       return map.r_port;
-               status = -EACCES;
-       }
-       return status;
-}
-EXPORT_SYMBOL_GPL(rpcb_getport_sync);
-
 static struct rpc_task *rpcb_call_async(struct rpc_clnt *rpcb_clnt, struct rpcbind_args *map, struct rpc_procinfo *proc)
 {
        struct rpc_message msg = {
index aa5dbda..243fc09 100644 (file)
@@ -908,7 +908,7 @@ static int rpciod_start(void)
         * Create the rpciod thread and wait for it to start.
         */
        dprintk("RPC:       creating workqueue rpciod\n");
-       wq = create_workqueue("rpciod");
+       wq = alloc_workqueue("rpciod", WQ_RESCUER, 0);
        rpciod_workqueue = wq;
        return rpciod_workqueue != NULL;
 }
index ea1046f..f71a731 100644 (file)
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svcsock.h>
 #include <linux/sunrpc/metrics.h>
-#include <net/net_namespace.h>
 
-#define RPCDBG_FACILITY        RPCDBG_MISC
+#include "netns.h"
 
-struct proc_dir_entry  *proc_net_rpc = NULL;
+#define RPCDBG_FACILITY        RPCDBG_MISC
 
 /*
  * Get RPC client stats
@@ -218,10 +217,11 @@ EXPORT_SYMBOL_GPL(rpc_print_iostats);
 static inline struct proc_dir_entry *
 do_register(const char *name, void *data, const struct file_operations *fops)
 {
-       rpc_proc_init();
-       dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
+       struct sunrpc_net *sn;
 
-       return proc_create_data(name, 0, proc_net_rpc, fops, data);
+       dprintk("RPC:       registering /proc/net/rpc/%s\n", name);
+       sn = net_generic(&init_net, sunrpc_net_id);
+       return proc_create_data(name, 0, sn->proc_net_rpc, fops, data);
 }
 
 struct proc_dir_entry *
@@ -234,7 +234,10 @@ EXPORT_SYMBOL_GPL(rpc_proc_register);
 void
 rpc_proc_unregister(const char *name)
 {
-       remove_proc_entry(name, proc_net_rpc);
+       struct sunrpc_net *sn;
+
+       sn = net_generic(&init_net, sunrpc_net_id);
+       remove_proc_entry(name, sn->proc_net_rpc);
 }
 EXPORT_SYMBOL_GPL(rpc_proc_unregister);
 
@@ -248,25 +251,29 @@ EXPORT_SYMBOL_GPL(svc_proc_register);
 void
 svc_proc_unregister(const char *name)
 {
-       remove_proc_entry(name, proc_net_rpc);
+       struct sunrpc_net *sn;
+
+       sn = net_generic(&init_net, sunrpc_net_id);
+       remove_proc_entry(name, sn->proc_net_rpc);
 }
 EXPORT_SYMBOL_GPL(svc_proc_unregister);
 
-void
-rpc_proc_init(void)
+int rpc_proc_init(struct net *net)
 {
+       struct sunrpc_net *sn;
+
        dprintk("RPC:       registering /proc/net/rpc\n");
-       if (!proc_net_rpc)
-               proc_net_rpc = proc_mkdir("rpc", init_net.proc_net);
+       sn = net_generic(net, sunrpc_net_id);
+       sn->proc_net_rpc = proc_mkdir("rpc", net->proc_net);
+       if (sn->proc_net_rpc == NULL)
+               return -ENOMEM;
+
+       return 0;
 }
 
-void
-rpc_proc_exit(void)
+void rpc_proc_exit(struct net *net)
 {
        dprintk("RPC:       unregistering /proc/net/rpc\n");
-       if (proc_net_rpc) {
-               proc_net_rpc = NULL;
-               remove_proc_entry("rpc", init_net.proc_net);
-       }
+       remove_proc_entry("rpc", net->proc_net);
 }
 
index c0d0850..9d08091 100644 (file)
 #include <linux/sunrpc/rpc_pipe_fs.h>
 #include <linux/sunrpc/xprtsock.h>
 
-extern struct cache_detail ip_map_cache, unix_gid_cache;
+#include "netns.h"
+
+int sunrpc_net_id;
+
+static __net_init int sunrpc_init_net(struct net *net)
+{
+       int err;
+
+       err = rpc_proc_init(net);
+       if (err)
+               goto err_proc;
+
+       err = ip_map_cache_create(net);
+       if (err)
+               goto err_ipmap;
+
+       return 0;
+
+err_ipmap:
+       rpc_proc_exit(net);
+err_proc:
+       return err;
+}
+
+static __net_exit void sunrpc_exit_net(struct net *net)
+{
+       ip_map_cache_destroy(net);
+       rpc_proc_exit(net);
+}
+
+static struct pernet_operations sunrpc_net_ops = {
+       .init = sunrpc_init_net,
+       .exit = sunrpc_exit_net,
+       .id = &sunrpc_net_id,
+       .size = sizeof(struct sunrpc_net),
+};
+
+extern struct cache_detail unix_gid_cache;
 
 extern void cleanup_rpcb_clnt(void);
 
@@ -38,18 +75,22 @@ init_sunrpc(void)
        err = rpcauth_init_module();
        if (err)
                goto out3;
+
+       cache_initialize();
+
+       err = register_pernet_subsys(&sunrpc_net_ops);
+       if (err)
+               goto out4;
 #ifdef RPC_DEBUG
        rpc_register_sysctl();
 #endif
-#ifdef CONFIG_PROC_FS
-       rpc_proc_init();
-#endif
-       cache_initialize();
-       cache_register(&ip_map_cache);
        cache_register(&unix_gid_cache);
        svc_init_xprt_sock();   /* svc sock transport */
        init_socket_xprt();     /* clnt sock transport */
        return 0;
+
+out4:
+       rpcauth_remove_module();
 out3:
        rpc_destroy_mempool();
 out2:
@@ -67,14 +108,11 @@ cleanup_sunrpc(void)
        svc_cleanup_xprt_sock();
        unregister_rpc_pipefs();
        rpc_destroy_mempool();
-       cache_unregister(&ip_map_cache);
        cache_unregister(&unix_gid_cache);
+       unregister_pernet_subsys(&sunrpc_net_ops);
 #ifdef RPC_DEBUG
        rpc_unregister_sysctl();
 #endif
-#ifdef CONFIG_PROC_FS
-       rpc_proc_exit();
-#endif
        rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 MODULE_LICENSE("GPL");
index d9017d6..6359c42 100644 (file)
@@ -1055,6 +1055,9 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv)
                goto err_bad;
        case SVC_DENIED:
                goto err_bad_auth;
+       case SVC_CLOSE:
+               if (test_bit(XPT_TEMP, &rqstp->rq_xprt->xpt_flags))
+                       svc_close_xprt(rqstp->rq_xprt);
        case SVC_DROP:
                goto dropit;
        case SVC_COMPLETE:
index cbc0849..c82fe73 100644 (file)
@@ -100,16 +100,14 @@ EXPORT_SYMBOL_GPL(svc_unreg_xprt_class);
  */
 int svc_print_xprts(char *buf, int maxlen)
 {
-       struct list_head *le;
+       struct svc_xprt_class *xcl;
        char tmpstr[80];
        int len = 0;
        buf[0] = '\0';
 
        spin_lock(&svc_xprt_class_lock);
-       list_for_each(le, &svc_xprt_class_list) {
+       list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
                int slen;
-               struct svc_xprt_class *xcl =
-                       list_entry(le, struct svc_xprt_class, xcl_list);
 
                sprintf(tmpstr, "%s %d\n", xcl->xcl_name, xcl->xcl_max_payload);
                slen = strlen(tmpstr);
@@ -128,9 +126,9 @@ static void svc_xprt_free(struct kref *kref)
        struct svc_xprt *xprt =
                container_of(kref, struct svc_xprt, xpt_ref);
        struct module *owner = xprt->xpt_class->xcl_owner;
-       if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags) &&
-           xprt->xpt_auth_cache != NULL)
-               svcauth_unix_info_release(xprt->xpt_auth_cache);
+       if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags))
+               svcauth_unix_info_release(xprt);
+       put_net(xprt->xpt_net);
        xprt->xpt_ops->xpo_free(xprt);
        module_put(owner);
 }
@@ -156,15 +154,18 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
        INIT_LIST_HEAD(&xprt->xpt_list);
        INIT_LIST_HEAD(&xprt->xpt_ready);
        INIT_LIST_HEAD(&xprt->xpt_deferred);
+       INIT_LIST_HEAD(&xprt->xpt_users);
        mutex_init(&xprt->xpt_mutex);
        spin_lock_init(&xprt->xpt_lock);
        set_bit(XPT_BUSY, &xprt->xpt_flags);
        rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending");
+       xprt->xpt_net = get_net(&init_net);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_init);
 
 static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
                                         struct svc_serv *serv,
+                                        struct net *net,
                                         const int family,
                                         const unsigned short port,
                                         int flags)
@@ -199,12 +200,12 @@ static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
                return ERR_PTR(-EAFNOSUPPORT);
        }
 
-       return xcl->xcl_ops->xpo_create(serv, sap, len, flags);
+       return xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
 }
 
 int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
-                   const int family, const unsigned short port,
-                   int flags)
+                   struct net *net, const int family,
+                   const unsigned short port, int flags)
 {
        struct svc_xprt_class *xcl;
 
@@ -220,7 +221,7 @@ int svc_create_xprt(struct svc_serv *serv, const char *xprt_name,
                        goto err;
 
                spin_unlock(&svc_xprt_class_lock);
-               newxprt = __svc_xpo_create(xcl, serv, family, port, flags);
+               newxprt = __svc_xpo_create(xcl, serv, net, family, port, flags);
                if (IS_ERR(newxprt)) {
                        module_put(xcl->xcl_owner);
                        return PTR_ERR(newxprt);
@@ -329,12 +330,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
                       "svc_xprt_enqueue: "
                       "threads and transports both waiting??\n");
 
-       if (test_bit(XPT_DEAD, &xprt->xpt_flags)) {
-               /* Don't enqueue dead transports */
-               dprintk("svc: transport %p is dead, not enqueued\n", xprt);
-               goto out_unlock;
-       }
-
        pool->sp_stats.packets++;
 
        /* Mark transport as busy. It will remain in this state until
@@ -651,6 +646,11 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
        if (signalled() || kthread_should_stop())
                return -EINTR;
 
+       /* Normally we will wait up to 5 seconds for any required
+        * cache information to be provided.
+        */
+       rqstp->rq_chandle.thread_wait = 5*HZ;
+
        spin_lock_bh(&pool->sp_lock);
        xprt = svc_xprt_dequeue(pool);
        if (xprt) {
@@ -658,6 +658,12 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                svc_xprt_get(xprt);
                rqstp->rq_reserved = serv->sv_max_mesg;
                atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
+
+               /* As there is a shortage of threads and this request
+                * had to be queued, don't allow the thread to wait so
+                * long for cache updates.
+                */
+               rqstp->rq_chandle.thread_wait = 1*HZ;
        } else {
                /* No data pending. Go to sleep */
                svc_thread_enqueue(pool, rqstp);
@@ -868,6 +874,19 @@ static void svc_age_temp_xprts(unsigned long closure)
        mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ);
 }
 
+static void call_xpt_users(struct svc_xprt *xprt)
+{
+       struct svc_xpt_user *u;
+
+       spin_lock(&xprt->xpt_lock);
+       while (!list_empty(&xprt->xpt_users)) {
+               u = list_first_entry(&xprt->xpt_users, struct svc_xpt_user, list);
+               list_del(&u->list);
+               u->callback(u);
+       }
+       spin_unlock(&xprt->xpt_lock);
+}
+
 /*
  * Remove a dead transport
  */
@@ -878,7 +897,7 @@ void svc_delete_xprt(struct svc_xprt *xprt)
 
        /* Only do this once */
        if (test_and_set_bit(XPT_DEAD, &xprt->xpt_flags))
-               return;
+               BUG();
 
        dprintk("svc: svc_delete_xprt(%p)\n", xprt);
        xprt->xpt_ops->xpo_detach(xprt);
@@ -900,6 +919,7 @@ void svc_delete_xprt(struct svc_xprt *xprt)
        while ((dr = svc_deferred_dequeue(xprt)) != NULL)
                kfree(dr);
 
+       call_xpt_users(xprt);
        svc_xprt_put(xprt);
 }
 
@@ -910,10 +930,7 @@ void svc_close_xprt(struct svc_xprt *xprt)
                /* someone else will have to effect the close */
                return;
 
-       svc_xprt_get(xprt);
        svc_delete_xprt(xprt);
-       clear_bit(XPT_BUSY, &xprt->xpt_flags);
-       svc_xprt_put(xprt);
 }
 EXPORT_SYMBOL_GPL(svc_close_xprt);
 
index 2073116..560677d 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <linux/sunrpc/clnt.h>
 
+#include "netns.h"
+
 /*
  * AUTHUNIX and AUTHNULL credentials are both handled here.
  * AUTHNULL is treated just like AUTHUNIX except that the uid/gid
@@ -92,7 +94,6 @@ struct ip_map {
        struct unix_domain      *m_client;
        int                     m_add_change;
 };
-static struct cache_head       *ip_table[IP_HASHMAX];
 
 static void ip_map_put(struct kref *kref)
 {
@@ -178,8 +179,8 @@ static int ip_map_upcall(struct cache_detail *cd, struct cache_head *h)
        return sunrpc_cache_pipe_upcall(cd, h, ip_map_request);
 }
 
-static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr);
-static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
+static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class, struct in6_addr *addr);
+static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm, struct unix_domain *udom, time_t expiry);
 
 static int ip_map_parse(struct cache_detail *cd,
                          char *mesg, int mlen)
@@ -219,10 +220,9 @@ static int ip_map_parse(struct cache_detail *cd,
        switch (address.sa.sa_family) {
        case AF_INET:
                /* Form a mapped IPv4 address in sin6 */
-               memset(&sin6, 0, sizeof(sin6));
                sin6.sin6_family = AF_INET6;
-               sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
-               sin6.sin6_addr.s6_addr32[3] = address.s4.sin_addr.s_addr;
+               ipv6_addr_set_v4mapped(address.s4.sin_addr.s_addr,
+                               &sin6.sin6_addr);
                break;
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case AF_INET6:
@@ -249,9 +249,9 @@ static int ip_map_parse(struct cache_detail *cd,
                dom = NULL;
 
        /* IPv6 scope IDs are ignored for now */
-       ipmp = ip_map_lookup(class, &sin6.sin6_addr);
+       ipmp = __ip_map_lookup(cd, class, &sin6.sin6_addr);
        if (ipmp) {
-               err = ip_map_update(ipmp,
+               err = __ip_map_update(cd, ipmp,
                             container_of(dom, struct unix_domain, h),
                             expiry);
        } else
@@ -294,29 +294,15 @@ static int ip_map_show(struct seq_file *m,
 }
 
 
-struct cache_detail ip_map_cache = {
-       .owner          = THIS_MODULE,
-       .hash_size      = IP_HASHMAX,
-       .hash_table     = ip_table,
-       .name           = "auth.unix.ip",
-       .cache_put      = ip_map_put,
-       .cache_upcall   = ip_map_upcall,
-       .cache_parse    = ip_map_parse,
-       .cache_show     = ip_map_show,
-       .match          = ip_map_match,
-       .init           = ip_map_init,
-       .update         = update,
-       .alloc          = ip_map_alloc,
-};
-
-static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
+static struct ip_map *__ip_map_lookup(struct cache_detail *cd, char *class,
+               struct in6_addr *addr)
 {
        struct ip_map ip;
        struct cache_head *ch;
 
        strcpy(ip.m_class, class);
        ipv6_addr_copy(&ip.m_addr, addr);
-       ch = sunrpc_cache_lookup(&ip_map_cache, &ip.h,
+       ch = sunrpc_cache_lookup(cd, &ip.h,
                                 hash_str(class, IP_HASHBITS) ^
                                 hash_ip6(*addr));
 
@@ -326,7 +312,17 @@ static struct ip_map *ip_map_lookup(char *class, struct in6_addr *addr)
                return NULL;
 }
 
-static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t expiry)
+static inline struct ip_map *ip_map_lookup(struct net *net, char *class,
+               struct in6_addr *addr)
+{
+       struct sunrpc_net *sn;
+
+       sn = net_generic(net, sunrpc_net_id);
+       return __ip_map_lookup(sn->ip_map_cache, class, addr);
+}
+
+static int __ip_map_update(struct cache_detail *cd, struct ip_map *ipm,
+               struct unix_domain *udom, time_t expiry)
 {
        struct ip_map ip;
        struct cache_head *ch;
@@ -344,17 +340,25 @@ static int ip_map_update(struct ip_map *ipm, struct unix_domain *udom, time_t ex
                        ip.m_add_change++;
        }
        ip.h.expiry_time = expiry;
-       ch = sunrpc_cache_update(&ip_map_cache,
-                                &ip.h, &ipm->h,
+       ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
                                 hash_str(ipm->m_class, IP_HASHBITS) ^
                                 hash_ip6(ipm->m_addr));
        if (!ch)
                return -ENOMEM;
-       cache_put(ch, &ip_map_cache);
+       cache_put(ch, cd);
        return 0;
 }
 
-int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
+static inline int ip_map_update(struct net *net, struct ip_map *ipm,
+               struct unix_domain *udom, time_t expiry)
+{
+       struct sunrpc_net *sn;
+
+       sn = net_generic(net, sunrpc_net_id);
+       return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry);
+}
+
+int auth_unix_add_addr(struct net *net, struct in6_addr *addr, struct auth_domain *dom)
 {
        struct unix_domain *udom;
        struct ip_map *ipmp;
@@ -362,10 +366,10 @@ int auth_unix_add_addr(struct in6_addr *addr, struct auth_domain *dom)
        if (dom->flavour != &svcauth_unix)
                return -EINVAL;
        udom = container_of(dom, struct unix_domain, h);
-       ipmp = ip_map_lookup("nfsd", addr);
+       ipmp = ip_map_lookup(net, "nfsd", addr);
 
        if (ipmp)
-               return ip_map_update(ipmp, udom, NEVER);
+               return ip_map_update(net, ipmp, udom, NEVER);
        else
                return -ENOMEM;
 }
@@ -383,16 +387,18 @@ int auth_unix_forget_old(struct auth_domain *dom)
 }
 EXPORT_SYMBOL_GPL(auth_unix_forget_old);
 
-struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
+struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
 {
        struct ip_map *ipm;
        struct auth_domain *rv;
+       struct sunrpc_net *sn;
 
-       ipm = ip_map_lookup("nfsd", addr);
+       sn = net_generic(net, sunrpc_net_id);
+       ipm = ip_map_lookup(net, "nfsd", addr);
 
        if (!ipm)
                return NULL;
-       if (cache_check(&ip_map_cache, &ipm->h, NULL))
+       if (cache_check(sn->ip_map_cache, &ipm->h, NULL))
                return NULL;
 
        if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
@@ -403,22 +409,29 @@ struct auth_domain *auth_unix_lookup(struct in6_addr *addr)
                rv = &ipm->m_client->h;
                kref_get(&rv->ref);
        }
-       cache_put(&ipm->h, &ip_map_cache);
+       cache_put(&ipm->h, sn->ip_map_cache);
        return rv;
 }
 EXPORT_SYMBOL_GPL(auth_unix_lookup);
 
 void svcauth_unix_purge(void)
 {
-       cache_purge(&ip_map_cache);
+       struct net *net;
+
+       for_each_net(net) {
+               struct sunrpc_net *sn;
+
+               sn = net_generic(net, sunrpc_net_id);
+               cache_purge(sn->ip_map_cache);
+       }
 }
 EXPORT_SYMBOL_GPL(svcauth_unix_purge);
 
 static inline struct ip_map *
-ip_map_cached_get(struct svc_rqst *rqstp)
+ip_map_cached_get(struct svc_xprt *xprt)
 {
        struct ip_map *ipm = NULL;
-       struct svc_xprt *xprt = rqstp->rq_xprt;
+       struct sunrpc_net *sn;
 
        if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
                spin_lock(&xprt->xpt_lock);
@@ -430,9 +443,10 @@ ip_map_cached_get(struct svc_rqst *rqstp)
                                 * remembered, e.g. by a second mount from the
                                 * same IP address.
                                 */
+                               sn = net_generic(xprt->xpt_net, sunrpc_net_id);
                                xprt->xpt_auth_cache = NULL;
                                spin_unlock(&xprt->xpt_lock);
-                               cache_put(&ipm->h, &ip_map_cache);
+                               cache_put(&ipm->h, sn->ip_map_cache);
                                return NULL;
                        }
                        cache_get(&ipm->h);
@@ -443,10 +457,8 @@ ip_map_cached_get(struct svc_rqst *rqstp)
 }
 
 static inline void
-ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm)
+ip_map_cached_put(struct svc_xprt *xprt, struct ip_map *ipm)
 {
-       struct svc_xprt *xprt = rqstp->rq_xprt;
-
        if (test_bit(XPT_CACHE_AUTH, &xprt->xpt_flags)) {
                spin_lock(&xprt->xpt_lock);
                if (xprt->xpt_auth_cache == NULL) {
@@ -456,15 +468,26 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm)
                }
                spin_unlock(&xprt->xpt_lock);
        }
-       if (ipm)
-               cache_put(&ipm->h, &ip_map_cache);
+       if (ipm) {
+               struct sunrpc_net *sn;
+
+               sn = net_generic(xprt->xpt_net, sunrpc_net_id);
+               cache_put(&ipm->h, sn->ip_map_cache);
+       }
 }
 
 void
-svcauth_unix_info_release(void *info)
+svcauth_unix_info_release(struct svc_xprt *xpt)
 {
-       struct ip_map *ipm = info;
-       cache_put(&ipm->h, &ip_map_cache);
+       struct ip_map *ipm;
+
+       ipm = xpt->xpt_auth_cache;
+       if (ipm != NULL) {
+               struct sunrpc_net *sn;
+
+               sn = net_generic(xpt->xpt_net, sunrpc_net_id);
+               cache_put(&ipm->h, sn->ip_map_cache);
+       }
 }
 
 /****************************************************************************
@@ -674,6 +697,8 @@ static struct group_info *unix_gid_find(uid_t uid, struct svc_rqst *rqstp)
        switch (ret) {
        case -ENOENT:
                return ERR_PTR(-ENOENT);
+       case -ETIMEDOUT:
+               return ERR_PTR(-ESHUTDOWN);
        case 0:
                gi = get_group_info(ug->gi);
                cache_put(&ug->h, &unix_gid_cache);
@@ -691,6 +716,9 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
        struct ip_map *ipm;
        struct group_info *gi;
        struct svc_cred *cred = &rqstp->rq_cred;
+       struct svc_xprt *xprt = rqstp->rq_xprt;
+       struct net *net = xprt->xpt_net;
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
 
        switch (rqstp->rq_addr.ss_family) {
        case AF_INET:
@@ -709,26 +737,27 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
        if (rqstp->rq_proc == 0)
                return SVC_OK;
 
-       ipm = ip_map_cached_get(rqstp);
+       ipm = ip_map_cached_get(xprt);
        if (ipm == NULL)
-               ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class,
+               ipm = __ip_map_lookup(sn->ip_map_cache, rqstp->rq_server->sv_program->pg_class,
                                    &sin6->sin6_addr);
 
        if (ipm == NULL)
                return SVC_DENIED;
 
-       switch (cache_check(&ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
+       switch (cache_check(sn->ip_map_cache, &ipm->h, &rqstp->rq_chandle)) {
                default:
                        BUG();
-               case -EAGAIN:
                case -ETIMEDOUT:
+                       return SVC_CLOSE;
+               case -EAGAIN:
                        return SVC_DROP;
                case -ENOENT:
                        return SVC_DENIED;
                case 0:
                        rqstp->rq_client = &ipm->m_client->h;
                        kref_get(&rqstp->rq_client->ref);
-                       ip_map_cached_put(rqstp, ipm);
+                       ip_map_cached_put(xprt, ipm);
                        break;
        }
 
@@ -736,6 +765,8 @@ svcauth_unix_set_client(struct svc_rqst *rqstp)
        switch (PTR_ERR(gi)) {
        case -EAGAIN:
                return SVC_DROP;
+       case -ESHUTDOWN:
+               return SVC_CLOSE;
        case -ENOENT:
                break;
        default:
@@ -776,7 +807,7 @@ svcauth_null_accept(struct svc_rqst *rqstp, __be32 *authp)
        cred->cr_gid = (gid_t) -1;
        cred->cr_group_info = groups_alloc(0);
        if (cred->cr_group_info == NULL)
-               return SVC_DROP; /* kmalloc failure - client must retry */
+               return SVC_CLOSE; /* kmalloc failure - client must retry */
 
        /* Put NULL verifier */
        svc_putnl(resv, RPC_AUTH_NULL);
@@ -840,7 +871,7 @@ svcauth_unix_accept(struct svc_rqst *rqstp, __be32 *authp)
                goto badcred;
        cred->cr_group_info = groups_alloc(slen);
        if (cred->cr_group_info == NULL)
-               return SVC_DROP;
+               return SVC_CLOSE;
        for (i = 0; i < slen; i++)
                GROUP_AT(cred->cr_group_info, i) = svc_getnl(argv);
        if (svc_getu32(argv) != htonl(RPC_AUTH_NULL) || svc_getu32(argv) != 0) {
@@ -886,3 +917,56 @@ struct auth_ops svcauth_unix = {
        .set_client     = svcauth_unix_set_client,
 };
 
+int ip_map_cache_create(struct net *net)
+{
+       int err = -ENOMEM;
+       struct cache_detail *cd;
+       struct cache_head **tbl;
+       struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
+
+       cd = kzalloc(sizeof(struct cache_detail), GFP_KERNEL);
+       if (cd == NULL)
+               goto err_cd;
+
+       tbl = kzalloc(IP_HASHMAX * sizeof(struct cache_head *), GFP_KERNEL);
+       if (tbl == NULL)
+               goto err_tbl;
+
+       cd->owner = THIS_MODULE,
+       cd->hash_size = IP_HASHMAX,
+       cd->hash_table = tbl,
+       cd->name = "auth.unix.ip",
+       cd->cache_put = ip_map_put,
+       cd->cache_upcall = ip_map_upcall,
+       cd->cache_parse = ip_map_parse,
+       cd->cache_show = ip_map_show,
+       cd->match = ip_map_match,
+       cd->init = ip_map_init,
+       cd->update = update,
+       cd->alloc = ip_map_alloc,
+
+       err = cache_register_net(cd, net);
+       if (err)
+               goto err_reg;
+
+       sn->ip_map_cache = cd;
+       return 0;
+
+err_reg:
+       kfree(tbl);
+err_tbl:
+       kfree(cd);
+err_cd:
+       return err;
+}
+
+void ip_map_cache_destroy(struct net *net)
+{
+       struct sunrpc_net *sn;
+
+       sn = net_generic(net, sunrpc_net_id);
+       cache_purge(sn->ip_map_cache);
+       cache_unregister_net(sn->ip_map_cache, net);
+       kfree(sn->ip_map_cache->hash_table);
+       kfree(sn->ip_map_cache);
+}
index 7e534dd..07919e1 100644 (file)
@@ -64,7 +64,8 @@ static void           svc_tcp_sock_detach(struct svc_xprt *);
 static void            svc_sock_free(struct svc_xprt *);
 
 static struct svc_xprt *svc_create_socket(struct svc_serv *, int,
-                                         struct sockaddr *, int, int);
+                                         struct net *, struct sockaddr *,
+                                         int, int);
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key svc_key[2];
 static struct lock_class_key svc_slock_key[2];
@@ -657,10 +658,11 @@ static struct svc_xprt *svc_udp_accept(struct svc_xprt *xprt)
 }
 
 static struct svc_xprt *svc_udp_create(struct svc_serv *serv,
+                                      struct net *net,
                                       struct sockaddr *sa, int salen,
                                       int flags)
 {
-       return svc_create_socket(serv, IPPROTO_UDP, sa, salen, flags);
+       return svc_create_socket(serv, IPPROTO_UDP, net, sa, salen, flags);
 }
 
 static struct svc_xprt_ops svc_udp_ops = {
@@ -1133,9 +1135,6 @@ static int svc_tcp_sendto(struct svc_rqst *rqstp)
        reclen = htonl(0x80000000|((xbufp->len ) - 4));
        memcpy(xbufp->head[0].iov_base, &reclen, 4);
 
-       if (test_bit(XPT_DEAD, &rqstp->rq_xprt->xpt_flags))
-               return -ENOTCONN;
-
        sent = svc_sendto(rqstp, &rqstp->rq_res);
        if (sent != xbufp->len) {
                printk(KERN_NOTICE
@@ -1178,10 +1177,11 @@ static int svc_tcp_has_wspace(struct svc_xprt *xprt)
 }
 
 static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
+                                      struct net *net,
                                       struct sockaddr *sa, int salen,
                                       int flags)
 {
-       return svc_create_socket(serv, IPPROTO_TCP, sa, salen, flags);
+       return svc_create_socket(serv, IPPROTO_TCP, net, sa, salen, flags);
 }
 
 static struct svc_xprt_ops svc_tcp_ops = {
@@ -1258,19 +1258,13 @@ void svc_sock_update_bufs(struct svc_serv *serv)
         * The number of server threads has changed. Update
         * rcvbuf and sndbuf accordingly on all sockets
         */
-       struct list_head *le;
+       struct svc_sock *svsk;
 
        spin_lock_bh(&serv->sv_lock);
-       list_for_each(le, &serv->sv_permsocks) {
-               struct svc_sock *svsk =
-                       list_entry(le, struct svc_sock, sk_xprt.xpt_list);
+       list_for_each_entry(svsk, &serv->sv_permsocks, sk_xprt.xpt_list)
                set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
-       }
-       list_for_each(le, &serv->sv_tempsocks) {
-               struct svc_sock *svsk =
-                       list_entry(le, struct svc_sock, sk_xprt.xpt_list);
+       list_for_each_entry(svsk, &serv->sv_tempsocks, sk_xprt.xpt_list)
                set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags);
-       }
        spin_unlock_bh(&serv->sv_lock);
 }
 EXPORT_SYMBOL_GPL(svc_sock_update_bufs);
@@ -1385,6 +1379,7 @@ EXPORT_SYMBOL_GPL(svc_addsock);
  */
 static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
                                          int protocol,
+                                         struct net *net,
                                          struct sockaddr *sin, int len,
                                          int flags)
 {
@@ -1421,7 +1416,7 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
                return ERR_PTR(-EINVAL);
        }
 
-       error = sock_create_kern(family, type, protocol, &sock);
+       error = __sock_create(net, family, type, protocol, &sock, 1);
        if (error < 0)
                return ERR_PTR(error);
 
index a1f82a8..cd9e841 100644 (file)
@@ -111,6 +111,23 @@ xdr_decode_string_inplace(__be32 *p, char **sp,
 }
 EXPORT_SYMBOL_GPL(xdr_decode_string_inplace);
 
+/**
+ * xdr_terminate_string - '\0'-terminate a string residing in an xdr_buf
+ * @buf: XDR buffer where string resides
+ * @len: length of string, in bytes
+ *
+ */
+void
+xdr_terminate_string(struct xdr_buf *buf, const u32 len)
+{
+       char *kaddr;
+
+       kaddr = kmap_atomic(buf->pages[0], KM_USER0);
+       kaddr[buf->page_base + len] = '\0';
+       kunmap_atomic(kaddr, KM_USER0);
+}
+EXPORT_SYMBOL(xdr_terminate_string);
+
 void
 xdr_encode_pages(struct xdr_buf *xdr, struct page **pages, unsigned int base,
                 unsigned int len)
@@ -395,24 +412,29 @@ xdr_shrink_pagelen(struct xdr_buf *buf, size_t len)
 {
        struct kvec *tail;
        size_t copy;
-       char *p;
        unsigned int pglen = buf->page_len;
+       unsigned int tailbuf_len;
 
        tail = buf->tail;
        BUG_ON (len > pglen);
 
+       tailbuf_len = buf->buflen - buf->head->iov_len - buf->page_len;
+
        /* Shift the tail first */
-       if (tail->iov_len != 0) {
-               p = (char *)tail->iov_base + len;
+       if (tailbuf_len != 0) {
+               unsigned int free_space = tailbuf_len - tail->iov_len;
+
+               if (len < free_space)
+                       free_space = len;
+               tail->iov_len += free_space;
+
+               copy = len;
                if (tail->iov_len > len) {
-                       copy = tail->iov_len - len;
-                       memmove(p, tail->iov_base, copy);
+                       char *p = (char *)tail->iov_base + len;
+                       memmove(p, tail->iov_base, tail->iov_len - len);
                } else
-                       buf->buflen -= len;
-               /* Copy from the inlined pages into the tail */
-               copy = len;
-               if (copy > tail->iov_len)
                        copy = tail->iov_len;
+               /* Copy from the inlined pages into the tail */
                _copy_from_pages((char *)tail->iov_base,
                                buf->pages, buf->page_base + pglen - len,
                                copy);
@@ -551,6 +573,27 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
 EXPORT_SYMBOL_GPL(xdr_init_decode);
 
 /**
+ * xdr_inline_peek - Allow read-ahead in the XDR data stream
+ * @xdr: pointer to xdr_stream struct
+ * @nbytes: number of bytes of data to decode
+ *
+ * Check if the input buffer is long enough to enable us to decode
+ * 'nbytes' more bytes of data starting at the current position.
+ * If so return the current pointer without updating the current
+ * pointer position.
+ */
+__be32 * xdr_inline_peek(struct xdr_stream *xdr, size_t nbytes)
+{
+       __be32 *p = xdr->p;
+       __be32 *q = p + XDR_QUADLEN(nbytes);
+
+       if (unlikely(q > xdr->end || q < p))
+               return NULL;
+       return p;
+}
+EXPORT_SYMBOL_GPL(xdr_inline_peek);
+
+/**
  * xdr_inline_decode - Retrieve non-page XDR data to decode
  * @xdr: pointer to xdr_stream struct
  * @nbytes: number of bytes of data to decode
index 970fb00..4c8f18a 100644 (file)
@@ -199,8 +199,6 @@ int xprt_reserve_xprt(struct rpc_task *task)
        if (test_and_set_bit(XPRT_LOCKED, &xprt->state)) {
                if (task == xprt->snd_task)
                        return 1;
-               if (task == NULL)
-                       return 0;
                goto out_sleep;
        }
        xprt->snd_task = task;
@@ -757,13 +755,11 @@ static void xprt_connect_status(struct rpc_task *task)
  */
 struct rpc_rqst *xprt_lookup_rqst(struct rpc_xprt *xprt, __be32 xid)
 {
-       struct list_head *pos;
+       struct rpc_rqst *entry;
 
-       list_for_each(pos, &xprt->recv) {
-               struct rpc_rqst *entry = list_entry(pos, struct rpc_rqst, rq_list);
+       list_for_each_entry(entry, &xprt->recv, rq_list)
                if (entry->rq_xid == xid)
                        return entry;
-       }
 
        dprintk("RPC:       xprt_lookup_rqst did not find xid %08x\n",
                        ntohl(xid));
@@ -962,6 +958,37 @@ static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
        spin_unlock(&xprt->reserve_lock);
 }
 
+struct rpc_xprt *xprt_alloc(struct net *net, int size, int max_req)
+{
+       struct rpc_xprt *xprt;
+
+       xprt = kzalloc(size, GFP_KERNEL);
+       if (xprt == NULL)
+               goto out;
+
+       xprt->max_reqs = max_req;
+       xprt->slot = kcalloc(max_req, sizeof(struct rpc_rqst), GFP_KERNEL);
+       if (xprt->slot == NULL)
+               goto out_free;
+
+       xprt->xprt_net = get_net(net);
+       return xprt;
+
+out_free:
+       kfree(xprt);
+out:
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(xprt_alloc);
+
+void xprt_free(struct rpc_xprt *xprt)
+{
+       put_net(xprt->xprt_net);
+       kfree(xprt->slot);
+       kfree(xprt);
+}
+EXPORT_SYMBOL_GPL(xprt_free);
+
 /**
  * xprt_reserve - allocate an RPC request slot
  * @task: RPC task requesting a slot allocation
index d718b8f..09af4fa 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/sysctl.h>
+#include <linux/workqueue.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/sched.h>
 #include <linux/sunrpc/svc_rdma.h>
@@ -74,6 +75,8 @@ atomic_t rdma_stat_sq_prod;
 struct kmem_cache *svc_rdma_map_cachep;
 struct kmem_cache *svc_rdma_ctxt_cachep;
 
+struct workqueue_struct *svc_rdma_wq;
+
 /*
  * This function implements reading and resetting an atomic_t stat
  * variable through read/write to a proc file. Any write to the file
@@ -231,7 +234,7 @@ static ctl_table svcrdma_root_table[] = {
 void svc_rdma_cleanup(void)
 {
        dprintk("SVCRDMA Module Removed, deregister RPC RDMA transport\n");
-       flush_scheduled_work();
+       destroy_workqueue(svc_rdma_wq);
        if (svcrdma_table_header) {
                unregister_sysctl_table(svcrdma_table_header);
                svcrdma_table_header = NULL;
@@ -249,6 +252,11 @@ int svc_rdma_init(void)
        dprintk("\tsq_depth         : %d\n",
                svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT);
        dprintk("\tmax_inline       : %d\n", svcrdma_max_req_size);
+
+       svc_rdma_wq = alloc_workqueue("svc_rdma", 0, 0);
+       if (!svc_rdma_wq)
+               return -ENOMEM;
+
        if (!svcrdma_table_header)
                svcrdma_table_header =
                        register_sysctl_table(svcrdma_root_table);
@@ -283,6 +291,7 @@ int svc_rdma_init(void)
        kmem_cache_destroy(svc_rdma_map_cachep);
  err0:
        unregister_sysctl_table(svcrdma_table_header);
+       destroy_workqueue(svc_rdma_wq);
        return -ENOMEM;
 }
 MODULE_AUTHOR("Tom Tucker <tom@opengridcomputing.com>");
index 0194de8..df67211 100644 (file)
@@ -263,9 +263,9 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt,
        frmr->page_list_len = PAGE_ALIGN(byte_count) >> PAGE_SHIFT;
        for (page_no = 0; page_no < frmr->page_list_len; page_no++) {
                frmr->page_list->page_list[page_no] =
-                       ib_dma_map_single(xprt->sc_cm_id->device,
-                                         page_address(rqstp->rq_arg.pages[page_no]),
-                                         PAGE_SIZE, DMA_FROM_DEVICE);
+                       ib_dma_map_page(xprt->sc_cm_id->device,
+                                       rqstp->rq_arg.pages[page_no], 0,
+                                       PAGE_SIZE, DMA_FROM_DEVICE);
                if (ib_dma_mapping_error(xprt->sc_cm_id->device,
                                         frmr->page_list->page_list[page_no]))
                        goto fatal_err;
@@ -309,17 +309,21 @@ static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt,
                             int count)
 {
        int i;
+       unsigned long off;
 
        ctxt->count = count;
        ctxt->direction = DMA_FROM_DEVICE;
        for (i = 0; i < count; i++) {
                ctxt->sge[i].length = 0; /* in case map fails */
                if (!frmr) {
+                       BUG_ON(0 == virt_to_page(vec[i].iov_base));
+                       off = (unsigned long)vec[i].iov_base & ~PAGE_MASK;
                        ctxt->sge[i].addr =
-                               ib_dma_map_single(xprt->sc_cm_id->device,
-                                                 vec[i].iov_base,
-                                                 vec[i].iov_len,
-                                                 DMA_FROM_DEVICE);
+                               ib_dma_map_page(xprt->sc_cm_id->device,
+                                               virt_to_page(vec[i].iov_base),
+                                               off,
+                                               vec[i].iov_len,
+                                               DMA_FROM_DEVICE);
                        if (ib_dma_mapping_error(xprt->sc_cm_id->device,
                                                 ctxt->sge[i].addr))
                                return -EINVAL;
@@ -491,6 +495,7 @@ next_sge:
                        printk(KERN_ERR "svcrdma: Error %d posting RDMA_READ\n",
                               err);
                        set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
+                       svc_rdma_unmap_dma(ctxt);
                        svc_rdma_put_context(ctxt, 0);
                        goto out;
                }
index b15e1eb..249a835 100644 (file)
@@ -70,8 +70,8 @@
  * on extra page for the RPCRMDA header.
  */
 static int fast_reg_xdr(struct svcxprt_rdma *xprt,
-                struct xdr_buf *xdr,
-                struct svc_rdma_req_map *vec)
+                       struct xdr_buf *xdr,
+                       struct svc_rdma_req_map *vec)
 {
        int sge_no;
        u32 sge_bytes;
@@ -96,21 +96,25 @@ static int fast_reg_xdr(struct svcxprt_rdma *xprt,
        vec->count = 2;
        sge_no++;
 
-       /* Build the FRMR */
+       /* Map the XDR head */
        frmr->kva = frva;
        frmr->direction = DMA_TO_DEVICE;
        frmr->access_flags = 0;
        frmr->map_len = PAGE_SIZE;
        frmr->page_list_len = 1;
+       page_off = (unsigned long)xdr->head[0].iov_base & ~PAGE_MASK;
        frmr->page_list->page_list[page_no] =
-               ib_dma_map_single(xprt->sc_cm_id->device,
-                                 (void *)xdr->head[0].iov_base,
-                                 PAGE_SIZE, DMA_TO_DEVICE);
+               ib_dma_map_page(xprt->sc_cm_id->device,
+                               virt_to_page(xdr->head[0].iov_base),
+                               page_off,
+                               PAGE_SIZE - page_off,
+                               DMA_TO_DEVICE);
        if (ib_dma_mapping_error(xprt->sc_cm_id->device,
                                 frmr->page_list->page_list[page_no]))
                goto fatal_err;
        atomic_inc(&xprt->sc_dma_used);
 
+       /* Map the XDR page list */
        page_off = xdr->page_base;
        page_bytes = xdr->page_len + page_off;
        if (!page_bytes)
@@ -128,9 +132,9 @@ static int fast_reg_xdr(struct svcxprt_rdma *xprt,
                page_bytes -= sge_bytes;
 
                frmr->page_list->page_list[page_no] =
-                       ib_dma_map_single(xprt->sc_cm_id->device,
-                                         page_address(page),
-                                         PAGE_SIZE, DMA_TO_DEVICE);
+                       ib_dma_map_page(xprt->sc_cm_id->device,
+                                       page, page_off,
+                                       sge_bytes, DMA_TO_DEVICE);
                if (ib_dma_mapping_error(xprt->sc_cm_id->device,
                                         frmr->page_list->page_list[page_no]))
                        goto fatal_err;
@@ -166,8 +170,10 @@ static int fast_reg_xdr(struct svcxprt_rdma *xprt,
                vec->sge[sge_no].iov_base = frva + frmr->map_len + page_off;
 
                frmr->page_list->page_list[page_no] =
-                       ib_dma_map_single(xprt->sc_cm_id->device, va, PAGE_SIZE,
-                                         DMA_TO_DEVICE);
+                   ib_dma_map_page(xprt->sc_cm_id->device, virt_to_page(va),
+                                   page_off,
+                                   PAGE_SIZE,
+                                   DMA_TO_DEVICE);
                if (ib_dma_mapping_error(xprt->sc_cm_id->device,
                                         frmr->page_list->page_list[page_no]))
                        goto fatal_err;
@@ -245,6 +251,35 @@ static int map_xdr(struct svcxprt_rdma *xprt,
        return 0;
 }
 
+static dma_addr_t dma_map_xdr(struct svcxprt_rdma *xprt,
+                             struct xdr_buf *xdr,
+                             u32 xdr_off, size_t len, int dir)
+{
+       struct page *page;
+       dma_addr_t dma_addr;
+       if (xdr_off < xdr->head[0].iov_len) {
+               /* This offset is in the head */
+               xdr_off += (unsigned long)xdr->head[0].iov_base & ~PAGE_MASK;
+               page = virt_to_page(xdr->head[0].iov_base);
+       } else {
+               xdr_off -= xdr->head[0].iov_len;
+               if (xdr_off < xdr->page_len) {
+                       /* This offset is in the page list */
+                       page = xdr->pages[xdr_off >> PAGE_SHIFT];
+                       xdr_off &= ~PAGE_MASK;
+               } else {
+                       /* This offset is in the tail */
+                       xdr_off -= xdr->page_len;
+                       xdr_off += (unsigned long)
+                               xdr->tail[0].iov_base & ~PAGE_MASK;
+                       page = virt_to_page(xdr->tail[0].iov_base);
+               }
+       }
+       dma_addr = ib_dma_map_page(xprt->sc_cm_id->device, page, xdr_off,
+                                  min_t(size_t, PAGE_SIZE, len), dir);
+       return dma_addr;
+}
+
 /* Assumptions:
  * - We are using FRMR
  *     - or -
@@ -293,10 +328,9 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
                sge[sge_no].length = sge_bytes;
                if (!vec->frmr) {
                        sge[sge_no].addr =
-                               ib_dma_map_single(xprt->sc_cm_id->device,
-                                                 (void *)
-                                                 vec->sge[xdr_sge_no].iov_base + sge_off,
-                                                 sge_bytes, DMA_TO_DEVICE);
+                               dma_map_xdr(xprt, &rqstp->rq_res, xdr_off,
+                                           sge_bytes, DMA_TO_DEVICE);
+                       xdr_off += sge_bytes;
                        if (ib_dma_mapping_error(xprt->sc_cm_id->device,
                                                 sge[sge_no].addr))
                                goto err;
@@ -333,6 +367,8 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
                goto err;
        return 0;
  err:
+       svc_rdma_unmap_dma(ctxt);
+       svc_rdma_put_frmr(xprt, vec->frmr);
        svc_rdma_put_context(ctxt, 0);
        /* Fatal error, close transport */
        return -EIO;
@@ -494,7 +530,8 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt,
  * In all three cases, this function prepares the RPCRDMA header in
  * sge[0], the 'type' parameter indicates the type to place in the
  * RPCRDMA header, and the 'byte_count' field indicates how much of
- * the XDR to include in this RDMA_SEND.
+ * the XDR to include in this RDMA_SEND. NB: The offset of the payload
+ * to send is zero in the XDR.
  */
 static int send_reply(struct svcxprt_rdma *rdma,
                      struct svc_rqst *rqstp,
@@ -536,23 +573,24 @@ static int send_reply(struct svcxprt_rdma *rdma,
        ctxt->sge[0].lkey = rdma->sc_dma_lkey;
        ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp);
        ctxt->sge[0].addr =
-               ib_dma_map_single(rdma->sc_cm_id->device, page_address(page),
-                                 ctxt->sge[0].length, DMA_TO_DEVICE);
+           ib_dma_map_page(rdma->sc_cm_id->device, page, 0,
+                           ctxt->sge[0].length, DMA_TO_DEVICE);
        if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr))
                goto err;
        atomic_inc(&rdma->sc_dma_used);
 
        ctxt->direction = DMA_TO_DEVICE;
 
-       /* Determine how many of our SGE are to be transmitted */
+       /* Map the payload indicated by 'byte_count' */
        for (sge_no = 1; byte_count && sge_no < vec->count; sge_no++) {
+               int xdr_off = 0;
                sge_bytes = min_t(size_t, vec->sge[sge_no].iov_len, byte_count);
                byte_count -= sge_bytes;
                if (!vec->frmr) {
                        ctxt->sge[sge_no].addr =
-                               ib_dma_map_single(rdma->sc_cm_id->device,
-                                                 vec->sge[sge_no].iov_base,
-                                                 sge_bytes, DMA_TO_DEVICE);
+                               dma_map_xdr(rdma, &rqstp->rq_res, xdr_off,
+                                           sge_bytes, DMA_TO_DEVICE);
+                       xdr_off += sge_bytes;
                        if (ib_dma_mapping_error(rdma->sc_cm_id->device,
                                                 ctxt->sge[sge_no].addr))
                                goto err;
index edea15a..9df1ead 100644 (file)
@@ -45,6 +45,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 #include <rdma/ib_verbs.h>
 #include <rdma/rdma_cm.h>
 #include <linux/sunrpc/svc_rdma.h>
@@ -52,6 +53,7 @@
 #define RPCDBG_FACILITY        RPCDBG_SVCXPRT
 
 static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
+                                       struct net *net,
                                        struct sockaddr *sa, int salen,
                                        int flags);
 static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt);
@@ -89,6 +91,9 @@ struct svc_xprt_class svc_rdma_class = {
 /* WR context cache. Created in svc_rdma.c  */
 extern struct kmem_cache *svc_rdma_ctxt_cachep;
 
+/* Workqueue created in svc_rdma.c */
+extern struct workqueue_struct *svc_rdma_wq;
+
 struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
 {
        struct svc_rdma_op_ctxt *ctxt;
@@ -120,7 +125,7 @@ void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt)
                 */
                if (ctxt->sge[i].lkey == xprt->sc_dma_lkey) {
                        atomic_dec(&xprt->sc_dma_used);
-                       ib_dma_unmap_single(xprt->sc_cm_id->device,
+                       ib_dma_unmap_page(xprt->sc_cm_id->device,
                                            ctxt->sge[i].addr,
                                            ctxt->sge[i].length,
                                            ctxt->direction);
@@ -502,8 +507,8 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
                BUG_ON(sge_no >= xprt->sc_max_sge);
                page = svc_rdma_get_page();
                ctxt->pages[sge_no] = page;
-               pa = ib_dma_map_single(xprt->sc_cm_id->device,
-                                    page_address(page), PAGE_SIZE,
+               pa = ib_dma_map_page(xprt->sc_cm_id->device,
+                                    page, 0, PAGE_SIZE,
                                     DMA_FROM_DEVICE);
                if (ib_dma_mapping_error(xprt->sc_cm_id->device, pa))
                        goto err_put_ctxt;
@@ -511,9 +516,9 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
                ctxt->sge[sge_no].addr = pa;
                ctxt->sge[sge_no].length = PAGE_SIZE;
                ctxt->sge[sge_no].lkey = xprt->sc_dma_lkey;
+               ctxt->count = sge_no + 1;
                buflen += PAGE_SIZE;
        }
-       ctxt->count = sge_no;
        recv_wr.next = NULL;
        recv_wr.sg_list = &ctxt->sge[0];
        recv_wr.num_sge = ctxt->count;
@@ -529,6 +534,7 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt)
        return ret;
 
  err_put_ctxt:
+       svc_rdma_unmap_dma(ctxt);
        svc_rdma_put_context(ctxt, 1);
        return -ENOMEM;
 }
@@ -670,6 +676,7 @@ static int rdma_cma_handler(struct rdma_cm_id *cma_id,
  * Create a listening RDMA service endpoint.
  */
 static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
+                                       struct net *net,
                                        struct sockaddr *sa, int salen,
                                        int flags)
 {
@@ -798,8 +805,8 @@ static void frmr_unmap_dma(struct svcxprt_rdma *xprt,
                if (ib_dma_mapping_error(frmr->mr->device, addr))
                        continue;
                atomic_dec(&xprt->sc_dma_used);
-               ib_dma_unmap_single(frmr->mr->device, addr, PAGE_SIZE,
-                                   frmr->direction);
+               ib_dma_unmap_page(frmr->mr->device, addr, PAGE_SIZE,
+                                 frmr->direction);
        }
 }
 
@@ -1184,7 +1191,7 @@ static void svc_rdma_free(struct svc_xprt *xprt)
        struct svcxprt_rdma *rdma =
                container_of(xprt, struct svcxprt_rdma, sc_xprt);
        INIT_WORK(&rdma->sc_work, __svc_rdma_free);
-       schedule_work(&rdma->sc_work);
+       queue_work(svc_rdma_wq, &rdma->sc_work);
 }
 
 static int svc_rdma_has_wspace(struct svc_xprt *xprt)
@@ -1274,7 +1281,7 @@ int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
                                   atomic_read(&xprt->sc_sq_count) <
                                   xprt->sc_sq_depth);
                        if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
-                               return 0;
+                               return -ENOTCONN;
                        continue;
                }
                /* Take a transport ref for each WR posted */
@@ -1306,7 +1313,6 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
                         enum rpcrdma_errcode err)
 {
        struct ib_send_wr err_wr;
-       struct ib_sge sge;
        struct page *p;
        struct svc_rdma_op_ctxt *ctxt;
        u32 *va;
@@ -1319,26 +1325,27 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
        /* XDR encode error */
        length = svc_rdma_xdr_encode_error(xprt, rmsgp, err, va);
 
+       ctxt = svc_rdma_get_context(xprt);
+       ctxt->direction = DMA_FROM_DEVICE;
+       ctxt->count = 1;
+       ctxt->pages[0] = p;
+
        /* Prepare SGE for local address */
-       sge.addr = ib_dma_map_single(xprt->sc_cm_id->device,
-                                  page_address(p), PAGE_SIZE, DMA_FROM_DEVICE);
-       if (ib_dma_mapping_error(xprt->sc_cm_id->device, sge.addr)) {
+       ctxt->sge[0].addr = ib_dma_map_page(xprt->sc_cm_id->device,
+                                           p, 0, length, DMA_FROM_DEVICE);
+       if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) {
                put_page(p);
                return;
        }
        atomic_inc(&xprt->sc_dma_used);
-       sge.lkey = xprt->sc_dma_lkey;
-       sge.length = length;
-
-       ctxt = svc_rdma_get_context(xprt);
-       ctxt->count = 1;
-       ctxt->pages[0] = p;
+       ctxt->sge[0].lkey = xprt->sc_dma_lkey;
+       ctxt->sge[0].length = length;
 
        /* Prepare SEND WR */
        memset(&err_wr, 0, sizeof err_wr);
        ctxt->wr_op = IB_WR_SEND;
        err_wr.wr_id = (unsigned long)ctxt;
-       err_wr.sg_list = &sge;
+       err_wr.sg_list = ctxt->sge;
        err_wr.num_sge = 1;
        err_wr.opcode = IB_WR_SEND;
        err_wr.send_flags = IB_SEND_SIGNALED;
@@ -1348,9 +1355,7 @@ void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
        if (ret) {
                dprintk("svcrdma: Error %d posting send for protocol error\n",
                        ret);
-               ib_dma_unmap_single(xprt->sc_cm_id->device,
-                                 sge.addr, PAGE_SIZE,
-                                 DMA_FROM_DEVICE);
+               svc_rdma_unmap_dma(ctxt);
                svc_rdma_put_context(ctxt, 1);
        }
 }
index a85e866..0867070 100644 (file)
@@ -237,8 +237,7 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
 
        dprintk("RPC:       %s: called\n", __func__);
 
-       cancel_delayed_work(&r_xprt->rdma_connect);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&r_xprt->rdma_connect);
 
        xprt_clear_connected(xprt);
 
@@ -251,9 +250,7 @@ xprt_rdma_destroy(struct rpc_xprt *xprt)
 
        xprt_rdma_free_addresses(xprt);
 
-       kfree(xprt->slot);
-       xprt->slot = NULL;
-       kfree(xprt);
+       xprt_free(xprt);
 
        dprintk("RPC:       %s: returning\n", __func__);
 
@@ -285,23 +282,14 @@ xprt_setup_rdma(struct xprt_create *args)
                return ERR_PTR(-EBADF);
        }
 
-       xprt = kzalloc(sizeof(struct rpcrdma_xprt), GFP_KERNEL);
+       xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt),
+                       xprt_rdma_slot_table_entries);
        if (xprt == NULL) {
                dprintk("RPC:       %s: couldn't allocate rpcrdma_xprt\n",
                        __func__);
                return ERR_PTR(-ENOMEM);
        }
 
-       xprt->max_reqs = xprt_rdma_slot_table_entries;
-       xprt->slot = kcalloc(xprt->max_reqs,
-                               sizeof(struct rpc_rqst), GFP_KERNEL);
-       if (xprt->slot == NULL) {
-               dprintk("RPC:       %s: couldn't allocate %d slots\n",
-                       __func__, xprt->max_reqs);
-               kfree(xprt);
-               return ERR_PTR(-ENOMEM);
-       }
-
        /* 60 second timeout, no retries */
        xprt->timeout = &xprt_rdma_default_timeout;
        xprt->bind_timeout = (60U * HZ);
@@ -410,8 +398,7 @@ out3:
 out2:
        rpcrdma_ia_close(&new_xprt->rx_ia);
 out1:
-       kfree(xprt->slot);
-       kfree(xprt);
+       xprt_free(xprt);
        return ERR_PTR(rc);
 }
 
@@ -460,7 +447,7 @@ xprt_rdma_connect(struct rpc_task *task)
        } else {
                schedule_delayed_work(&r_xprt->rdma_connect, 0);
                if (!RPC_IS_ASYNC(task))
-                       flush_scheduled_work();
+                       flush_delayed_work(&r_xprt->rdma_connect);
        }
 }
 
index fe9306b..dfcab5a 100644 (file)
@@ -774,8 +774,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
 
        xs_close(xprt);
        xs_free_peer_addresses(xprt);
-       kfree(xprt->slot);
-       kfree(xprt);
+       xprt_free(xprt);
        module_put(THIS_MODULE);
 }
 
@@ -1516,7 +1515,7 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
        xs_update_peer_port(xprt);
 }
 
-static unsigned short xs_get_srcport(struct sock_xprt *transport, struct socket *sock)
+static unsigned short xs_get_srcport(struct sock_xprt *transport)
 {
        unsigned short port = transport->srcport;
 
@@ -1525,7 +1524,7 @@ static unsigned short xs_get_srcport(struct sock_xprt *transport, struct socket
        return port;
 }
 
-static unsigned short xs_next_srcport(struct sock_xprt *transport, struct socket *sock, unsigned short port)
+static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned short port)
 {
        if (transport->srcport != 0)
                transport->srcport = 0;
@@ -1535,23 +1534,18 @@ static unsigned short xs_next_srcport(struct sock_xprt *transport, struct socket
                return xprt_max_resvport;
        return --port;
 }
-
-static int xs_bind4(struct sock_xprt *transport, struct socket *sock)
+static int xs_bind(struct sock_xprt *transport, struct socket *sock)
 {
-       struct sockaddr_in myaddr = {
-               .sin_family = AF_INET,
-       };
-       struct sockaddr_in *sa;
+       struct sockaddr_storage myaddr;
        int err, nloop = 0;
-       unsigned short port = xs_get_srcport(transport, sock);
+       unsigned short port = xs_get_srcport(transport);
        unsigned short last;
 
-       sa = (struct sockaddr_in *)&transport->srcaddr;
-       myaddr.sin_addr = sa->sin_addr;
+       memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen);
        do {
-               myaddr.sin_port = htons(port);
-               err = kernel_bind(sock, (struct sockaddr *) &myaddr,
-                                               sizeof(myaddr));
+               rpc_set_port((struct sockaddr *)&myaddr, port);
+               err = kernel_bind(sock, (struct sockaddr *)&myaddr,
+                               transport->xprt.addrlen);
                if (port == 0)
                        break;
                if (err == 0) {
@@ -1559,48 +1553,23 @@ static int xs_bind4(struct sock_xprt *transport, struct socket *sock)
                        break;
                }
                last = port;
-               port = xs_next_srcport(transport, sock, port);
+               port = xs_next_srcport(transport, port);
                if (port > last)
                        nloop++;
        } while (err == -EADDRINUSE && nloop != 2);
-       dprintk("RPC:       %s %pI4:%u: %s (%d)\n",
-                       __func__, &myaddr.sin_addr,
-                       port, err ? "failed" : "ok", err);
-       return err;
-}
-
-static int xs_bind6(struct sock_xprt *transport, struct socket *sock)
-{
-       struct sockaddr_in6 myaddr = {
-               .sin6_family = AF_INET6,
-       };
-       struct sockaddr_in6 *sa;
-       int err, nloop = 0;
-       unsigned short port = xs_get_srcport(transport, sock);
-       unsigned short last;
 
-       sa = (struct sockaddr_in6 *)&transport->srcaddr;
-       myaddr.sin6_addr = sa->sin6_addr;
-       do {
-               myaddr.sin6_port = htons(port);
-               err = kernel_bind(sock, (struct sockaddr *) &myaddr,
-                                               sizeof(myaddr));
-               if (port == 0)
-                       break;
-               if (err == 0) {
-                       transport->srcport = port;
-                       break;
-               }
-               last = port;
-               port = xs_next_srcport(transport, sock, port);
-               if (port > last)
-                       nloop++;
-       } while (err == -EADDRINUSE && nloop != 2);
-       dprintk("RPC:       xs_bind6 %pI6:%u: %s (%d)\n",
-               &myaddr.sin6_addr, port, err ? "failed" : "ok", err);
+       if (myaddr.ss_family == AF_INET)
+               dprintk("RPC:       %s %pI4:%u: %s (%d)\n", __func__,
+                               &((struct sockaddr_in *)&myaddr)->sin_addr,
+                               port, err ? "failed" : "ok", err);
+       else
+               dprintk("RPC:       %s %pI6:%u: %s (%d)\n", __func__,
+                               &((struct sockaddr_in6 *)&myaddr)->sin6_addr,
+                               port, err ? "failed" : "ok", err);
        return err;
 }
 
+
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 static struct lock_class_key xs_key[2];
 static struct lock_class_key xs_slock_key[2];
@@ -1622,6 +1591,18 @@ static inline void xs_reclassify_socket6(struct socket *sock)
        sock_lock_init_class_and_name(sk, "slock-AF_INET6-RPC",
                &xs_slock_key[1], "sk_lock-AF_INET6-RPC", &xs_key[1]);
 }
+
+static inline void xs_reclassify_socket(int family, struct socket *sock)
+{
+       switch (family) {
+       case AF_INET:
+               xs_reclassify_socket4(sock);
+               break;
+       case AF_INET6:
+               xs_reclassify_socket6(sock);
+               break;
+       }
+}
 #else
 static inline void xs_reclassify_socket4(struct socket *sock)
 {
@@ -1630,8 +1611,36 @@ static inline void xs_reclassify_socket4(struct socket *sock)
 static inline void xs_reclassify_socket6(struct socket *sock)
 {
 }
+
+static inline void xs_reclassify_socket(int family, struct socket *sock)
+{
+}
 #endif
 
+static struct socket *xs_create_sock(struct rpc_xprt *xprt,
+               struct sock_xprt *transport, int family, int type, int protocol)
+{
+       struct socket *sock;
+       int err;
+
+       err = __sock_create(xprt->xprt_net, family, type, protocol, &sock, 1);
+       if (err < 0) {
+               dprintk("RPC:       can't create %d transport socket (%d).\n",
+                               protocol, -err);
+               goto out;
+       }
+       xs_reclassify_socket(family, sock);
+
+       if (xs_bind(transport, sock)) {
+               sock_release(sock);
+               goto out;
+       }
+
+       return sock;
+out:
+       return ERR_PTR(err);
+}
+
 static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
 {
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
@@ -1661,82 +1670,23 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
        xs_udp_do_set_buffer_size(xprt);
 }
 
-/**
- * xs_udp_connect_worker4 - set up a UDP socket
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_udp_connect_worker4(struct work_struct *work)
+static void xs_udp_setup_socket(struct work_struct *work)
 {
        struct sock_xprt *transport =
                container_of(work, struct sock_xprt, connect_worker.work);
        struct rpc_xprt *xprt = &transport->xprt;
        struct socket *sock = transport->sock;
-       int err, status = -EIO;
+       int status = -EIO;
 
        if (xprt->shutdown)
                goto out;
 
        /* Start by resetting any existing state */
        xs_reset_transport(transport);
-
-       err = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock);
-       if (err < 0) {
-               dprintk("RPC:       can't create UDP transport socket (%d).\n", -err);
+       sock = xs_create_sock(xprt, transport,
+                       xs_addr(xprt)->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+       if (IS_ERR(sock))
                goto out;
-       }
-       xs_reclassify_socket4(sock);
-
-       if (xs_bind4(transport, sock)) {
-               sock_release(sock);
-               goto out;
-       }
-
-       dprintk("RPC:       worker connecting xprt %p via %s to "
-                               "%s (port %s)\n", xprt,
-                       xprt->address_strings[RPC_DISPLAY_PROTO],
-                       xprt->address_strings[RPC_DISPLAY_ADDR],
-                       xprt->address_strings[RPC_DISPLAY_PORT]);
-
-       xs_udp_finish_connecting(xprt, sock);
-       status = 0;
-out:
-       xprt_clear_connecting(xprt);
-       xprt_wake_pending_tasks(xprt, status);
-}
-
-/**
- * xs_udp_connect_worker6 - set up a UDP socket
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_udp_connect_worker6(struct work_struct *work)
-{
-       struct sock_xprt *transport =
-               container_of(work, struct sock_xprt, connect_worker.work);
-       struct rpc_xprt *xprt = &transport->xprt;
-       struct socket *sock = transport->sock;
-       int err, status = -EIO;
-
-       if (xprt->shutdown)
-               goto out;
-
-       /* Start by resetting any existing state */
-       xs_reset_transport(transport);
-
-       err = sock_create_kern(PF_INET6, SOCK_DGRAM, IPPROTO_UDP, &sock);
-       if (err < 0) {
-               dprintk("RPC:       can't create UDP transport socket (%d).\n", -err);
-               goto out;
-       }
-       xs_reclassify_socket6(sock);
-
-       if (xs_bind6(transport, sock) < 0) {
-               sock_release(sock);
-               goto out;
-       }
 
        dprintk("RPC:       worker connecting xprt %p via %s to "
                                "%s (port %s)\n", xprt,
@@ -1755,12 +1705,12 @@ out:
  * We need to preserve the port number so the reply cache on the server can
  * find our cached RPC replies when we get around to reconnecting.
  */
-static void xs_abort_connection(struct rpc_xprt *xprt, struct sock_xprt *transport)
+static void xs_abort_connection(struct sock_xprt *transport)
 {
        int result;
        struct sockaddr any;
 
-       dprintk("RPC:       disconnecting xprt %p to reuse port\n", xprt);
+       dprintk("RPC:       disconnecting xprt %p to reuse port\n", transport);
 
        /*
         * Disconnect the transport socket by doing a connect operation
@@ -1770,13 +1720,13 @@ static void xs_abort_connection(struct rpc_xprt *xprt, struct sock_xprt *transpo
        any.sa_family = AF_UNSPEC;
        result = kernel_connect(transport->sock, &any, sizeof(any), 0);
        if (!result)
-               xs_sock_mark_closed(xprt);
+               xs_sock_mark_closed(&transport->xprt);
        else
                dprintk("RPC:       AF_UNSPEC connect return code %d\n",
                                result);
 }
 
-static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *transport)
+static void xs_tcp_reuse_connection(struct sock_xprt *transport)
 {
        unsigned int state = transport->inet->sk_state;
 
@@ -1799,7 +1749,7 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt, struct sock_xprt *tra
                                "sk_shutdown set to %d\n",
                                __func__, transport->inet->sk_shutdown);
        }
-       xs_abort_connection(xprt, transport);
+       xs_abort_connection(transport);
 }
 
 static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
@@ -1852,12 +1802,12 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
  *
  * Invoked by a work queue tasklet.
  */
-static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
-               struct sock_xprt *transport,
-               struct socket *(*create_sock)(struct rpc_xprt *,
-                       struct sock_xprt *))
+static void xs_tcp_setup_socket(struct work_struct *work)
 {
+       struct sock_xprt *transport =
+               container_of(work, struct sock_xprt, connect_worker.work);
        struct socket *sock = transport->sock;
+       struct rpc_xprt *xprt = &transport->xprt;
        int status = -EIO;
 
        if (xprt->shutdown)
@@ -1865,7 +1815,8 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
 
        if (!sock) {
                clear_bit(XPRT_CONNECTION_ABORT, &xprt->state);
-               sock = create_sock(xprt, transport);
+               sock = xs_create_sock(xprt, transport,
+                               xs_addr(xprt)->sa_family, SOCK_STREAM, IPPROTO_TCP);
                if (IS_ERR(sock)) {
                        status = PTR_ERR(sock);
                        goto out;
@@ -1876,7 +1827,7 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
                abort_and_exit = test_and_clear_bit(XPRT_CONNECTION_ABORT,
                                &xprt->state);
                /* "close" the socket, preserving the local port */
-               xs_tcp_reuse_connection(xprt, transport);
+               xs_tcp_reuse_connection(transport);
 
                if (abort_and_exit)
                        goto out_eagain;
@@ -1925,84 +1876,6 @@ out:
        xprt_wake_pending_tasks(xprt, status);
 }
 
-static struct socket *xs_create_tcp_sock4(struct rpc_xprt *xprt,
-               struct sock_xprt *transport)
-{
-       struct socket *sock;
-       int err;
-
-       /* start from scratch */
-       err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
-       if (err < 0) {
-               dprintk("RPC:       can't create TCP transport socket (%d).\n",
-                               -err);
-               goto out_err;
-       }
-       xs_reclassify_socket4(sock);
-
-       if (xs_bind4(transport, sock) < 0) {
-               sock_release(sock);
-               goto out_err;
-       }
-       return sock;
-out_err:
-       return ERR_PTR(-EIO);
-}
-
-/**
- * xs_tcp_connect_worker4 - connect a TCP socket to a remote endpoint
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_tcp_connect_worker4(struct work_struct *work)
-{
-       struct sock_xprt *transport =
-               container_of(work, struct sock_xprt, connect_worker.work);
-       struct rpc_xprt *xprt = &transport->xprt;
-
-       xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock4);
-}
-
-static struct socket *xs_create_tcp_sock6(struct rpc_xprt *xprt,
-               struct sock_xprt *transport)
-{
-       struct socket *sock;
-       int err;
-
-       /* start from scratch */
-       err = sock_create_kern(PF_INET6, SOCK_STREAM, IPPROTO_TCP, &sock);
-       if (err < 0) {
-               dprintk("RPC:       can't create TCP transport socket (%d).\n",
-                               -err);
-               goto out_err;
-       }
-       xs_reclassify_socket6(sock);
-
-       if (xs_bind6(transport, sock) < 0) {
-               sock_release(sock);
-               goto out_err;
-       }
-       return sock;
-out_err:
-       return ERR_PTR(-EIO);
-}
-
-/**
- * xs_tcp_connect_worker6 - connect a TCP socket to a remote endpoint
- * @work: RPC transport to connect
- *
- * Invoked by a work queue tasklet.
- */
-static void xs_tcp_connect_worker6(struct work_struct *work)
-{
-       struct sock_xprt *transport =
-               container_of(work, struct sock_xprt, connect_worker.work);
-       struct rpc_xprt *xprt = &transport->xprt;
-
-       xs_tcp_setup_socket(xprt, transport, xs_create_tcp_sock6);
-}
-
 /**
  * xs_connect - connect a socket to a remote endpoint
  * @task: address of RPC task that manages state of connect request
@@ -2262,6 +2135,31 @@ static struct rpc_xprt_ops bc_tcp_ops = {
        .print_stats            = xs_tcp_print_stats,
 };
 
+static int xs_init_anyaddr(const int family, struct sockaddr *sap)
+{
+       static const struct sockaddr_in sin = {
+               .sin_family             = AF_INET,
+               .sin_addr.s_addr        = htonl(INADDR_ANY),
+       };
+       static const struct sockaddr_in6 sin6 = {
+               .sin6_family            = AF_INET6,
+               .sin6_addr              = IN6ADDR_ANY_INIT,
+       };
+
+       switch (family) {
+       case AF_INET:
+               memcpy(sap, &sin, sizeof(sin));
+               break;
+       case AF_INET6:
+               memcpy(sap, &sin6, sizeof(sin6));
+               break;
+       default:
+               dprintk("RPC:       %s: Bad address family\n", __func__);
+               return -EAFNOSUPPORT;
+       }
+       return 0;
+}
+
 static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
                                      unsigned int slot_table_size)
 {
@@ -2273,27 +2171,25 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
                return ERR_PTR(-EBADF);
        }
 
-       new = kzalloc(sizeof(*new), GFP_KERNEL);
-       if (new == NULL) {
+       xprt = xprt_alloc(args->net, sizeof(*new), slot_table_size);
+       if (xprt == NULL) {
                dprintk("RPC:       xs_setup_xprt: couldn't allocate "
                                "rpc_xprt\n");
                return ERR_PTR(-ENOMEM);
        }
-       xprt = &new->xprt;
-
-       xprt->max_reqs = slot_table_size;
-       xprt->slot = kcalloc(xprt->max_reqs, sizeof(struct rpc_rqst), GFP_KERNEL);
-       if (xprt->slot == NULL) {
-               kfree(xprt);
-               dprintk("RPC:       xs_setup_xprt: couldn't allocate slot "
-                               "table\n");
-               return ERR_PTR(-ENOMEM);
-       }
 
+       new = container_of(xprt, struct sock_xprt, xprt);
        memcpy(&xprt->addr, args->dstaddr, args->addrlen);
        xprt->addrlen = args->addrlen;
        if (args->srcaddr)
                memcpy(&new->srcaddr, args->srcaddr, args->addrlen);
+       else {
+               int err;
+               err = xs_init_anyaddr(args->dstaddr->sa_family,
+                                       (struct sockaddr *)&new->srcaddr);
+               if (err != 0)
+                       return ERR_PTR(err);
+       }
 
        return xprt;
 }
@@ -2341,7 +2237,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
                        xprt_set_bound(xprt);
 
                INIT_DELAYED_WORK(&transport->connect_worker,
-                                       xs_udp_connect_worker4);
+                                       xs_udp_setup_socket);
                xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP);
                break;
        case AF_INET6:
@@ -2349,7 +2245,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
                        xprt_set_bound(xprt);
 
                INIT_DELAYED_WORK(&transport->connect_worker,
-                                       xs_udp_connect_worker6);
+                                       xs_udp_setup_socket);
                xs_format_peer_addresses(xprt, "udp", RPCBIND_NETID_UDP6);
                break;
        default:
@@ -2371,8 +2267,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args)
                return xprt;
        ret = ERR_PTR(-EINVAL);
 out_err:
-       kfree(xprt->slot);
-       kfree(xprt);
+       xprt_free(xprt);
        return ret;
 }
 
@@ -2416,7 +2311,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
                        xprt_set_bound(xprt);
 
                INIT_DELAYED_WORK(&transport->connect_worker,
-                                       xs_tcp_connect_worker4);
+                                       xs_tcp_setup_socket);
                xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP);
                break;
        case AF_INET6:
@@ -2424,7 +2319,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
                        xprt_set_bound(xprt);
 
                INIT_DELAYED_WORK(&transport->connect_worker,
-                                       xs_tcp_connect_worker6);
+                                       xs_tcp_setup_socket);
                xs_format_peer_addresses(xprt, "tcp", RPCBIND_NETID_TCP6);
                break;
        default:
@@ -2447,8 +2342,7 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args)
                return xprt;
        ret = ERR_PTR(-EINVAL);
 out_err:
-       kfree(xprt->slot);
-       kfree(xprt);
+       xprt_free(xprt);
        return ret;
 }
 
@@ -2507,15 +2401,10 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
                goto out_err;
        }
 
-       if (xprt_bound(xprt))
-               dprintk("RPC:       set up xprt to %s (port %s) via %s\n",
-                               xprt->address_strings[RPC_DISPLAY_ADDR],
-                               xprt->address_strings[RPC_DISPLAY_PORT],
-                               xprt->address_strings[RPC_DISPLAY_PROTO]);
-       else
-               dprintk("RPC:       set up xprt to %s (autobind) via %s\n",
-                               xprt->address_strings[RPC_DISPLAY_ADDR],
-                               xprt->address_strings[RPC_DISPLAY_PROTO]);
+       dprintk("RPC:       set up xprt to %s (port %s) via %s\n",
+                       xprt->address_strings[RPC_DISPLAY_ADDR],
+                       xprt->address_strings[RPC_DISPLAY_PORT],
+                       xprt->address_strings[RPC_DISPLAY_PROTO]);
 
        /*
         * Since we don't want connections for the backchannel, we set
@@ -2528,8 +2417,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
                return xprt;
        ret = ERR_PTR(-EINVAL);
 out_err:
-       kfree(xprt->slot);
-       kfree(xprt);
+       xprt_free(xprt);
        return ret;
 }
 
index 2039acd..90b54d4 100755 (executable)
@@ -2,7 +2,7 @@
 # (c) 2001, Dave Jones. (the file handling bit)
 # (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
 # (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
-# (c) 2008,2009, Andy Whitcroft <apw@canonical.com>
+# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
 # Licensed under the terms of the GNU GPL License version 2
 
 use strict;
@@ -10,7 +10,7 @@ use strict;
 my $P = $0;
 $P =~ s@.*/@@g;
 
-my $V = '0.30';
+my $V = '0.31';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -103,6 +103,8 @@ for my $key (keys %debug) {
        die "$@" if ($@);
 }
 
+my $rpt_cleaners = 0;
+
 if ($terse) {
        $emacs = 1;
        $quiet++;
@@ -150,6 +152,20 @@ our $Sparse        = qr{
 # We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
 our $Attribute = qr{
                        const|
+                       __percpu|
+                       __nocast|
+                       __safe|
+                       __bitwise__|
+                       __packed__|
+                       __packed2__|
+                       __naked|
+                       __maybe_unused|
+                       __always_unused|
+                       __noreturn|
+                       __used|
+                       __cold|
+                       __noclone|
+                       __deprecated|
                        __read_mostly|
                        __kprobes|
                        __(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
@@ -675,15 +691,15 @@ sub ctx_block_get {
                $blk .= $rawlines[$line];
 
                # Handle nested #if/#else.
-               if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
+               if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
                        push(@stack, $level);
-               } elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
+               } elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
                        $level = $stack[$#stack - 1];
-               } elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) {
+               } elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
                        $level = pop(@stack);
                }
 
-               foreach my $c (split(//, $rawlines[$line])) {
+               foreach my $c (split(//, $lines[$line])) {
                        ##print "C<$c>L<$level><$open$close>O<$off>\n";
                        if ($off > 0) {
                                $off--;
@@ -843,7 +859,12 @@ sub annotate_values {
                                $av_preprocessor = 0;
                        }
 
-               } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
+               } elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
+                       print "CAST($1)\n" if ($dbg_values > 1);
+                       push(@av_paren_type, $type);
+                       $type = 'C';
+
+               } elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
                        print "DECLARE($1)\n" if ($dbg_values > 1);
                        $type = 'T';
 
@@ -1308,7 +1329,11 @@ sub process {
                $here = "#$realline: " if ($file);
 
                # extract the filename as it passes
-               if ($line=~/^\+\+\+\s+(\S+)/) {
+               if ($line =~ /^diff --git.*?(\S+)$/) {
+                       $realfile = $1;
+                       $realfile =~ s@^([^/]*)/@@;
+
+               } elsif ($line =~ /^\+\+\+\s+(\S+)/) {
                        $realfile = $1;
                        $realfile =~ s@^([^/]*)/@@;
 
@@ -1332,6 +1357,14 @@ sub process {
 
                $cnt_lines++ if ($realcnt != 0);
 
+# Check for incorrect file permissions
+               if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
+                       my $permhere = $here . "FILE: $realfile\n";
+                       if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
+                               ERROR("do not set execute permissions for source files\n" . $permhere);
+                       }
+               }
+
 #check the patch for a signoff:
                if ($line =~ /^\s*signed-off-by:/i) {
                        # This is a signoff, if ugly, so do not double report.
@@ -1389,21 +1422,38 @@ sub process {
                } elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
                        ERROR("trailing whitespace\n" . $herevet);
+                       $rpt_cleaners = 1;
                }
 
 # check for Kconfig help text having a real description
+# Only applies when adding the entry originally, after that we do not have
+# sufficient context to determine whether it is indeed long enough.
                if ($realfile =~ /Kconfig/ &&
-                   $line =~ /\+?\s*(---)?help(---)?$/) {
+                   $line =~ /\+\s*(?:---)?help(?:---)?$/) {
                        my $length = 0;
-                       for (my $l = $linenr; defined($lines[$l]); $l++) {
-                               my $f = $lines[$l];
+                       my $cnt = $realcnt;
+                       my $ln = $linenr + 1;
+                       my $f;
+                       my $is_end = 0;
+                       while ($cnt > 0 && defined $lines[$ln - 1]) {
+                               $f = $lines[$ln - 1];
+                               $cnt-- if ($lines[$ln - 1] !~ /^-/);
+                               $is_end = $lines[$ln - 1] =~ /^\+/;
+                               $ln++;
+
+                               next if ($f =~ /^-/);
+                               $f =~ s/^.//;
                                $f =~ s/#.*//;
                                $f =~ s/^\s+//;
                                next if ($f =~ /^$/);
-                               last if ($f =~ /^\s*config\s/);
+                               if ($f =~ /^\s*config\s/) {
+                                       $is_end = 1;
+                                       last;
+                               }
                                $length++;
                        }
-                       WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($length < 4);
+                       WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
+                       #print "is_end<$is_end> length<$length>\n";
                }
 
 # check we are in a valid source file if not then ignore this hunk
@@ -1450,6 +1500,7 @@ sub process {
                    $rawline =~ /^\+\s*        \s*/) {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
                        ERROR("code indent should use tabs where possible\n" . $herevet);
+                       $rpt_cleaners = 1;
                }
 
 # check for space before tabs.
@@ -1459,10 +1510,13 @@ sub process {
                }
 
 # check for spaces at the beginning of a line.
-               if ($rawline =~ /^\+ / && $rawline !~ /\+ +\*/)  {
+# Exceptions:
+#  1) within comments
+#  2) indented preprocessor commands
+#  3) hanging labels
+               if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/)  {
                        my $herevet = "$here\n" . cat_vet($rawline) . "\n";
-                       WARN("please, no space for starting a line, \
-                               excluding comments\n" . $herevet);
+                       WARN("please, no spaces at the start of a line\n" . $herevet);
                }
 
 # check we are in a valid C source file if not then ignore this hunk
@@ -1598,7 +1652,7 @@ sub process {
 
                        if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
                                ERROR("that open brace { should be on the previous line\n" .
-                                       "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+                                       "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
                        }
                        if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
                            $ctx =~ /\)\s*\;\s*$/ &&
@@ -1607,7 +1661,7 @@ sub process {
                                my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
                                if ($nindent > $indent) {
                                        WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
-                                               "$here\n$ctx\n$lines[$ctx_ln - 1]\n");
+                                               "$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
                                }
                        }
                }
@@ -1768,8 +1822,17 @@ sub process {
                    !defined $suppress_export{$realline_next} &&
                    ($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
                     $lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
+                       # Handle definitions which produce identifiers with
+                       # a prefix:
+                       #   XXX(foo);
+                       #   EXPORT_SYMBOL(something_foo);
                        my $name = $1;
-                       if ($stat !~ /(?:
+                       if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
+                           $name =~ /^${Ident}_$2/) {
+#print "FOO C name<$name>\n";
+                               $suppress_export{$realline_next} = 1;
+
+                       } elsif ($stat !~ /(?:
                                \n.}\s*$|
                                ^.DEFINE_$Ident\(\Q$name\E\)|
                                ^.DECLARE_$Ident\(\Q$name\E\)|
@@ -1806,6 +1869,23 @@ sub process {
                                $herecurr);
                }
 
+# check for static const char * arrays.
+               if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
+                       WARN("static const char * array should probably be static const char * const\n" .
+                               $herecurr);
+               }
+
+# check for static char foo[] = "bar" declarations.
+               if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
+                       WARN("static char array declaration should probably be static const char\n" .
+                               $herecurr);
+               }
+
+# check for declarations of struct pci_device_id
+               if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
+                       WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
+               }
+
 # check for new typedefs, only function parameters and sparse annotations
 # make sense.
                if ($line =~ /\btypedef\s/ &&
@@ -1899,6 +1979,11 @@ sub process {
                        ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
                }
 
+# missing space after union, struct or enum definition
+               if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
+                   WARN("missing space after $1 definition\n" . $herecurr);
+               }
+
 # check for spacing round square brackets; allowed:
 #  1. with a type on the left -- int [] a;
 #  2. at the beginning of a line for slice initialisers -- [0...10] = 5,
@@ -2176,21 +2261,29 @@ sub process {
                        my $value = $2;
 
                        # Flatten any parentheses
-                       $value =~ s/\)\(/\) \(/g;
+                       $value =~ s/\(/ \(/g;
+                       $value =~ s/\)/\) /g;
                        while ($value =~ s/\[[^\{\}]*\]/1/ ||
                               $value !~ /(?:$Ident|-?$Constant)\s*
                                             $Compare\s*
                                             (?:$Ident|-?$Constant)/x &&
                               $value =~ s/\([^\(\)]*\)/1/) {
                        }
-
-                       if ($value =~ /^(?:$Ident|-?$Constant)$/) {
+#print "value<$value>\n";
+                       if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
                                ERROR("return is not a function, parentheses are not required\n" . $herecurr);
 
                        } elsif ($spacing !~ /\s+/) {
                                ERROR("space required before the open parenthesis '('\n" . $herecurr);
                        }
                }
+# Return of what appears to be an errno should normally be -'ve
+               if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
+                       my $name = $1;
+                       if ($name ne 'EOF' && $name ne 'ERROR') {
+                               WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
+                       }
+               }
 
 # Need a space before open parenthesis after if, while etc
                if ($line=~/\b(if|while|for|switch)\(/) {
@@ -2409,8 +2502,8 @@ sub process {
                                \.$Ident\s*=\s*|
                                ^\"|\"$
                        }x;
-                       #print "REST<$rest> dstat<$dstat>\n";
-                       if ($rest ne '') {
+                       #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
+                       if ($rest ne '' && $rest ne ',') {
                                if ($rest !~ /while\s*\(/ &&
                                    $dstat !~ /$exceptions/)
                                {
@@ -2839,6 +2932,15 @@ sub process {
                print "\n" if ($quiet == 0);
        }
 
+       if ($quiet == 0) {
+               # If there were whitespace errors which cleanpatch can fix
+               # then suggest that.
+               if ($rpt_cleaners) {
+                       print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
+                       print "      scripts/cleanfile\n\n";
+               }
+       }
+
        if ($clean == 1 && $quiet == 0) {
                print "$vname has no obvious style problems and is ready for submission.\n"
        }
index b228198..d21ec3a 100755 (executable)
@@ -13,7 +13,7 @@
 use strict;
 
 my $P = $0;
-my $V = '0.24';
+my $V = '0.26-beta6';
 
 use Getopt::Long qw(:config no_auto_abbrev);
 
@@ -24,15 +24,19 @@ my $email_maintainer = 1;
 my $email_list = 1;
 my $email_subscriber_list = 0;
 my $email_git_penguin_chiefs = 0;
-my $email_git = 1;
+my $email_git = 0;
 my $email_git_all_signature_types = 0;
 my $email_git_blame = 0;
+my $email_git_blame_signatures = 1;
+my $email_git_fallback = 1;
 my $email_git_min_signatures = 1;
 my $email_git_max_maintainers = 5;
 my $email_git_min_percent = 5;
 my $email_git_since = "1-year-ago";
 my $email_hg_since = "-365";
+my $interactive = 0;
 my $email_remove_duplicates = 1;
+my $email_use_mailmap = 1;
 my $output_multiline = 1;
 my $output_separator = ", ";
 my $output_roles = 0;
@@ -49,8 +53,13 @@ my $pattern_depth = 0;
 my $version = 0;
 my $help = 0;
 
+my $vcs_used = 0;
+
 my $exit = 0;
 
+my %commit_author_hash;
+my %commit_signer_hash;
+
 my @penguin_chief = ();
 push(@penguin_chief, "Linus Torvalds:torvalds\@linux-foundation.org");
 #Andrew wants in on most everything - 2009/01/14
@@ -73,7 +82,6 @@ my @signature_tags = ();
 push(@signature_tags, "Signed-off-by:");
 push(@signature_tags, "Reviewed-by:");
 push(@signature_tags, "Acked-by:");
-my $signaturePattern = "\(" . join("|", @signature_tags) . "\)";
 
 # rfc822 email address - preloaded methods go here.
 my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
@@ -86,31 +94,70 @@ my %VCS_cmds;
 my %VCS_cmds_git = (
     "execute_cmd" => \&git_execute_cmd,
     "available" => '(which("git") ne "") && (-d ".git")',
-    "find_signers_cmd" => "git log --no-color --since=\$email_git_since -- \$file",
-    "find_commit_signers_cmd" => "git log --no-color -1 \$commit",
+    "find_signers_cmd" =>
+       "git log --no-color --since=\$email_git_since " .
+           '--format="GitCommit: %H%n' .
+                     'GitAuthor: %an <%ae>%n' .
+                     'GitDate: %aD%n' .
+                     'GitSubject: %s%n' .
+                     '%b%n"' .
+           " -- \$file",
+    "find_commit_signers_cmd" =>
+       "git log --no-color " .
+           '--format="GitCommit: %H%n' .
+                     'GitAuthor: %an <%ae>%n' .
+                     'GitDate: %aD%n' .
+                     'GitSubject: %s%n' .
+                     '%b%n"' .
+           " -1 \$commit",
+    "find_commit_author_cmd" =>
+       "git log --no-color " .
+           '--format="GitCommit: %H%n' .
+                     'GitAuthor: %an <%ae>%n' .
+                     'GitDate: %aD%n' .
+                     'GitSubject: %s%n"' .
+           " -1 \$commit",
     "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
     "blame_file_cmd" => "git blame -l \$file",
-    "commit_pattern" => "^commit [0-9a-f]{40,40}",
-    "blame_commit_pattern" => "^([0-9a-f]+) "
+    "commit_pattern" => "^GitCommit: ([0-9a-f]{40,40})",
+    "blame_commit_pattern" => "^([0-9a-f]+) ",
+    "author_pattern" => "^GitAuthor: (.*)",
+    "subject_pattern" => "^GitSubject: (.*)",
 );
 
 my %VCS_cmds_hg = (
     "execute_cmd" => \&hg_execute_cmd,
     "available" => '(which("hg") ne "") && (-d ".hg")',
     "find_signers_cmd" =>
-       "hg log --date=\$email_hg_since" .
-               " --template='commit {node}\\n{desc}\\n' -- \$file",
-    "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit",
+       "hg log --date=\$email_hg_since " .
+           "--template='HgCommit: {node}\\n" .
+                       "HgAuthor: {author}\\n" .
+                       "HgSubject: {desc}\\n'" .
+           " -- \$file",
+    "find_commit_signers_cmd" =>
+       "hg log " .
+           "--template='HgSubject: {desc}\\n'" .
+           " -r \$commit",
+    "find_commit_author_cmd" =>
+       "hg log " .
+           "--template='HgCommit: {node}\\n" .
+                       "HgAuthor: {author}\\n" .
+                       "HgSubject: {desc|firstline}\\n'" .
+           " -r \$commit",
     "blame_range_cmd" => "",           # not supported
-    "blame_file_cmd" => "hg blame -c \$file",
-    "commit_pattern" => "^commit [0-9a-f]{40,40}",
-    "blame_commit_pattern" => "^([0-9a-f]+):"
+    "blame_file_cmd" => "hg blame -n \$file",
+    "commit_pattern" => "^HgCommit: ([0-9a-f]{40,40})",
+    "blame_commit_pattern" => "^([ 0-9a-f]+):",
+    "author_pattern" => "^HgAuthor: (.*)",
+    "subject_pattern" => "^HgSubject: (.*)",
 );
 
-if (-f "${lk_path}.get_maintainer.conf") {
+my $conf = which_conf(".get_maintainer.conf");
+if (-f $conf) {
     my @conf_args;
-    open(my $conffile, '<', "${lk_path}.get_maintainer.conf")
-       or warn "$P: Can't open .get_maintainer.conf: $!\n";
+    open(my $conffile, '<', "$conf")
+       or warn "$P: Can't find a readable .get_maintainer.conf file $!\n";
+
     while (<$conffile>) {
        my $line = $_;
 
@@ -136,13 +183,17 @@ if (!GetOptions(
                'git!' => \$email_git,
                'git-all-signature-types!' => \$email_git_all_signature_types,
                'git-blame!' => \$email_git_blame,
+               'git-blame-signatures!' => \$email_git_blame_signatures,
+               'git-fallback!' => \$email_git_fallback,
                'git-chief-penguins!' => \$email_git_penguin_chiefs,
                'git-min-signatures=i' => \$email_git_min_signatures,
                'git-max-maintainers=i' => \$email_git_max_maintainers,
                'git-min-percent=i' => \$email_git_min_percent,
                'git-since=s' => \$email_git_since,
                'hg-since=s' => \$email_hg_since,
+               'i|interactive!' => \$interactive,
                'remove-duplicates!' => \$email_remove_duplicates,
+               'mailmap!' => \$email_use_mailmap,
                'm!' => \$email_maintainer,
                'n!' => \$email_usename,
                'l!' => \$email_list,
@@ -181,13 +232,9 @@ if (-t STDIN && !@ARGV) {
     die "$P: missing patchfile or -f file - use --help if necessary\n";
 }
 
-if ($output_separator ne ", ") {
-    $output_multiline = 0;
-}
-
-if ($output_rolestats) {
-    $output_roles = 1;
-}
+$output_multiline = 0 if ($output_separator ne ", ");
+$output_rolestats = 1 if ($interactive);
+$output_roles = 1 if ($output_rolestats);
 
 if ($sections) {
     $email = 0;
@@ -197,6 +244,7 @@ if ($sections) {
     $subsystem = 0;
     $web = 0;
     $keywords = 0;
+    $interactive = 0;
 } else {
     my $selections = $email + $scm + $status + $subsystem + $web;
     if ($selections == 0) {
@@ -215,10 +263,6 @@ if (!top_of_kernel_tree($lk_path)) {
        . "a linux kernel source tree.\n";
 }
 
-if ($email_git_all_signature_types) {
-    $signaturePattern = "(.+?)[Bb][Yy]:";
-}
-
 ## Read MAINTAINERS for type/value pairs
 
 my @typevalue = ();
@@ -253,31 +297,82 @@ while (<$maint>) {
 }
 close($maint);
 
-my %mailmap;
 
-if ($email_remove_duplicates) {
-    open(my $mailmap, '<', "${lk_path}.mailmap")
-       or warn "$P: Can't open .mailmap: $!\n";
-    while (<$mailmap>) {
-       my $line = $_;
+#
+# Read mail address map
+#
 
-       next if ($line =~ m/^\s*#/);
-       next if ($line =~ m/^\s*$/);
+my $mailmap;
 
-       my ($name, $address) = parse_email($line);
-       $line = format_email($name, $address, $email_usename);
+read_mailmap();
 
-       next if ($line =~ m/^\s*$/);
+sub read_mailmap {
+    $mailmap = {
+       names => {},
+       addresses => {}
+    };
 
-       if (exists($mailmap{$name})) {
-           my $obj = $mailmap{$name};
-           push(@$obj, $address);
-       } else {
-           my @arr = ($address);
-           $mailmap{$name} = \@arr;
+    return if (!$email_use_mailmap || !(-f "${lk_path}.mailmap"));
+
+    open(my $mailmap_file, '<', "${lk_path}.mailmap")
+       or warn "$P: Can't open .mailmap: $!\n";
+
+    while (<$mailmap_file>) {
+       s/#.*$//; #strip comments
+       s/^\s+|\s+$//g; #trim
+
+       next if (/^\s*$/); #skip empty lines
+       #entries have one of the following formats:
+       # name1 <mail1>
+       # <mail1> <mail2>
+       # name1 <mail1> <mail2>
+       # name1 <mail1> name2 <mail2>
+       # (see man git-shortlog)
+       if (/^(.+)<(.+)>$/) {
+           my $real_name = $1;
+           my $address = $2;
+
+           $real_name =~ s/\s+$//;
+           ($real_name, $address) = parse_email("$real_name <$address>");
+           $mailmap->{names}->{$address} = $real_name;
+
+       } elsif (/^<([^\s]+)>\s*<([^\s]+)>$/) {
+           my $real_address = $1;
+           my $wrong_address = $2;
+
+           $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+       } elsif (/^(.+)<([^\s]+)>\s*<([^\s]+)>$/) {
+           my $real_name = $1;
+           my $real_address = $2;
+           my $wrong_address = $3;
+
+           $real_name =~ s/\s+$//;
+           ($real_name, $real_address) =
+               parse_email("$real_name <$real_address>");
+           $mailmap->{names}->{$wrong_address} = $real_name;
+           $mailmap->{addresses}->{$wrong_address} = $real_address;
+
+       } elsif (/^(.+)<([^\s]+)>\s*([^\s].*)<([^\s]+)>$/) {
+           my $real_name = $1;
+           my $real_address = $2;
+           my $wrong_name = $3;
+           my $wrong_address = $4;
+
+           $real_name =~ s/\s+$//;
+           ($real_name, $real_address) =
+               parse_email("$real_name <$real_address>");
+
+           $wrong_name =~ s/\s+$//;
+           ($wrong_name, $wrong_address) =
+               parse_email("$wrong_name <$wrong_address>");
+
+           my $wrong_email = format_email($wrong_name, $wrong_address, 1);
+           $mailmap->{names}->{$wrong_email} = $real_name;
+           $mailmap->{addresses}->{$wrong_email} = $real_address;
        }
     }
-    close($mailmap);
+    close($mailmap_file);
 }
 
 ## use the filenames on the command line or find the filenames in the patchfiles
@@ -302,7 +397,7 @@ foreach my $file (@ARGV) {
     }
     if ($from_filename) {
        push(@files, $file);
-       if (-f $file && ($keywords || $file_emails)) {
+       if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) {
            open(my $f, '<', $file)
                or die "$P: Can't open $file: $!\n";
            my $text = do { local($/) ; <$f> };
@@ -357,67 +452,127 @@ foreach my $file (@ARGV) {
 
 @file_emails = uniq(@file_emails);
 
+my %email_hash_name;
+my %email_hash_address;
 my @email_to = ();
+my %hash_list_to;
 my @list_to = ();
 my @scm = ();
 my @web = ();
 my @subsystem = ();
 my @status = ();
+my %deduplicate_name_hash = ();
+my %deduplicate_address_hash = ();
+my $signature_pattern;
 
-# Find responsible parties
+my @maintainers = get_maintainers();
 
-foreach my $file (@files) {
+if (@maintainers) {
+    @maintainers = merge_email(@maintainers);
+    output(@maintainers);
+}
 
-    my %hash;
-    my $tvi = find_first_section();
-    while ($tvi < @typevalue) {
-       my $start = find_starting_index($tvi);
-       my $end = find_ending_index($tvi);
-       my $exclude = 0;
-       my $i;
-
-       #Do not match excluded file patterns
-
-       for ($i = $start; $i < $end; $i++) {
-           my $line = $typevalue[$i];
-           if ($line =~ m/^(\C):\s*(.*)/) {
-               my $type = $1;
-               my $value = $2;
-               if ($type eq 'X') {
-                   if (file_match_pattern($file, $value)) {
-                       $exclude = 1;
-                       last;
-                   }
-               }
-           }
-       }
+if ($scm) {
+    @scm = uniq(@scm);
+    output(@scm);
+}
+
+if ($status) {
+    @status = uniq(@status);
+    output(@status);
+}
+
+if ($subsystem) {
+    @subsystem = uniq(@subsystem);
+    output(@subsystem);
+}
+
+if ($web) {
+    @web = uniq(@web);
+    output(@web);
+}
+
+exit($exit);
+
+sub get_maintainers {
+    %email_hash_name = ();
+    %email_hash_address = ();
+    %commit_author_hash = ();
+    %commit_signer_hash = ();
+    @email_to = ();
+    %hash_list_to = ();
+    @list_to = ();
+    @scm = ();
+    @web = ();
+    @subsystem = ();
+    @status = ();
+    %deduplicate_name_hash = ();
+    %deduplicate_address_hash = ();
+    if ($email_git_all_signature_types) {
+       $signature_pattern = "(.+?)[Bb][Yy]:";
+    } else {
+       $signature_pattern = "\(" . join("|", @signature_tags) . "\)";
+    }
+
+    # Find responsible parties
+
+    my %exact_pattern_match_hash = ();
+
+    foreach my $file (@files) {
+
+       my %hash;
+       my $tvi = find_first_section();
+       while ($tvi < @typevalue) {
+           my $start = find_starting_index($tvi);
+           my $end = find_ending_index($tvi);
+           my $exclude = 0;
+           my $i;
+
+           #Do not match excluded file patterns
 
-       if (!$exclude) {
            for ($i = $start; $i < $end; $i++) {
                my $line = $typevalue[$i];
                if ($line =~ m/^(\C):\s*(.*)/) {
                    my $type = $1;
                    my $value = $2;
-                   if ($type eq 'F') {
+                   if ($type eq 'X') {
                        if (file_match_pattern($file, $value)) {
-                           my $value_pd = ($value =~ tr@/@@);
-                           my $file_pd = ($file  =~ tr@/@@);
-                           $value_pd++ if (substr($value,-1,1) ne "/");
-                           if ($pattern_depth == 0 ||
-                               (($file_pd - $value_pd) < $pattern_depth)) {
-                               $hash{$tvi} = $value_pd;
+                           $exclude = 1;
+                           last;
+                       }
+                   }
+               }
+           }
+
+           if (!$exclude) {
+               for ($i = $start; $i < $end; $i++) {
+                   my $line = $typevalue[$i];
+                   if ($line =~ m/^(\C):\s*(.*)/) {
+                       my $type = $1;
+                       my $value = $2;
+                       if ($type eq 'F') {
+                           if (file_match_pattern($file, $value)) {
+                               my $value_pd = ($value =~ tr@/@@);
+                               my $file_pd = ($file  =~ tr@/@@);
+                               $value_pd++ if (substr($value,-1,1) ne "/");
+                               $value_pd = -1 if ($value =~ /^\.\*/);
+                               if ($value_pd >= $file_pd) {
+                                   $exact_pattern_match_hash{$file} = 1;
+                               }
+                               if ($pattern_depth == 0 ||
+                                   (($file_pd - $value_pd) < $pattern_depth)) {
+                                   $hash{$tvi} = $value_pd;
+                               }
                            }
                        }
                    }
                }
            }
+           $tvi = $end + 1;
        }
 
-       $tvi = $end + 1;
-    }
-
-    foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
-       add_categories($line);
+       foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
+           add_categories($line);
            if ($sections) {
                my $i;
                my $start = find_starting_index($line);
@@ -435,80 +590,71 @@ foreach my $file (@files) {
                }
                print("\n");
            }
+       }
     }
 
-    if ($email && $email_git) {
-       vcs_file_signoffs($file);
+    if ($keywords) {
+       @keyword_tvi = sort_and_uniq(@keyword_tvi);
+       foreach my $line (@keyword_tvi) {
+           add_categories($line);
+       }
     }
 
-    if ($email && $email_git_blame) {
-       vcs_file_blame($file);
+    foreach my $email (@email_to, @list_to) {
+       $email->[0] = deduplicate_email($email->[0]);
     }
-}
 
-if ($keywords) {
-    @keyword_tvi = sort_and_uniq(@keyword_tvi);
-    foreach my $line (@keyword_tvi) {
-       add_categories($line);
+    foreach my $file (@files) {
+       if ($email &&
+           ($email_git || ($email_git_fallback &&
+                           !$exact_pattern_match_hash{$file}))) {
+           vcs_file_signoffs($file);
+       }
+       if ($email && $email_git_blame) {
+           vcs_file_blame($file);
+       }
     }
-}
 
-if ($email) {
-    foreach my $chief (@penguin_chief) {
-       if ($chief =~ m/^(.*):(.*)/) {
-           my $email_address;
+    if ($email) {
+       foreach my $chief (@penguin_chief) {
+           if ($chief =~ m/^(.*):(.*)/) {
+               my $email_address;
 
-           $email_address = format_email($1, $2, $email_usename);
-           if ($email_git_penguin_chiefs) {
-               push(@email_to, [$email_address, 'chief penguin']);
-           } else {
-               @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
+               $email_address = format_email($1, $2, $email_usename);
+               if ($email_git_penguin_chiefs) {
+                   push(@email_to, [$email_address, 'chief penguin']);
+               } else {
+                   @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
+               }
            }
        }
-    }
 
-    foreach my $email (@file_emails) {
-       my ($name, $address) = parse_email($email);
+       foreach my $email (@file_emails) {
+           my ($name, $address) = parse_email($email);
 
-       my $tmp_email = format_email($name, $address, $email_usename);
-       push_email_address($tmp_email, '');
-       add_role($tmp_email, 'in file');
+           my $tmp_email = format_email($name, $address, $email_usename);
+           push_email_address($tmp_email, '');
+           add_role($tmp_email, 'in file');
+       }
     }
-}
 
-if ($email || $email_list) {
     my @to = ();
-    if ($email) {
-       @to = (@to, @email_to);
-    }
-    if ($email_list) {
-       @to = (@to, @list_to);
+    if ($email || $email_list) {
+       if ($email) {
+           @to = (@to, @email_to);
+       }
+       if ($email_list) {
+           @to = (@to, @list_to);
+       }
     }
-    output(merge_email(@to));
-}
-
-if ($scm) {
-    @scm = uniq(@scm);
-    output(@scm);
-}
-
-if ($status) {
-    @status = uniq(@status);
-    output(@status);
-}
 
-if ($subsystem) {
-    @subsystem = uniq(@subsystem);
-    output(@subsystem);
-}
+    if ($interactive) {
+       @to = interactive_get_maintainers(\@to);
+    }
 
-if ($web) {
-    @web = uniq(@web);
-    output(@web);
+    return @to;
 }
 
-exit($exit);
-
 sub file_match_pattern {
     my ($file, $pattern) = @_;
     if (substr($pattern, -1) eq "/") {
@@ -537,7 +683,8 @@ MAINTAINER field selection options:
   --email => print email address(es) if any
     --git => include recent git \*-by: signers
     --git-all-signature-types => include signers regardless of signature type
-        or use only ${signaturePattern} signers (default: $email_git_all_signature_types)
+        or use only ${signature_pattern} signers (default: $email_git_all_signature_types)
+    --git-fallback => use git when no exact MAINTAINERS pattern (default: $email_git_fallback)
     --git-chief-penguins => include ${penguin_chiefs}
     --git-min-signatures => number of signatures required (default: $email_git_min_signatures)
     --git-max-maintainers => maximum maintainers to add (default: $email_git_max_maintainers)
@@ -545,6 +692,7 @@ MAINTAINER field selection options:
     --git-blame => use git blame to find modified commits for patch or file
     --git-since => git history to use (default: $email_git_since)
     --hg-since => hg history to use (default: $email_hg_since)
+    --interactive => display a menu (mostly useful if used with the --git option)
     --m => include maintainer(s) if any
     --n => include name 'Full Name <addr\@domain.tld>'
     --l => include list(s) if any
@@ -565,8 +713,9 @@ Output type options:
 
 Other options:
   --pattern-depth => Number of pattern directory traversals (default: 0 (all))
-  --keywords => scan patch for keywords (default: 1 (on))
-  --sections => print the entire subsystem sections with pattern matches
+  --keywords => scan patch for keywords (default: $keywords)
+  --sections => print all of the subsystem sections with pattern matches
+  --mailmap => use .mailmap file (default: $email_use_mailmap)
   --version => show version
   --help => show this help information
 
@@ -606,30 +755,30 @@ EOT
 }
 
 sub top_of_kernel_tree {
-       my ($lk_path) = @_;
+    my ($lk_path) = @_;
 
-       if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
-           $lk_path .= "/";
-       }
-       if (   (-f "${lk_path}COPYING")
-           && (-f "${lk_path}CREDITS")
-           && (-f "${lk_path}Kbuild")
-           && (-f "${lk_path}MAINTAINERS")
-           && (-f "${lk_path}Makefile")
-           && (-f "${lk_path}README")
-           && (-d "${lk_path}Documentation")
-           && (-d "${lk_path}arch")
-           && (-d "${lk_path}include")
-           && (-d "${lk_path}drivers")
-           && (-d "${lk_path}fs")
-           && (-d "${lk_path}init")
-           && (-d "${lk_path}ipc")
-           && (-d "${lk_path}kernel")
-           && (-d "${lk_path}lib")
-           && (-d "${lk_path}scripts")) {
-               return 1;
-       }
-       return 0;
+    if ($lk_path ne "" && substr($lk_path,length($lk_path)-1,1) ne "/") {
+       $lk_path .= "/";
+    }
+    if (   (-f "${lk_path}COPYING")
+       && (-f "${lk_path}CREDITS")
+       && (-f "${lk_path}Kbuild")
+       && (-f "${lk_path}MAINTAINERS")
+       && (-f "${lk_path}Makefile")
+       && (-f "${lk_path}README")
+       && (-d "${lk_path}Documentation")
+       && (-d "${lk_path}arch")
+       && (-d "${lk_path}include")
+       && (-d "${lk_path}drivers")
+       && (-d "${lk_path}fs")
+       && (-d "${lk_path}init")
+       && (-d "${lk_path}ipc")
+       && (-d "${lk_path}kernel")
+       && (-d "${lk_path}lib")
+       && (-d "${lk_path}scripts")) {
+       return 1;
+    }
+    return 0;
 }
 
 sub parse_email {
@@ -821,11 +970,19 @@ sub add_categories {
                }
                if ($list_additional =~ m/subscribers-only/) {
                    if ($email_subscriber_list) {
-                       push(@list_to, [$list_address, "subscriber list${list_role}"]);
+                       if (!$hash_list_to{lc($list_address)}) {
+                           $hash_list_to{lc($list_address)} = 1;
+                           push(@list_to, [$list_address,
+                                           "subscriber list${list_role}"]);
+                       }
                    }
                } else {
                    if ($email_list) {
-                       push(@list_to, [$list_address, "open list${list_role}"]);
+                       if (!$hash_list_to{lc($list_address)}) {
+                           $hash_list_to{lc($list_address)} = 1;
+                           push(@list_to, [$list_address,
+                                           "open list${list_role}"]);
+                       }
                    }
                }
            } elsif ($ptype eq "M") {
@@ -856,15 +1013,12 @@ sub add_categories {
     }
 }
 
-my %email_hash_name;
-my %email_hash_address;
-
 sub email_inuse {
     my ($name, $address) = @_;
 
     return 1 if (($name eq "") && ($address eq ""));
-    return 1 if (($name ne "") && exists($email_hash_name{$name}));
-    return 1 if (($address ne "") && exists($email_hash_address{$address}));
+    return 1 if (($name ne "") && exists($email_hash_name{lc($name)}));
+    return 1 if (($address ne "") && exists($email_hash_address{lc($address)}));
 
     return 0;
 }
@@ -882,8 +1036,8 @@ sub push_email_address {
        push(@email_to, [format_email($name, $address, $email_usename), $role]);
     } elsif (!email_inuse($name, $address)) {
        push(@email_to, [format_email($name, $address, $email_usename), $role]);
-       $email_hash_name{$name}++;
-       $email_hash_address{$address}++;
+       $email_hash_name{lc($name)}++ if ($name ne "");
+       $email_hash_address{lc($address)}++;
     }
 
     return 1;
@@ -952,30 +1106,69 @@ sub which {
     return "";
 }
 
-sub mailmap {
-    my (@lines) = @_;
-    my %hash;
+sub which_conf {
+    my ($conf) = @_;
 
-    foreach my $line (@lines) {
-       my ($name, $address) = parse_email($line);
-       if (!exists($hash{$name})) {
-           $hash{$name} = $address;
-       } elsif ($address ne $hash{$name}) {
-           $address = $hash{$name};
-           $line = format_email($name, $address, $email_usename);
+    foreach my $path (split(/:/, ".:$ENV{HOME}:.scripts")) {
+       if (-e "$path/$conf") {
+           return "$path/$conf";
        }
-       if (exists($mailmap{$name})) {
-           my $obj = $mailmap{$name};
-           foreach my $map_address (@$obj) {
-               if (($map_address eq $address) &&
-                   ($map_address ne $hash{$name})) {
-                   $line = format_email($name, $hash{$name}, $email_usename);
-               }
-           }
+    }
+
+    return "";
+}
+
+sub mailmap_email {
+    my ($line) = @_;
+
+    my ($name, $address) = parse_email($line);
+    my $email = format_email($name, $address, 1);
+    my $real_name = $name;
+    my $real_address = $address;
+
+    if (exists $mailmap->{names}->{$email} ||
+       exists $mailmap->{addresses}->{$email}) {
+       if (exists $mailmap->{names}->{$email}) {
+           $real_name = $mailmap->{names}->{$email};
+       }
+       if (exists $mailmap->{addresses}->{$email}) {
+           $real_address = $mailmap->{addresses}->{$email};
+       }
+    } else {
+       if (exists $mailmap->{names}->{$address}) {
+           $real_name = $mailmap->{names}->{$address};
+       }
+       if (exists $mailmap->{addresses}->{$address}) {
+           $real_address = $mailmap->{addresses}->{$address};
        }
     }
+    return format_email($real_name, $real_address, 1);
+}
 
-    return @lines;
+sub mailmap {
+    my (@addresses) = @_;
+
+    my @mapped_emails = ();
+    foreach my $line (@addresses) {
+       push(@mapped_emails, mailmap_email($line));
+    }
+    merge_by_realname(@mapped_emails) if ($email_use_mailmap);
+    return @mapped_emails;
+}
+
+sub merge_by_realname {
+    my %address_map;
+    my (@emails) = @_;
+
+    foreach my $email (@emails) {
+       my ($name, $address) = parse_email($email);
+       if (exists $address_map{$name}) {
+           $address = $address_map{$name};
+           $email = format_email($name, $address, 1);
+       } else {
+           $address_map{$name} = $address;
+       }
+    }
 }
 
 sub git_execute_cmd {
@@ -999,10 +1192,30 @@ sub hg_execute_cmd {
     return @lines;
 }
 
+sub extract_formatted_signatures {
+    my (@signature_lines) = @_;
+
+    my @type = @signature_lines;
+
+    s/\s*(.*):.*/$1/ for (@type);
+
+    # cut -f2- -d":"
+    s/\s*.*:\s*(.+)\s*/$1/ for (@signature_lines);
+
+## Reformat email addresses (with names) to avoid badly written signatures
+
+    foreach my $signer (@signature_lines) {
+       $signer = deduplicate_email($signer);
+    }
+
+    return (\@type, \@signature_lines);
+}
+
 sub vcs_find_signers {
     my ($cmd) = @_;
-    my @lines = ();
     my $commits;
+    my @lines = ();
+    my @signatures = ();
 
     @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
 
@@ -1010,21 +1223,48 @@ sub vcs_find_signers {
 
     $commits = grep(/$pattern/, @lines);       # of commits
 
-    @lines = grep(/^[ \t]*${signaturePattern}.*\@.*$/, @lines);
+    @signatures = grep(/^[ \t]*${signature_pattern}.*\@.*$/, @lines);
+
+    return (0, @signatures) if !@signatures;
+
+    save_commits_by_author(@lines) if ($interactive);
+    save_commits_by_signer(@lines) if ($interactive);
+
+    if (!$email_git_penguin_chiefs) {
+       @signatures = grep(!/${penguin_chiefs}/i, @signatures);
+    }
+
+    my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+
+    return ($commits, @$signers_ref);
+}
+
+sub vcs_find_author {
+    my ($cmd) = @_;
+    my @lines = ();
+
+    @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
     if (!$email_git_penguin_chiefs) {
        @lines = grep(!/${penguin_chiefs}/i, @lines);
     }
-    # cut -f2- -d":"
-    s/.*:\s*(.+)\s*/$1/ for (@lines);
 
-## Reformat email addresses (with names) to avoid badly written signatures
+    return @lines if !@lines;
 
+    my @authors = ();
     foreach my $line (@lines) {
-       my ($name, $address) = parse_email($line);
-       $line = format_email($name, $address, 1);
+       if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+           my $author = $1;
+           my ($name, $address) = parse_email($author);
+           $author = format_email($name, $address, 1);
+           push(@authors, $author);
+       }
     }
 
-    return ($commits, @lines);
+    save_commits_by_author(@lines) if ($interactive);
+    save_commits_by_signer(@lines) if ($interactive);
+
+    return @authors;
 }
 
 sub vcs_save_commits {
@@ -1084,6 +1324,10 @@ sub vcs_blame {
        @commits = vcs_save_commits($cmd);
     }
 
+    foreach my $commit (@commits) {
+       $commit =~ s/^\^//g;
+    }
+
     return @commits;
 }
 
@@ -1092,7 +1336,7 @@ sub vcs_exists {
     %VCS_cmds = %VCS_cmds_git;
     return 1 if eval $VCS_cmds{"available"};
     %VCS_cmds = %VCS_cmds_hg;
-    return 1 if eval $VCS_cmds{"available"};
+    return 2 if eval $VCS_cmds{"available"};
     %VCS_cmds = ();
     if (!$printed_novcs) {
        warn("$P: No supported VCS found.  Add --nogit to options?\n");
@@ -1104,6 +1348,405 @@ sub vcs_exists {
     return 0;
 }
 
+sub vcs_is_git {
+    vcs_exists();
+    return $vcs_used == 1;
+}
+
+sub vcs_is_hg {
+    return $vcs_used == 2;
+}
+
+sub interactive_get_maintainers {
+    my ($list_ref) = @_;
+    my @list = @$list_ref;
+
+    vcs_exists();
+
+    my %selected;
+    my %authored;
+    my %signed;
+    my $count = 0;
+    my $maintained = 0;
+    foreach my $entry (@list) {
+       $maintained = 1 if ($entry->[1] =~ /^(maintainer|supporter)/i);
+       $selected{$count} = 1;
+       $authored{$count} = 0;
+       $signed{$count} = 0;
+       $count++;
+    }
+
+    #menu loop
+    my $done = 0;
+    my $print_options = 0;
+    my $redraw = 1;
+    while (!$done) {
+       $count = 0;
+       if ($redraw) {
+           printf STDERR "\n%1s %2s %-65s",
+                         "*", "#", "email/list and role:stats";
+           if ($email_git ||
+               ($email_git_fallback && !$maintained) ||
+               $email_git_blame) {
+               print STDERR "auth sign";
+           }
+           print STDERR "\n";
+           foreach my $entry (@list) {
+               my $email = $entry->[0];
+               my $role = $entry->[1];
+               my $sel = "";
+               $sel = "*" if ($selected{$count});
+               my $commit_author = $commit_author_hash{$email};
+               my $commit_signer = $commit_signer_hash{$email};
+               my $authored = 0;
+               my $signed = 0;
+               $authored++ for (@{$commit_author});
+               $signed++ for (@{$commit_signer});
+               printf STDERR "%1s %2d %-65s", $sel, $count + 1, $email;
+               printf STDERR "%4d %4d", $authored, $signed
+                   if ($authored > 0 || $signed > 0);
+               printf STDERR "\n     %s\n", $role;
+               if ($authored{$count}) {
+                   my $commit_author = $commit_author_hash{$email};
+                   foreach my $ref (@{$commit_author}) {
+                       print STDERR "     Author: @{$ref}[1]\n";
+                   }
+               }
+               if ($signed{$count}) {
+                   my $commit_signer = $commit_signer_hash{$email};
+                   foreach my $ref (@{$commit_signer}) {
+                       print STDERR "     @{$ref}[2]: @{$ref}[1]\n";
+                   }
+               }
+
+               $count++;
+           }
+       }
+       my $date_ref = \$email_git_since;
+       $date_ref = \$email_hg_since if (vcs_is_hg());
+       if ($print_options) {
+           $print_options = 0;
+           if (vcs_exists()) {
+               print STDERR <<EOT
+
+Version Control options:
+g  use git history      [$email_git]
+gf use git-fallback     [$email_git_fallback]
+b  use git blame        [$email_git_blame]
+bs use blame signatures [$email_git_blame_signatures]
+c# minimum commits      [$email_git_min_signatures]
+%# min percent          [$email_git_min_percent]
+d# history to use       [$$date_ref]
+x# max maintainers      [$email_git_max_maintainers]
+t  all signature types  [$email_git_all_signature_types]
+m  use .mailmap         [$email_use_mailmap]
+EOT
+           }
+           print STDERR <<EOT
+
+Additional options:
+0  toggle all
+tm toggle maintainers
+tg toggle git entries
+tl toggle open list entries
+ts toggle subscriber list entries
+f  emails in file       [$file_emails]
+k  keywords in file     [$keywords]
+r  remove duplicates    [$email_remove_duplicates]
+p# pattern match depth  [$pattern_depth]
+EOT
+       }
+       print STDERR
+"\n#(toggle), A#(author), S#(signed) *(all), ^(none), O(options), Y(approve): ";
+
+       my $input = <STDIN>;
+       chomp($input);
+
+       $redraw = 1;
+       my $rerun = 0;
+       my @wish = split(/[, ]+/, $input);
+       foreach my $nr (@wish) {
+           $nr = lc($nr);
+           my $sel = substr($nr, 0, 1);
+           my $str = substr($nr, 1);
+           my $val = 0;
+           $val = $1 if $str =~ /^(\d+)$/;
+
+           if ($sel eq "y") {
+               $interactive = 0;
+               $done = 1;
+               $output_rolestats = 0;
+               $output_roles = 0;
+               last;
+           } elsif ($nr =~ /^\d+$/ && $nr > 0 && $nr <= $count) {
+               $selected{$nr - 1} = !$selected{$nr - 1};
+           } elsif ($sel eq "*" || $sel eq '^') {
+               my $toggle = 0;
+               $toggle = 1 if ($sel eq '*');
+               for (my $i = 0; $i < $count; $i++) {
+                   $selected{$i} = $toggle;
+               }
+           } elsif ($sel eq "0") {
+               for (my $i = 0; $i < $count; $i++) {
+                   $selected{$i} = !$selected{$i};
+               }
+           } elsif ($sel eq "t") {
+               if (lc($str) eq "m") {
+                   for (my $i = 0; $i < $count; $i++) {
+                       $selected{$i} = !$selected{$i}
+                           if ($list[$i]->[1] =~ /^(maintainer|supporter)/i);
+                   }
+               } elsif (lc($str) eq "g") {
+                   for (my $i = 0; $i < $count; $i++) {
+                       $selected{$i} = !$selected{$i}
+                           if ($list[$i]->[1] =~ /^(author|commit|signer)/i);
+                   }
+               } elsif (lc($str) eq "l") {
+                   for (my $i = 0; $i < $count; $i++) {
+                       $selected{$i} = !$selected{$i}
+                           if ($list[$i]->[1] =~ /^(open list)/i);
+                   }
+               } elsif (lc($str) eq "s") {
+                   for (my $i = 0; $i < $count; $i++) {
+                       $selected{$i} = !$selected{$i}
+                           if ($list[$i]->[1] =~ /^(subscriber list)/i);
+                   }
+               }
+           } elsif ($sel eq "a") {
+               if ($val > 0 && $val <= $count) {
+                   $authored{$val - 1} = !$authored{$val - 1};
+               } elsif ($str eq '*' || $str eq '^') {
+                   my $toggle = 0;
+                   $toggle = 1 if ($str eq '*');
+                   for (my $i = 0; $i < $count; $i++) {
+                       $authored{$i} = $toggle;
+                   }
+               }
+           } elsif ($sel eq "s") {
+               if ($val > 0 && $val <= $count) {
+                   $signed{$val - 1} = !$signed{$val - 1};
+               } elsif ($str eq '*' || $str eq '^') {
+                   my $toggle = 0;
+                   $toggle = 1 if ($str eq '*');
+                   for (my $i = 0; $i < $count; $i++) {
+                       $signed{$i} = $toggle;
+                   }
+               }
+           } elsif ($sel eq "o") {
+               $print_options = 1;
+               $redraw = 1;
+           } elsif ($sel eq "g") {
+               if ($str eq "f") {
+                   bool_invert(\$email_git_fallback);
+               } else {
+                   bool_invert(\$email_git);
+               }
+               $rerun = 1;
+           } elsif ($sel eq "b") {
+               if ($str eq "s") {
+                   bool_invert(\$email_git_blame_signatures);
+               } else {
+                   bool_invert(\$email_git_blame);
+               }
+               $rerun = 1;
+           } elsif ($sel eq "c") {
+               if ($val > 0) {
+                   $email_git_min_signatures = $val;
+                   $rerun = 1;
+               }
+           } elsif ($sel eq "x") {
+               if ($val > 0) {
+                   $email_git_max_maintainers = $val;
+                   $rerun = 1;
+               }
+           } elsif ($sel eq "%") {
+               if ($str ne "" && $val >= 0) {
+                   $email_git_min_percent = $val;
+                   $rerun = 1;
+               }
+           } elsif ($sel eq "d") {
+               if (vcs_is_git()) {
+                   $email_git_since = $str;
+               } elsif (vcs_is_hg()) {
+                   $email_hg_since = $str;
+               }
+               $rerun = 1;
+           } elsif ($sel eq "t") {
+               bool_invert(\$email_git_all_signature_types);
+               $rerun = 1;
+           } elsif ($sel eq "f") {
+               bool_invert(\$file_emails);
+               $rerun = 1;
+           } elsif ($sel eq "r") {
+               bool_invert(\$email_remove_duplicates);
+               $rerun = 1;
+           } elsif ($sel eq "m") {
+               bool_invert(\$email_use_mailmap);
+               read_mailmap();
+               $rerun = 1;
+           } elsif ($sel eq "k") {
+               bool_invert(\$keywords);
+               $rerun = 1;
+           } elsif ($sel eq "p") {
+               if ($str ne "" && $val >= 0) {
+                   $pattern_depth = $val;
+                   $rerun = 1;
+               }
+           } elsif ($sel eq "h" || $sel eq "?") {
+               print STDERR <<EOT
+
+Interactive mode allows you to select the various maintainers, submitters,
+commit signers and mailing lists that could be CC'd on a patch.
+
+Any *'d entry is selected.
+
+If you have git or hg installed, you can choose to summarize the commit
+history of files in the patch.  Also, each line of the current file can
+be matched to its commit author and that commits signers with blame.
+
+Various knobs exist to control the length of time for active commit
+tracking, the maximum number of commit authors and signers to add,
+and such.
+
+Enter selections at the prompt until you are satisfied that the selected
+maintainers are appropriate.  You may enter multiple selections separated
+by either commas or spaces.
+
+EOT
+           } else {
+               print STDERR "invalid option: '$nr'\n";
+               $redraw = 0;
+           }
+       }
+       if ($rerun) {
+           print STDERR "git-blame can be very slow, please have patience..."
+               if ($email_git_blame);
+           goto &get_maintainers;
+       }
+    }
+
+    #drop not selected entries
+    $count = 0;
+    my @new_emailto = ();
+    foreach my $entry (@list) {
+       if ($selected{$count}) {
+           push(@new_emailto, $list[$count]);
+       }
+       $count++;
+    }
+    return @new_emailto;
+}
+
+sub bool_invert {
+    my ($bool_ref) = @_;
+
+    if ($$bool_ref) {
+       $$bool_ref = 0;
+    } else {
+       $$bool_ref = 1;
+    }
+}
+
+sub deduplicate_email {
+    my ($email) = @_;
+
+    my $matched = 0;
+    my ($name, $address) = parse_email($email);
+    $email = format_email($name, $address, 1);
+    $email = mailmap_email($email);
+
+    return $email if (!$email_remove_duplicates);
+
+    ($name, $address) = parse_email($email);
+
+    if ($name ne "" && $deduplicate_name_hash{lc($name)}) {
+       $name = $deduplicate_name_hash{lc($name)}->[0];
+       $address = $deduplicate_name_hash{lc($name)}->[1];
+       $matched = 1;
+    } elsif ($deduplicate_address_hash{lc($address)}) {
+       $name = $deduplicate_address_hash{lc($address)}->[0];
+       $address = $deduplicate_address_hash{lc($address)}->[1];
+       $matched = 1;
+    }
+    if (!$matched) {
+       $deduplicate_name_hash{lc($name)} = [ $name, $address ];
+       $deduplicate_address_hash{lc($address)} = [ $name, $address ];
+    }
+    $email = format_email($name, $address, 1);
+    $email = mailmap_email($email);
+    return $email;
+}
+
+sub save_commits_by_author {
+    my (@lines) = @_;
+
+    my @authors = ();
+    my @commits = ();
+    my @subjects = ();
+
+    foreach my $line (@lines) {
+       if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+           my $author = $1;
+           $author = deduplicate_email($author);
+           push(@authors, $author);
+       }
+       push(@commits, $1) if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+       push(@subjects, $1) if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+    }
+
+    for (my $i = 0; $i < @authors; $i++) {
+       my $exists = 0;
+       foreach my $ref(@{$commit_author_hash{$authors[$i]}}) {
+           if (@{$ref}[0] eq $commits[$i] &&
+               @{$ref}[1] eq $subjects[$i]) {
+               $exists = 1;
+               last;
+           }
+       }
+       if (!$exists) {
+           push(@{$commit_author_hash{$authors[$i]}},
+                [ ($commits[$i], $subjects[$i]) ]);
+       }
+    }
+}
+
+sub save_commits_by_signer {
+    my (@lines) = @_;
+
+    my $commit = "";
+    my $subject = "";
+
+    foreach my $line (@lines) {
+       $commit = $1 if ($line =~ m/$VCS_cmds{"commit_pattern"}/);
+       $subject = $1 if ($line =~ m/$VCS_cmds{"subject_pattern"}/);
+       if ($line =~ /^[ \t]*${signature_pattern}.*\@.*$/) {
+           my @signatures = ($line);
+           my ($types_ref, $signers_ref) = extract_formatted_signatures(@signatures);
+           my @types = @$types_ref;
+           my @signers = @$signers_ref;
+
+           my $type = $types[0];
+           my $signer = $signers[0];
+
+           $signer = deduplicate_email($signer);
+
+           my $exists = 0;
+           foreach my $ref(@{$commit_signer_hash{$signer}}) {
+               if (@{$ref}[0] eq $commit &&
+                   @{$ref}[1] eq $subject &&
+                   @{$ref}[2] eq $type) {
+                   $exists = 1;
+                   last;
+               }
+           }
+           if (!$exists) {
+               push(@{$commit_signer_hash{$signer}},
+                    [ ($commit, $subject, $type) ]);
+           }
+       }
+    }
+}
+
 sub vcs_assign {
     my ($role, $divisor, @lines) = @_;
 
@@ -1117,9 +1760,9 @@ sub vcs_assign {
        $divisor = 1;
     }
 
-    if ($email_remove_duplicates) {
-       @lines = mailmap(@lines);
-    }
+    @lines = mailmap(@lines);
+
+    return if (@lines <= 0);
 
     @lines = sort(@lines);
 
@@ -1152,12 +1795,18 @@ sub vcs_file_signoffs {
     my @signers = ();
     my $commits;
 
-    return if (!vcs_exists());
+    $vcs_used = vcs_exists();
+    return if (!$vcs_used);
 
     my $cmd = $VCS_cmds{"find_signers_cmd"};
     $cmd =~ s/(\$\w+)/$1/eeg;          # interpolate $cmd
 
     ($commits, @signers) = vcs_find_signers($cmd);
+
+    foreach my $signer (@signers) {
+       $signer = deduplicate_email($signer);
+    }
+
     vcs_assign("commit_signer", $commits, @signers);
 }
 
@@ -1165,29 +1814,114 @@ sub vcs_file_blame {
     my ($file) = @_;
 
     my @signers = ();
+    my @all_commits = ();
     my @commits = ();
     my $total_commits;
+    my $total_lines;
 
-    return if (!vcs_exists());
+    $vcs_used = vcs_exists();
+    return if (!$vcs_used);
 
-    @commits = vcs_blame($file);
-    @commits = uniq(@commits);
+    @all_commits = vcs_blame($file);
+    @commits = uniq(@all_commits);
     $total_commits = @commits;
+    $total_lines = @all_commits;
 
-    foreach my $commit (@commits) {
-       my $commit_count;
-       my @commit_signers = ();
+    if ($email_git_blame_signatures) {
+       if (vcs_is_hg()) {
+           my $commit_count;
+           my @commit_signers = ();
+           my $commit = join(" -r ", @commits);
+           my $cmd;
+
+           $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+           $cmd =~ s/(\$\w+)/$1/eeg;   #substitute variables in $cmd
+
+           ($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+           push(@signers, @commit_signers);
+       } else {
+           foreach my $commit (@commits) {
+               my $commit_count;
+               my @commit_signers = ();
+               my $cmd;
 
-       my $cmd = $VCS_cmds{"find_commit_signers_cmd"};
-       $cmd =~ s/(\$\w+)/$1/eeg;       #interpolate $cmd
+               $cmd = $VCS_cmds{"find_commit_signers_cmd"};
+               $cmd =~ s/(\$\w+)/$1/eeg;       #substitute variables in $cmd
 
-       ($commit_count, @commit_signers) = vcs_find_signers($cmd);
-       push(@signers, @commit_signers);
+               ($commit_count, @commit_signers) = vcs_find_signers($cmd);
+
+               push(@signers, @commit_signers);
+           }
+       }
     }
 
     if ($from_filename) {
+       if ($output_rolestats) {
+           my @blame_signers;
+           if (vcs_is_hg()) {{         # Double brace for last exit
+               my $commit_count;
+               my @commit_signers = ();
+               @commits = uniq(@commits);
+               @commits = sort(@commits);
+               my $commit = join(" -r ", @commits);
+               my $cmd;
+
+               $cmd = $VCS_cmds{"find_commit_author_cmd"};
+               $cmd =~ s/(\$\w+)/$1/eeg;       #substitute variables in $cmd
+
+               my @lines = ();
+
+               @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
+
+               if (!$email_git_penguin_chiefs) {
+                   @lines = grep(!/${penguin_chiefs}/i, @lines);
+               }
+
+               last if !@lines;
+
+               my @authors = ();
+               foreach my $line (@lines) {
+                   if ($line =~ m/$VCS_cmds{"author_pattern"}/) {
+                       my $author = $1;
+                       $author = deduplicate_email($author);
+                       push(@authors, $author);
+                   }
+               }
+
+               save_commits_by_author(@lines) if ($interactive);
+               save_commits_by_signer(@lines) if ($interactive);
+
+               push(@signers, @authors);
+           }}
+           else {
+               foreach my $commit (@commits) {
+                   my $i;
+                   my $cmd = $VCS_cmds{"find_commit_author_cmd"};
+                   $cmd =~ s/(\$\w+)/$1/eeg;   #interpolate $cmd
+                   my @author = vcs_find_author($cmd);
+                   next if !@author;
+
+                   my $formatted_author = deduplicate_email($author[0]);
+
+                   my $count = grep(/$commit/, @all_commits);
+                   for ($i = 0; $i < $count ; $i++) {
+                       push(@blame_signers, $formatted_author);
+                   }
+               }
+           }
+           if (@blame_signers) {
+               vcs_assign("authored lines", $total_lines, @blame_signers);
+           }
+       }
+       foreach my $signer (@signers) {
+           $signer = deduplicate_email($signer);
+       }
        vcs_assign("commits", $total_commits, @signers);
     } else {
+       foreach my $signer (@signers) {
+           $signer = deduplicate_email($signer);
+       }
        vcs_assign("modified commits", $total_commits, @signers);
     }
 }
index 3fbcd1d..ac79032 100644 (file)
@@ -70,6 +70,7 @@ int ima_init(void);
 void ima_cleanup(void);
 int ima_fs_init(void);
 void ima_fs_cleanup(void);
+int ima_inode_alloc(struct inode *inode);
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
                           const char *op, struct inode *inode);
 int ima_calc_hash(struct file *file, char *digest);
@@ -96,19 +97,16 @@ static inline unsigned long ima_hash_key(u8 *digest)
 }
 
 /* iint cache flags */
-#define IMA_MEASURED           1
+#define IMA_MEASURED           0x01
 
 /* integrity data associated with an inode */
 struct ima_iint_cache {
+       struct rb_node rb_node; /* rooted in ima_iint_tree */
+       struct inode *inode;    /* back pointer to inode in question */
        u64 version;            /* track inode changes */
-       unsigned long flags;
+       unsigned char flags;
        u8 digest[IMA_DIGEST_SIZE];
        struct mutex mutex;     /* protects: version, flags, digest */
-       long readcount;         /* measured files readcount */
-       long writecount;        /* measured files writecount */
-       long opencount;         /* opens reference count */
-       struct kref refcount;   /* ima_iint_cache reference count */
-       struct rcu_head rcu;
 };
 
 /* LIM API function definitions */
@@ -122,13 +120,11 @@ int ima_store_template(struct ima_template_entry *entry, int violation,
 void ima_template_show(struct seq_file *m, void *e,
                       enum ima_show_type show);
 
-/* radix tree calls to lookup, insert, delete
+/* rbtree tree calls to lookup, insert, delete
  * integrity data associated with an inode.
  */
 struct ima_iint_cache *ima_iint_insert(struct inode *inode);
-struct ima_iint_cache *ima_iint_find_get(struct inode *inode);
-void iint_free(struct kref *kref);
-void iint_rcu_free(struct rcu_head *rcu);
+struct ima_iint_cache *ima_iint_find(struct inode *inode);
 
 /* IMA policy related functions */
 enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK };
index 52015d0..d3963de 100644 (file)
@@ -116,7 +116,7 @@ int ima_must_measure(struct ima_iint_cache *iint, struct inode *inode,
 {
        int must_measure;
 
-       if (iint->flags & IMA_MEASURED)
+       if (iint && iint->flags & IMA_MEASURED)
                return 1;
 
        must_measure = ima_match_policy(inode, function, mask);
index afba4ae..c442e47 100644 (file)
  * File: ima_iint.c
  *     - implements the IMA hooks: ima_inode_alloc, ima_inode_free
  *     - cache integrity information associated with an inode
- *       using a radix tree.
+ *       using a rbtree tree.
  */
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <linux/radix-tree.h>
+#include <linux/rbtree.h>
 #include "ima.h"
 
-RADIX_TREE(ima_iint_store, GFP_ATOMIC);
-DEFINE_SPINLOCK(ima_iint_lock);
+static struct rb_root ima_iint_tree = RB_ROOT;
+static DEFINE_SPINLOCK(ima_iint_lock);
 static struct kmem_cache *iint_cache __read_mostly;
 
 int iint_initialized = 0;
 
-/* ima_iint_find_get - return the iint associated with an inode
- *
- * ima_iint_find_get gets a reference to the iint. Caller must
- * remember to put the iint reference.
+/*
+ * __ima_iint_find - return the iint associated with an inode
  */
-struct ima_iint_cache *ima_iint_find_get(struct inode *inode)
+static struct ima_iint_cache *__ima_iint_find(struct inode *inode)
 {
        struct ima_iint_cache *iint;
+       struct rb_node *n = ima_iint_tree.rb_node;
+
+       assert_spin_locked(&ima_iint_lock);
+
+       while (n) {
+               iint = rb_entry(n, struct ima_iint_cache, rb_node);
+
+               if (inode < iint->inode)
+                       n = n->rb_left;
+               else if (inode > iint->inode)
+                       n = n->rb_right;
+               else
+                       break;
+       }
+       if (!n)
+               return NULL;
 
-       rcu_read_lock();
-       iint = radix_tree_lookup(&ima_iint_store, (unsigned long)inode);
-       if (!iint)
-               goto out;
-       kref_get(&iint->refcount);
-out:
-       rcu_read_unlock();
        return iint;
 }
 
-/**
- * ima_inode_alloc - allocate an iint associated with an inode
- * @inode: pointer to the inode
+/*
+ * ima_iint_find - return the iint associated with an inode
  */
-int ima_inode_alloc(struct inode *inode)
+struct ima_iint_cache *ima_iint_find(struct inode *inode)
 {
-       struct ima_iint_cache *iint = NULL;
-       int rc = 0;
-
-       iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
-       if (!iint)
-               return -ENOMEM;
+       struct ima_iint_cache *iint;
 
-       rc = radix_tree_preload(GFP_NOFS);
-       if (rc < 0)
-               goto out;
+       if (!IS_IMA(inode))
+               return NULL;
 
        spin_lock(&ima_iint_lock);
-       rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint);
+       iint = __ima_iint_find(inode);
        spin_unlock(&ima_iint_lock);
-       radix_tree_preload_end();
-out:
-       if (rc < 0)
-               kmem_cache_free(iint_cache, iint);
 
-       return rc;
+       return iint;
 }
 
-/* iint_free - called when the iint refcount goes to zero */
-void iint_free(struct kref *kref)
+static void iint_free(struct ima_iint_cache *iint)
 {
-       struct ima_iint_cache *iint = container_of(kref, struct ima_iint_cache,
-                                                  refcount);
        iint->version = 0;
        iint->flags = 0UL;
-       if (iint->readcount != 0) {
-               printk(KERN_INFO "%s: readcount: %ld\n", __func__,
-                      iint->readcount);
-               iint->readcount = 0;
-       }
-       if (iint->writecount != 0) {
-               printk(KERN_INFO "%s: writecount: %ld\n", __func__,
-                      iint->writecount);
-               iint->writecount = 0;
-       }
-       if (iint->opencount != 0) {
-               printk(KERN_INFO "%s: opencount: %ld\n", __func__,
-                      iint->opencount);
-               iint->opencount = 0;
-       }
-       kref_init(&iint->refcount);
        kmem_cache_free(iint_cache, iint);
 }
 
-void iint_rcu_free(struct rcu_head *rcu_head)
+/**
+ * ima_inode_alloc - allocate an iint associated with an inode
+ * @inode: pointer to the inode
+ */
+int ima_inode_alloc(struct inode *inode)
 {
-       struct ima_iint_cache *iint = container_of(rcu_head,
-                                                  struct ima_iint_cache, rcu);
-       kref_put(&iint->refcount, iint_free);
+       struct rb_node **p;
+       struct rb_node *new_node, *parent = NULL;
+       struct ima_iint_cache *new_iint, *test_iint;
+       int rc;
+
+       new_iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
+       if (!new_iint)
+               return -ENOMEM;
+
+       new_iint->inode = inode;
+       new_node = &new_iint->rb_node;
+
+       mutex_lock(&inode->i_mutex); /* i_flags */
+       spin_lock(&ima_iint_lock);
+
+       p = &ima_iint_tree.rb_node;
+       while (*p) {
+               parent = *p;
+               test_iint = rb_entry(parent, struct ima_iint_cache, rb_node);
+
+               rc = -EEXIST;
+               if (inode < test_iint->inode)
+                       p = &(*p)->rb_left;
+               else if (inode > test_iint->inode)
+                       p = &(*p)->rb_right;
+               else
+                       goto out_err;
+       }
+
+       inode->i_flags |= S_IMA;
+       rb_link_node(new_node, parent, p);
+       rb_insert_color(new_node, &ima_iint_tree);
+
+       spin_unlock(&ima_iint_lock);
+       mutex_unlock(&inode->i_mutex); /* i_flags */
+
+       return 0;
+out_err:
+       spin_unlock(&ima_iint_lock);
+       mutex_unlock(&inode->i_mutex); /* i_flags */
+       iint_free(new_iint);
+
+       return rc;
 }
 
 /**
@@ -116,11 +137,20 @@ void ima_inode_free(struct inode *inode)
 {
        struct ima_iint_cache *iint;
 
+       if (inode->i_readcount)
+               printk(KERN_INFO "%s: readcount: %u\n", __func__, inode->i_readcount);
+
+       inode->i_readcount = 0;
+
+       if (!IS_IMA(inode))
+               return;
+
        spin_lock(&ima_iint_lock);
-       iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode);
+       iint = __ima_iint_find(inode);
+       rb_erase(&iint->rb_node, &ima_iint_tree);
        spin_unlock(&ima_iint_lock);
-       if (iint)
-               call_rcu(&iint->rcu, iint_rcu_free);
+
+       iint_free(iint);
 }
 
 static void init_once(void *foo)
@@ -131,10 +161,6 @@ static void init_once(void *foo)
        iint->version = 0;
        iint->flags = 0UL;
        mutex_init(&iint->mutex);
-       iint->readcount = 0;
-       iint->writecount = 0;
-       iint->opencount = 0;
-       kref_init(&iint->refcount);
 }
 
 static int __init ima_iintcache_init(void)
index e662b89..203de97 100644 (file)
@@ -85,50 +85,6 @@ out:
        return found;
 }
 
-/* ima_read_write_check - reflect possible reading/writing errors in the PCR.
- *
- * When opening a file for read, if the file is already open for write,
- * the file could change, resulting in a file measurement error.
- *
- * Opening a file for write, if the file is already open for read, results
- * in a time of measure, time of use (ToMToU) error.
- *
- * In either case invalidate the PCR.
- */
-enum iint_pcr_error { TOMTOU, OPEN_WRITERS };
-static void ima_read_write_check(enum iint_pcr_error error,
-                                struct ima_iint_cache *iint,
-                                struct inode *inode,
-                                const unsigned char *filename)
-{
-       switch (error) {
-       case TOMTOU:
-               if (iint->readcount > 0)
-                       ima_add_violation(inode, filename, "invalid_pcr",
-                                         "ToMToU");
-               break;
-       case OPEN_WRITERS:
-               if (iint->writecount > 0)
-                       ima_add_violation(inode, filename, "invalid_pcr",
-                                         "open_writers");
-               break;
-       }
-}
-
-/*
- * Update the counts given an fmode_t
- */
-static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode)
-{
-       BUG_ON(!mutex_is_locked(&iint->mutex));
-
-       iint->opencount++;
-       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-               iint->readcount++;
-       if (mode & FMODE_WRITE)
-               iint->writecount++;
-}
-
 /*
  * ima_counts_get - increment file counts
  *
@@ -145,62 +101,101 @@ void ima_counts_get(struct file *file)
        struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = dentry->d_inode;
        fmode_t mode = file->f_mode;
-       struct ima_iint_cache *iint;
        int rc;
+       bool send_tomtou = false, send_writers = false;
 
-       if (!iint_initialized || !S_ISREG(inode->i_mode))
+       if (!S_ISREG(inode->i_mode))
                return;
-       iint = ima_iint_find_get(inode);
-       if (!iint)
-               return;
-       mutex_lock(&iint->mutex);
+
+       spin_lock(&inode->i_lock);
+
        if (!ima_initialized)
                goto out;
-       rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK);
-       if (rc < 0)
-               goto out;
 
        if (mode & FMODE_WRITE) {
-               ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name);
+               if (inode->i_readcount && IS_IMA(inode))
+                       send_tomtou = true;
                goto out;
        }
-       ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name);
+
+       rc = ima_must_measure(NULL, inode, MAY_READ, FILE_CHECK);
+       if (rc < 0)
+               goto out;
+
+       if (atomic_read(&inode->i_writecount) > 0)
+               send_writers = true;
 out:
-       ima_inc_counts(iint, file->f_mode);
-       mutex_unlock(&iint->mutex);
+       /* remember the vfs deals with i_writecount */
+       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
+               inode->i_readcount++;
 
-       kref_put(&iint->refcount, iint_free);
+       spin_unlock(&inode->i_lock);
+
+       if (send_tomtou)
+               ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
+                                 "ToMToU");
+       if (send_writers)
+               ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
+                                 "open_writers");
 }
 
 /*
  * Decrement ima counts
  */
-static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
-                          struct file *file)
+static void ima_dec_counts(struct inode *inode, struct file *file)
 {
        mode_t mode = file->f_mode;
-       BUG_ON(!mutex_is_locked(&iint->mutex));
 
-       iint->opencount--;
-       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
-               iint->readcount--;
-       if (mode & FMODE_WRITE) {
-               iint->writecount--;
-               if (iint->writecount == 0) {
-                       if (iint->version != inode->i_version)
-                               iint->flags &= ~IMA_MEASURED;
+       assert_spin_locked(&inode->i_lock);
+
+       if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
+               if (unlikely(inode->i_readcount == 0)) {
+                       if (!ima_limit_imbalance(file)) {
+                               printk(KERN_INFO "%s: open/free imbalance (r:%u)\n",
+                                      __func__, inode->i_readcount);
+                               dump_stack();
+                       }
+                       return;
                }
+               inode->i_readcount--;
        }
+}
 
-       if (((iint->opencount < 0) ||
-            (iint->readcount < 0) ||
-            (iint->writecount < 0)) &&
-           !ima_limit_imbalance(file)) {
-               printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n",
-                      __func__, iint->readcount, iint->writecount,
-                      iint->opencount);
-               dump_stack();
-       }
+static void ima_check_last_writer(struct ima_iint_cache *iint,
+                                 struct inode *inode,
+                                 struct file *file)
+{
+       mode_t mode = file->f_mode;
+
+       BUG_ON(!mutex_is_locked(&iint->mutex));
+       assert_spin_locked(&inode->i_lock);
+
+       if (mode & FMODE_WRITE &&
+           atomic_read(&inode->i_writecount) == 1 &&
+           iint->version != inode->i_version)
+               iint->flags &= ~IMA_MEASURED;
+}
+
+static void ima_file_free_iint(struct ima_iint_cache *iint, struct inode *inode,
+                              struct file *file)
+{
+       mutex_lock(&iint->mutex);
+       spin_lock(&inode->i_lock);
+
+       ima_dec_counts(inode, file);
+       ima_check_last_writer(iint, inode, file);
+
+       spin_unlock(&inode->i_lock);
+       mutex_unlock(&iint->mutex);
+}
+
+static void ima_file_free_noiint(struct inode *inode, struct file *file)
+{
+       spin_lock(&inode->i_lock);
+
+       ima_dec_counts(inode, file);
+
+       spin_unlock(&inode->i_lock);
 }
 
 /**
@@ -208,7 +203,7 @@ static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode,
  * @file: pointer to file structure being freed
  *
  * Flag files that changed, based on i_version;
- * and decrement the iint readcount/writecount.
+ * and decrement the i_readcount.
  */
 void ima_file_free(struct file *file)
 {
@@ -217,14 +212,14 @@ void ima_file_free(struct file *file)
 
        if (!iint_initialized || !S_ISREG(inode->i_mode))
                return;
-       iint = ima_iint_find_get(inode);
-       if (!iint)
-               return;
 
-       mutex_lock(&iint->mutex);
-       ima_dec_counts(iint, inode, file);
-       mutex_unlock(&iint->mutex);
-       kref_put(&iint->refcount, iint_free);
+       iint = ima_iint_find(inode);
+
+       if (iint)
+               ima_file_free_iint(iint, inode, file);
+       else
+               ima_file_free_noiint(inode, file);
+
 }
 
 static int process_measurement(struct file *file, const unsigned char *filename,
@@ -236,11 +231,21 @@ static int process_measurement(struct file *file, const unsigned char *filename,
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
                return 0;
-       iint = ima_iint_find_get(inode);
-       if (!iint)
-               return -ENOMEM;
+
+       rc = ima_must_measure(NULL, inode, mask, function);
+       if (rc != 0)
+               return rc;
+retry:
+       iint = ima_iint_find(inode);
+       if (!iint) {
+               rc = ima_inode_alloc(inode);
+               if (!rc || rc == -EEXIST)
+                       goto retry;
+               return rc;
+       }
 
        mutex_lock(&iint->mutex);
+
        rc = ima_must_measure(iint, inode, mask, function);
        if (rc != 0)
                goto out;
@@ -250,7 +255,6 @@ static int process_measurement(struct file *file, const unsigned char *filename,
                ima_store_measurement(iint, file, filename);
 out:
        mutex_unlock(&iint->mutex);
-       kref_put(&iint->refcount, iint_free);
        return rc;
 }
 
index b50f472..3ef5e2a 100644 (file)
@@ -325,16 +325,8 @@ EXPORT_SYMBOL(security_sb_parse_opts_str);
 
 int security_inode_alloc(struct inode *inode)
 {
-       int ret;
-
        inode->i_security = NULL;
-       ret =  security_ops->inode_alloc_security(inode);
-       if (ret)
-               return ret;
-       ret = ima_inode_alloc(inode);
-       if (ret)
-               security_inode_free(inode);
-       return ret;
+       return security_ops->inode_alloc_security(inode);
 }
 
 void security_inode_free(struct inode *inode)
index 9969618..d211c9f 100644 (file)
@@ -31,7 +31,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
 #include "omap-mcbsp.h"
@@ -598,93 +597,6 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
-static int omap_mcbsp_dai_set_clks_src(struct omap_mcbsp_data *mcbsp_data,
-                                      int clk_id)
-{
-       int sel_bit;
-       u16 reg, reg_devconf1 = OMAP243X_CONTROL_DEVCONF1;
-
-       if (cpu_class_is_omap1()) {
-               /* OMAP1's can use only external source clock */
-               if (unlikely(clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK))
-                       return -EINVAL;
-               else
-                       return 0;
-       }
-
-       if (cpu_is_omap2420() && mcbsp_data->bus_id > 1)
-               return -EINVAL;
-
-       if (cpu_is_omap343x())
-               reg_devconf1 = OMAP343X_CONTROL_DEVCONF1;
-
-       switch (mcbsp_data->bus_id) {
-       case 0:
-               reg = OMAP2_CONTROL_DEVCONF0;
-               sel_bit = 2;
-               break;
-       case 1:
-               reg = OMAP2_CONTROL_DEVCONF0;
-               sel_bit = 6;
-               break;
-       case 2:
-               reg = reg_devconf1;
-               sel_bit = 0;
-               break;
-       case 3:
-               reg = reg_devconf1;
-               sel_bit = 2;
-               break;
-       case 4:
-               reg = reg_devconf1;
-               sel_bit = 4;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK)
-               omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
-       else
-               omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
-
-       return 0;
-}
-
-static int omap_mcbsp_dai_set_rcvr_src(struct omap_mcbsp_data *mcbsp_data,
-                                      int clk_id)
-{
-       int sel_bit, set = 0;
-       u16 reg = OMAP2_CONTROL_DEVCONF0;
-
-       if (cpu_class_is_omap1())
-               return -EINVAL; /* TODO: Can this be implemented for OMAP1? */
-       if (mcbsp_data->bus_id != 0)
-               return -EINVAL;
-
-       switch (clk_id) {
-       case OMAP_MCBSP_CLKR_SRC_CLKX:
-               set = 1;
-       case OMAP_MCBSP_CLKR_SRC_CLKR:
-               sel_bit = 3;
-               break;
-       case OMAP_MCBSP_FSR_SRC_FSX:
-               set = 1;
-       case OMAP_MCBSP_FSR_SRC_FSR:
-               sel_bit = 4;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       if (set)
-               omap_ctrl_writel(omap_ctrl_readl(reg) | (1 << sel_bit), reg);
-       else
-               omap_ctrl_writel(omap_ctrl_readl(reg) & ~(1 << sel_bit), reg);
-
-       return 0;
-}
-
 static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                                         int clk_id, unsigned int freq,
                                         int dir)
@@ -693,6 +605,14 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int err = 0;
 
+       /* The McBSP signal muxing functions are only available on McBSP1 */
+       if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
+           clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
+           clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
+           clk_id == OMAP_MCBSP_FSR_SRC_FSX)
+               if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
+                       return -EINVAL;
+
        mcbsp_data->in_freq = freq;
 
        switch (clk_id) {
@@ -700,8 +620,20 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                regs->srgr2     |= CLKSM;
                break;
        case OMAP_MCBSP_SYSCLK_CLKS_FCLK:
+               if (cpu_class_is_omap1()) {
+                       err = -EINVAL;
+                       break;
+               }
+               err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+                                              MCBSP_CLKS_PRCM_SRC);
+               break;
        case OMAP_MCBSP_SYSCLK_CLKS_EXT:
-               err = omap_mcbsp_dai_set_clks_src(mcbsp_data, clk_id);
+               if (cpu_class_is_omap1()) {
+                       err = 0;
+                       break;
+               }
+               err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+                                              MCBSP_CLKS_PAD_SRC);
                break;
 
        case OMAP_MCBSP_SYSCLK_CLKX_EXT:
@@ -710,11 +642,18 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
                regs->pcr0      |= SCLKME;
                break;
 
+
        case OMAP_MCBSP_CLKR_SRC_CLKR:
+               omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
+               break;
        case OMAP_MCBSP_CLKR_SRC_CLKX:
+               omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
+               break;
        case OMAP_MCBSP_FSR_SRC_FSR:
+               omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
+               break;
        case OMAP_MCBSP_FSR_SRC_FSX:
-               err = omap_mcbsp_dai_set_rcvr_src(mcbsp_data, clk_id);
+               omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
                break;
        default:
                err = -ENODEV;
index f161c2f..bed09c2 100644 (file)
@@ -32,7 +32,6 @@
 #include <sound/initval.h>
 #include <sound/soc.h>
 
-#include <plat/control.h>
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
 #include "mcpdm.h"