]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'for-next' of git://git.o-hand.com/linux-mfd
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Oct 2008 16:22:47 +0000 (09:22 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 20 Oct 2008 16:22:47 +0000 (09:22 -0700)
* 'for-next' of git://git.o-hand.com/linux-mfd:
  mfd: further unbork the ucb1400 ac97_bus dependencies
  mfd: ucb1400 needs GPIO
  mfd: ucb1400 sound driver uses/depends on AC97_BUS:
  mfd: Don't use NO_IRQ in WM8350
  mfd: update TMIO drivers to use the clock API
  mfd: twl4030-core irq simplification
  mfd: add base support for Dialog DA9030/DA9034 PMICs
  mfd: TWL4030 core driver
  mfd: support tmiofb cell on tc6393xb
  mfd: add OHCI cell to tc6393xb
  mfd: Fix htc-egpio compile warning
  mfd: do tcb6393xb state restore on resume only if requested
  mfd: provide and use setup hook for tc6393xb
  mfd: update sm501 debugging/low information messages
  mfd: reduce stack usage in mfd-core.c

545 files changed:
.mailmap
Documentation/cgroups/cgroups.txt [moved from Documentation/cgroups.txt with 100% similarity]
Documentation/cgroups/freezer-subsystem.txt [new file with mode: 0644]
Documentation/controllers/memory.txt
Documentation/cpusets.txt
Documentation/filesystems/ext3.txt
Documentation/filesystems/proc.txt
Documentation/filesystems/ubifs.txt
Documentation/kernel-parameters.txt
Documentation/mtd/nand_ecc.txt [new file with mode: 0644]
Documentation/sysrq.txt
Documentation/vm/unevictable-lru.txt [new file with mode: 0644]
arch/alpha/Kconfig
arch/alpha/include/asm/thread_info.h
arch/alpha/kernel/core_marvel.c
arch/alpha/kernel/time.c
arch/arm/Kconfig
arch/arm/mach-pxa/include/mach/pxa3xx_nand.h
arch/arm/plat-mxc/include/mach/mxc_nand.h [new file with mode: 0644]
arch/arm/plat-omap/include/mach/onenand.h
arch/avr32/Kconfig
arch/avr32/include/asm/thread_info.h
arch/blackfin/Kconfig
arch/cris/Kconfig
arch/cris/arch-v10/drivers/ds1302.c
arch/cris/arch-v10/drivers/pcf8563.c
arch/cris/arch-v32/drivers/pcf8563.c
arch/cris/kernel/time.c
arch/frv/Kconfig
arch/h8300/Kconfig
arch/h8300/include/asm/thread_info.h
arch/ia64/Kconfig
arch/ia64/hp/common/sba_iommu.c
arch/ia64/kernel/crash_dump.c
arch/ia64/kernel/efi.c
arch/ia64/kernel/setup.c
arch/ia64/mm/init.c
arch/m32r/Kconfig
arch/m68k/Kconfig
arch/m68k/bvme6000/rtc.c
arch/m68knommu/Kconfig
arch/m68knommu/include/asm/thread_info.h
arch/mips/Kconfig
arch/mips/dec/time.c
arch/mips/include/asm/mc146818-time.h
arch/mips/pmc-sierra/yosemite/setup.c
arch/mips/sibyte/swarm/rtc_m41t81.c
arch/mips/sibyte/swarm/rtc_xicor1241.c
arch/mn10300/Kconfig
arch/mn10300/kernel/rtc.c
arch/parisc/Kconfig
arch/powerpc/Kconfig
arch/powerpc/include/asm/ps3av.h
arch/powerpc/kernel/crash_dump.c
arch/powerpc/mm/mem.c
arch/s390/Kconfig
arch/s390/include/asm/thread_info.h
arch/s390/mm/init.c
arch/sh/Kconfig
arch/sh/Kconfig.debug
arch/sh/Makefile
arch/sh/boards/Kconfig
arch/sh/boards/Makefile
arch/sh/boards/board-ap325rxa.c
arch/sh/boards/board-edosk7760.c [new file with mode: 0644]
arch/sh/boards/board-magicpanelr2.c
arch/sh/boards/board-rsk7203.c
arch/sh/boards/board-sh7785lcr.c
arch/sh/boards/board-shmin.c
arch/sh/boards/mach-edosk7705/io.c
arch/sh/boards/mach-edosk7705/setup.c
arch/sh/boards/mach-highlander/irq-r7780mp.c
arch/sh/boards/mach-highlander/irq-r7780rp.c
arch/sh/boards/mach-highlander/irq-r7785rp.c
arch/sh/boards/mach-highlander/psw.c
arch/sh/boards/mach-highlander/setup.c
arch/sh/boards/mach-hp6xx/hp6xx_apm.c
arch/sh/boards/mach-hp6xx/pm.c
arch/sh/boards/mach-hp6xx/setup.c
arch/sh/boards/mach-lboxre2/irq.c
arch/sh/boards/mach-lboxre2/setup.c
arch/sh/boards/mach-microdev/io.c
arch/sh/boards/mach-microdev/irq.c
arch/sh/boards/mach-microdev/setup.c
arch/sh/boards/mach-migor/lcd_qvga.c
arch/sh/boards/mach-migor/setup.c
arch/sh/boards/mach-r2d/irq.c
arch/sh/boards/mach-r2d/setup.c
arch/sh/boards/mach-sdk7780/irq.c
arch/sh/boards/mach-sdk7780/setup.c
arch/sh/boards/mach-sh7763rdp/irq.c
arch/sh/boards/mach-sh7763rdp/setup.c
arch/sh/boards/mach-snapgear/setup.c
arch/sh/boards/mach-systemh/io.c
arch/sh/boards/mach-systemh/irq.c
arch/sh/boards/mach-systemh/setup.c
arch/sh/boards/mach-titan/io.c
arch/sh/boards/mach-titan/setup.c
arch/sh/boot/.gitignore
arch/sh/boot/Makefile
arch/sh/boot/compressed/Makefile_32
arch/sh/boot/compressed/misc_32.c
arch/sh/configs/edosk7760_defconfig [new file with mode: 0644]
arch/sh/configs/rts7751r2dplus_qemu_defconfig [new file with mode: 0644]
arch/sh/drivers/pci/ops-lboxre2.c
arch/sh/drivers/pci/ops-r7780rp.c
arch/sh/drivers/pci/ops-rts7751r2d.c
arch/sh/drivers/pci/ops-sdk7780.c
arch/sh/drivers/pci/ops-titan.c
arch/sh/include/asm/bitops-llsc.h [new file with mode: 0644]
arch/sh/include/asm/bitops.h
arch/sh/include/asm/clock.h
arch/sh/include/asm/cmpxchg-llsc.h [new file with mode: 0644]
arch/sh/include/asm/elf.h
arch/sh/include/asm/fpu.h
arch/sh/include/asm/ftrace.h [new file with mode: 0644]
arch/sh/include/asm/gpio.h
arch/sh/include/asm/hw_irq.h
arch/sh/include/asm/io.h
arch/sh/include/asm/io_generic.h
arch/sh/include/asm/irq.h
arch/sh/include/asm/kprobes.h [new file with mode: 0644]
arch/sh/include/asm/machvec.h
arch/sh/include/asm/mmzone.h
arch/sh/include/asm/page.h
arch/sh/include/asm/pgtable.h
arch/sh/include/asm/processor.h
arch/sh/include/asm/processor_32.h
arch/sh/include/asm/processor_64.h
arch/sh/include/asm/ptrace.h
arch/sh/include/asm/rtc.h
arch/sh/include/asm/setup.h
arch/sh/include/asm/sizes.h [new file with mode: 0644]
arch/sh/include/asm/smp.h
arch/sh/include/asm/syscall.h [new file with mode: 0644]
arch/sh/include/asm/syscall_32.h [new file with mode: 0644]
arch/sh/include/asm/syscall_64.h [new file with mode: 0644]
arch/sh/include/asm/syscalls.h [new file with mode: 0644]
arch/sh/include/asm/syscalls_32.h [new file with mode: 0644]
arch/sh/include/asm/syscalls_64.h [new file with mode: 0644]
arch/sh/include/asm/system.h
arch/sh/include/asm/system_32.h
arch/sh/include/asm/thread_info.h
arch/sh/include/asm/uaccess_64.h
arch/sh/include/cpu-sh2a/cpu/sh7203.h [new file with mode: 0644]
arch/sh/include/cpu-sh3/cpu/sh7720.h [new file with mode: 0644]
arch/sh/include/cpu-sh4/cpu/sh7722.h [new file with mode: 0644]
arch/sh/include/cpu-sh4/cpu/sh7723.h [new file with mode: 0644]
arch/sh/include/mach-common/mach/edosk7705.h [moved from arch/sh/include/asm/edosk7705.h with 100% similarity]
arch/sh/include/mach-common/mach/highlander.h [moved from arch/sh/include/asm/r7780rp.h with 100% similarity]
arch/sh/include/mach-common/mach/hp6xx.h [moved from arch/sh/include/asm/hp6xx.h with 100% similarity]
arch/sh/include/mach-common/mach/lboxre2.h [moved from arch/sh/include/asm/lboxre2.h with 100% similarity]
arch/sh/include/mach-common/mach/magicpanelr2.h [moved from arch/sh/include/asm/magicpanelr2.h with 100% similarity]
arch/sh/include/mach-common/mach/microdev.h [moved from arch/sh/include/asm/microdev.h with 100% similarity]
arch/sh/include/mach-common/mach/migor.h [moved from arch/sh/include/asm/migor.h with 94% similarity]
arch/sh/include/mach-common/mach/r2d.h [moved from arch/sh/include/asm/rts7751r2d.h with 100% similarity]
arch/sh/include/mach-common/mach/sdk7780.h [moved from arch/sh/include/asm/sdk7780.h with 100% similarity]
arch/sh/include/mach-common/mach/sh7763rdp.h [moved from arch/sh/include/asm/sh7763rdp.h with 100% similarity]
arch/sh/include/mach-common/mach/sh7785lcr.h [moved from arch/sh/include/asm/sh7785lcr.h with 100% similarity]
arch/sh/include/mach-common/mach/shmin.h [moved from arch/sh/include/asm/shmin.h with 100% similarity]
arch/sh/include/mach-common/mach/snapgear.h [moved from arch/sh/include/asm/snapgear.h with 100% similarity]
arch/sh/include/mach-common/mach/systemh7751.h [moved from arch/sh/include/asm/systemh7751.h with 100% similarity]
arch/sh/include/mach-common/mach/titan.h [moved from arch/sh/include/asm/titan.h with 100% similarity]
arch/sh/kernel/Makefile_32
arch/sh/kernel/Makefile_64
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/irq/Makefile
arch/sh/kernel/cpu/irq/ipr.c
arch/sh/kernel/cpu/sh2a/Makefile
arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh3/Makefile
arch/sh/kernel/cpu/sh3/pinmux-sh7720.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4/fpu.c
arch/sh/kernel/cpu/sh4/setup-sh7760.c
arch/sh/kernel/cpu/sh4/softfloat.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/smp-shx3.c
arch/sh/kernel/cpu/sh5/Makefile
arch/sh/kernel/cpu/sh5/clock-sh5.c [new file with mode: 0644]
arch/sh/kernel/crash_dump.c
arch/sh/kernel/dump_task.c [deleted file]
arch/sh/kernel/entry-common.S
arch/sh/kernel/gpio.c [new file with mode: 0644]
arch/sh/kernel/io.c
arch/sh/kernel/io_generic.c
arch/sh/kernel/kprobes.c [new file with mode: 0644]
arch/sh/kernel/machvec.c
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/ptrace_64.c
arch/sh/kernel/setup.c
arch/sh/kernel/sh_ksyms_32.c
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c
arch/sh/kernel/smp.c
arch/sh/kernel/stacktrace.c
arch/sh/kernel/sys_sh.c
arch/sh/kernel/sys_sh32.c
arch/sh/kernel/time_32.c
arch/sh/kernel/time_64.c
arch/sh/kernel/timers/Makefile
arch/sh/kernel/timers/timer-broadcast.c [new file with mode: 0644]
arch/sh/kernel/timers/timer-cmt.c
arch/sh/kernel/timers/timer-tmu.c
arch/sh/kernel/traps_32.c
arch/sh/lib/div64-generic.c
arch/sh/lib/io.c
arch/sh/mm/Kconfig
arch/sh/mm/cache-debugfs.c
arch/sh/mm/cache-sh4.c
arch/sh/mm/consistent.c
arch/sh/mm/fault_32.c
arch/sh/mm/init.c
arch/sh/mm/pg-nommu.c
arch/sh/mm/pmb.c
arch/sh/mm/tlb-nommu.c
arch/sh/tools/mach-types
arch/sparc/Kconfig
arch/sparc/include/asm/thread_info_32.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc64/Kconfig
arch/um/Kconfig
arch/um/sys-i386/signal.c
arch/x86/Kconfig
arch/x86/kernel/crash_dump_32.c
arch/x86/kernel/crash_dump_64.c
arch/x86/kernel/rtc.c
arch/x86/kernel/setup.c
arch/x86/mm/pageattr.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/xtensa/Kconfig
drivers/acpi/battery.c
drivers/acpi/sbs.c
drivers/acpi/sleep/proc.c
drivers/acpi/system.c
drivers/base/memory.c
drivers/base/node.c
drivers/block/aoe/aoeblk.c
drivers/block/nbd.c
drivers/char/ds1286.c
drivers/char/ds1302.c
drivers/char/ip27-rtc.c
drivers/char/pc8736x_gpio.c
drivers/char/rtc.c
drivers/char/sx.c
drivers/char/sysrq.c
drivers/char/tpm/tpm.c
drivers/edac/cell_edac.c
drivers/firmware/iscsi_ibft.c
drivers/gpio/gpiolib.c
drivers/hwmon/applesmc.c
drivers/hwmon/pc87360.c
drivers/i2c/chips/at24.c
drivers/i2c/chips/ds1682.c
drivers/i2c/chips/menelaus.c
drivers/infiniband/core/cm.c
drivers/input/touchscreen/hp680_ts_input.c
drivers/leds/leds-hp6xx.c
drivers/media/dvb/ttpci/av7110.c
drivers/media/video/cx18/cx18-driver.h
drivers/media/video/ivtv/ivtv-driver.h
drivers/memstick/core/mspro_block.c
drivers/misc/hp-wmi.c
drivers/mtd/Kconfig
drivers/mtd/chips/Kconfig
drivers/mtd/chips/cfi_cmdset_0001.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/chips/cfi_probe.c
drivers/mtd/chips/cfi_util.c
drivers/mtd/chips/gen_probe.c
drivers/mtd/cmdlinepart.c
drivers/mtd/devices/Kconfig
drivers/mtd/devices/m25p80.c
drivers/mtd/devices/mtd_dataflash.c
drivers/mtd/inftlcore.c
drivers/mtd/maps/Kconfig
drivers/mtd/maps/Makefile
drivers/mtd/maps/ebony.c [deleted file]
drivers/mtd/maps/ocotea.c [deleted file]
drivers/mtd/maps/omap-toto-flash.c [deleted file]
drivers/mtd/maps/pci.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/maps/walnut.c [deleted file]
drivers/mtd/mtdchar.c
drivers/mtd/mtdconcat.c
drivers/mtd/mtdoops.c
drivers/mtd/mtdpart.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/atmel_nand.c
drivers/mtd/nand/cs553x_nand.c
drivers/mtd/nand/fsl_elbc_nand.c
drivers/mtd/nand/fsl_upm.c
drivers/mtd/nand/gpio.c [new file with mode: 0644]
drivers/mtd/nand/mxc_nand.c [new file with mode: 0644]
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_ecc.c
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/pxa3xx_nand.c
drivers/mtd/nand/sh_flctl.c [new file with mode: 0644]
drivers/mtd/nand/toto.c [deleted file]
drivers/mtd/ofpart.c
drivers/mtd/onenand/Kconfig
drivers/mtd/onenand/Makefile
drivers/mtd/onenand/omap2.c [new file with mode: 0644]
drivers/mtd/onenand/onenand_base.c
drivers/mtd/ssfdc.c
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/scan.c
drivers/mtd/ubi/vtbl.c
drivers/net/sh_eth.c
drivers/pci/intel-iommu.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/rom.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/power/power_supply_sysfs.c
drivers/ps3/ps3av.c
drivers/ps3/ps3av_cmd.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-bq4802.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-ds1216.c
drivers/rtc/rtc-ds1302.c
drivers/rtc/rtc-ds1305.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1511.c
drivers/rtc/rtc-ds1553.c
drivers/rtc/rtc-ds1742.c
drivers/rtc/rtc-fm3130.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-m41t94.c
drivers/rtc/rtc-m48t59.c
drivers/rtc/rtc-m48t86.c
drivers/rtc/rtc-max6900.c
drivers/rtc/rtc-max6902.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-pcf8563.c
drivers/rtc/rtc-pcf8583.c
drivers/rtc/rtc-r9701.c
drivers/rtc/rtc-rs5c313.c
drivers/rtc/rtc-rs5c348.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-stk17ta8.c
drivers/rtc/rtc-v3020.c
drivers/rtc/rtc-x1205.c
drivers/scsi/arcmsr/arcmsr_attr.c
drivers/scsi/sr_vendor.c
drivers/serial/8250_gsc.c
drivers/serial/serial_txx9.c
drivers/serial/sh-sci.c
drivers/serial/sh-sci.h
drivers/serial/sn_console.c
drivers/sh/Makefile
drivers/sh/intc.c [moved from arch/sh/kernel/cpu/irq/intc.c with 96% similarity]
drivers/staging/go7007/Kconfig
drivers/staging/sxg/Kconfig
drivers/telephony/phonedev.c
drivers/video/backlight/hp680_bl.c
drivers/video/fbmem.c
drivers/video/sh_mobile_lcdcfb.c
drivers/w1/slaves/w1_ds2760.c
fs/Kconfig
fs/Kconfig.binfmt
fs/binfmt_elf.c
fs/buffer.c
fs/cifs/Kconfig [new file with mode: 0644]
fs/cifs/file.c
fs/exec.c
fs/ext3/balloc.c
fs/ext3/dir.c
fs/ext3/inode.c
fs/ext3/resize.c
fs/ext3/super.c
fs/hfsplus/extents.c
fs/hfsplus/inode.c
fs/jbd/commit.c
fs/jbd/transaction.c
fs/jffs2/Kconfig [new file with mode: 0644]
fs/jffs2/compr.c
fs/jffs2/dir.c
fs/jffs2/erase.c
fs/jffs2/fs.c
fs/jffs2/nodemgmt.c
fs/jffs2/wbuf.c
fs/nfs/dir.c
fs/ntfs/file.c
fs/proc/proc_misc.c
fs/proc/vmcore.c
fs/ramfs/file-nommu.c
fs/ramfs/inode.c
fs/seq_file.c
fs/ubifs/budget.c
fs/ubifs/compress.c
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/file.c
fs/ubifs/find.c
fs/ubifs/gc.c
fs/ubifs/io.c
fs/ubifs/key.h
fs/ubifs/lprops.c
fs/ubifs/lpt.c
fs/ubifs/lpt_commit.c
fs/ubifs/misc.h
fs/ubifs/scan.c
fs/ubifs/super.c
fs/ubifs/tnc.c
fs/ubifs/tnc_misc.c
fs/ubifs/ubifs-media.h
fs/ubifs/ubifs.h
fs/ubifs/xattr.c
include/asm-cris/thread_info.h
include/asm-generic/rtc.h
include/asm-m68k/thread_info.h
include/asm-parisc/thread_info.h
include/asm-um/thread_info.h
include/asm-xtensa/thread_info.h
include/linux/Kbuild
include/linux/backing-dev.h
include/linux/bcd.h
include/linux/bitmap.h
include/linux/buffer_head.h
include/linux/byteorder/Kbuild
include/linux/byteorder/big_endian.h
include/linux/byteorder/little_endian.h
include/linux/cgroup.h
include/linux/cgroup_subsys.h
include/linux/crash_dump.h
include/linux/ext3_fs.h
include/linux/fb.h
include/linux/freezer.h
include/linux/jbd.h
include/linux/memcontrol.h
include/linux/migrate.h
include/linux/mm.h
include/linux/mm_inline.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/mtd/cfi.h
include/linux/mtd/flashchip.h
include/linux/mtd/mtd.h
include/linux/mtd/nand-gpio.h [new file with mode: 0644]
include/linux/mtd/nand.h
include/linux/mtd/onenand_regs.h
include/linux/mtd/partitions.h
include/linux/mtd/sh_flctl.h [new file with mode: 0644]
include/linux/page-flags.h
include/linux/page_cgroup.h [new file with mode: 0644]
include/linux/pagemap.h
include/linux/pagevec.h
include/linux/pci.h
include/linux/ptrace.h
include/linux/rmap.h
include/linux/sched.h
include/linux/seq_file.h
include/linux/sh_intc.h [new file with mode: 0644]
include/linux/swab.h
include/linux/swap.h
include/linux/sysfs.h
include/linux/vmalloc.h
include/linux/vmstat.h
include/net/netns/x_tables.h
include/video/sh_mobile_lcdc.h [moved from arch/sh/include/asm/sh_mobile_lcdc.h with 82% similarity]
init/Kconfig
init/main.c
ipc/mqueue.c
ipc/shm.c
kernel/Kconfig.freezer [new file with mode: 0644]
kernel/Makefile
kernel/cgroup.c
kernel/cgroup_debug.c
kernel/cgroup_freezer.c [new file with mode: 0644]
kernel/configs.c
kernel/cpuset.c
kernel/freezer.c [new file with mode: 0644]
kernel/kexec.c
kernel/kthread.c
kernel/power/process.c
kernel/ptrace.c
kernel/rcupreempt.c
kernel/sysctl.c
lib/bitmap.c
lib/vsprintf.c
mm/Kconfig
mm/Makefile
mm/filemap.c
mm/fremap.c
mm/hugetlb.c
mm/internal.h
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/migrate.c
mm/mlock.c
mm/mmap.c
mm/mremap.c
mm/nommu.c
mm/page-writeback.c
mm/page_alloc.c
mm/page_cgroup.c [new file with mode: 0644]
mm/readahead.c
mm/rmap.c
mm/shmem.c
mm/swap.c
mm/swap_state.c
mm/swapfile.c
mm/truncate.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/bridge/br_netfilter.c
net/core/dev.c
net/dccp/ipv6.c
net/dccp/minisocks.c
net/dccp/output.c
net/ipv4/arp.c
net/ipv4/netfilter/nf_nat_snmp_basic.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/netfilter/Kconfig
net/netfilter/ipvs/Kconfig
net/netfilter/nf_conntrack_netlink.c
net/netfilter/xt_NFQUEUE.c
net/netfilter/xt_iprange.c
net/netfilter/xt_recent.c
net/sched/sch_generic.c
security/device_cgroup.c
sound/core/pcm_misc.c
sound/drivers/dummy.c
sound/oss/sh_dac_audio.c
sound/pci/ca0106/ca0106_main.c
sound/ppc/snd_ps3.c
sound/ppc/snd_ps3.h
sound/soc/omap/omap-mcbsp.c

index dfab12f809ed9c678638844ced3717742986ab26..eba9bf953ef5bc2e21bc670d33c845a8483e20a6 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -66,6 +66,7 @@ Kenneth W Chen <kenneth.w.chen@intel.com>
 Koushik <raghavendra.koushik@neterion.com>
 Leonid I Ananiev <leonid.i.ananiev@intel.com>
 Linas Vepstas <linas@austin.ibm.com>
+Mark Brown <broonie@sirena.org.uk>
 Matthieu CASTET <castet.matthieu@free.fr>
 Michael Buesch <mb@bu3sch.de>
 Michael Buesch <mbuesch@freenet.de>
diff --git a/Documentation/cgroups/freezer-subsystem.txt b/Documentation/cgroups/freezer-subsystem.txt
new file mode 100644 (file)
index 0000000..c50ab58
--- /dev/null
@@ -0,0 +1,99 @@
+       The cgroup freezer is useful to batch job management system which start
+and stop sets of tasks in order to schedule the resources of a machine
+according to the desires of a system administrator. This sort of program
+is often used on HPC clusters to schedule access to the cluster as a
+whole. The cgroup freezer uses cgroups to describe the set of tasks to
+be started/stopped by the batch job management system. It also provides
+a means to start and stop the tasks composing the job.
+
+       The cgroup freezer will also be useful for checkpointing running groups
+of tasks. The freezer allows the checkpoint code to obtain a consistent
+image of the tasks by attempting to force the tasks in a cgroup into a
+quiescent state. Once the tasks are quiescent another task can
+walk /proc or invoke a kernel interface to gather information about the
+quiesced tasks. Checkpointed tasks can be restarted later should a
+recoverable error occur. This also allows the checkpointed tasks to be
+migrated between nodes in a cluster by copying the gathered information
+to another node and restarting the tasks there.
+
+       Sequences of SIGSTOP and SIGCONT are not always sufficient for stopping
+and resuming tasks in userspace. Both of these signals are observable
+from within the tasks we wish to freeze. While SIGSTOP cannot be caught,
+blocked, or ignored it can be seen by waiting or ptracing parent tasks.
+SIGCONT is especially unsuitable since it can be caught by the task. Any
+programs designed to watch for SIGSTOP and SIGCONT could be broken by
+attempting to use SIGSTOP and SIGCONT to stop and resume tasks. We can
+demonstrate this problem using nested bash shells:
+
+       $ echo $$
+       16644
+       $ bash
+       $ echo $$
+       16690
+
+       From a second, unrelated bash shell:
+       $ kill -SIGSTOP 16690
+       $ kill -SIGCONT 16990
+
+       <at this point 16990 exits and causes 16644 to exit too>
+
+       This happens because bash can observe both signals and choose how it
+responds to them.
+
+       Another example of a program which catches and responds to these
+signals is gdb. In fact any program designed to use ptrace is likely to
+have a problem with this method of stopping and resuming tasks.
+
+        In contrast, the cgroup freezer uses the kernel freezer code to
+prevent the freeze/unfreeze cycle from becoming visible to the tasks
+being frozen. This allows the bash example above and gdb to run as
+expected.
+
+       The freezer subsystem in the container filesystem defines a file named
+freezer.state. Writing "FROZEN" to the state file will freeze all tasks in the
+cgroup. Subsequently writing "THAWED" will unfreeze the tasks in the cgroup.
+Reading will return the current state.
+
+* Examples of usage :
+
+   # mkdir /containers/freezer
+   # mount -t cgroup -ofreezer freezer  /containers
+   # mkdir /containers/0
+   # echo $some_pid > /containers/0/tasks
+
+to get status of the freezer subsystem :
+
+   # cat /containers/0/freezer.state
+   THAWED
+
+to freeze all tasks in the container :
+
+   # echo FROZEN > /containers/0/freezer.state
+   # cat /containers/0/freezer.state
+   FREEZING
+   # cat /containers/0/freezer.state
+   FROZEN
+
+to unfreeze all tasks in the container :
+
+   # echo THAWED > /containers/0/freezer.state
+   # cat /containers/0/freezer.state
+   THAWED
+
+This is the basic mechanism which should do the right thing for user space task
+in a simple scenario.
+
+It's important to note that freezing can be incomplete. In that case we return
+EBUSY. This means that some tasks in the cgroup are busy doing something that
+prevents us from completely freezing the cgroup at this time. After EBUSY,
+the cgroup will remain partially frozen -- reflected by freezer.state reporting
+"FREEZING" when read. The state will remain "FREEZING" until one of these
+things happens:
+
+       1) Userspace cancels the freezing operation by writing "THAWED" to
+               the freezer.state file
+       2) Userspace retries the freezing operation by writing "FROZEN" to
+               the freezer.state file (writing "FREEZING" is not legal
+               and returns EIO)
+       3) The tasks that blocked the cgroup from entering the "FROZEN"
+               state disappear from the cgroup's set of tasks.
index 9b53d5827361fd647f3388212e648f502defc698..1c07547d3f81f28a19edb9de8752f8865b44478d 100644 (file)
@@ -112,14 +112,22 @@ the per cgroup LRU.
 
 2.2.1 Accounting details
 
-All mapped pages (RSS) and unmapped user pages (Page Cache) are accounted.
-RSS pages are accounted at the time of page_add_*_rmap() unless they've already
-been accounted for earlier. A file page will be accounted for as Page Cache;
-it's mapped into the page tables of a process, duplicate accounting is carefully
-avoided. Page Cache pages are accounted at the time of add_to_page_cache().
-The corresponding routines that remove a page from the page tables or removes
-a page from Page Cache is used to decrement the accounting counters of the
-cgroup.
+All mapped anon pages (RSS) and cache pages (Page Cache) are accounted.
+(some pages which never be reclaimable and will not be on global LRU
+ are not accounted. we just accounts pages under usual vm management.)
+
+RSS pages are accounted at page_fault unless they've already been accounted
+for earlier. A file page will be accounted for as Page Cache when it's
+inserted into inode (radix-tree). While it's mapped into the page tables of
+processes, duplicate accounting is carefully avoided.
+
+A RSS page is unaccounted when it's fully unmapped. A PageCache page is
+unaccounted when it's removed from radix-tree.
+
+At page migration, accounting information is kept.
+
+Note: we just account pages-on-lru because our purpose is to control amount
+of used pages. not-on-lru pages are tend to be out-of-control from vm view.
 
 2.3 Shared Page Accounting
 
index 47e568a9370afa28f703acf9ce55f88a8ca52519..5c86c258c7913dd9c97da4a3e4f7a0dd666745bc 100644 (file)
@@ -48,7 +48,7 @@ hooks, beyond what is already present, required to manage dynamic
 job placement on large systems.
 
 Cpusets use the generic cgroup subsystem described in
-Documentation/cgroup.txt.
+Documentation/cgroups/cgroups.txt.
 
 Requests by a task, using the sched_setaffinity(2) system call to
 include CPUs in its CPU affinity mask, and using the mbind(2) and
index 295f26cd895a0d5cd460267a84ebbb687978fa69..9dd2a3bb2acc87b85d473a2080284910f04f8585 100644 (file)
@@ -96,6 +96,11 @@ errors=remount-ro(*) Remount the filesystem read-only on an error.
 errors=continue                Keep going on a filesystem error.
 errors=panic           Panic and halt the machine if an error occurs.
 
+data_err=ignore(*)     Just print an error message if an error occurs
+                       in a file data buffer in ordered mode.
+data_err=abort         Abort the journal if an error occurs in a file
+                       data buffer in ordered mode.
+
 grpid                  Give objects the same group ID as their creator.
 bsdgroups
 
index c032bf39e8b9b581b6ada65f7a99b97b2dae7019..bcceb99b81dd8038130fd9b1032b3e4ba80dc113 100644 (file)
@@ -1384,15 +1384,18 @@ causes the kernel to prefer to reclaim dentries and inodes.
 dirty_background_ratio
 ----------------------
 
-Contains, as a percentage of total system memory, the number of pages at which
-the pdflush background writeback daemon will start writing out dirty data.
+Contains, as a percentage of the dirtyable system memory (free pages + mapped
+pages + file cache, not including locked pages and HugePages), the number of
+pages at which the pdflush background writeback daemon will start writing out
+dirty data.
 
 dirty_ratio
 -----------------
 
-Contains, as a percentage of total system memory, the number of pages at which
-a process which is generating disk writes will itself start writing out dirty
-data.
+Contains, as a percentage of the dirtyable system memory (free pages + mapped
+pages + file cache, not including locked pages and HugePages), the number of
+pages at which a process which is generating disk writes will itself start
+writing out dirty data.
 
 dirty_writeback_centisecs
 -------------------------
@@ -2412,24 +2415,29 @@ will be dumped when the <pid> process is dumped. coredump_filter is a bitmask
 of memory types. If a bit of the bitmask is set, memory segments of the
 corresponding memory type are dumped, otherwise they are not dumped.
 
-The following 4 memory types are supported:
+The following 7 memory types are supported:
   - (bit 0) anonymous private memory
   - (bit 1) anonymous shared memory
   - (bit 2) file-backed private memory
   - (bit 3) file-backed shared memory
   - (bit 4) ELF header pages in file-backed private memory areas (it is
             effective only if the bit 2 is cleared)
+  - (bit 5) hugetlb private memory
+  - (bit 6) hugetlb shared memory
 
   Note that MMIO pages such as frame buffer are never dumped and vDSO pages
   are always dumped regardless of the bitmask status.
 
-Default value of coredump_filter is 0x3; this means all anonymous memory
-segments are dumped.
+  Note bit 0-4 doesn't effect any hugetlb memory. hugetlb memory are only
+  effected by bit 5-6.
+
+Default value of coredump_filter is 0x23; this means all anonymous memory
+segments and hugetlb private memory are dumped.
 
 If you don't want to dump all shared memory segments attached to pid 1234,
-write 1 to the process's proc file.
+write 0x21 to the process's proc file.
 
-  $ echo 0x1 > /proc/1234/coredump_filter
+  $ echo 0x21 > /proc/1234/coredump_filter
 
 When a new process is created, the process inherits the bitmask status from its
 parent. It is useful to set up coredump_filter before the program runs.
index 6a0d70a22f05f238cb1da86208437818f192b495..dd84ea3c10daf00cf78a2361dce9f8b691095e4d 100644 (file)
@@ -86,6 +86,15 @@ norm_unmount (*)     commit on unmount; the journal is committed
 fast_unmount           do not commit on unmount; this option makes
                        unmount faster, but the next mount slower
                        because of the need to replay the journal.
+bulk_read              read more in one go to take advantage of flash
+                       media that read faster sequentially
+no_bulk_read (*)       do not bulk-read
+no_chk_data_crc                skip checking of CRCs on data nodes in order to
+                       improve read performance. Use this option only
+                       if the flash media is highly reliable. The effect
+                       of this option is that corruption of the contents
+                       of a file can go unnoticed.
+chk_data_crc (*)       do not skip checking CRCs on data nodes
 
 
 Quick usage instructions
index d4f4875fc7c6d2e463e9c2b6e26d2d278cf1399c..0f1544f67400b4288887649bf73b9fb09449b92c 100644 (file)
@@ -690,7 +690,7 @@ and is between 256 and 4096 characters. It is defined in the file
                        See Documentation/block/as-iosched.txt and
                        Documentation/block/deadline-iosched.txt for details.
 
-       elfcorehdr=     [X86-32, X86_64]
+       elfcorehdr=     [IA64,PPC,SH,X86-32,X86_64]
                        Specifies physical address of start of kernel core
                        image elf header. Generally kexec loader will
                        pass this option to capture kernel.
@@ -796,6 +796,8 @@ and is between 256 and 4096 characters. It is defined in the file
                        Defaults to the default architecture's huge page size
                        if not specified.
 
+       hlt             [BUGS=ARM,SH]
+
        i8042.debug     [HW] Toggle i8042 debug mode
        i8042.direct    [HW] Put keyboard port into non-translated mode
        i8042.dumbkbd   [HW] Pretend that controller can only read data from
@@ -1211,6 +1213,10 @@ and is between 256 and 4096 characters. It is defined in the file
        mem=nopentium   [BUGS=X86-32] Disable usage of 4MB pages for kernel
                        memory.
 
+       memchunk=nn[KMG]
+                       [KNL,SH] Allow user to override the default size for
+                       per-device physically contiguous DMA buffers.
+
        memmap=exactmap [KNL,X86-32,X86_64] Enable setting of an exact
                        E820 memory map, as specified by the user.
                        Such memmap=exactmap lines can be constructed based on
@@ -1393,6 +1399,8 @@ and is between 256 and 4096 characters. It is defined in the file
 
        nodisconnect    [HW,SCSI,M68K] Disables SCSI disconnects.
 
+       nodsp           [SH] Disable hardware DSP at boot time.
+
        noefi           [X86-32,X86-64] Disable EFI runtime services support.
 
        noexec          [IA-64]
@@ -1409,13 +1417,15 @@ and is between 256 and 4096 characters. It is defined in the file
                        noexec32=off: disable non-executable mappings
                                read implies executable mappings
 
+       nofpu           [SH] Disable hardware FPU at boot time.
+
        nofxsr          [BUGS=X86-32] Disables x86 floating point extended
                        register save and restore. The kernel will only save
                        legacy floating-point registers on task switch.
 
        noclflush       [BUGS=X86] Don't use the CLFLUSH instruction
 
-       nohlt           [BUGS=ARM]
+       nohlt           [BUGS=ARM,SH]
 
        no-hlt          [BUGS=X86-32] Tells the kernel that the hlt
                        instruction doesn't work correctly and not to
diff --git a/Documentation/mtd/nand_ecc.txt b/Documentation/mtd/nand_ecc.txt
new file mode 100644 (file)
index 0000000..bdf93b7
--- /dev/null
@@ -0,0 +1,714 @@
+Introduction
+============
+
+Having looked at the linux mtd/nand driver and more specific at nand_ecc.c
+I felt there was room for optimisation. I bashed the code for a few hours
+performing tricks like table lookup removing superfluous code etc.
+After that the speed was increased by 35-40%.
+Still I was not too happy as I felt there was additional room for improvement.
+
+Bad! I was hooked.
+I decided to annotate my steps in this file. Perhaps it is useful to someone
+or someone learns something from it.
+
+
+The problem
+===========
+
+NAND flash (at least SLC one) typically has sectors of 256 bytes.
+However NAND flash is not extremely reliable so some error detection
+(and sometimes correction) is needed.
+
+This is done by means of a Hamming code. I'll try to explain it in
+laymans terms (and apologies to all the pro's in the field in case I do
+not use the right terminology, my coding theory class was almost 30
+years ago, and I must admit it was not one of my favourites).
+
+As I said before the ecc calculation is performed on sectors of 256
+bytes. This is done by calculating several parity bits over the rows and
+columns. The parity used is even parity which means that the parity bit = 1
+if the data over which the parity is calculated is 1 and the parity bit = 0
+if the data over which the parity is calculated is 0. So the total
+number of bits over the data over which the parity is calculated + the
+parity bit is even. (see wikipedia if you can't follow this).
+Parity is often calculated by means of an exclusive or operation,
+sometimes also referred to as xor. In C the operator for xor is ^
+
+Back to ecc.
+Let's give a small figure:
+
+byte   0:  bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0   rp0 rp2 rp4 ... rp14
+byte   1:  bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0   rp1 rp2 rp4 ... rp14
+byte   2:  bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0   rp0 rp3 rp4 ... rp14
+byte   3:  bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0   rp1 rp3 rp4 ... rp14
+byte   4:  bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0   rp0 rp2 rp5 ... rp14
+....
+byte 254:  bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0   rp0 rp3 rp5 ... rp15
+byte 255:  bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0   rp1 rp3 rp5 ... rp15
+           cp1  cp0  cp1  cp0  cp1  cp0  cp1  cp0
+           cp3  cp3  cp2  cp2  cp3  cp3  cp2  cp2
+           cp5  cp5  cp5  cp5  cp4  cp4  cp4  cp4
+
+This figure represents a sector of 256 bytes.
+cp is my abbreviaton for column parity, rp for row parity.
+
+Let's start to explain column parity.
+cp0 is the parity that belongs to all bit0, bit2, bit4, bit6.
+so the sum of all bit0, bit2, bit4 and bit6 values + cp0 itself is even.
+Similarly cp1 is the sum of all bit1, bit3, bit5 and bit7.
+cp2 is the parity over bit0, bit1, bit4 and bit5
+cp3 is the parity over bit2, bit3, bit6 and bit7.
+cp4 is the parity over bit0, bit1, bit2 and bit3.
+cp5 is the parity over bit4, bit5, bit6 and bit7.
+Note that each of cp0 .. cp5 is exactly one bit.
+
+Row parity actually works almost the same.
+rp0 is the parity of all even bytes (0, 2, 4, 6, ... 252, 254)
+rp1 is the parity of all odd bytes (1, 3, 5, 7, ..., 253, 255)
+rp2 is the parity of all bytes 0, 1, 4, 5, 8, 9, ...
+(so handle two bytes, then skip 2 bytes).
+rp3 is covers the half rp2 does not cover (bytes 2, 3, 6, 7, 10, 11, ...)
+for rp4 the rule is cover 4 bytes, skip 4 bytes, cover 4 bytes, skip 4 etc.
+so rp4 calculates parity over bytes 0, 1, 2, 3, 8, 9, 10, 11, 16, ...)
+and rp5 covers the other half, so bytes 4, 5, 6, 7, 12, 13, 14, 15, 20, ..
+The story now becomes quite boring. I guess you get the idea.
+rp6 covers 8 bytes then skips 8 etc
+rp7 skips 8 bytes then covers 8 etc
+rp8 covers 16 bytes then skips 16 etc
+rp9 skips 16 bytes then covers 16 etc
+rp10 covers 32 bytes then skips 32 etc
+rp11 skips 32 bytes then covers 32 etc
+rp12 covers 64 bytes then skips 64 etc
+rp13 skips 64 bytes then covers 64 etc
+rp14 covers 128 bytes then skips 128
+rp15 skips 128 bytes then covers 128
+
+In the end the parity bits are grouped together in three bytes as
+follows:
+ECC    Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
+ECC 0   rp07  rp06  rp05  rp04  rp03  rp02  rp01  rp00
+ECC 1   rp15  rp14  rp13  rp12  rp11  rp10  rp09  rp08
+ECC 2   cp5   cp4   cp3   cp2   cp1   cp0      1     1
+
+I detected after writing this that ST application note AN1823
+(http://www.st.com/stonline/books/pdf/docs/10123.pdf) gives a much
+nicer picture.(but they use line parity as term where I use row parity)
+Oh well, I'm graphically challenged, so suffer with me for a moment :-)
+And I could not reuse the ST picture anyway for copyright reasons.
+
+
+Attempt 0
+=========
+
+Implementing the parity calculation is pretty simple.
+In C pseudocode:
+for (i = 0; i < 256; i++)
+{
+    if (i & 0x01)
+       rp1 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp1;
+    else
+       rp0 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp1;
+    if (i & 0x02)
+       rp3 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp3;
+    else
+       rp2 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp2;
+    if (i & 0x04)
+      rp5 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp5;
+    else
+      rp4 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp4;
+    if (i & 0x08)
+      rp7 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp7;
+    else
+      rp6 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp6;
+    if (i & 0x10)
+      rp9 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp9;
+    else
+      rp8 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp8;
+    if (i & 0x20)
+      rp11 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp11;
+    else
+    rp10 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp10;
+    if (i & 0x40)
+      rp13 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp13;
+    else
+      rp12 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp12;
+    if (i & 0x80)
+      rp15 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp15;
+    else
+      rp14 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ bit3 ^ bit2 ^ bit1 ^ bit0 ^ rp14;
+    cp0 = bit6 ^ bit4 ^ bit2 ^ bit0 ^ cp0;
+    cp1 = bit7 ^ bit5 ^ bit3 ^ bit1 ^ cp1;
+    cp2 = bit5 ^ bit4 ^ bit1 ^ bit0 ^ cp2;
+    cp3 = bit7 ^ bit6 ^ bit3 ^ bit2 ^ cp3
+    cp4 = bit3 ^ bit2 ^ bit1 ^ bit0 ^ cp4
+    cp5 = bit7 ^ bit6 ^ bit5 ^ bit4 ^ cp5
+}
+
+
+Analysis 0
+==========
+
+C does have bitwise operators but not really operators to do the above
+efficiently (and most hardware has no such instructions either).
+Therefore without implementing this it was clear that the code above was
+not going to bring me a Nobel prize :-)
+
+Fortunately the exclusive or operation is commutative, so we can combine
+the values in any order. So instead of calculating all the bits
+individually, let us try to rearrange things.
+For the column parity this is easy. We can just xor the bytes and in the
+end filter out the relevant bits. This is pretty nice as it will bring
+all cp calculation out of the if loop.
+
+Similarly we can first xor the bytes for the various rows.
+This leads to:
+
+
+Attempt 1
+=========
+
+const char parity[256] = {
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+    0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0
+};
+
+void ecc1(const unsigned char *buf, unsigned char *code)
+{
+    int i;
+    const unsigned char *bp = buf;
+    unsigned char cur;
+    unsigned char rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
+    unsigned char rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15;
+    unsigned char par;
+
+    par = 0;
+    rp0 = 0; rp1 = 0; rp2 = 0; rp3 = 0;
+    rp4 = 0; rp5 = 0; rp6 = 0; rp7 = 0;
+    rp8 = 0; rp9 = 0; rp10 = 0; rp11 = 0;
+    rp12 = 0; rp13 = 0; rp14 = 0; rp15 = 0;
+
+    for (i = 0; i < 256; i++)
+    {
+        cur = *bp++;
+        par ^= cur;
+        if (i & 0x01) rp1 ^= cur; else rp0 ^= cur;
+        if (i & 0x02) rp3 ^= cur; else rp2 ^= cur;
+        if (i & 0x04) rp5 ^= cur; else rp4 ^= cur;
+        if (i & 0x08) rp7 ^= cur; else rp6 ^= cur;
+        if (i & 0x10) rp9 ^= cur; else rp8 ^= cur;
+        if (i & 0x20) rp11 ^= cur; else rp10 ^= cur;
+        if (i & 0x40) rp13 ^= cur; else rp12 ^= cur;
+        if (i & 0x80) rp15 ^= cur; else rp14 ^= cur;
+    }
+    code[0] =
+        (parity[rp7] << 7) |
+        (parity[rp6] << 6) |
+        (parity[rp5] << 5) |
+        (parity[rp4] << 4) |
+        (parity[rp3] << 3) |
+        (parity[rp2] << 2) |
+        (parity[rp1] << 1) |
+        (parity[rp0]);
+    code[1] =
+        (parity[rp15] << 7) |
+        (parity[rp14] << 6) |
+        (parity[rp13] << 5) |
+        (parity[rp12] << 4) |
+        (parity[rp11] << 3) |
+        (parity[rp10] << 2) |
+        (parity[rp9]  << 1) |
+        (parity[rp8]);
+    code[2] =
+        (parity[par & 0xf0] << 7) |
+        (parity[par & 0x0f] << 6) |
+        (parity[par & 0xcc] << 5) |
+        (parity[par & 0x33] << 4) |
+        (parity[par & 0xaa] << 3) |
+        (parity[par & 0x55] << 2);
+    code[0] = ~code[0];
+    code[1] = ~code[1];
+    code[2] = ~code[2];
+}
+
+Still pretty straightforward. The last three invert statements are there to
+give a checksum of 0xff 0xff 0xff for an empty flash. In an empty flash
+all data is 0xff, so the checksum then matches.
+
+I also introduced the parity lookup. I expected this to be the fastest
+way to calculate the parity, but I will investigate alternatives later
+on.
+
+
+Analysis 1
+==========
+
+The code works, but is not terribly efficient. On my system it took
+almost 4 times as much time as the linux driver code. But hey, if it was
+*that* easy this would have been done long before.
+No pain. no gain.
+
+Fortunately there is plenty of room for improvement.
+
+In step 1 we moved from bit-wise calculation to byte-wise calculation.
+However in C we can also use the unsigned long data type and virtually
+every modern microprocessor supports 32 bit operations, so why not try
+to write our code in such a way that we process data in 32 bit chunks.
+
+Of course this means some modification as the row parity is byte by
+byte. A quick analysis:
+for the column parity we use the par variable. When extending to 32 bits
+we can in the end easily calculate p0 and p1 from it.
+(because par now consists of 4 bytes, contributing to rp1, rp0, rp1, rp0
+respectively)
+also rp2 and rp3 can be easily retrieved from par as rp3 covers the
+first two bytes and rp2 the last two bytes.
+
+Note that of course now the loop is executed only 64 times (256/4).
+And note that care must taken wrt byte ordering. The way bytes are
+ordered in a long is machine dependent, and might affect us.
+Anyway, if there is an issue: this code is developed on x86 (to be
+precise: a DELL PC with a D920 Intel CPU)
+
+And of course the performance might depend on alignment, but I expect
+that the I/O buffers in the nand driver are aligned properly (and
+otherwise that should be fixed to get maximum performance).
+
+Let's give it a try...
+
+
+Attempt 2
+=========
+
+extern const char parity[256];
+
+void ecc2(const unsigned char *buf, unsigned char *code)
+{
+    int i;
+    const unsigned long *bp = (unsigned long *)buf;
+    unsigned long cur;
+    unsigned long rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
+    unsigned long rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15;
+    unsigned long par;
+
+    par = 0;
+    rp0 = 0; rp1 = 0; rp2 = 0; rp3 = 0;
+    rp4 = 0; rp5 = 0; rp6 = 0; rp7 = 0;
+    rp8 = 0; rp9 = 0; rp10 = 0; rp11 = 0;
+    rp12 = 0; rp13 = 0; rp14 = 0; rp15 = 0;
+
+    for (i = 0; i < 64; i++)
+    {
+        cur = *bp++;
+        par ^= cur;
+        if (i & 0x01) rp5 ^= cur; else rp4 ^= cur;
+        if (i & 0x02) rp7 ^= cur; else rp6 ^= cur;
+        if (i & 0x04) rp9 ^= cur; else rp8 ^= cur;
+        if (i & 0x08) rp11 ^= cur; else rp10 ^= cur;
+        if (i & 0x10) rp13 ^= cur; else rp12 ^= cur;
+        if (i & 0x20) rp15 ^= cur; else rp14 ^= cur;
+    }
+    /*
+       we need to adapt the code generation for the fact that rp vars are now
+       long; also the column parity calculation needs to be changed.
+       we'll bring rp4 to 15 back to single byte entities by shifting and
+       xoring
+    */
+    rp4 ^= (rp4 >> 16); rp4 ^= (rp4 >> 8); rp4 &= 0xff;
+    rp5 ^= (rp5 >> 16); rp5 ^= (rp5 >> 8); rp5 &= 0xff;
+    rp6 ^= (rp6 >> 16); rp6 ^= (rp6 >> 8); rp6 &= 0xff;
+    rp7 ^= (rp7 >> 16); rp7 ^= (rp7 >> 8); rp7 &= 0xff;
+    rp8 ^= (rp8 >> 16); rp8 ^= (rp8 >> 8); rp8 &= 0xff;
+    rp9 ^= (rp9 >> 16); rp9 ^= (rp9 >> 8); rp9 &= 0xff;
+    rp10 ^= (rp10 >> 16); rp10 ^= (rp10 >> 8); rp10 &= 0xff;
+    rp11 ^= (rp11 >> 16); rp11 ^= (rp11 >> 8); rp11 &= 0xff;
+    rp12 ^= (rp12 >> 16); rp12 ^= (rp12 >> 8); rp12 &= 0xff;
+    rp13 ^= (rp13 >> 16); rp13 ^= (rp13 >> 8); rp13 &= 0xff;
+    rp14 ^= (rp14 >> 16); rp14 ^= (rp14 >> 8); rp14 &= 0xff;
+    rp15 ^= (rp15 >> 16); rp15 ^= (rp15 >> 8); rp15 &= 0xff;
+    rp3 = (par >> 16); rp3 ^= (rp3 >> 8); rp3 &= 0xff;
+    rp2 = par & 0xffff; rp2 ^= (rp2 >> 8); rp2 &= 0xff;
+    par ^= (par >> 16);
+    rp1 = (par >> 8); rp1 &= 0xff;
+    rp0 = (par & 0xff);
+    par ^= (par >> 8); par &= 0xff;
+
+    code[0] =
+        (parity[rp7] << 7) |
+        (parity[rp6] << 6) |
+        (parity[rp5] << 5) |
+        (parity[rp4] << 4) |
+        (parity[rp3] << 3) |
+        (parity[rp2] << 2) |
+        (parity[rp1] << 1) |
+        (parity[rp0]);
+    code[1] =
+        (parity[rp15] << 7) |
+        (parity[rp14] << 6) |
+        (parity[rp13] << 5) |
+        (parity[rp12] << 4) |
+        (parity[rp11] << 3) |
+        (parity[rp10] << 2) |
+        (parity[rp9]  << 1) |
+        (parity[rp8]);
+    code[2] =
+        (parity[par & 0xf0] << 7) |
+        (parity[par & 0x0f] << 6) |
+        (parity[par & 0xcc] << 5) |
+        (parity[par & 0x33] << 4) |
+        (parity[par & 0xaa] << 3) |
+        (parity[par & 0x55] << 2);
+    code[0] = ~code[0];
+    code[1] = ~code[1];
+    code[2] = ~code[2];
+}
+
+The parity array is not shown any more. Note also that for these
+examples I kinda deviated from my regular programming style by allowing
+multiple statements on a line, not using { } in then and else blocks
+with only a single statement and by using operators like ^=
+
+
+Analysis 2
+==========
+
+The code (of course) works, and hurray: we are a little bit faster than
+the linux driver code (about 15%). But wait, don't cheer too quickly.
+THere is more to be gained.
+If we look at e.g. rp14 and rp15 we see that we either xor our data with
+rp14 or with rp15. However we also have par which goes over all data.
+This means there is no need to calculate rp14 as it can be calculated from
+rp15 through rp14 = par ^ rp15;
+(or if desired we can avoid calculating rp15 and calculate it from
+rp14).  That is why some places refer to inverse parity.
+Of course the same thing holds for rp4/5, rp6/7, rp8/9, rp10/11 and rp12/13.
+Effectively this means we can eliminate the else clause from the if
+statements. Also we can optimise the calculation in the end a little bit
+by going from long to byte first. Actually we can even avoid the table
+lookups
+
+Attempt 3
+=========
+
+Odd replaced:
+        if (i & 0x01) rp5 ^= cur; else rp4 ^= cur;
+        if (i & 0x02) rp7 ^= cur; else rp6 ^= cur;
+        if (i & 0x04) rp9 ^= cur; else rp8 ^= cur;
+        if (i & 0x08) rp11 ^= cur; else rp10 ^= cur;
+        if (i & 0x10) rp13 ^= cur; else rp12 ^= cur;
+        if (i & 0x20) rp15 ^= cur; else rp14 ^= cur;
+with
+        if (i & 0x01) rp5 ^= cur;
+        if (i & 0x02) rp7 ^= cur;
+        if (i & 0x04) rp9 ^= cur;
+        if (i & 0x08) rp11 ^= cur;
+        if (i & 0x10) rp13 ^= cur;
+        if (i & 0x20) rp15 ^= cur;
+
+        and outside the loop added:
+    rp4  = par ^ rp5;
+    rp6  = par ^ rp7;
+    rp8  = par ^ rp9;
+    rp10  = par ^ rp11;
+    rp12  = par ^ rp13;
+    rp14  = par ^ rp15;
+
+And after that the code takes about 30% more time, although the number of
+statements is reduced. This is also reflected in the assembly code.
+
+
+Analysis 3
+==========
+
+Very weird. Guess it has to do with caching or instruction parallellism
+or so. I also tried on an eeePC (Celeron, clocked at 900 Mhz). Interesting
+observation was that this one is only 30% slower (according to time)
+executing the code as my 3Ghz D920 processor.
+
+Well, it was expected not to be easy so maybe instead move to a
+different track: let's move back to the code from attempt2 and do some
+loop unrolling. This will eliminate a few if statements. I'll try
+different amounts of unrolling to see what works best.
+
+
+Attempt 4
+=========
+
+Unrolled the loop 1, 2, 3 and 4 times.
+For 4 the code starts with:
+
+    for (i = 0; i < 4; i++)
+    {
+        cur = *bp++;
+        par ^= cur;
+        rp4 ^= cur;
+        rp6 ^= cur;
+        rp8 ^= cur;
+        rp10 ^= cur;
+        if (i & 0x1) rp13 ^= cur; else rp12 ^= cur;
+        if (i & 0x2) rp15 ^= cur; else rp14 ^= cur;
+        cur = *bp++;
+        par ^= cur;
+        rp5 ^= cur;
+        rp6 ^= cur;
+        ...
+
+
+Analysis 4
+==========
+
+Unrolling once gains about 15%
+Unrolling twice keeps the gain at about 15%
+Unrolling three times gives a gain of 30% compared to attempt 2.
+Unrolling four times gives a marginal improvement compared to unrolling
+three times.
+
+I decided to proceed with a four time unrolled loop anyway. It was my gut
+feeling that in the next steps I would obtain additional gain from it.
+
+The next step was triggered by the fact that par contains the xor of all
+bytes and rp4 and rp5 each contain the xor of half of the bytes.
+So in effect par = rp4 ^ rp5. But as xor is commutative we can also say
+that rp5 = par ^ rp4. So no need to keep both rp4 and rp5 around. We can
+eliminate rp5 (or rp4, but I already foresaw another optimisation).
+The same holds for rp6/7, rp8/9, rp10/11 rp12/13 and rp14/15.
+
+
+Attempt 5
+=========
+
+Effectively so all odd digit rp assignments in the loop were removed.
+This included the else clause of the if statements.
+Of course after the loop we need to correct things by adding code like:
+    rp5 = par ^ rp4;
+Also the initial assignments (rp5 = 0; etc) could be removed.
+Along the line I also removed the initialisation of rp0/1/2/3.
+
+
+Analysis 5
+==========
+
+Measurements showed this was a good move. The run-time roughly halved
+compared with attempt 4 with 4 times unrolled, and we only require 1/3rd
+of the processor time compared to the current code in the linux kernel.
+
+However, still I thought there was more. I didn't like all the if
+statements. Why not keep a running parity and only keep the last if
+statement. Time for yet another version!
+
+
+Attempt 6
+=========
+
+THe code within the for loop was changed to:
+
+    for (i = 0; i < 4; i++)
+    {
+        cur = *bp++; tmppar  = cur; rp4 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= tmppar;
+        cur = *bp++; tmppar ^= cur; rp4 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp8 ^= tmppar;
+
+        cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp6 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= cur;
+           cur = *bp++; tmppar ^= cur; rp4 ^= cur;
+           cur = *bp++; tmppar ^= cur; rp10 ^= tmppar;
+
+           cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp6 ^= cur; rp8 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= cur; rp8 ^= cur;
+           cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp8 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp8 ^= cur;
+
+        cur = *bp++; tmppar ^= cur; rp4 ^= cur; rp6 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp4 ^= cur;
+        cur = *bp++; tmppar ^= cur;
+
+           par ^= tmppar;
+        if ((i & 0x1) == 0) rp12 ^= tmppar;
+        if ((i & 0x2) == 0) rp14 ^= tmppar;
+    }
+
+As you can see tmppar is used to accumulate the parity within a for
+iteration. In the last 3 statements is is added to par and, if needed,
+to rp12 and rp14.
+
+While making the changes I also found that I could exploit that tmppar
+contains the running parity for this iteration. So instead of having:
+rp4 ^= cur; rp6 = cur;
+I removed the rp6 = cur; statement and did rp6 ^= tmppar; on next
+statement. A similar change was done for rp8 and rp10
+
+
+Analysis 6
+==========
+
+Measuring this code again showed big gain. When executing the original
+linux code 1 million times, this took about 1 second on my system.
+(using time to measure the performance). After this iteration I was back
+to 0.075 sec. Actually I had to decide to start measuring over 10
+million interations in order not to loose too much accuracy. This one
+definitely seemed to be the jackpot!
+
+There is a little bit more room for improvement though. There are three
+places with statements:
+rp4 ^= cur; rp6 ^= cur;
+It seems more efficient to also maintain a variable rp4_6 in the while
+loop; This eliminates 3 statements per loop. Of course after the loop we
+need to correct by adding:
+    rp4 ^= rp4_6;
+    rp6 ^= rp4_6
+Furthermore there are 4 sequential assingments to rp8. This can be
+encoded slightly more efficient by saving tmppar before those 4 lines
+and later do rp8 = rp8 ^ tmppar ^ notrp8;
+(where notrp8 is the value of rp8 before those 4 lines).
+Again a use of the commutative property of xor.
+Time for a new test!
+
+
+Attempt 7
+=========
+
+The new code now looks like:
+
+    for (i = 0; i < 4; i++)
+    {
+        cur = *bp++; tmppar  = cur; rp4 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= tmppar;
+        cur = *bp++; tmppar ^= cur; rp4 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp8 ^= tmppar;
+
+        cur = *bp++; tmppar ^= cur; rp4_6 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= cur;
+           cur = *bp++; tmppar ^= cur; rp4 ^= cur;
+           cur = *bp++; tmppar ^= cur; rp10 ^= tmppar;
+
+           notrp8 = tmppar;
+           cur = *bp++; tmppar ^= cur; rp4_6 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= cur;
+           cur = *bp++; tmppar ^= cur; rp4 ^= cur;
+        cur = *bp++; tmppar ^= cur;
+           rp8 = rp8 ^ tmppar ^ notrp8;
+
+        cur = *bp++; tmppar ^= cur; rp4_6 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp6 ^= cur;
+        cur = *bp++; tmppar ^= cur; rp4 ^= cur;
+        cur = *bp++; tmppar ^= cur;
+
+           par ^= tmppar;
+        if ((i & 0x1) == 0) rp12 ^= tmppar;
+        if ((i & 0x2) == 0) rp14 ^= tmppar;
+    }
+    rp4 ^= rp4_6;
+    rp6 ^= rp4_6;
+
+
+Not a big change, but every penny counts :-)
+
+
+Analysis 7
+==========
+
+Acutally this made things worse. Not very much, but I don't want to move
+into the wrong direction. Maybe something to investigate later. Could
+have to do with caching again.
+
+Guess that is what there is to win within the loop. Maybe unrolling one
+more time will help. I'll keep the optimisations from 7 for now.
+
+
+Attempt 8
+=========
+
+Unrolled the loop one more time.
+
+
+Analysis 8
+==========
+
+This makes things worse. Let's stick with attempt 6 and continue from there.
+Although it seems that the code within the loop cannot be optimised
+further there is still room to optimize the generation of the ecc codes.
+We can simply calcualate the total parity. If this is 0 then rp4 = rp5
+etc. If the parity is 1, then rp4 = !rp5;
+But if rp4 = rp5 we do not need rp5 etc. We can just write the even bits
+in the result byte and then do something like
+    code[0] |= (code[0] << 1);
+Lets test this.
+
+
+Attempt 9
+=========
+
+Changed the code but again this slightly degrades performance. Tried all
+kind of other things, like having dedicated parity arrays to avoid the
+shift after parity[rp7] << 7; No gain.
+Change the lookup using the parity array by using shift operators (e.g.
+replace parity[rp7] << 7 with:
+rp7 ^= (rp7 << 4);
+rp7 ^= (rp7 << 2);
+rp7 ^= (rp7 << 1);
+rp7 &= 0x80;
+No gain.
+
+The only marginal change was inverting the parity bits, so we can remove
+the last three invert statements.
+
+Ah well, pity this does not deliver more. Then again 10 million
+iterations using the linux driver code takes between 13 and 13.5
+seconds, whereas my code now takes about 0.73 seconds for those 10
+million iterations. So basically I've improved the performance by a
+factor 18 on my system. Not that bad. Of course on different hardware
+you will get different results. No warranties!
+
+But of course there is no such thing as a free lunch. The codesize almost
+tripled (from 562 bytes to 1434 bytes). Then again, it is not that much.
+
+
+Correcting errors
+=================
+
+For correcting errors I again used the ST application note as a starter,
+but I also peeked at the existing code.
+The algorithm itself is pretty straightforward. Just xor the given and
+the calculated ecc. If all bytes are 0 there is no problem. If 11 bits
+are 1 we have one correctable bit error. If there is 1 bit 1, we have an
+error in the given ecc code.
+It proved to be fastest to do some table lookups. Performance gain
+introduced by this is about a factor 2 on my system when a repair had to
+be done, and 1% or so if no repair had to be done.
+Code size increased from 330 bytes to 686 bytes for this function.
+(gcc 4.2, -O3)
+
+
+Conclusion
+==========
+
+The gain when calculating the ecc is tremendous. Om my development hardware
+a speedup of a factor of 18 for ecc calculation was achieved. On a test on an
+embedded system with a MIPS core a factor 7 was obtained.
+On  a test with a Linksys NSLU2 (ARMv5TE processor) the speedup was a factor
+5 (big endian mode, gcc 4.1.2, -O3)
+For correction not much gain could be obtained (as bitflips are rare). Then
+again there are also much less cycles spent there.
+
+It seems there is not much more gain possible in this, at least when
+programmed in C. Of course it might be possible to squeeze something more
+out of it with an assembler program, but due to pipeline behaviour etc
+this is very tricky (at least for intel hw).
+
+Author: Frans Meulenbroeks
+Copyright (C) 2008 Koninklijke Philips Electronics NV.
index 5ce0952aa06546096fc165d9562f35565ed17025..49378a9f2b5f276c4a050e76b0898c25a74303e0 100644 (file)
@@ -95,7 +95,8 @@ On all -  write a character to /proc/sysrq-trigger.  e.g.:
 
 'p'     - Will dump the current registers and flags to your console.
 
-'q'     - Will dump a list of all running timers.
+'q'     - Will dump a list of all running hrtimers.
+         WARNING: Does not cover any other timers
 
 'r'     - Turns off keyboard raw mode and sets it to XLATE.
 
diff --git a/Documentation/vm/unevictable-lru.txt b/Documentation/vm/unevictable-lru.txt
new file mode 100644 (file)
index 0000000..125eed5
--- /dev/null
@@ -0,0 +1,615 @@
+
+This document describes the Linux memory management "Unevictable LRU"
+infrastructure and the use of this infrastructure to manage several types
+of "unevictable" pages.  The document attempts to provide the overall
+rationale behind this mechanism and the rationale for some of the design
+decisions that drove the implementation.  The latter design rationale is
+discussed in the context of an implementation description.  Admittedly, one
+can obtain the implementation details--the "what does it do?"--by reading the
+code.  One hopes that the descriptions below add value by provide the answer
+to "why does it do that?".
+
+Unevictable LRU Infrastructure:
+
+The Unevictable LRU adds an additional LRU list to track unevictable pages
+and to hide these pages from vmscan.  This mechanism is based on a patch by
+Larry Woodman of Red Hat to address several scalability problems with page
+reclaim in Linux.  The problems have been observed at customer sites on large
+memory x86_64 systems.  For example, a non-numal x86_64 platform with 128GB
+of main memory will have over 32 million 4k pages in a single zone.  When a
+large fraction of these pages are not evictable for any reason [see below],
+vmscan will spend a lot of time scanning the LRU lists looking for the small
+fraction of pages that are evictable.  This can result in a situation where
+all cpus are spending 100% of their time in vmscan for hours or days on end,
+with the system completely unresponsive.
+
+The Unevictable LRU infrastructure addresses the following classes of
+unevictable pages:
+
++ page owned by ramfs
++ page mapped into SHM_LOCKed shared memory regions
++ page mapped into VM_LOCKED [mlock()ed] vmas
+
+The infrastructure might be able to handle other conditions that make pages
+unevictable, either by definition or by circumstance, in the future.
+
+
+The Unevictable LRU List
+
+The Unevictable LRU infrastructure consists of an additional, per-zone, LRU list
+called the "unevictable" list and an associated page flag, PG_unevictable, to
+indicate that the page is being managed on the unevictable list.  The
+PG_unevictable flag is analogous to, and mutually exclusive with, the PG_active
+flag in that it indicates on which LRU list a page resides when PG_lru is set.
+The unevictable LRU list is source configurable based on the UNEVICTABLE_LRU
+Kconfig option.
+
+The Unevictable LRU infrastructure maintains unevictable pages on an additional
+LRU list for a few reasons:
+
+1) We get to "treat unevictable pages just like we treat other pages in the
+   system, which means we get to use the same code to manipulate them, the
+   same code to isolate them (for migrate, etc.), the same code to keep track
+   of the statistics, etc..." [Rik van Riel]
+
+2) We want to be able to migrate unevictable pages between nodes--for memory
+   defragmentation, workload management and memory hotplug.  The linux kernel
+   can only migrate pages that it can successfully isolate from the lru lists.
+   If we were to maintain pages elsewise than on an lru-like list, where they
+   can be found by isolate_lru_page(), we would prevent their migration, unless
+   we reworked migration code to find the unevictable pages.
+
+
+The unevictable LRU list does not differentiate between file backed and swap
+backed [anon] pages.  This differentiation is only important while the pages
+are, in fact, evictable.
+
+The unevictable LRU list benefits from the "arrayification" of the per-zone
+LRU lists and statistics originally proposed and posted by Christoph Lameter.
+
+The unevictable list does not use the lru pagevec mechanism. Rather,
+unevictable pages are placed directly on the page's zone's unevictable
+list under the zone lru_lock.  The reason for this is to prevent stranding
+of pages on the unevictable list when one task has the page isolated from the
+lru and other tasks are changing the "evictability" state of the page.
+
+
+Unevictable LRU and Memory Controller Interaction
+
+The memory controller data structure automatically gets a per zone unevictable
+lru list as a result of the "arrayification" of the per-zone LRU lists.  The
+memory controller tracks the movement of pages to and from the unevictable list.
+When a memory control group comes under memory pressure, the controller will
+not attempt to reclaim pages on the unevictable list.  This has a couple of
+effects.  Because the pages are "hidden" from reclaim on the unevictable list,
+the reclaim process can be more efficient, dealing only with pages that have
+a chance of being reclaimed.  On the other hand, if too many of the pages
+charged to the control group are unevictable, the evictable portion of the
+working set of the tasks in the control group may not fit into the available
+memory.  This can cause the control group to thrash or to oom-kill tasks.
+
+
+Unevictable LRU:  Detecting Unevictable Pages
+
+The function page_evictable(page, vma) in vmscan.c determines whether a
+page is evictable or not.  For ramfs pages and pages in SHM_LOCKed regions,
+page_evictable() tests a new address space flag, AS_UNEVICTABLE, in the page's
+address space using a wrapper function.  Wrapper functions are used to set,
+clear and test the flag to reduce the requirement for #ifdef's throughout the
+source code.  AS_UNEVICTABLE is set on ramfs inode/mapping when it is created.
+This flag remains for the life of the inode.
+
+For shared memory regions, AS_UNEVICTABLE is set when an application
+successfully SHM_LOCKs the region and is removed when the region is
+SHM_UNLOCKed.  Note that shmctl(SHM_LOCK, ...) does not populate the page
+tables for the region as does, for example, mlock().   So, we make no special
+effort to push any pages in the SHM_LOCKed region to the unevictable list.
+Vmscan will do this when/if it encounters the pages during reclaim.  On
+SHM_UNLOCK, shmctl() scans the pages in the region and "rescues" them from the
+unevictable list if no other condition keeps them unevictable.  If a SHM_LOCKed
+region is destroyed, the pages are also "rescued" from the unevictable list in
+the process of freeing them.
+
+page_evictable() detects mlock()ed pages by testing an additional page flag,
+PG_mlocked via the PageMlocked() wrapper.  If the page is NOT mlocked, and a
+non-NULL vma is supplied, page_evictable() will check whether the vma is
+VM_LOCKED via is_mlocked_vma().  is_mlocked_vma() will SetPageMlocked() and
+update the appropriate statistics if the vma is VM_LOCKED.  This method allows
+efficient "culling" of pages in the fault path that are being faulted in to
+VM_LOCKED vmas.
+
+
+Unevictable Pages and Vmscan [shrink_*_list()]
+
+If unevictable pages are culled in the fault path, or moved to the unevictable
+list at mlock() or mmap() time, vmscan will never encounter the pages until
+they have become evictable again, for example, via munlock() and have been
+"rescued" from the unevictable list.  However, there may be situations where we
+decide, for the sake of expediency, to leave a unevictable page on one of the
+regular active/inactive LRU lists for vmscan to deal with.  Vmscan checks for
+such pages in all of the shrink_{active|inactive|page}_list() functions and
+will "cull" such pages that it encounters--that is, it diverts those pages to
+the unevictable list for the zone being scanned.
+
+There may be situations where a page is mapped into a VM_LOCKED vma, but the
+page is not marked as PageMlocked.  Such pages will make it all the way to
+shrink_page_list() where they will be detected when vmscan walks the reverse
+map in try_to_unmap().  If try_to_unmap() returns SWAP_MLOCK, shrink_page_list()
+will cull the page at that point.
+
+Note that for anonymous pages, shrink_page_list() attempts to add the page to
+the swap cache before it tries to unmap the page.  To avoid this unnecessary
+consumption of swap space, shrink_page_list() calls try_to_munlock() to check
+whether any VM_LOCKED vmas map the page without attempting to unmap the page.
+If try_to_munlock() returns SWAP_MLOCK, shrink_page_list() will cull the page
+without consuming swap space.  try_to_munlock() will be described below.
+
+To "cull" an unevictable page, vmscan simply puts the page back on the lru
+list using putback_lru_page()--the inverse operation to isolate_lru_page()--
+after dropping the page lock.  Because the condition which makes the page
+unevictable may change once the page is unlocked, putback_lru_page() will
+recheck the unevictable state of a page that it places on the unevictable lru
+list.  If the page has become unevictable, putback_lru_page() removes it from
+the list and retries, including the page_unevictable() test.  Because such a
+race is a rare event and movement of pages onto the unevictable list should be
+rare, these extra evictabilty checks should not occur in the majority of calls
+to putback_lru_page().
+
+
+Mlocked Page:  Prior Work
+
+The "Unevictable Mlocked Pages" infrastructure is based on work originally
+posted by Nick Piggin in an RFC patch entitled "mm: mlocked pages off LRU".
+Nick posted his patch as an alternative to a patch posted by Christoph
+Lameter to achieve the same objective--hiding mlocked pages from vmscan.
+In Nick's patch, he used one of the struct page lru list link fields as a count
+of VM_LOCKED vmas that map the page.  This use of the link field for a count
+prevented the management of the pages on an LRU list.  Thus, mlocked pages were
+not migratable as isolate_lru_page() could not find them and the lru list link
+field was not available to the migration subsystem.  Nick resolved this by
+putting mlocked pages back on the lru list before attempting to isolate them,
+thus abandoning the count of VM_LOCKED vmas.  When Nick's patch was integrated
+with the Unevictable LRU work, the count was replaced by walking the reverse
+map to determine whether any VM_LOCKED vmas mapped the page.  More on this
+below.
+
+
+Mlocked Pages:  Basic Management
+
+Mlocked pages--pages mapped into a VM_LOCKED vma--represent one class of
+unevictable pages.  When such a page has been "noticed" by the memory
+management subsystem, the page is marked with the PG_mlocked [PageMlocked()]
+flag.  A PageMlocked() page will be placed on the unevictable LRU list when
+it is added to the LRU.   Pages can be "noticed" by memory management in
+several places:
+
+1) in the mlock()/mlockall() system call handlers.
+2) in the mmap() system call handler when mmap()ing a region with the
+   MAP_LOCKED flag, or mmap()ing a region in a task that has called
+   mlockall() with the MCL_FUTURE flag.  Both of these conditions result
+   in the VM_LOCKED flag being set for the vma.
+3) in the fault path, if mlocked pages are "culled" in the fault path,
+   and when a VM_LOCKED stack segment is expanded.
+4) as mentioned above, in vmscan:shrink_page_list() with attempting to
+   reclaim a page in a VM_LOCKED vma--via try_to_unmap() or try_to_munlock().
+
+Mlocked pages become unlocked and rescued from the unevictable list when:
+
+1) mapped in a range unlocked via the munlock()/munlockall() system calls.
+2) munmapped() out of the last VM_LOCKED vma that maps the page, including
+   unmapping at task exit.
+3) when the page is truncated from the last VM_LOCKED vma of an mmap()ed file.
+4) before a page is COWed in a VM_LOCKED vma.
+
+
+Mlocked Pages:  mlock()/mlockall() System Call Handling
+
+Both [do_]mlock() and [do_]mlockall() system call handlers call mlock_fixup()
+for each vma in the range specified by the call.  In the case of mlockall(),
+this is the entire active address space of the task.  Note that mlock_fixup()
+is used for both mlock()ing and munlock()ing a range of memory.  A call to
+mlock() an already VM_LOCKED vma, or to munlock() a vma that is not VM_LOCKED
+is treated as a no-op--mlock_fixup() simply returns.
+
+If the vma passes some filtering described in "Mlocked Pages:  Filtering Vmas"
+below, mlock_fixup() will attempt to merge the vma with its neighbors or split
+off a subset of the vma if the range does not cover the entire vma.  Once the
+vma has been merged or split or neither, mlock_fixup() will call
+__mlock_vma_pages_range() to fault in the pages via get_user_pages() and
+to mark the pages as mlocked via mlock_vma_page().
+
+Note that the vma being mlocked might be mapped with PROT_NONE.  In this case,
+get_user_pages() will be unable to fault in the pages.  That's OK.  If pages
+do end up getting faulted into this VM_LOCKED vma, we'll handle them in the
+fault path or in vmscan.
+
+Also note that a page returned by get_user_pages() could be truncated or
+migrated out from under us, while we're trying to mlock it.  To detect
+this, __mlock_vma_pages_range() tests the page_mapping after acquiring
+the page lock.  If the page is still associated with its mapping, we'll
+go ahead and call mlock_vma_page().  If the mapping is gone, we just
+unlock the page and move on.  Worse case, this results in page mapped
+in a VM_LOCKED vma remaining on a normal LRU list without being
+PageMlocked().  Again, vmscan will detect and cull such pages.
+
+mlock_vma_page(), called with the page locked [N.B., not "mlocked"], will
+TestSetPageMlocked() for each page returned by get_user_pages().  We use
+TestSetPageMlocked() because the page might already be mlocked by another
+task/vma and we don't want to do extra work.  We especially do not want to
+count an mlocked page more than once in the statistics.  If the page was
+already mlocked, mlock_vma_page() is done.
+
+If the page was NOT already mlocked, mlock_vma_page() attempts to isolate the
+page from the LRU, as it is likely on the appropriate active or inactive list
+at that time.  If the isolate_lru_page() succeeds, mlock_vma_page() will
+putback the page--putback_lru_page()--which will notice that the page is now
+mlocked and divert the page to the zone's unevictable LRU list.  If
+mlock_vma_page() is unable to isolate the page from the LRU, vmscan will handle
+it later if/when it attempts to reclaim the page.
+
+
+Mlocked Pages:  Filtering Special Vmas
+
+mlock_fixup() filters several classes of "special" vmas:
+
+1) vmas with VM_IO|VM_PFNMAP set are skipped entirely.  The pages behind
+   these mappings are inherently pinned, so we don't need to mark them as
+   mlocked.  In any case, most of the pages have no struct page in which to
+   so mark the page.  Because of this, get_user_pages() will fail for these
+   vmas, so there is no sense in attempting to visit them.
+
+2) vmas mapping hugetlbfs page are already effectively pinned into memory.
+   We don't need nor want to mlock() these pages.  However, to preserve the
+   prior behavior of mlock()--before the unevictable/mlock changes--mlock_fixup()
+   will call make_pages_present() in the hugetlbfs vma range to allocate the
+   huge pages and populate the ptes.
+
+3) vmas with VM_DONTEXPAND|VM_RESERVED are generally user space mappings of
+   kernel pages, such as the vdso page, relay channel pages, etc.  These pages
+   are inherently unevictable and are not managed on the LRU lists.
+   mlock_fixup() treats these vmas the same as hugetlbfs vmas.  It calls
+   make_pages_present() to populate the ptes.
+
+Note that for all of these special vmas, mlock_fixup() does not set the
+VM_LOCKED flag.  Therefore, we won't have to deal with them later during
+munlock() or munmap()--for example, at task exit.  Neither does mlock_fixup()
+account these vmas against the task's "locked_vm".
+
+Mlocked Pages:  Downgrading the Mmap Semaphore.
+
+mlock_fixup() must be called with the mmap semaphore held for write, because
+it may have to merge or split vmas.  However, mlocking a large region of
+memory can take a long time--especially if vmscan must reclaim pages to
+satisfy the regions requirements.  Faulting in a large region with the mmap
+semaphore held for write can hold off other faults on the address space, in
+the case of a multi-threaded task.  It can also hold off scans of the task's
+address space via /proc.  While testing under heavy load, it was observed that
+the ps(1) command could be held off for many minutes while a large segment was
+mlock()ed down.
+
+To address this issue, and to make the system more responsive during mlock()ing
+of large segments, mlock_fixup() downgrades the mmap semaphore to read mode
+during the call to __mlock_vma_pages_range().  This works fine.  However, the
+callers of mlock_fixup() expect the semaphore to be returned in write mode.
+So, mlock_fixup() "upgrades" the semphore to write mode.  Linux does not
+support an atomic upgrade_sem() call, so mlock_fixup() must drop the semaphore
+and reacquire it in write mode.  In a multi-threaded task, it is possible for
+the task memory map to change while the semaphore is dropped.  Therefore,
+mlock_fixup() looks up the vma at the range start address after reacquiring
+the semaphore in write mode and verifies that it still covers the original
+range.  If not, mlock_fixup() returns an error [-EAGAIN].  All callers of
+mlock_fixup() have been changed to deal with this new error condition.
+
+Note:  when munlocking a region, all of the pages should already be resident--
+unless we have racing threads mlocking() and munlocking() regions.  So,
+unlocking should not have to wait for page allocations nor faults  of any kind.
+Therefore mlock_fixup() does not downgrade the semaphore for munlock().
+
+
+Mlocked Pages:  munlock()/munlockall() System Call Handling
+
+The munlock() and munlockall() system calls are handled by the same functions--
+do_mlock[all]()--as the mlock() and mlockall() system calls with the unlock
+vs lock operation indicated by an argument.  So, these system calls are also
+handled by mlock_fixup().  Again, if called for an already munlock()ed vma,
+mlock_fixup() simply returns.  Because of the vma filtering discussed above,
+VM_LOCKED will not be set in any "special" vmas.  So, these vmas will be
+ignored for munlock.
+
+If the vma is VM_LOCKED, mlock_fixup() again attempts to merge or split off
+the specified range.  The range is then munlocked via the function
+__mlock_vma_pages_range()--the same function used to mlock a vma range--
+passing a flag to indicate that munlock() is being performed.
+
+Because the vma access protections could have been changed to PROT_NONE after
+faulting in and mlocking some pages, get_user_pages() was unreliable for visiting
+these pages for munlocking.  Because we don't want to leave pages mlocked(),
+get_user_pages() was enhanced to accept a flag to ignore the permissions when
+fetching the pages--all of which should be resident as a result of previous
+mlock()ing.
+
+For munlock(), __mlock_vma_pages_range() unlocks individual pages by calling
+munlock_vma_page().  munlock_vma_page() unconditionally clears the PG_mlocked
+flag using TestClearPageMlocked().  As with mlock_vma_page(), munlock_vma_page()
+use the Test*PageMlocked() function to handle the case where the page might
+have already been unlocked by another task.  If the page was mlocked,
+munlock_vma_page() updates that zone statistics for the number of mlocked
+pages.  Note, however, that at this point we haven't checked whether the page
+is mapped by other VM_LOCKED vmas.
+
+We can't call try_to_munlock(), the function that walks the reverse map to check
+for other VM_LOCKED vmas, without first isolating the page from the LRU.
+try_to_munlock() is a variant of try_to_unmap() and thus requires that the page
+not be on an lru list.  [More on these below.]  However, the call to
+isolate_lru_page() could fail, in which case we couldn't try_to_munlock().
+So, we go ahead and clear PG_mlocked up front, as this might be the only chance
+we have.  If we can successfully isolate the page, we go ahead and
+try_to_munlock(), which will restore the PG_mlocked flag and update the zone
+page statistics if it finds another vma holding the page mlocked.  If we fail
+to isolate the page, we'll have left a potentially mlocked page on the LRU.
+This is fine, because we'll catch it later when/if vmscan tries to reclaim the
+page.  This should be relatively rare.
+
+Mlocked Pages:  Migrating Them...
+
+A page that is being migrated has been isolated from the lru lists and is
+held locked across unmapping of the page, updating the page's mapping
+[address_space] entry and copying the contents and state, until the
+page table entry has been replaced with an entry that refers to the new
+page.  Linux supports migration of mlocked pages and other unevictable
+pages.  This involves simply moving the PageMlocked and PageUnevictable states
+from the old page to the new page.
+
+Note that page migration can race with mlocking or munlocking of the same
+page.  This has been discussed from the mlock/munlock perspective in the
+respective sections above.  Both processes [migration, m[un]locking], hold
+the page locked.  This provides the first level of synchronization.  Page
+migration zeros out the page_mapping of the old page before unlocking it,
+so m[un]lock can skip these pages by testing the page mapping under page
+lock.
+
+When completing page migration, we place the new and old pages back onto the
+lru after dropping the page lock.  The "unneeded" page--old page on success,
+new page on failure--will be freed when the reference count held by the
+migration process is released.  To ensure that we don't strand pages on the
+unevictable list because of a race between munlock and migration, page
+migration uses the putback_lru_page() function to add migrated pages back to
+the lru.
+
+
+Mlocked Pages:  mmap(MAP_LOCKED) System Call Handling
+
+In addition the the mlock()/mlockall() system calls, an application can request
+that a region of memory be mlocked using the MAP_LOCKED flag with the mmap()
+call.  Furthermore, any mmap() call or brk() call that expands the heap by a
+task that has previously called mlockall() with the MCL_FUTURE flag will result
+in the newly mapped memory being mlocked.  Before the unevictable/mlock changes,
+the kernel simply called make_pages_present() to allocate pages and populate
+the page table.
+
+To mlock a range of memory under the unevictable/mlock infrastructure, the
+mmap() handler and task address space expansion functions call
+mlock_vma_pages_range() specifying the vma and the address range to mlock.
+mlock_vma_pages_range() filters vmas like mlock_fixup(), as described above in
+"Mlocked Pages:  Filtering Vmas".  It will clear the VM_LOCKED flag, which will
+have already been set by the caller, in filtered vmas.  Thus these vma's need
+not be visited for munlock when the region is unmapped.
+
+For "normal" vmas, mlock_vma_pages_range() calls __mlock_vma_pages_range() to
+fault/allocate the pages and mlock them.  Again, like mlock_fixup(),
+mlock_vma_pages_range() downgrades the mmap semaphore to read mode before
+attempting to fault/allocate and mlock the pages; and "upgrades" the semaphore
+back to write mode before returning.
+
+The callers of mlock_vma_pages_range() will have already added the memory
+range to be mlocked to the task's "locked_vm".  To account for filtered vmas,
+mlock_vma_pages_range() returns the number of pages NOT mlocked.  All of the
+callers then subtract a non-negative return value from the task's locked_vm.
+A negative return value represent an error--for example, from get_user_pages()
+attempting to fault in a vma with PROT_NONE access.  In this case, we leave
+the memory range accounted as locked_vm, as the protections could be changed
+later and pages allocated into that region.
+
+
+Mlocked Pages:  munmap()/exit()/exec() System Call Handling
+
+When unmapping an mlocked region of memory, whether by an explicit call to
+munmap() or via an internal unmap from exit() or exec() processing, we must
+munlock the pages if we're removing the last VM_LOCKED vma that maps the pages.
+Before the unevictable/mlock changes, mlocking did not mark the pages in any way,
+so unmapping them required no processing.
+
+To munlock a range of memory under the unevictable/mlock infrastructure, the
+munmap() hander and task address space tear down function call
+munlock_vma_pages_all().  The name reflects the observation that one always
+specifies the entire vma range when munlock()ing during unmap of a region.
+Because of the vma filtering when mlocking() regions, only "normal" vmas that
+actually contain mlocked pages will be passed to munlock_vma_pages_all().
+
+munlock_vma_pages_all() clears the VM_LOCKED vma flag and, like mlock_fixup()
+for the munlock case, calls __munlock_vma_pages_range() to walk the page table
+for the vma's memory range and munlock_vma_page() each resident page mapped by
+the vma.  This effectively munlocks the page, only if this is the last
+VM_LOCKED vma that maps the page.
+
+
+Mlocked Page:  try_to_unmap()
+
+[Note:  the code changes represented by this section are really quite small
+compared to the text to describe what happening and why, and to discuss the
+implications.]
+
+Pages can, of course, be mapped into multiple vmas.  Some of these vmas may
+have VM_LOCKED flag set.  It is possible for a page mapped into one or more
+VM_LOCKED vmas not to have the PG_mlocked flag set and therefore reside on one
+of the active or inactive LRU lists.  This could happen if, for example, a
+task in the process of munlock()ing the page could not isolate the page from
+the LRU.  As a result, vmscan/shrink_page_list() might encounter such a page
+as described in "Unevictable Pages and Vmscan [shrink_*_list()]".  To
+handle this situation, try_to_unmap() has been enhanced to check for VM_LOCKED
+vmas while it is walking a page's reverse map.
+
+try_to_unmap() is always called, by either vmscan for reclaim or for page
+migration, with the argument page locked and isolated from the LRU.  BUG_ON()
+assertions enforce this requirement.  Separate functions handle anonymous and
+mapped file pages, as these types of pages have different reverse map
+mechanisms.
+
+       try_to_unmap_anon()
+
+To unmap anonymous pages, each vma in the list anchored in the anon_vma must be
+visited--at least until a VM_LOCKED vma is encountered.  If the page is being
+unmapped for migration, VM_LOCKED vmas do not stop the process because mlocked
+pages are migratable.  However, for reclaim, if the page is mapped into a
+VM_LOCKED vma, the scan stops.  try_to_unmap() attempts to acquire the mmap
+semphore of the mm_struct to which the vma belongs in read mode.  If this is
+successful, try_to_unmap() will mlock the page via mlock_vma_page()--we
+wouldn't have gotten to try_to_unmap() if the page were already mlocked--and
+will return SWAP_MLOCK, indicating that the page is unevictable.  If the
+mmap semaphore cannot be acquired, we are not sure whether the page is really
+unevictable or not.  In this case, try_to_unmap() will return SWAP_AGAIN.
+
+       try_to_unmap_file() -- linear mappings
+
+Unmapping of a mapped file page works the same, except that the scan visits
+all vmas that maps the page's index/page offset in the page's mapping's
+reverse map priority search tree.  It must also visit each vma in the page's
+mapping's non-linear list, if the list is non-empty.  As for anonymous pages,
+on encountering a VM_LOCKED vma for a mapped file page, try_to_unmap() will
+attempt to acquire the associated mm_struct's mmap semaphore to mlock the page,
+returning SWAP_MLOCK if this is successful, and SWAP_AGAIN, if not.
+
+       try_to_unmap_file() -- non-linear mappings
+
+If a page's mapping contains a non-empty non-linear mapping vma list, then
+try_to_un{map|lock}() must also visit each vma in that list to determine
+whether the page is mapped in a VM_LOCKED vma.  Again, the scan must visit
+all vmas in the non-linear list to ensure that the pages is not/should not be
+mlocked.  If a VM_LOCKED vma is found in the list, the scan could terminate.
+However, there is no easy way to determine whether the page is actually mapped
+in a given vma--either for unmapping or testing whether the VM_LOCKED vma
+actually pins the page.
+
+So, try_to_unmap_file() handles non-linear mappings by scanning a certain
+number of pages--a "cluster"--in each non-linear vma associated with the page's
+mapping, for each file mapped page that vmscan tries to unmap.  If this happens
+to unmap the page we're trying to unmap, try_to_unmap() will notice this on
+return--(page_mapcount(page) == 0)--and return SWAP_SUCCESS.  Otherwise, it
+will return SWAP_AGAIN, causing vmscan to recirculate this page.  We take
+advantage of the cluster scan in try_to_unmap_cluster() as follows:
+
+For each non-linear vma, try_to_unmap_cluster() attempts to acquire the mmap
+semaphore of the associated mm_struct for read without blocking.  If this
+attempt is successful and the vma is VM_LOCKED, try_to_unmap_cluster() will
+retain the mmap semaphore for the scan; otherwise it drops it here.  Then,
+for each page in the cluster, if we're holding the mmap semaphore for a locked
+vma, try_to_unmap_cluster() calls mlock_vma_page() to mlock the page.  This
+call is a no-op if the page is already locked, but will mlock any pages in
+the non-linear mapping that happen to be unlocked.  If one of the pages so
+mlocked is the page passed in to try_to_unmap(), try_to_unmap_cluster() will
+return SWAP_MLOCK, rather than the default SWAP_AGAIN.  This will allow vmscan
+to cull the page, rather than recirculating it on the inactive list.  Again,
+if try_to_unmap_cluster() cannot acquire the vma's mmap sem, it returns
+SWAP_AGAIN, indicating that the page is mapped by a VM_LOCKED vma, but
+couldn't be mlocked.
+
+
+Mlocked pages:  try_to_munlock() Reverse Map Scan
+
+TODO/FIXME:  a better name might be page_mlocked()--analogous to the
+page_referenced() reverse map walker--especially if we continue to call this
+from shrink_page_list().  See related TODO/FIXME below.
+
+When munlock_vma_page()--see "Mlocked Pages:  munlock()/munlockall() System
+Call Handling" above--tries to munlock a page, or when shrink_page_list()
+encounters an anonymous page that is not yet in the swap cache, they need to
+determine whether or not the page is mapped by any VM_LOCKED vma, without
+actually attempting to unmap all ptes from the page.  For this purpose, the
+unevictable/mlock infrastructure introduced a variant of try_to_unmap() called
+try_to_munlock().
+
+try_to_munlock() calls the same functions as try_to_unmap() for anonymous and
+mapped file pages with an additional argument specifing unlock versus unmap
+processing.  Again, these functions walk the respective reverse maps looking
+for VM_LOCKED vmas.  When such a vma is found for anonymous pages and file
+pages mapped in linear VMAs, as in the try_to_unmap() case, the functions
+attempt to acquire the associated mmap semphore, mlock the page via
+mlock_vma_page() and return SWAP_MLOCK.  This effectively undoes the
+pre-clearing of the page's PG_mlocked done by munlock_vma_page() and informs
+shrink_page_list() that the anonymous page should be culled rather than added
+to the swap cache in preparation for a try_to_unmap() that will almost
+certainly fail.
+
+If try_to_unmap() is unable to acquire a VM_LOCKED vma's associated mmap
+semaphore, it will return SWAP_AGAIN.  This will allow shrink_page_list()
+to recycle the page on the inactive list and hope that it has better luck
+with the page next time.
+
+For file pages mapped into non-linear vmas, the try_to_munlock() logic works
+slightly differently.  On encountering a VM_LOCKED non-linear vma that might
+map the page, try_to_munlock() returns SWAP_AGAIN without actually mlocking
+the page.  munlock_vma_page() will just leave the page unlocked and let
+vmscan deal with it--the usual fallback position.
+
+Note that try_to_munlock()'s reverse map walk must visit every vma in a pages'
+reverse map to determine that a page is NOT mapped into any VM_LOCKED vma.
+However, the scan can terminate when it encounters a VM_LOCKED vma and can
+successfully acquire the vma's mmap semphore for read and mlock the page.
+Although try_to_munlock() can be called many [very many!] times when
+munlock()ing a large region or tearing down a large address space that has been
+mlocked via mlockall(), overall this is a fairly rare event.  In addition,
+although shrink_page_list() calls try_to_munlock() for every anonymous page that
+it handles that is not yet in the swap cache, on average anonymous pages will
+have very short reverse map lists.
+
+Mlocked Page:  Page Reclaim in shrink_*_list()
+
+shrink_active_list() culls any obviously unevictable pages--i.e.,
+!page_evictable(page, NULL)--diverting these to the unevictable lru
+list.  However, shrink_active_list() only sees unevictable pages that
+made it onto the active/inactive lru lists.  Note that these pages do not
+have PageUnevictable set--otherwise, they would be on the unevictable list and
+shrink_active_list would never see them.
+
+Some examples of these unevictable pages on the LRU lists are:
+
+1) ramfs pages that have been placed on the lru lists when first allocated.
+
+2) SHM_LOCKed shared memory pages.  shmctl(SHM_LOCK) does not attempt to
+   allocate or fault in the pages in the shared memory region.  This happens
+   when an application accesses the page the first time after SHM_LOCKing
+   the segment.
+
+3) Mlocked pages that could not be isolated from the lru and moved to the
+   unevictable list in mlock_vma_page().
+
+3) Pages mapped into multiple VM_LOCKED vmas, but try_to_munlock() couldn't
+   acquire the vma's mmap semaphore to test the flags and set PageMlocked.
+   munlock_vma_page() was forced to let the page back on to the normal
+   LRU list for vmscan to handle.
+
+shrink_inactive_list() also culls any unevictable pages that it finds
+on the inactive lists, again diverting them to the appropriate zone's unevictable
+lru list.  shrink_inactive_list() should only see SHM_LOCKed pages that became
+SHM_LOCKed after shrink_active_list() had moved them to the inactive list, or
+pages mapped into VM_LOCKED vmas that munlock_vma_page() couldn't isolate from
+the lru to recheck via try_to_munlock().  shrink_inactive_list() won't notice
+the latter, but will pass on to shrink_page_list().
+
+shrink_page_list() again culls obviously unevictable pages that it could
+encounter for similar reason to shrink_inactive_list().  As already discussed,
+shrink_page_list() proactively looks for anonymous pages that should have
+PG_mlocked set but don't--these would not be detected by page_evictable()--to
+avoid adding them to the swap cache unnecessarily.  File pages mapped into
+VM_LOCKED vmas but without PG_mlocked set will make it all the way to
+try_to_unmap().  shrink_page_list() will divert them to the unevictable list when
+try_to_unmap() returns SWAP_MLOCK, as discussed above.
+
+TODO/FIXME:  If we can enhance the swap cache to reliably remove entries
+with page_count(page) > 2, as long as all ptes are mapped to the page and
+not the swap entry, we can probably remove the call to try_to_munlock() in
+shrink_page_list() and just remove the page from the swap cache when
+try_to_unmap() returns SWAP_MLOCK.   Currently, remove_exclusive_swap_page()
+doesn't seem to allow that.
+
+
index a0f642b6a4b92b556e08c8c1d1e357979cd48322..6110197757a3f6283bf999519f1e7649fb96a867 100644 (file)
@@ -70,6 +70,7 @@ config AUTO_IRQ_AFFINITY
        default y
 
 source "init/Kconfig"
+source "kernel/Kconfig.freezer"
 
 
 menu "System setup"
index 15fda434442428660e3d896661ec11c9f134e71e..d069526bd7673f9ead6eb33e825782ea690e2fb0 100644 (file)
@@ -74,12 +74,14 @@ register struct thread_info *__current_thread_info __asm__("$8");
 #define TIF_UAC_SIGBUS         7
 #define TIF_MEMDIE             8
 #define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal */
+#define TIF_FREEZE             16      /* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 /* Work to do on interrupt/exception return.  */
 #define _TIF_WORK_MASK         (_TIF_SIGPENDING | _TIF_NEED_RESCHED)
index 04dcc5e5d4c1c4954d8c80186ac3390d1a9074cc..9cd8dca742a733f8791b850872f96d68e72497a7 100644 (file)
@@ -655,7 +655,7 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write)
 
        case 0x71:                                      /* RTC_PORT(1) */
                rtc_access.index = index;
-               rtc_access.data = BCD_TO_BIN(b);
+               rtc_access.data = bcd2bin(b);
                rtc_access.function = 0x48 + !write;    /* GET/PUT_TOY */
 
 #ifdef CONFIG_SMP
@@ -668,7 +668,7 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write)
 #else
                __marvel_access_rtc(&rtc_access);
 #endif
-               ret = BIN_TO_BCD(rtc_access.data);
+               ret = bin2bcd(rtc_access.data);
                break;
 
        default:
index 75480cab0893c391619e681bdc1ee6dd6adbf7ed..e6a231435cbac57f90ffe77907af51cf4b5ccc4f 100644 (file)
@@ -346,12 +346,12 @@ time_init(void)
        year = CMOS_READ(RTC_YEAR);
 
        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(sec);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(hour);
-               BCD_TO_BIN(day);
-               BCD_TO_BIN(mon);
-               BCD_TO_BIN(year);
+               sec = bcd2bin(sec);
+               min = bcd2bin(min);
+               hour = bcd2bin(hour);
+               day = bcd2bin(day);
+               mon = bcd2bin(mon);
+               year = bcd2bin(year);
        }
 
        /* PC-like is standard; used for year >= 70 */
@@ -525,7 +525,7 @@ set_rtc_mmss(unsigned long nowtime)
 
        cmos_minutes = CMOS_READ(RTC_MINUTES);
        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               BCD_TO_BIN(cmos_minutes);
+               cmos_minutes = bcd2bin(cmos_minutes);
 
        /*
         * since we're only adjusting minutes and seconds,
@@ -543,8 +543,8 @@ set_rtc_mmss(unsigned long nowtime)
 
        if (abs(real_minutes - cmos_minutes) < 30) {
                if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-                       BIN_TO_BCD(real_seconds);
-                       BIN_TO_BCD(real_minutes);
+                       real_seconds = bin2bcd(real_seconds);
+                       real_minutes = bin2bcd(real_minutes);
                }
                CMOS_WRITE(real_seconds,RTC_SECONDS);
                CMOS_WRITE(real_minutes,RTC_MINUTES);
index 4853f9df37bd22a037f122bd7d78a9a6600cc474..df39d20f7425ad9c41679a566ae212f924a222ff 100644 (file)
@@ -192,6 +192,8 @@ config VECTORS_BASE
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "System Type"
 
 choice
index eb4b190b6657256898dfbc2da475a32a98ee6f4d..eb35fca9aea527bde9992f80917fd69cc174c346 100644 (file)
@@ -4,6 +4,43 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 
+struct pxa3xx_nand_timing {
+       unsigned int    tCH;  /* Enable signal hold time */
+       unsigned int    tCS;  /* Enable signal setup time */
+       unsigned int    tWH;  /* ND_nWE high duration */
+       unsigned int    tWP;  /* ND_nWE pulse time */
+       unsigned int    tRH;  /* ND_nRE high duration */
+       unsigned int    tRP;  /* ND_nRE pulse width */
+       unsigned int    tR;   /* ND_nWE high to ND_nRE low for read */
+       unsigned int    tWHR; /* ND_nWE high to ND_nRE low for status read */
+       unsigned int    tAR;  /* ND_ALE low to ND_nRE low delay */
+};
+
+struct pxa3xx_nand_cmdset {
+       uint16_t        read1;
+       uint16_t        read2;
+       uint16_t        program;
+       uint16_t        read_status;
+       uint16_t        read_id;
+       uint16_t        erase;
+       uint16_t        reset;
+       uint16_t        lock;
+       uint16_t        unlock;
+       uint16_t        lock_status;
+};
+
+struct pxa3xx_nand_flash {
+       const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
+       const struct pxa3xx_nand_cmdset *cmdset;
+
+       uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
+       uint32_t page_size;     /* Page size in bytes (PAGE_SZ) */
+       uint32_t flash_width;   /* Width of Flash memory (DWIDTH_M) */
+       uint32_t dfc_width;     /* Width of flash controller(DWIDTH_C) */
+       uint32_t num_blocks;    /* Number of physical blocks in Flash */
+       uint32_t chip_id;
+};
+
 struct pxa3xx_nand_platform_data {
 
        /* the data flash bus is shared between the Static Memory
@@ -12,8 +49,11 @@ struct pxa3xx_nand_platform_data {
         */
        int     enable_arbiter;
 
-       struct mtd_partition *parts;
-       unsigned int    nr_parts;
+       const struct mtd_partition              *parts;
+       unsigned int                            nr_parts;
+
+       const struct pxa3xx_nand_flash *        flash;
+       size_t                                  num_flash;
 };
 
 extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info);
diff --git a/arch/arm/plat-mxc/include/mach/mxc_nand.h b/arch/arm/plat-mxc/include/mach/mxc_nand.h
new file mode 100644 (file)
index 0000000..2b972df
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
+ *
+ * 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 __ASM_ARCH_NAND_H
+#define __ASM_ARCH_NAND_H
+
+struct mxc_nand_platform_data {
+       int width;      /* data bus width in bytes */
+       int hw_ecc;     /* 0 if supress hardware ECC */
+};
+#endif /* __ASM_ARCH_NAND_H */
index d57f20226b28733743c35455bb798836ba34f299..4649d302c263723abb48c6c33579d39f96813e4f 100644 (file)
@@ -16,6 +16,10 @@ struct omap_onenand_platform_data {
        int                     gpio_irq;
        struct mtd_partition    *parts;
        int                     nr_parts;
-       int                     (*onenand_setup)(void __iomem *);
+       int                     (*onenand_setup)(void __iomem *, int freq);
        int                     dma_channel;
 };
+
+int omap2_onenand_rephase(void);
+
+#define ONENAND_MAX_PARTITIONS 8
index 7c239a916275b6b66b326e7fc93c6207bdbaf270..33a5b2969eb4addf24e36a59159d72488530dc0b 100644 (file)
@@ -72,6 +72,8 @@ config GENERIC_BUG
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "System Type and features"
 
 source "kernel/time/Kconfig"
index 294b25f9323dda6a4885de1a6b874b4a6a3bb825..4442f8d2d4239a09470e04583aa9f168583246d9 100644 (file)
@@ -96,6 +96,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_MEMDIE            (1 << TIF_MEMDIE)
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_CPU_GOING_TO_SLEEP (1 << TIF_CPU_GOING_TO_SLEEP)
+#define _TIF_FREEZE            (1 << TIF_FREEZE)
 
 /* Note: The masks below must never span more than 16 bits! */
 
index 8102c79aaa94044369612ab3a8dc3bb6e33aa807..29e71ed6b8a7fb9c5e4b8381244a4c3d5b1d47db 100644 (file)
@@ -64,8 +64,11 @@ config HARDWARE_PM
        depends on OPROFILE
 
 source "init/Kconfig"
+
 source "kernel/Kconfig.preempt"
 
+source "kernel/Kconfig.freezer"
+
 menu "Blackfin Processor Options"
 
 comment "Processor and Board Settings"
index 9389d38f222f2f749497b106872278a7da5bdd0b..07335e719bf835d7ad5e88a6b844f07210b4b6ba 100644 (file)
@@ -62,6 +62,8 @@ config HZ
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "General setup"
 
 source "fs/Kconfig.binfmt"
index c9aa3904be05610f35425ced24c0a88a93383350..3bdfaf43390ce00b03ead8226136b3849a63e1e6 100644 (file)
@@ -215,12 +215,12 @@ get_rtc_time(struct rtc_time *rtc_tm)
 
        local_irq_restore(flags);
        
-       BCD_TO_BIN(rtc_tm->tm_sec);
-       BCD_TO_BIN(rtc_tm->tm_min);
-       BCD_TO_BIN(rtc_tm->tm_hour);
-       BCD_TO_BIN(rtc_tm->tm_mday);
-       BCD_TO_BIN(rtc_tm->tm_mon);
-       BCD_TO_BIN(rtc_tm->tm_year);
+       rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+       rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+       rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+       rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+       rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+       rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
 
        /*
         * Account for differences between how the RTC uses the values
@@ -295,12 +295,12 @@ rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
                        else
                                yrs -= 1900;    /* RTC (70, 71, ... 99) */
 
-                       BIN_TO_BCD(sec);
-                       BIN_TO_BCD(min);
-                       BIN_TO_BCD(hrs);
-                       BIN_TO_BCD(day);
-                       BIN_TO_BCD(mon);
-                       BIN_TO_BCD(yrs);
+                       sec = bin2bcd(sec);
+                       min = bin2bcd(min);
+                       hrs = bin2bcd(hrs);
+                       day = bin2bcd(day);
+                       mon = bin2bcd(mon);
+                       yrs = bin2bcd(yrs);
 
                        local_irq_save(flags);
                        CMOS_WRITE(yrs, RTC_YEAR);
index 8769dc914073804ce0c75240e0aa6b60fc7c602a..1e90c1a9c849bd4453b462e3b611808171e5c475 100644 (file)
@@ -122,7 +122,7 @@ get_rtc_time(struct rtc_time *tm)
                       "information is no longer guaranteed!\n", PCF8563_NAME);
        }
 
-       tm->tm_year  = BCD_TO_BIN(tm->tm_year) +
+       tm->tm_year  = bcd2bin(tm->tm_year) +
                       ((tm->tm_mon & 0x80) ? 100 : 0);
        tm->tm_sec  &= 0x7F;
        tm->tm_min  &= 0x7F;
@@ -131,11 +131,11 @@ get_rtc_time(struct rtc_time *tm)
        tm->tm_wday &= 0x07; /* Not coded in BCD. */
        tm->tm_mon  &= 0x1F;
 
-       BCD_TO_BIN(tm->tm_sec);
-       BCD_TO_BIN(tm->tm_min);
-       BCD_TO_BIN(tm->tm_hour);
-       BCD_TO_BIN(tm->tm_mday);
-       BCD_TO_BIN(tm->tm_mon);
+       tm->tm_sec = bcd2bin(tm->tm_sec);
+       tm->tm_min = bcd2bin(tm->tm_min);
+       tm->tm_hour = bcd2bin(tm->tm_hour);
+       tm->tm_mday = bcd2bin(tm->tm_mday);
+       tm->tm_mon = bcd2bin(tm->tm_mon);
        tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
 }
 
@@ -282,12 +282,12 @@ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                century = (tm.tm_year >= 2000) ? 0x80 : 0;
                tm.tm_year = tm.tm_year % 100;
 
-               BIN_TO_BCD(tm.tm_year);
-               BIN_TO_BCD(tm.tm_mon);
-               BIN_TO_BCD(tm.tm_mday);
-               BIN_TO_BCD(tm.tm_hour);
-               BIN_TO_BCD(tm.tm_min);
-               BIN_TO_BCD(tm.tm_sec);
+               tm.tm_year = bin2bcd(tm.tm_year);
+               tm.tm_mon = bin2bcd(tm.tm_mon);
+               tm.tm_mday = bin2bcd(tm.tm_mday);
+               tm.tm_hour = bin2bcd(tm.tm_hour);
+               tm.tm_min = bin2bcd(tm.tm_min);
+               tm.tm_sec = bin2bcd(tm.tm_sec);
                tm.tm_mon |= century;
 
                mutex_lock(&rtc_lock);
index f263ab571221cb66e5fc200659069ea2291450d7..f4478506e52ca1df58b52180ffd871e77c51e726 100644 (file)
@@ -118,7 +118,7 @@ get_rtc_time(struct rtc_time *tm)
                       "information is no longer guaranteed!\n", PCF8563_NAME);
        }
 
-       tm->tm_year  = BCD_TO_BIN(tm->tm_year) +
+       tm->tm_year  = bcd2bin(tm->tm_year) +
                       ((tm->tm_mon & 0x80) ? 100 : 0);
        tm->tm_sec  &= 0x7F;
        tm->tm_min  &= 0x7F;
@@ -127,11 +127,11 @@ get_rtc_time(struct rtc_time *tm)
        tm->tm_wday &= 0x07; /* Not coded in BCD. */
        tm->tm_mon  &= 0x1F;
 
-       BCD_TO_BIN(tm->tm_sec);
-       BCD_TO_BIN(tm->tm_min);
-       BCD_TO_BIN(tm->tm_hour);
-       BCD_TO_BIN(tm->tm_mday);
-       BCD_TO_BIN(tm->tm_mon);
+       tm->tm_sec = bcd2bin(tm->tm_sec);
+       tm->tm_min = bcd2bin(tm->tm_min);
+       tm->tm_hour = bcd2bin(tm->tm_hour);
+       tm->tm_mday = bcd2bin(tm->tm_mday);
+       tm->tm_mon = bcd2bin(tm->tm_mon);
        tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
 }
 
@@ -279,12 +279,12 @@ int pcf8563_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
                century = (tm.tm_year >= 2000) ? 0x80 : 0;
                tm.tm_year = tm.tm_year % 100;
 
-               BIN_TO_BCD(tm.tm_year);
-               BIN_TO_BCD(tm.tm_mon);
-               BIN_TO_BCD(tm.tm_mday);
-               BIN_TO_BCD(tm.tm_hour);
-               BIN_TO_BCD(tm.tm_min);
-               BIN_TO_BCD(tm.tm_sec);
+               tm.tm_year = bin2bcd(tm.tm_year);
+               tm.tm_mon = bin2bcd(tm.tm_mon);
+               tm.tm_mday = bin2bcd(tm.tm_mday);
+               tm.tm_hour = bin2bcd(tm.tm_hour);
+               tm.tm_min = bin2bcd(tm.tm_min);
+               tm.tm_sec = bin2bcd(tm.tm_sec);
                tm.tm_mon |= century;
 
                mutex_lock(&rtc_lock);
index ff4c6aa75defa157e1e4bd436cf47d4c4526e415..074fe7dea96bbaa44c27f6ef513253552646a756 100644 (file)
@@ -127,7 +127,7 @@ int set_rtc_mmss(unsigned long nowtime)
                return 0;
 
        cmos_minutes = CMOS_READ(RTC_MINUTES);
-       BCD_TO_BIN(cmos_minutes);
+       cmos_minutes = bcd2bin(cmos_minutes);
 
        /*
         * since we're only adjusting minutes and seconds,
@@ -142,8 +142,8 @@ int set_rtc_mmss(unsigned long nowtime)
        real_minutes %= 60;
 
        if (abs(real_minutes - cmos_minutes) < 30) {
-               BIN_TO_BCD(real_seconds);
-               BIN_TO_BCD(real_minutes);
+               real_seconds = bin2bcd(real_seconds);
+               real_minutes = bin2bcd(real_minutes);
                CMOS_WRITE(real_seconds,RTC_SECONDS);
                CMOS_WRITE(real_minutes,RTC_MINUTES);
        } else {
@@ -170,12 +170,12 @@ get_cmos_time(void)
        mon = CMOS_READ(RTC_MONTH);
        year = CMOS_READ(RTC_YEAR);
 
-       BCD_TO_BIN(sec);
-       BCD_TO_BIN(min);
-       BCD_TO_BIN(hour);
-       BCD_TO_BIN(day);
-       BCD_TO_BIN(mon);
-       BCD_TO_BIN(year);
+       sec = bcd2bin(sec);
+       min = bcd2bin(min);
+       hour = bcd2bin(hour);
+       day = bcd2bin(day);
+       mon = bcd2bin(mon);
+       year = bcd2bin(year);
 
        if ((year += 1900) < 1970)
                year += 100;
index a5aac1b075628b8a30004d52bb73d2e1ce7d978f..9d1552a9ee2c88ddb40bc7d70dea316f725d2843 100644 (file)
@@ -66,6 +66,8 @@ mainmenu "Fujitsu FR-V Kernel Configuration"
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 
 menu "Fujitsu FR-V system setup"
 
index c7966746fbfec582938b77a37baaed384d1b0ec2..bd1995403c67d0f9b37b34674a6c80ab7ee2a76b 100644 (file)
@@ -90,6 +90,8 @@ config HZ
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 source "arch/h8300/Kconfig.cpu"
 
 menu "Executable file formats"
index aafd4d322ec3e2e8c6767aac9ea125587ff4b322..700014d2155fd8d82a4aeadb54c4b3ad682855bb 100644 (file)
@@ -89,6 +89,7 @@ static inline struct thread_info *current_thread_info(void)
                                           TIF_NEED_RESCHED */
 #define TIF_MEMDIE             4
 #define TIF_RESTORE_SIGMASK    5       /* restore signal mask in do_signal() */
+#define TIF_FREEZE             16      /* is freezing for suspend */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
@@ -96,6 +97,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 
index 3b7aa38254a8408b5564a260eb7a2ef30cf8d5f8..912c57db2d2180888ee9b366d7fae435c45c354d 100644 (file)
@@ -7,6 +7,8 @@ mainmenu "IA-64 Linux Kernel Configuration"
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "Processor type and features"
 
 config IA64
index 4956be40d7b56d9c03a3224e45f743e8f6e34d39..d98f0f4ff83f22c01df79ffc063d5aaafd8be4a7 100644 (file)
@@ -2070,14 +2070,13 @@ sba_init(void)
        if (!ia64_platform_is("hpzx1") && !ia64_platform_is("hpzx1_swiotlb"))
                return 0;
 
-#if defined(CONFIG_IA64_GENERIC) && defined(CONFIG_CRASH_DUMP) && \
-        defined(CONFIG_PROC_FS)
+#if defined(CONFIG_IA64_GENERIC)
        /* If we are booting a kdump kernel, the sba_iommu will
         * cause devices that were not shutdown properly to MCA
         * as soon as they are turned back on.  Our only option for
         * a successful kdump kernel boot is to use the swiotlb.
         */
-       if (elfcorehdr_addr < ELFCORE_ADDR_MAX) {
+       if (is_kdump_kernel()) {
                if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
                        panic("Unable to initialize software I/O TLB:"
                                  " Try machvec=dig boot option");
index da60e90eeeb1493ee21ab75b130eb3d15732ae83..23e91290e41faf3151bbb93a7bfdde76553ecb3a 100644 (file)
@@ -8,10 +8,14 @@
 
 #include <linux/errno.h>
 #include <linux/types.h>
+#include <linux/crash_dump.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
 
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
index 51b75cea701866629449f7945ddef10079faa7ab..efaff15d8cf1dc9cad35a767a53b3865d51037b4 100644 (file)
@@ -1335,7 +1335,7 @@ kdump_find_rsvd_region (unsigned long size, struct rsvd_region *r, int n)
 }
 #endif
 
-#ifdef CONFIG_PROC_VMCORE
+#ifdef CONFIG_CRASH_DUMP
 /* locate the size find a the descriptor at a certain address */
 unsigned long __init
 vmcore_find_descriptor_size (unsigned long address)
index de636b215677e801c23076d74f6d5a2d29e68efb..916ba898237f27a6eca8d5b79cc92cce86b716f1 100644 (file)
@@ -352,7 +352,7 @@ reserve_memory (void)
        }
 #endif
 
-#ifdef CONFIG_PROC_VMCORE
+#ifdef CONFIG_CRASH_KERNEL
        if (reserve_elfcorehdr(&rsvd_region[n].start,
                               &rsvd_region[n].end) == 0)
                n++;
@@ -478,7 +478,12 @@ static __init int setup_nomca(char *s)
 }
 early_param("nomca", setup_nomca);
 
-#ifdef CONFIG_PROC_VMCORE
+/*
+ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
+ * is_kdump_kernel() to determine if we are booting after a panic. Hence
+ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
+ */
+#ifdef CONFIG_CRASH_DUMP
 /* elfcorehdr= specifies the location of elf core header
  * stored by the crashed kernel.
  */
@@ -502,11 +507,11 @@ int __init reserve_elfcorehdr(unsigned long *start, unsigned long *end)
         * to work properly.
         */
 
-       if (elfcorehdr_addr >= ELFCORE_ADDR_MAX)
+       if (!is_vmcore_usable())
                return -EINVAL;
 
        if ((length = vmcore_find_descriptor_size(elfcorehdr_addr)) == 0) {
-               elfcorehdr_addr = ELFCORE_ADDR_MAX;
+               vmcore_unusable();
                return -EINVAL;
        }
 
index f482a9098e32aadec0fc194befc4906a6be7f6b2..054bcd9439aa887a724fc031ec91701b7fefb218 100644 (file)
@@ -700,23 +700,6 @@ int arch_add_memory(int nid, u64 start, u64 size)
 
        return ret;
 }
-#ifdef CONFIG_MEMORY_HOTREMOVE
-int remove_memory(u64 start, u64 size)
-{
-       unsigned long start_pfn, end_pfn;
-       unsigned long timeout = 120 * HZ;
-       int ret;
-       start_pfn = start >> PAGE_SHIFT;
-       end_pfn = start_pfn + (size >> PAGE_SHIFT);
-       ret = offline_pages(start_pfn, end_pfn, timeout);
-       if (ret)
-               goto out;
-       /* we can free mem_map at this point */
-out:
-       return ret;
-}
-EXPORT_SYMBOL_GPL(remove_memory);
-#endif /* CONFIG_MEMORY_HOTREMOVE */
 #endif
 
 /*
index 00289c178f895a6ad62a7fb34603af08d52bc961..dbaed4a638153bc43c5fa4d6e138039bb5cca8df 100644 (file)
@@ -42,6 +42,8 @@ config HZ
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 
 menu "Processor type and features"
 
index 677c93a490f6f49501e4c7d2e375fd42bb4dabc5..836fb66f080dcbadeb5f6d96fba8f01679d85d02 100644 (file)
@@ -62,6 +62,8 @@ mainmenu "Linux/68k Kernel Configuration"
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "Platform dependent setup"
 
 config EISA
index 808c9018b115022dd2ba8dee88a070fc003448ce..c50bec8aabb1983e3517857b5abafa75f91b7ace 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/mc146818rtc.h> /* For struct rtc_time and ioctls, etc */
-#include <linux/smp_lock.h>
 #include <linux/bcd.h>
 #include <asm/bvme6000hw.h>
 
index 0a8998315e5ed9fcdada66d87c5ee1127e35b9ac..76b66feb74df82d42b21a4b8ac67d6df0f498812 100644 (file)
@@ -75,6 +75,8 @@ config NO_IOPORT
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "Processor type and features"
 
 choice
index 0c9bc095f3f0bc3cae753f788f72786a67b96512..82529f424ea3d567d0c1a9a2991b9591f7dacd85 100644 (file)
@@ -84,12 +84,14 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_POLLING_NRFLAG     3       /* true if poll_idle() is polling
                                           TIF_NEED_RESCHED */
 #define TIF_MEMDIE             4
+#define TIF_FREEZE             16      /* is freezing for suspend */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 
index b905744d79153be3d3170e9f81ce4e0805974d71..5f149b030c0f9fc7949793c6d8591d4bf0fd0450 100644 (file)
@@ -1885,6 +1885,8 @@ config PROBE_INITRD_HEADER
          add initrd or initramfs image to the kernel image.
          Otherwise, say N.
 
+source "kernel/Kconfig.freezer"
+
 menu "Bus options (PCI, PCMCIA, EISA, ISA, TC)"
 
 config HW_HAS_EISA
index 3965fda94a89afd60fdc861f9520340cc9d246cd..1359c03ded5111adb0892029b59ebffbd26eee7f 100644 (file)
@@ -45,12 +45,12 @@ unsigned long read_persistent_clock(void)
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               sec = BCD2BIN(sec);
-               min = BCD2BIN(min);
-               hour = BCD2BIN(hour);
-               day = BCD2BIN(day);
-               mon = BCD2BIN(mon);
-               year = BCD2BIN(year);
+               sec = bcd2bin(sec);
+               min = bcd2bin(min);
+               hour = bcd2bin(hour);
+               day = bcd2bin(day);
+               mon = bcd2bin(mon);
+               year = bcd2bin(year);
        }
 
        year += real_year - 72 + 2000;
@@ -83,7 +83,7 @@ int rtc_mips_set_mmss(unsigned long nowtime)
 
        cmos_minutes = CMOS_READ(RTC_MINUTES);
        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               cmos_minutes = BCD2BIN(cmos_minutes);
+               cmos_minutes = bcd2bin(cmos_minutes);
 
        /*
         * since we're only adjusting minutes and seconds,
@@ -99,8 +99,8 @@ int rtc_mips_set_mmss(unsigned long nowtime)
 
        if (abs(real_minutes - cmos_minutes) < 30) {
                if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-                       real_seconds = BIN2BCD(real_seconds);
-                       real_minutes = BIN2BCD(real_minutes);
+                       real_seconds = bin2bcd(real_seconds);
+                       real_minutes = bin2bcd(real_minutes);
                }
                CMOS_WRITE(real_seconds, RTC_SECONDS);
                CMOS_WRITE(real_minutes, RTC_MINUTES);
index cdc379a0a94ea6c39bd2f4ebdeed2e2774d72c27..199b45733a95ba4ff2d99d548fa354cfb219c7a4 100644 (file)
@@ -44,7 +44,7 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
 
        cmos_minutes = CMOS_READ(RTC_MINUTES);
        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               BCD_TO_BIN(cmos_minutes);
+               cmos_minutes = bcd2bin(cmos_minutes);
 
        /*
         * since we're only adjusting minutes and seconds,
@@ -60,8 +60,8 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
 
        if (abs(real_minutes - cmos_minutes) < 30) {
                if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-                       BIN_TO_BCD(real_seconds);
-                       BIN_TO_BCD(real_minutes);
+                       real_seconds = bin2bcd(real_seconds);
+                       real_minutes = bin2bcd(real_minutes);
                }
                CMOS_WRITE(real_seconds, RTC_SECONDS);
                CMOS_WRITE(real_minutes, RTC_MINUTES);
@@ -103,12 +103,12 @@ static inline unsigned long mc146818_get_cmos_time(void)
        } while (sec != CMOS_READ(RTC_SECONDS));
 
        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(sec);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(hour);
-               BCD_TO_BIN(day);
-               BCD_TO_BIN(mon);
-               BCD_TO_BIN(year);
+               sec = bcd2bin(sec);
+               min = bcd2bin(min);
+               hour = bcd2bin(hour);
+               day = bcd2bin(day);
+               mon = bcd2bin(mon);
+               year = bcd2bin(year);
        }
        spin_unlock_irqrestore(&rtc_lock, flags);
        year = mc146818_decode_year(year);
index 6537d90a25bbcbd1cc0430a41e2e0d6b46950616..2d3c0dca275d40fd75a1db2b0aba1b54d635f338 100644 (file)
@@ -79,14 +79,14 @@ unsigned long read_persistent_clock(void)
        /* Stop the update to the time */
        m48t37_base->control = 0x40;
 
-       year = BCD2BIN(m48t37_base->year);
-       year += BCD2BIN(m48t37_base->century) * 100;
+       year = bcd2bin(m48t37_base->year);
+       year += bcd2bin(m48t37_base->century) * 100;
 
-       month = BCD2BIN(m48t37_base->month);
-       day = BCD2BIN(m48t37_base->date);
-       hour = BCD2BIN(m48t37_base->hour);
-       min = BCD2BIN(m48t37_base->min);
-       sec = BCD2BIN(m48t37_base->sec);
+       month = bcd2bin(m48t37_base->month);
+       day = bcd2bin(m48t37_base->date);
+       hour = bcd2bin(m48t37_base->hour);
+       min = bcd2bin(m48t37_base->min);
+       sec = bcd2bin(m48t37_base->sec);
 
        /* Start the update to the time again */
        m48t37_base->control = 0x00;
@@ -113,22 +113,22 @@ int rtc_mips_set_time(unsigned long tim)
        m48t37_base->control = 0x80;
 
        /* year */
-       m48t37_base->year = BIN2BCD(tm.tm_year % 100);
-       m48t37_base->century = BIN2BCD(tm.tm_year / 100);
+       m48t37_base->year = bin2bcd(tm.tm_year % 100);
+       m48t37_base->century = bin2bcd(tm.tm_year / 100);
 
        /* month */
-       m48t37_base->month = BIN2BCD(tm.tm_mon);
+       m48t37_base->month = bin2bcd(tm.tm_mon);
 
        /* day */
-       m48t37_base->date = BIN2BCD(tm.tm_mday);
+       m48t37_base->date = bin2bcd(tm.tm_mday);
 
        /* hour/min/sec */
-       m48t37_base->hour = BIN2BCD(tm.tm_hour);
-       m48t37_base->min = BIN2BCD(tm.tm_min);
-       m48t37_base->sec = BIN2BCD(tm.tm_sec);
+       m48t37_base->hour = bin2bcd(tm.tm_hour);
+       m48t37_base->min = bin2bcd(tm.tm_min);
+       m48t37_base->sec = bin2bcd(tm.tm_sec);
 
        /* day of week -- not really used, but let's keep it up-to-date */
-       m48t37_base->day = BIN2BCD(tm.tm_wday + 1);
+       m48t37_base->day = bin2bcd(tm.tm_wday + 1);
 
        /* disable writing */
        m48t37_base->control = 0x00;
index 26fbff4c15b1ece152870eef2bdf152cf0e15cc8..b732600b47f5e5e8ad7908e61cd55d22d9f4f6f2 100644 (file)
@@ -156,32 +156,32 @@ int m41t81_set_time(unsigned long t)
         */
 
        spin_lock_irqsave(&rtc_lock, flags);
-       tm.tm_sec = BIN2BCD(tm.tm_sec);
+       tm.tm_sec = bin2bcd(tm.tm_sec);
        m41t81_write(M41T81REG_SC, tm.tm_sec);
 
-       tm.tm_min = BIN2BCD(tm.tm_min);
+       tm.tm_min = bin2bcd(tm.tm_min);
        m41t81_write(M41T81REG_MN, tm.tm_min);
 
-       tm.tm_hour = BIN2BCD(tm.tm_hour);
+       tm.tm_hour = bin2bcd(tm.tm_hour);
        tm.tm_hour = (tm.tm_hour & 0x3f) | (m41t81_read(M41T81REG_HR) & 0xc0);
        m41t81_write(M41T81REG_HR, tm.tm_hour);
 
        /* tm_wday starts from 0 to 6 */
        if (tm.tm_wday == 0) tm.tm_wday = 7;
-       tm.tm_wday = BIN2BCD(tm.tm_wday);
+       tm.tm_wday = bin2bcd(tm.tm_wday);
        m41t81_write(M41T81REG_DY, tm.tm_wday);
 
-       tm.tm_mday = BIN2BCD(tm.tm_mday);
+       tm.tm_mday = bin2bcd(tm.tm_mday);
        m41t81_write(M41T81REG_DT, tm.tm_mday);
 
        /* tm_mon starts from 0, *ick* */
        tm.tm_mon ++;
-       tm.tm_mon = BIN2BCD(tm.tm_mon);
+       tm.tm_mon = bin2bcd(tm.tm_mon);
        m41t81_write(M41T81REG_MO, tm.tm_mon);
 
        /* we don't do century, everything is beyond 2000 */
        tm.tm_year %= 100;
-       tm.tm_year = BIN2BCD(tm.tm_year);
+       tm.tm_year = bin2bcd(tm.tm_year);
        m41t81_write(M41T81REG_YR, tm.tm_year);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
@@ -209,12 +209,12 @@ unsigned long m41t81_get_time(void)
        year = m41t81_read(M41T81REG_YR);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       sec = BCD2BIN(sec);
-       min = BCD2BIN(min);
-       hour = BCD2BIN(hour);
-       day = BCD2BIN(day);
-       mon = BCD2BIN(mon);
-       year = BCD2BIN(year);
+       sec = bcd2bin(sec);
+       min = bcd2bin(min);
+       hour = bcd2bin(hour);
+       day = bcd2bin(day);
+       mon = bcd2bin(mon);
+       year = bcd2bin(year);
 
        year += 2000;
 
index ff3e5dabb348edda9707e69b5f18c77a0a69790c..4438b2195c4475d8f1b659422d354de78d07e132 100644 (file)
@@ -124,18 +124,18 @@ int xicor_set_time(unsigned long t)
        xicor_write(X1241REG_SR, X1241REG_SR_WEL | X1241REG_SR_RWEL);
 
        /* trivial ones */
-       tm.tm_sec = BIN2BCD(tm.tm_sec);
+       tm.tm_sec = bin2bcd(tm.tm_sec);
        xicor_write(X1241REG_SC, tm.tm_sec);
 
-       tm.tm_min = BIN2BCD(tm.tm_min);
+       tm.tm_min = bin2bcd(tm.tm_min);
        xicor_write(X1241REG_MN, tm.tm_min);
 
-       tm.tm_mday = BIN2BCD(tm.tm_mday);
+       tm.tm_mday = bin2bcd(tm.tm_mday);
        xicor_write(X1241REG_DT, tm.tm_mday);
 
        /* tm_mon starts from 0, *ick* */
        tm.tm_mon ++;
-       tm.tm_mon = BIN2BCD(tm.tm_mon);
+       tm.tm_mon = bin2bcd(tm.tm_mon);
        xicor_write(X1241REG_MO, tm.tm_mon);
 
        /* year is split */
@@ -148,7 +148,7 @@ int xicor_set_time(unsigned long t)
        tmp = xicor_read(X1241REG_HR);
        if (tmp & X1241REG_HR_MIL) {
                /* 24 hour format */
-               tm.tm_hour = BIN2BCD(tm.tm_hour);
+               tm.tm_hour = bin2bcd(tm.tm_hour);
                tmp = (tmp & ~0x3f) | (tm.tm_hour & 0x3f);
        } else {
                /* 12 hour format, with 0x2 for pm */
@@ -157,7 +157,7 @@ int xicor_set_time(unsigned long t)
                        tmp |= 0x20;
                        tm.tm_hour -= 12;
                }
-               tm.tm_hour = BIN2BCD(tm.tm_hour);
+               tm.tm_hour = bin2bcd(tm.tm_hour);
                tmp |= tm.tm_hour;
        }
        xicor_write(X1241REG_HR, tmp);
@@ -191,13 +191,13 @@ unsigned long xicor_get_time(void)
        y2k = xicor_read(X1241REG_Y2K);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       sec = BCD2BIN(sec);
-       min = BCD2BIN(min);
-       hour = BCD2BIN(hour);
-       day = BCD2BIN(day);
-       mon = BCD2BIN(mon);
-       year = BCD2BIN(year);
-       y2k = BCD2BIN(y2k);
+       sec = bcd2bin(sec);
+       min = bcd2bin(min);
+       hour = bcd2bin(hour);
+       day = bcd2bin(day);
+       mon = bcd2bin(mon);
+       year = bcd2bin(year);
+       y2k = bcd2bin(y2k);
 
        year += (y2k * 100);
 
index dd557c9cf001be6226441b78cb84753f5e50cb15..9a9f433588792f5030796b2686193f4983c98ce9 100644 (file)
@@ -68,6 +68,8 @@ mainmenu "Matsushita MN10300/AM33 Kernel Configuration"
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 
 menu "Matsushita MN10300 system setup"
 
index 042f792d843052c7396ce76641a5cc8b472e7215..7978470b5749352e3b1f81beb018648be65ac786 100644 (file)
@@ -67,7 +67,7 @@ static int set_rtc_mmss(unsigned long nowtime)
 
        cmos_minutes = CMOS_READ(RTC_MINUTES);
        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               BCD_TO_BIN(cmos_minutes);
+               cmos_minutes = bcd2bin(cmos_minutes);
 
        /*
         * since we're only adjusting minutes and seconds,
@@ -84,8 +84,8 @@ static int set_rtc_mmss(unsigned long nowtime)
 
        if (abs(real_minutes - cmos_minutes) < 30) {
                if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-                       BIN_TO_BCD(real_seconds);
-                       BIN_TO_BCD(real_minutes);
+                       real_seconds = bin2bcd(real_seconds);
+                       real_minutes = bin2bcd(real_minutes);
                }
                CMOS_WRITE(real_seconds, RTC_SECONDS);
                CMOS_WRITE(real_minutes, RTC_MINUTES);
index 8313fccced5e1553f6f3d7ff484d897d2d20b812..2bd1f6ef5db0c6bd45269701b36b4713c0a6def3 100644 (file)
@@ -90,6 +90,8 @@ config ARCH_MAY_HAVE_PC_FDC
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 
 menu "Processor type and features"
 
index 380baa1780e9197b060ce1594aa098340d4da538..9391199d9e7731d166b45130fa322e27936b1da0 100644 (file)
@@ -230,6 +230,8 @@ config PPC_OF_PLATFORM_PCI
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 source "arch/powerpc/sysdev/Kconfig"
 source "arch/powerpc/platforms/Kconfig"
 
index fda98715cd356a4b74a18e66c860c81ed62ee50a..5aa22cffdbd658d02c616ba822e3071ac642e3ac 100644 (file)
@@ -678,6 +678,8 @@ struct ps3av_pkt_avb_param {
        u8 buf[PS3AV_PKT_AVB_PARAM_MAX_BUF_SIZE];
 };
 
+/* channel status */
+extern u8 ps3av_mode_cs_info[];
 
 /** command status **/
 #define PS3AV_STATUS_SUCCESS                   0x0000  /* success */
@@ -735,6 +737,7 @@ extern int ps3av_get_mode(void);
 extern int ps3av_video_mode2res(u32, u32 *, u32 *);
 extern int ps3av_video_mute(int);
 extern int ps3av_audio_mute(int);
+extern int ps3av_audio_mute_analog(int);
 extern int ps3av_dev_open(void);
 extern int ps3av_dev_close(void);
 extern void ps3av_register_flip_ctl(void (*flip_ctl)(int on, void *data),
index a323c9b32ee12f76604631a532e2c5dc85436aa1..97e056379728c5f936aba586c0f9cf2acf044e34 100644 (file)
@@ -27,6 +27,9 @@
 #define DBG(fmt...)
 #endif
 
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
 void __init reserve_kdump_trampoline(void)
 {
        lmb_reserve(0, KDUMP_RESERVE_LIMIT);
@@ -66,7 +69,11 @@ void __init setup_kdump_trampoline(void)
        DBG(" <- setup_kdump_trampoline()\n");
 }
 
-#ifdef CONFIG_PROC_VMCORE
+/*
+ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
+ * is_kdump_kernel() to determine if we are booting after a panic. Hence
+ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
+ */
 static int __init parse_elfcorehdr(char *p)
 {
        if (p)
@@ -75,7 +82,6 @@ static int __init parse_elfcorehdr(char *p)
        return 1;
 }
 __setup("elfcorehdr=", parse_elfcorehdr);
-#endif
 
 static int __init parse_savemaxmem(char *p)
 {
index 98d7bf99533aff312712d747beed29141294608d..b9e1a1da6e52a35f2276c798b71e717bb224ec88 100644 (file)
@@ -134,23 +134,6 @@ int arch_add_memory(int nid, u64 start, u64 size)
 
        return __add_pages(zone, start_pfn, nr_pages);
 }
-
-#ifdef CONFIG_MEMORY_HOTREMOVE
-int remove_memory(u64 start, u64 size)
-{
-       unsigned long start_pfn, end_pfn;
-       int ret;
-
-       start_pfn = start >> PAGE_SHIFT;
-       end_pfn = start_pfn + (size >> PAGE_SHIFT);
-       ret = offline_pages(start_pfn, end_pfn, 120 * HZ);
-       if (ret)
-               goto out;
-       /* Arch-specific calls go here - next patch */
-out:
-       return ret;
-}
-#endif /* CONFIG_MEMORY_HOTREMOVE */
 #endif /* CONFIG_MEMORY_HOTPLUG */
 
 /*
index bc581d8a7cd9c35995e6bb75ae1f17d101840de1..70b7645ce745aa03863360201183a832aec3f130 100644 (file)
@@ -78,6 +78,8 @@ config S390
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "Base setup"
 
 comment "Processor type and features"
index ea40a9d690fcc19407d8fd8a610d1af5b25a7a7d..de3fad60c6828d95c45a10944b2bc42a9b8fefb5 100644 (file)
@@ -99,6 +99,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_31BIT              18      /* 32bit process */ 
 #define TIF_MEMDIE             19
 #define TIF_RESTORE_SIGMASK    20      /* restore signal mask in do_signal() */
+#define TIF_FREEZE             21      /* thread is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
@@ -112,6 +113,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT             (1<<TIF_31BIT)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 #endif /* __KERNEL__ */
 
index 1169130a97efdc2661a8e51fcfa9abbb33f4f5cc..158b0d6d70462942975048759222c6fa69874433 100644 (file)
@@ -189,14 +189,3 @@ int arch_add_memory(int nid, u64 start, u64 size)
        return rc;
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
-
-#ifdef CONFIG_MEMORY_HOTREMOVE
-int remove_memory(u64 start, u64 size)
-{
-       unsigned long start_pfn, end_pfn;
-
-       start_pfn = PFN_DOWN(start);
-       end_pfn = start_pfn + PFN_DOWN(size);
-       return offline_pages(start_pfn, end_pfn, 120 * HZ);
-}
-#endif /* CONFIG_MEMORY_HOTREMOVE */
index 5131d50f851ac44f0a81709708023e2c6f00a5af..cb2c87df70ceeb9d8c4558fbafde0e3b35eb9220 100644 (file)
@@ -12,6 +12,7 @@ config SUPERH
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_GENERIC_DMA_COHERENT
+       select HAVE_IOREMAP_PROT if MMU
        help
          The SuperH is a RISC processor targeted for use in embedded systems
          and consumer electronics; it was also used in the Sega Dreamcast
@@ -20,6 +21,10 @@ config SUPERH
 
 config SUPERH32
        def_bool !SUPERH64
+       select HAVE_KPROBES
+       select HAVE_KRETPROBES
+       select HAVE_ARCH_TRACEHOOK
+       select HAVE_FTRACE
 
 config SUPERH64
        def_bool y if CPU_SH5
@@ -54,8 +59,11 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
 config GENERIC_IRQ_PROBE
        def_bool y
 
+config GENERIC_GPIO
+       def_bool n
+
 config GENERIC_CALIBRATE_DELAY
-       def_bool y
+       bool
 
 config GENERIC_IOMAP
        bool
@@ -66,6 +74,9 @@ config GENERIC_TIME
 config GENERIC_CLOCKEVENTS
        def_bool n
 
+config GENERIC_CLOCKEVENTS_BROADCAST
+       bool
+
 config GENERIC_LOCKBREAK
        def_bool y
        depends on SMP && PREEMPT
@@ -92,6 +103,10 @@ config STACKTRACE_SUPPORT
 config LOCKDEP_SUPPORT
        def_bool y
 
+config HAVE_LATENCYTOP_SUPPORT
+       def_bool y
+       depends on !SMP
+
 config ARCH_HAS_ILOG2_U32
        def_bool n
 
@@ -106,6 +121,8 @@ config IO_TRAPPED
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "System type"
 
 #
@@ -323,6 +340,7 @@ config CPU_SUBTYPE_SHX3
        select ARCH_SPARSEMEM_ENABLE
        select SYS_SUPPORTS_NUMA
        select SYS_SUPPORTS_SMP
+       select GENERIC_CLOCKEVENTS_BROADCAST if SMP
 
 # SH4AL-DSP Processor Support
 
@@ -490,7 +508,6 @@ config CRASH_DUMP
 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
index 4d2d102e00d5657cef9a8a9b3b53d5f04cf7bdb5..e6d2c8b11abdaea5490fe00e83d750d7d141017b 100644 (file)
@@ -82,7 +82,7 @@ config DEBUG_STACK_USAGE
 
 config 4KSTACKS
        bool "Use 4Kb for kernel stacks instead of 8Kb"
-       depends on DEBUG_KERNEL && (MMU || BROKEN)
+       depends on DEBUG_KERNEL && (MMU || BROKEN) && !PAGE_SIZE_64KB
        help
          If you say Y here the kernel will use a 4Kb stacksize for the
          kernel stack attached to each process/thread. This facilitates
index 01d85c74481d9a42a066ecc9e8ecd0216621961a..1f409bf81809b12af3300b0b3c4f49b2f94d2a34 100644 (file)
@@ -76,8 +76,10 @@ KBUILD_IMAGE         := $(defaultimage-y)
 # error messages during linking.
 #
 ifdef CONFIG_SUPERH32
+UTS_MACHINE    := sh
 LDFLAGS_vmlinux        += -e _stext
 else
+UTS_MACHINE    := sh64
 LDFLAGS_vmlinux        += --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \
                   --defsym phys_stext_shmedia=phys_stext+1 \
                   -e phys_stext_shmedia
@@ -123,6 +125,9 @@ core-y      += $(addprefix arch/sh/boards/, \
             $(filter-out ., $(patsubst %,%/,$(machdir-y))))
 endif
 
+# Common machine type headers. Not part of the arch/sh/boards/ hierarchy.
+machdir-y      += mach-common
+
 # Companion chips
 core-$(CONFIG_HD6446X_SERIES)  += arch/sh/cchips/hd6446x/
 
index ae194869fd60af8b465fe4b0a087eee872b65278..50467f9d0d0bf70844d03f9915846dd00bad9bf0 100644 (file)
@@ -128,6 +128,7 @@ config SH_RTS7751R2D
 
 config SH_RSK7203
        bool "RSK7203"
+       select GENERIC_GPIO
        depends on CPU_SUBTYPE_SH7203
 
 config SH_SDK7780
@@ -162,6 +163,7 @@ config SH_SH7785LCR_29BIT_PHYSMAPS
 config SH_MIGOR
        bool "Migo-R"
        depends on CPU_SUBTYPE_SH7722
+       select GENERIC_GPIO
        help
          Select Migo-R if configuring for the SH7722 Migo-R platform
           by Renesas System Solutions Asia Pte. Ltd.
@@ -169,6 +171,7 @@ config SH_MIGOR
 config SH_AP325RXA
        bool "AP-325RXA"
        depends on CPU_SUBTYPE_SH7723
+       select GENERIC_GPIO
        help
          Renesas "AP-325RXA" support.
          Compatible with ALGO SYSTEM CO.,LTD. "AP-320A"
@@ -184,6 +187,13 @@ config SH_EDOSK7705
        bool "EDOSK7705"
        depends on CPU_SUBTYPE_SH7705
 
+config SH_EDOSK7760
+       bool "EDOSK7760"
+       depends on CPU_SUBTYPE_SH7760
+       help
+         Select if configuring for a Renesas EDOSK7760
+         evaluation board.
+
 config SH_SH4202_MICRODEV
        bool "SH4-202 MicroDev"
        depends on CPU_SUBTYPE_SH4_202
@@ -228,6 +238,7 @@ config SH_X3PROTO
 config SH_MAGIC_PANEL_R2
        bool "Magic Panel R2"
        depends on CPU_SUBTYPE_SH7720
+       select GENERIC_GPIO
        help
          Select Magic Panel R2 if configuring for Magic Panel R2.
 
index 463022c7df3ceeb3dc0bf46a734debfa2af19081..d9efa3923721d356131608196690c6d0ccebcb5f 100644 (file)
@@ -6,3 +6,4 @@ obj-$(CONFIG_SH_MAGIC_PANEL_R2) += board-magicpanelr2.o
 obj-$(CONFIG_SH_RSK7203)       += board-rsk7203.o
 obj-$(CONFIG_SH_SH7785LCR)     += board-sh7785lcr.o
 obj-$(CONFIG_SH_SHMIN)         += board-shmin.o
+obj-$(CONFIG_SH_EDOSK7760)     += board-edosk7760.o
index fd1612590bf4feb96e7d9e714da12203cf300ac5..7c7874e6ac36c744b508b523201bfc87a68fe64f 100644 (file)
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/smc911x.h>
+#include <linux/gpio.h>
 #include <media/soc_camera_platform.h>
 #include <media/sh_mobile_ceu.h>
-#include <asm/sh_mobile_lcdc.h>
+#include <video/sh_mobile_lcdc.h>
 #include <asm/io.h>
 #include <asm/clock.h>
+#include <cpu/sh7723.h>
 
 static struct smc911x_platdata smc911x_info = {
        .flags = SMC911X_USE_32BIT,
@@ -52,20 +54,33 @@ static struct platform_device smc9118_device = {
        },
 };
 
+/*
+ * AP320 and AP325RXA has CPLD data in NOR Flash(0xA80000-0xABFFFF).
+ * If this area erased, this board can not boot.
+ */
 static struct mtd_partition ap325rxa_nor_flash_partitions[] = {
        {
-                .name = "uboot",
-                .offset = 0,
-                .size = (1 * 1024 * 1024),
-                .mask_flags = MTD_WRITEABLE,   /* Read-only */
+               .name = "uboot",
+               .offset = 0,
+               .size = (1 * 1024 * 1024),
+               .mask_flags = MTD_WRITEABLE,    /* Read-only */
+       }, {
+               .name = "kernel",
+               .offset = MTDPART_OFS_APPEND,
+               .size = (2 * 1024 * 1024),
+       }, {
+               .name = "free-area0",
+               .offset = MTDPART_OFS_APPEND,
+               .size = ((7 * 1024 * 1024) + (512 * 1024)),
        }, {
-                .name = "kernel",
-                .offset = MTDPART_OFS_APPEND,
-                .size = (2 * 1024 * 1024),
+               .name = "CPLD-Data",
+               .offset = MTDPART_OFS_APPEND,
+               .mask_flags = MTD_WRITEABLE,    /* Read-only */
+               .size = (1024 * 128 * 2),
        }, {
-                .name = "other",
-                .offset = MTDPART_OFS_APPEND,
-                .size = MTDPART_SIZ_FULL,
+               .name = "free-area1",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
        },
 };
 
@@ -96,17 +111,7 @@ static struct platform_device ap325rxa_nor_flash_device = {
 #define FPGA_LCDREG    0xB4100180
 #define FPGA_BKLREG    0xB4100212
 #define FPGA_LCDREG_VAL        0x0018
-#define PORT_PHCR      0xA405010E
-#define PORT_PLCR      0xA4050114
-#define PORT_PMCR      0xA4050116
-#define PORT_PRCR      0xA405011C
-#define PORT_PSCR      0xA405011E
-#define PORT_PZCR      0xA405014C
-#define PORT_HIZCRA    0xA4050158
 #define PORT_MSELCRB   0xA4050182
-#define PORT_PSDR      0xA405013E
-#define PORT_PZDR      0xA405016C
-#define PORT_PSELD     0xA4050154
 
 static void ap320_wvga_power_on(void *board_data)
 {
@@ -116,8 +121,7 @@ static void ap320_wvga_power_on(void *board_data)
        ctrl_outw(FPGA_LCDREG_VAL, FPGA_LCDREG);
 
        /* backlight */
-       ctrl_outw((ctrl_inw(PORT_PSCR) & ~0x00C0) | 0x40, PORT_PSCR);
-       ctrl_outb(ctrl_inb(PORT_PSDR) & ~0x08, PORT_PSDR);
+       gpio_set_value(GPIO_PTS3, 0);
        ctrl_outw(0x100, FPGA_BKLREG);
 }
 
@@ -281,12 +285,84 @@ static struct platform_device *ap325rxa_devices[] __initdata = {
 };
 
 static struct i2c_board_info __initdata ap325rxa_i2c_devices[] = {
+       {
+               I2C_BOARD_INFO("pcf8563", 0x51),
+       },
 };
 
 static int __init ap325rxa_devices_setup(void)
 {
-       clk_always_enable("mstp200"); /* LCDC */
-       clk_always_enable("mstp203"); /* CEU */
+       /* LD3 and LD4 LEDs */
+       gpio_request(GPIO_PTX5, NULL); /* RUN */
+       gpio_direction_output(GPIO_PTX5, 1);
+       gpio_export(GPIO_PTX5, 0);
+
+       gpio_request(GPIO_PTX4, NULL); /* INDICATOR */
+       gpio_direction_output(GPIO_PTX4, 0);
+       gpio_export(GPIO_PTX4, 0);
+
+       /* SW1 input */
+       gpio_request(GPIO_PTF7, NULL); /* MODE */
+       gpio_direction_input(GPIO_PTF7);
+       gpio_export(GPIO_PTF7, 0);
+
+       /* LCDC */
+       clk_always_enable("mstp200");
+       gpio_request(GPIO_FN_LCDD15, NULL);
+       gpio_request(GPIO_FN_LCDD14, NULL);
+       gpio_request(GPIO_FN_LCDD13, NULL);
+       gpio_request(GPIO_FN_LCDD12, NULL);
+       gpio_request(GPIO_FN_LCDD11, NULL);
+       gpio_request(GPIO_FN_LCDD10, NULL);
+       gpio_request(GPIO_FN_LCDD9, NULL);
+       gpio_request(GPIO_FN_LCDD8, NULL);
+       gpio_request(GPIO_FN_LCDD7, NULL);
+       gpio_request(GPIO_FN_LCDD6, NULL);
+       gpio_request(GPIO_FN_LCDD5, NULL);
+       gpio_request(GPIO_FN_LCDD4, NULL);
+       gpio_request(GPIO_FN_LCDD3, NULL);
+       gpio_request(GPIO_FN_LCDD2, NULL);
+       gpio_request(GPIO_FN_LCDD1, NULL);
+       gpio_request(GPIO_FN_LCDD0, NULL);
+       gpio_request(GPIO_FN_LCDLCLK_PTR, NULL);
+       gpio_request(GPIO_FN_LCDDCK, NULL);
+       gpio_request(GPIO_FN_LCDVEPWC, NULL);
+       gpio_request(GPIO_FN_LCDVCPWC, NULL);
+       gpio_request(GPIO_FN_LCDVSYN, NULL);
+       gpio_request(GPIO_FN_LCDHSYN, NULL);
+       gpio_request(GPIO_FN_LCDDISP, NULL);
+       gpio_request(GPIO_FN_LCDDON, NULL);
+
+       /* LCD backlight */
+       gpio_request(GPIO_PTS3, NULL);
+       gpio_direction_output(GPIO_PTS3, 1);
+
+       /* CEU */
+       clk_always_enable("mstp203");
+       gpio_request(GPIO_FN_VIO_CLK2, NULL);
+       gpio_request(GPIO_FN_VIO_VD2, NULL);
+       gpio_request(GPIO_FN_VIO_HD2, NULL);
+       gpio_request(GPIO_FN_VIO_FLD, NULL);
+       gpio_request(GPIO_FN_VIO_CKO, NULL);
+       gpio_request(GPIO_FN_VIO_D15, NULL);
+       gpio_request(GPIO_FN_VIO_D14, NULL);
+       gpio_request(GPIO_FN_VIO_D13, NULL);
+       gpio_request(GPIO_FN_VIO_D12, NULL);
+       gpio_request(GPIO_FN_VIO_D11, NULL);
+       gpio_request(GPIO_FN_VIO_D10, NULL);
+       gpio_request(GPIO_FN_VIO_D9, NULL);
+       gpio_request(GPIO_FN_VIO_D8, NULL);
+
+       gpio_request(GPIO_PTZ7, NULL);
+       gpio_direction_output(GPIO_PTZ7, 0); /* OE_CAM */
+       gpio_request(GPIO_PTZ6, NULL);
+       gpio_direction_output(GPIO_PTZ6, 0); /* STBY_CAM */
+       gpio_request(GPIO_PTZ5, NULL);
+       gpio_direction_output(GPIO_PTZ5, 1); /* RST_CAM */
+       gpio_request(GPIO_PTZ4, NULL);
+       gpio_direction_output(GPIO_PTZ4, 0); /* SADDR */
+
+       ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0001, PORT_MSELCRB);
 
        platform_resource_setup_memory(&ceu_device, "ceu", 4 << 20);
 
@@ -300,18 +376,6 @@ device_initcall(ap325rxa_devices_setup);
 
 static void __init ap325rxa_setup(char **cmdline_p)
 {
-       /* LCDC configuration */
-       ctrl_outw(ctrl_inw(PORT_PHCR) & ~0xffff, PORT_PHCR);
-       ctrl_outw(ctrl_inw(PORT_PLCR) & ~0xffff, PORT_PLCR);
-       ctrl_outw(ctrl_inw(PORT_PMCR) & ~0xffff, PORT_PMCR);
-       ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x03ff, PORT_PRCR);
-       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01C0, PORT_HIZCRA);
-
-       /* CEU */
-       ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0001, PORT_MSELCRB);
-       ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x0003, PORT_PSELD);
-       ctrl_outw((ctrl_inw(PORT_PZCR) & ~0xff00) | 0x5500, PORT_PZCR);
-       ctrl_outb((ctrl_inb(PORT_PZDR) & ~0xf0) | 0x20, PORT_PZDR);
 }
 
 static struct sh_machine_vector mv_ap325rxa __initmv = {
diff --git a/arch/sh/boards/board-edosk7760.c b/arch/sh/boards/board-edosk7760.c
new file mode 100644 (file)
index 0000000..35dc099
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Renesas Europe EDOSK7760 Board Support
+ *
+ * Copyright (C) 2008 SPES Societa' Progettazione Elettronica e Software Ltd.
+ * Author: Luca Santini <luca.santini@spesonline.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/smc91x.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/mtd/physmap.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/delay.h>
+#include <asm/i2c-sh7760.h>
+#include <asm/sizes.h>
+
+/* Bus state controller registers for CS4 area */
+#define BSC_CS4BCR     0xA4FD0010
+#define BSC_CS4WCR     0xA4FD0030
+
+#define SMC_IOBASE     0xA2000000
+#define SMC_IO_OFFSET  0x300
+#define SMC_IOADDR     (SMC_IOBASE + SMC_IO_OFFSET)
+
+#define ETHERNET_IRQ   5
+
+/* NOR flash */
+static struct mtd_partition edosk7760_nor_flash_partitions[] = {
+       {
+               .name = "bootloader",
+               .offset = 0,
+               .size = SZ_256K,
+               .mask_flags = MTD_WRITEABLE,    /* Read-only */
+       }, {
+               .name = "kernel",
+               .offset = MTDPART_OFS_APPEND,
+               .size = SZ_2M,
+       }, {
+               .name = "fs",
+               .offset = MTDPART_OFS_APPEND,
+               .size = SZ_26M,
+       }, {
+               .name = "other",
+               .offset = MTDPART_OFS_APPEND,
+               .size = MTDPART_SIZ_FULL,
+       },
+};
+
+static struct physmap_flash_data edosk7760_nor_flash_data = {
+       .width          = 4,
+       .parts          = edosk7760_nor_flash_partitions,
+       .nr_parts       = ARRAY_SIZE(edosk7760_nor_flash_partitions),
+};
+
+static struct resource edosk7760_nor_flash_resources[] = {
+       [0] = {
+               .name   = "NOR Flash",
+               .start  = 0x00000000,
+               .end    = 0x00000000 + SZ_32M - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device edosk7760_nor_flash_device = {
+       .name           = "physmap-flash",
+       .resource       = edosk7760_nor_flash_resources,
+       .num_resources  = ARRAY_SIZE(edosk7760_nor_flash_resources),
+       .dev            = {
+               .platform_data = &edosk7760_nor_flash_data,
+       },
+};
+
+/* i2c initialization functions */
+static struct sh7760_i2c_platdata i2c_pd = {
+       .speed_khz      = 400,
+};
+
+static struct resource sh7760_i2c1_res[] = {
+       {
+               .start  = SH7760_I2C1_MMIO,
+               .end    = SH7760_I2C1_MMIOEND,
+               .flags  = IORESOURCE_MEM,
+       },{
+               .start  = SH7760_I2C1_IRQ,
+               .end    = SH7760_I2C1_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device sh7760_i2c1_dev = {
+       .dev    = {
+               .platform_data  = &i2c_pd,
+       },
+
+       .name           = SH7760_I2C_DEVNAME,
+       .id             = 1,
+       .resource       = sh7760_i2c1_res,
+       .num_resources  = ARRAY_SIZE(sh7760_i2c1_res),
+};
+
+static struct resource sh7760_i2c0_res[] = {
+       {
+               .start  = SH7760_I2C0_MMIO,
+               .end    = SH7760_I2C0_MMIOEND,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = SH7760_I2C0_IRQ,
+               .end    = SH7760_I2C0_IRQ,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device sh7760_i2c0_dev = {
+       .dev    = {
+               .platform_data  = &i2c_pd,
+       },
+       .name           = SH7760_I2C_DEVNAME,
+       .id             = 0,
+       .resource       = sh7760_i2c0_res,
+       .num_resources  = ARRAY_SIZE(sh7760_i2c0_res),
+};
+
+/* eth initialization functions */
+static struct smc91x_platdata smc91x_info = {
+       .flags = SMC91X_USE_16BIT | SMC91X_IO_SHIFT_1 | IORESOURCE_IRQ_LOWLEVEL,
+};
+
+static struct resource smc91x_res[] = {
+       [0] = {
+               .start  = SMC_IOADDR,
+               .end    = SMC_IOADDR + SZ_32 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = ETHERNET_IRQ,
+               .end    = ETHERNET_IRQ,
+               .flags  = IORESOURCE_IRQ ,
+       }
+};
+
+static struct platform_device smc91x_dev = {
+       .name           = "smc91x",
+       .id             = -1,
+       .num_resources  = ARRAY_SIZE(smc91x_res),
+       .resource       = smc91x_res,
+
+       .dev    = {
+               .platform_data  = &smc91x_info,
+       },
+};
+
+/* platform init code */
+static struct platform_device *edosk7760_devices[] __initdata = {
+       &smc91x_dev,
+       &edosk7760_nor_flash_device,
+       &sh7760_i2c0_dev,
+       &sh7760_i2c1_dev,
+};
+
+static int __init init_edosk7760_devices(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRQ);
+
+       return platform_add_devices(edosk7760_devices,
+                                   ARRAY_SIZE(edosk7760_devices));
+}
+__initcall(init_edosk7760_devices);
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_edosk7760 __initmv = {
+       .mv_name        = "EDOSK7760",
+       .mv_nr_irqs     = 128,
+};
index f3b8b07ea5d65a922d8a4d98114ca884db589d93..3de22ccdeb7efebefcd42de79350b583b54ce1ff 100644 (file)
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/map.h>
-#include <asm/magicpanelr2.h>
+#include <mach/magicpanelr2.h>
 #include <asm/heartbeat.h>
+#include <cpu/sh7720.h>
 
 #define LAN9115_READY  (ctrl_inl(0xA8000084UL) & 0x00000001UL)
 
@@ -170,7 +172,14 @@ static void __init setup_port_multiplexing(void)
        /* R7 A25;           R6 A24;         R5 A23;              R4 A22;
         * R3 A21;           R2 A20;         R1 A19;              R0 A0;
         */
-       ctrl_outw(0x0000, PORT_PRCR);   /* 00 00 00 00 00 00 00 00 */
+       gpio_request(GPIO_FN_A25, NULL);
+       gpio_request(GPIO_FN_A24, NULL);
+       gpio_request(GPIO_FN_A23, NULL);
+       gpio_request(GPIO_FN_A22, NULL);
+       gpio_request(GPIO_FN_A21, NULL);
+       gpio_request(GPIO_FN_A20, NULL);
+       gpio_request(GPIO_FN_A19, NULL);
+       gpio_request(GPIO_FN_A0, NULL);
 
        /* S7 (x);              S6 (x);        S5 (x);       S4 GPO(EEPROM_CS2);
         * S3 GPO(EEPROM_CS1);  S2 SIOF0_TXD;  S1 SIOF0_RXD; S0 SIOF0_SCK;
index ffbedc59a9738e0bcbf2ce7cc0fd283af4db4156..ded799cf3eae6f3099d0ef158a8824fc95549f04 100644 (file)
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/map.h>
 #include <linux/smc911x.h>
+#include <linux/gpio.h>
 #include <asm/machvec.h>
 #include <asm/io.h>
+#include <asm/sh7203.h>
 
 static struct smc911x_platdata smc911x_info = {
        .flags          = SMC911X_USE_16BIT,
@@ -122,6 +124,15 @@ static struct platform_device *rsk7203_devices[] __initdata = {
 
 static int __init rsk7203_devices_setup(void)
 {
+       /* Select pins for SCIF0 */
+       gpio_request(GPIO_FN_TXD0, NULL);
+       gpio_request(GPIO_FN_RXD0, NULL);
+
+       /* Lit LED0 */
+       gpio_request(GPIO_PE10, NULL);
+       gpio_direction_output(GPIO_PE10, 0);
+       gpio_export(GPIO_PE10, 0);
+
        set_mtd_partitions();
        return platform_add_devices(rsk7203_devices,
                                    ARRAY_SIZE(rsk7203_devices));
index b95d674ee704426b380adce271820ccae675a63e..408bbddaf3258b02f544fe10405acea2946cfee1 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/i2c-pca-platform.h>
 #include <linux/i2c-algo-pca.h>
 #include <asm/heartbeat.h>
-#include <asm/sh7785lcr.h>
+#include <mach/sh7785lcr.h>
 
 /*
  * NOTE: This board has 2 physical memory maps.
index 16e5dae8ecfb409702deff42cab3149d04c75898..5cc0867de5ab88809d37cb8f1e36dda5f0e580b3 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <asm/machvec.h>
-#include <asm/shmin.h>
+#include <mach/shmin.h>
 #include <asm/clock.h>
 #include <asm/io.h>
 
index 541cea2a652f3434d6c9f603f70d160ebab84ae3..7d153e50a01b73df05466c71d6825308333b4679 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <asm/io.h>
-#include <asm/edosk7705/io.h>
+#include <mach/edosk7705.h>
 #include <asm/addrspace.h>
 
 #define SMC_IOADDR     0xA2000000
index f076c45308ddab2f3178e9a1680ff8f629517132..ab3f47bffdf3ea2f644391f25cd8870d2a8d489b 100644 (file)
@@ -10,7 +10,7 @@
  */
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/edosk7705/io.h>
+#include <mach/edosk7705.h>
 
 static void __init sh_edosk7705_init_irq(void)
 {
index ae1cfcb297008f76f8cb003872cf2ba87c6a8aa0..83c28bcd4d2a7de7f9a6f176487d1be987c246c6 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/r7780rp.h>
+#include <mach/highlander.h>
 
 enum {
        UNUSED = 0,
index 9d3921fe27c0b4506322ad5a3a0837c652a63c02..b721e86b5af4b226c59a7d44ef75d121e83254f6 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/r7780rp.h>
+#include <mach/highlander.h>
 
 enum {
        UNUSED = 0,
index 896c045aa39d63ab66ebc4eceed0b38f00911b59..3811b060a39b4f922b62456470eb0bb043d4f6f8 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/r7780rp.h>
+#include <mach/highlander.h>
 
 enum {
        UNUSED = 0,
index be8d5477fc6584799183c1154bcab628a76f27e5..37b1a2ee71a5398685b1579ad3a67170fc94a2e3 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <asm/r7780rp.h>
+#include <mach/highlander.h>
 #include <asm/push-switch.h>
 
 static irqreturn_t psw_irq_handler(int irq, void *arg)
index bc79afb6fc4c04c7c13335b9ae03e4938ec51939..c5a40f7906d789b453ff9e8a4e1fc2961b345fc8 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/i2c.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
-#include <asm/r7780rp.h>
+#include <mach/highlander.h>
 #include <asm/clock.h>
 #include <asm/heartbeat.h>
 #include <asm/io.h>
index 177f4f028e0dd5769d6d530290b6b6fec9097318..e85212faf40a8c1bfea2635e1de6dee710f1ce0c 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/apm-emulation.h>
 #include <linux/io.h>
 #include <asm/adc.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
 
 /* percentage values */
 #define APM_CRITICAL                   10
index e96684def788c064cbe1a036e5f0eea71d99bf1f..64af1f2eef05707b3925ab9ccd6ed3e1ec0ef420 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/time.h>
 #include <asm/io.h>
 #include <asm/hd64461.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
 #include <cpu/dac.h>
 #include <asm/pm.h>
 
index 475b46caec1fed133119d10cab1b99198f315806..48fece78ff54da2ca07eaab00c75330757794455 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/hd64461.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
 #include <cpu/dac.h>
 
 #define        SCPCR   0xa4000116
index 5a1c3bbe7b50c3542e86665ab50cf264d9e8f531..8aa171ab833e4c05734fbef453afe2fb78f9ab75 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/irq.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/lboxre2.h>
+#include <mach/lboxre2.h>
 
 /*
  * Initialize IRQ setting
index c74440d38ee974aa40482ed5a2af56334f25e9a1..2b0b5818e1e477d23ea6a95529a560b736a73e25 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/ata_platform.h>
 #include <asm/machvec.h>
 #include <asm/addrspace.h>
-#include <asm/lboxre2.h>
+#include <mach/lboxre2.h>
 #include <asm/io.h>
 
 static struct resource cf_ide_resources[] = {
index 9f8a540f7e141d0ee61f9094c7d9436fc1135b1c..52dd748211c769607f99834913261340eba3f143 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/pci.h>
 #include <linux/wait.h>
 #include <asm/io.h>
-#include <asm/microdev.h>
+#include <mach/microdev.h>
 
        /*
         *      we need to have a 'safe' address to re-direct all I/O requests
index 4d335077a3ffc8c590594f6065ece5573be91d31..702753cbd28f2b418027839b0d20e83e0b21e1fe 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/interrupt.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/microdev.h>
+#include <mach/microdev.h>
 
 #define NUM_EXTERNAL_IRQS 16   /* IRL0 .. IRL15 */
 
index fc8cd06d66cf287a29cd65505bb685a21ef35eab..a9202fe3cb590b2139ecdc878e6a00b52446b70a 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
 #include <video/s1d13xxxfb.h>
-#include <asm/microdev.h>
+#include <mach/microdev.h>
 #include <asm/io.h>
 #include <asm/machvec.h>
 
index 6e960959644825daba418076b68c6a70ab753087..de9014a8a93ed3fffa961582f6bbfe960d33803a 100644 (file)
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <asm/sh_mobile_lcdc.h>
-#include <asm/migor.h>
+#include <linux/gpio.h>
+#include <video/sh_mobile_lcdc.h>
+#include <cpu/sh7722.h>
+#include <mach/migor.h>
 
 /* LCD Module is a PH240320T according to board schematics. This module
  * is made up of a 240x320 LCD hooked up to a R61505U (or HX8347-A01?)
@@ -30,9 +32,9 @@
 
 static void reset_lcd_module(void)
 {
-       ctrl_outb(ctrl_inb(PORT_PHDR) & ~0x04, PORT_PHDR);
+       gpio_set_value(GPIO_PTH2, 0);
        mdelay(2);
-       ctrl_outb(ctrl_inb(PORT_PHDR) | 0x04, PORT_PHDR);
+       gpio_set_value(GPIO_PTH2, 1);
        mdelay(1);
 }
 
index 714dce91cc9bbb30684764c33eef963c09844866..769d630434248ff5a92acc40c4210cfb22dae042 100644 (file)
 #include <linux/smc91x.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
 #include <media/soc_camera_platform.h>
 #include <media/sh_mobile_ceu.h>
+#include <video/sh_mobile_lcdc.h>
 #include <asm/clock.h>
 #include <asm/machvec.h>
 #include <asm/io.h>
 #include <asm/sh_keysc.h>
-#include <asm/sh_mobile_lcdc.h>
-#include <asm/migor.h>
+#include <mach/migor.h>
+#include <cpu/sh7722.h>
 
 /* Address     IRQ  Size  Bus  Description
  * 0x00000000       64MB  16   NOR Flash (SP29PL256N)
@@ -35,7 +37,7 @@
  */
 
 static struct smc91x_platdata smc91x_info = {
-       .flags = SMC91X_USE_16BIT,
+       .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT,
 };
 
 static struct resource smc91x_eth_resources[] = {
@@ -169,7 +171,7 @@ static void migor_nand_flash_cmd_ctl(struct mtd_info *mtd, int cmd,
 
 static int migor_nand_flash_ready(struct mtd_info *mtd)
 {
-       return ctrl_inb(PORT_PADR) & 0x02; /* PTA1 */
+       return gpio_get_value(GPIO_PTA1); /* NAND_RBn */
 }
 
 struct platform_nand_data migor_nand_flash_data = {
@@ -286,22 +288,15 @@ static struct clk *camera_clk;
 
 static void camera_power_on(void)
 {
-       unsigned char value;
-
        camera_clk = clk_get(NULL, "video_clk");
        clk_set_rate(camera_clk, 24000000);
        clk_enable(camera_clk); /* start VIO_CKO */
 
+       /* use VIO_RST to take camera out of reset */
        mdelay(10);
-       value = ctrl_inb(PORT_PTDR);
-       value &= ~0x09;
-#ifndef CONFIG_SH_MIGOR_RTA_WVGA
-       value |= 0x01;
-#endif
-       ctrl_outb(value, PORT_PTDR);
+       gpio_set_value(GPIO_PTT3, 0);
        mdelay(10);
-
-       ctrl_outb(value | 8, PORT_PTDR);
+       gpio_set_value(GPIO_PTT3, 1);
 }
 
 static void camera_power_off(void)
@@ -309,7 +304,7 @@ static void camera_power_off(void)
        clk_disable(camera_clk); /* stop VIO_CKO */
        clk_put(camera_clk);
 
-       ctrl_outb(ctrl_inb(PORT_PTDR) & ~0x08, PORT_PTDR);
+       gpio_set_value(GPIO_PTT3, 0);
 }
 
 #ifdef CONFIG_I2C
@@ -458,75 +453,135 @@ static struct i2c_board_info migor_i2c_devices[] = {
 
 static int __init migor_devices_setup(void)
 {
+       /* Lit D11 LED */
+       gpio_request(GPIO_PTJ7, NULL);
+       gpio_direction_output(GPIO_PTJ7, 1);
+       gpio_export(GPIO_PTJ7, 0);
+
+       /* Lit D12 LED */
+       gpio_request(GPIO_PTJ5, NULL);
+       gpio_direction_output(GPIO_PTJ5, 1);
+       gpio_export(GPIO_PTJ5, 0);
+
+       /* SMC91C111 - Enable IRQ0, Setup CS4 for 16-bit fast access */
+       gpio_request(GPIO_FN_IRQ0, NULL);
+       ctrl_outl(0x00003400, BSC_CS4BCR);
+       ctrl_outl(0x00110080, BSC_CS4WCR);
+
+       /* KEYSC */
        clk_always_enable("mstp214"); /* KEYSC */
+       gpio_request(GPIO_FN_KEYOUT0, NULL);
+       gpio_request(GPIO_FN_KEYOUT1, NULL);
+       gpio_request(GPIO_FN_KEYOUT2, NULL);
+       gpio_request(GPIO_FN_KEYOUT3, NULL);
+       gpio_request(GPIO_FN_KEYOUT4_IN6, NULL);
+       gpio_request(GPIO_FN_KEYIN1, NULL);
+       gpio_request(GPIO_FN_KEYIN2, NULL);
+       gpio_request(GPIO_FN_KEYIN3, NULL);
+       gpio_request(GPIO_FN_KEYIN4, NULL);
+       gpio_request(GPIO_FN_KEYOUT5_IN5, NULL);
+
+       /* NAND Flash */
+       gpio_request(GPIO_FN_CS6A_CE2B, NULL);
+       ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x0600) | 0x0200, BSC_CS6ABCR);
+       gpio_request(GPIO_PTA1, NULL);
+       gpio_direction_input(GPIO_PTA1);
+
+       /* Touch Panel */
+       gpio_request(GPIO_FN_IRQ6, NULL);
+
+       /* LCD Panel */
        clk_always_enable("mstp200"); /* LCDC */
+#ifdef CONFIG_SH_MIGOR_QVGA /* LCDC - QVGA - Enable SYS Interface signals */
+       gpio_request(GPIO_FN_LCDD17, NULL);
+       gpio_request(GPIO_FN_LCDD16, NULL);
+       gpio_request(GPIO_FN_LCDD15, NULL);
+       gpio_request(GPIO_FN_LCDD14, NULL);
+       gpio_request(GPIO_FN_LCDD13, NULL);
+       gpio_request(GPIO_FN_LCDD12, NULL);
+       gpio_request(GPIO_FN_LCDD11, NULL);
+       gpio_request(GPIO_FN_LCDD10, NULL);
+       gpio_request(GPIO_FN_LCDD8, NULL);
+       gpio_request(GPIO_FN_LCDD7, NULL);
+       gpio_request(GPIO_FN_LCDD6, NULL);
+       gpio_request(GPIO_FN_LCDD5, NULL);
+       gpio_request(GPIO_FN_LCDD4, NULL);
+       gpio_request(GPIO_FN_LCDD3, NULL);
+       gpio_request(GPIO_FN_LCDD2, NULL);
+       gpio_request(GPIO_FN_LCDD1, NULL);
+       gpio_request(GPIO_FN_LCDRS, NULL);
+       gpio_request(GPIO_FN_LCDCS, NULL);
+       gpio_request(GPIO_FN_LCDRD, NULL);
+       gpio_request(GPIO_FN_LCDWR, NULL);
+       gpio_request(GPIO_PTH2, NULL); /* LCD_DON */
+       gpio_direction_output(GPIO_PTH2, 1);
+#endif
+#ifdef CONFIG_SH_MIGOR_RTA_WVGA /* LCDC - WVGA - Enable RGB Interface signals */
+       gpio_request(GPIO_FN_LCDD15, NULL);
+       gpio_request(GPIO_FN_LCDD14, NULL);
+       gpio_request(GPIO_FN_LCDD13, NULL);
+       gpio_request(GPIO_FN_LCDD12, NULL);
+       gpio_request(GPIO_FN_LCDD11, NULL);
+       gpio_request(GPIO_FN_LCDD10, NULL);
+       gpio_request(GPIO_FN_LCDD9, NULL);
+       gpio_request(GPIO_FN_LCDD8, NULL);
+       gpio_request(GPIO_FN_LCDD7, NULL);
+       gpio_request(GPIO_FN_LCDD6, NULL);
+       gpio_request(GPIO_FN_LCDD5, NULL);
+       gpio_request(GPIO_FN_LCDD4, NULL);
+       gpio_request(GPIO_FN_LCDD3, NULL);
+       gpio_request(GPIO_FN_LCDD2, NULL);
+       gpio_request(GPIO_FN_LCDD1, NULL);
+       gpio_request(GPIO_FN_LCDD0, NULL);
+       gpio_request(GPIO_FN_LCDLCLK, NULL);
+       gpio_request(GPIO_FN_LCDDCK, NULL);
+       gpio_request(GPIO_FN_LCDVEPWC, NULL);
+       gpio_request(GPIO_FN_LCDVCPWC, NULL);
+       gpio_request(GPIO_FN_LCDVSYN, NULL);
+       gpio_request(GPIO_FN_LCDHSYN, NULL);
+       gpio_request(GPIO_FN_LCDDISP, NULL);
+       gpio_request(GPIO_FN_LCDDON, NULL);
+#endif
+
+       /* CEU */
        clk_always_enable("mstp203"); /* CEU */
+       gpio_request(GPIO_FN_VIO_CLK2, NULL);
+       gpio_request(GPIO_FN_VIO_VD2, NULL);
+       gpio_request(GPIO_FN_VIO_HD2, NULL);
+       gpio_request(GPIO_FN_VIO_FLD, NULL);
+       gpio_request(GPIO_FN_VIO_CKO, NULL);
+       gpio_request(GPIO_FN_VIO_D15, NULL);
+       gpio_request(GPIO_FN_VIO_D14, NULL);
+       gpio_request(GPIO_FN_VIO_D13, NULL);
+       gpio_request(GPIO_FN_VIO_D12, NULL);
+       gpio_request(GPIO_FN_VIO_D11, NULL);
+       gpio_request(GPIO_FN_VIO_D10, NULL);
+       gpio_request(GPIO_FN_VIO_D9, NULL);
+       gpio_request(GPIO_FN_VIO_D8, NULL);
+
+       gpio_request(GPIO_PTT3, NULL); /* VIO_RST */
+       gpio_direction_output(GPIO_PTT3, 0);
+       gpio_request(GPIO_PTT2, NULL); /* TV_IN_EN */
+       gpio_direction_output(GPIO_PTT2, 1);
+       gpio_request(GPIO_PTT0, NULL); /* CAM_EN */
+#ifdef CONFIG_SH_MIGOR_RTA_WVGA
+       gpio_direction_output(GPIO_PTT0, 0);
+#else
+       gpio_direction_output(GPIO_PTT0, 1);
+#endif
+       ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2000, PORT_MSELCRB); /* D15->D8 */
 
        platform_resource_setup_memory(&migor_ceu_device, "ceu", 4 << 20);
 
        i2c_register_board_info(0, migor_i2c_devices,
                                ARRAY_SIZE(migor_i2c_devices));
+
        return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices));
 }
 __initcall(migor_devices_setup);
 
 static void __init migor_setup(char **cmdline_p)
 {
-       /* SMC91C111 - Enable IRQ0 */
-       ctrl_outw(ctrl_inw(PORT_PJCR) & ~0x0003, PORT_PJCR);
-
-       /* KEYSC */
-       ctrl_outw(ctrl_inw(PORT_PYCR) & ~0x0fff, PORT_PYCR);
-       ctrl_outw(ctrl_inw(PORT_PZCR) & ~0x0ff0, PORT_PZCR);
-       ctrl_outw(ctrl_inw(PORT_PSELA) & ~0x4100, PORT_PSELA);
-       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x4000, PORT_HIZCRA);
-       ctrl_outw(ctrl_inw(PORT_HIZCRC) & ~0xc000, PORT_HIZCRC);
-
-       /* NAND Flash */
-       ctrl_outw(ctrl_inw(PORT_PXCR) & 0x0fff, PORT_PXCR);
-       ctrl_outl((ctrl_inl(BSC_CS6ABCR) & ~0x00000600) | 0x00000200,
-                 BSC_CS6ABCR);
-
-       /* Touch Panel - Enable IRQ6 */
-       ctrl_outw(ctrl_inw(PORT_PZCR) & ~0xc, PORT_PZCR);
-       ctrl_outw((ctrl_inw(PORT_PSELA) | 0x8000), PORT_PSELA);
-       ctrl_outw((ctrl_inw(PORT_HIZCRC) & ~0x4000), PORT_HIZCRC);
-
-#ifdef CONFIG_SH_MIGOR_RTA_WVGA
-       /* LCDC - WVGA - Enable RGB Interface signals */
-       ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
-       ctrl_outw(0x0000, PORT_PHCR);
-       ctrl_outw(0x0000, PORT_PLCR);
-       ctrl_outw(0x0000, PORT_PMCR);
-       ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x000f, PORT_PRCR);
-       ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x000d) | 0x0400, PORT_PSELD);
-       ctrl_outw(ctrl_inw(PORT_MSELCRB) & ~0x0100, PORT_MSELCRB);
-       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
-#endif
-#ifdef CONFIG_SH_MIGOR_QVGA
-       /* LCDC - QVGA - Enable SYS Interface signals */
-       ctrl_outw(ctrl_inw(PORT_PACR) & ~0x0003, PORT_PACR);
-       ctrl_outw((ctrl_inw(PORT_PHCR) & ~0xcfff) | 0x0010, PORT_PHCR);
-       ctrl_outw(0x0000, PORT_PLCR);
-       ctrl_outw(0x0000, PORT_PMCR);
-       ctrl_outw(ctrl_inw(PORT_PRCR) & ~0x030f, PORT_PRCR);
-       ctrl_outw((ctrl_inw(PORT_PSELD) & ~0x0001) | 0x0420, PORT_PSELD);
-       ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x0100, PORT_MSELCRB);
-       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x01e0, PORT_HIZCRA);
-#endif
-
-       /* CEU */
-       ctrl_outw((ctrl_inw(PORT_PTCR) & ~0x03c3) | 0x0051, PORT_PTCR);
-       ctrl_outw(ctrl_inw(PORT_PUCR) & ~0x03ff, PORT_PUCR);
-       ctrl_outw(ctrl_inw(PORT_PVCR) & ~0x03ff, PORT_PVCR);
-       ctrl_outw(ctrl_inw(PORT_PWCR) & ~0x3c00, PORT_PWCR);
-       ctrl_outw(ctrl_inw(PORT_PSELC) | 0x0001, PORT_PSELC);
-       ctrl_outw(ctrl_inw(PORT_PSELD) & ~0x2000, PORT_PSELD);
-       ctrl_outw(ctrl_inw(PORT_PSELE) | 0x000f, PORT_PSELE);
-       ctrl_outw(ctrl_inw(PORT_MSELCRB) | 0x2200, PORT_MSELCRB);
-       ctrl_outw(ctrl_inw(PORT_HIZCRA) & ~0x0a00, PORT_HIZCRA);
-       ctrl_outw(ctrl_inw(PORT_HIZCRB) & ~0x0003, PORT_HIZCRB);
 }
 
 static struct sh_machine_vector mv_migor __initmv = {
index 8e49f6e51247b199eb74a96746b44c2b6e464364..c70fecedcac424625d32232378616b4a606be4ba 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/irq.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
-#include <asm/rts7751r2d.h>
+#include <mach/r2d.h>
 
 #define R2D_NR_IRL 13
 
index 2308e8753bcdee2bcb66f49ab2bfecd207a5b9e1..c585be00956ea9a8d541656081ac80a2f86ae3f4 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <asm/machvec.h>
-#include <asm/rts7751r2d.h>
+#include <mach/r2d.h>
 #include <asm/io.h>
 #include <asm/io_trapped.h>
 #include <asm/spi.h>
index 87cdc578f6fff983967c0d84bf61c7e2759ce0de..855558163c58686c62c4830be9b4bbe6d3b485bd 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/sdk7780.h>
+#include <mach/sdk7780.h>
 
 enum {
        UNUSED = 0,
index acc5932587f11ad994793d1f5d6941b2aa8bcdc3..aad94a78dc702a3c98b3673d0d99f9596cc48dc0 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/ata_platform.h>
 #include <asm/machvec.h>
-#include <asm/sdk7780.h>
+#include <mach/sdk7780.h>
 #include <asm/heartbeat.h>
 #include <asm/io.h>
 #include <asm/addrspace.h>
index fd850bad2decd17407819c4b645e7fc766e7c968..d8ebfa7d8c7616de1a66a0999ad1da7f18276a32 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/irq.h>
 #include <asm/io.h>
 #include <asm/irq.h>
-#include <asm/sh7763rdp.h>
+#include <mach/sh7763rdp.h>
 
 #define INTC_BASE              (0xFFD00000)
 #define INTC_INT2PRI7   (INTC_BASE+0x4001C)
index 23850da05e3c8a6d53ce30b95dc89df59f7ebea3..6f926fd2162b20380034add765471f2f72b7f2b0 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/fb.h>
 #include <linux/io.h>
-#include <asm/sh7763rdp.h>
+#include <mach/sh7763rdp.h>
 #include <asm/sh_eth.h>
 #include <asm/sh7760fb.h>
 
index a5e349d3dda20b37057ab16cd781e9fe3a73f3a3..a3277a23cf14a2904dc22dbe8fd88ee84212c1d2 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <asm/machvec.h>
-#include <asm/snapgear.h>
+#include <mach/snapgear.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <cpu/timer.h>
index 1b767e1a142859d50999f341f30c36f24fd4bf54..dec3db0ee933ba61a11d0438f64c81201d3edd0b 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/pci.h>
-#include <asm/systemh7751.h>
+#include <mach/systemh7751.h>
 #include <asm/addrspace.h>
 #include <asm/io.h>
 
index 601c9c8cdbec0af1c0757349f466701a685c71e3..538406872a8923dce7aa0b4d98d8888aba9ee168 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/interrupt.h>
 
 #include <asm/io.h>
-#include <asm/systemh7751.h>
+#include <mach/systemh7751.h>
 #include <asm/smc37c93x.h>
 
 /* address of external interrupt mask register
index ee78af842778e80dc6a89fab923b71aa8ba09efc..219fd800a43fb7b30e8d73c443485b13e5c04ab7 100644 (file)
@@ -16,7 +16,7 @@
  */
 #include <linux/init.h>
 #include <asm/machvec.h>
-#include <asm/systemh7751.h>
+#include <mach/systemh7751.h>
 
 extern void make_systemh_irq(unsigned int irq);
 
index 4730c1dd697d37c8218239fe79657cd970fbad06..4badad4c6f30329036768e76c0bfa148c1ec0034 100644 (file)
@@ -4,7 +4,7 @@
 #include <linux/pci.h>
 #include <asm/machvec.h>
 #include <asm/addrspace.h>
-#include <asm/titan.h>
+#include <mach/titan.h>
 #include <asm/io.h>
 
 static inline unsigned int port2adr(unsigned int port)
index 5de3b2ad71af86fc4d2e6dbe956e373ca0d05a22..81e7e0f03863d510f9144d9c99f3eff1ed0fe938 100644 (file)
@@ -9,7 +9,7 @@
  */
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <asm/titan.h>
+#include <mach/titan.h>
 #include <asm/io.h>
 
 static void __init init_titan_irq(void)
index b6718de236934fa592a6ae38baf75d4a7e4a1f42..aad5edddf93baf232cafbb216172a5e712a4fe31 100644 (file)
@@ -1 +1,4 @@
 zImage
+vmlinux.srec
+uImage
+uImage.srec
index 5b54965eef9819779613856a572311c928b386cd..c16ccd4bfa16ac4b424e1032ada796f75ea88e32 100644 (file)
@@ -33,10 +33,16 @@ $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
 $(obj)/compressed/vmlinux: FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
+ifeq ($(CONFIG_32BIT),y)
+KERNEL_LOAD    := $(shell /bin/bash -c 'printf "0x%08x" \
+                    $$[$(CONFIG_PAGE_OFFSET)  + \
+                       $(CONFIG_ZERO_PAGE_OFFSET)]')
+else
 KERNEL_LOAD    := $(shell /bin/bash -c 'printf "0x%08x" \
                     $$[$(CONFIG_PAGE_OFFSET)  + \
                        $(CONFIG_MEMORY_START) + \
                        $(CONFIG_ZERO_PAGE_OFFSET)]')
+endif
 
 KERNEL_ENTRY   := $(shell /bin/bash -c 'printf "0x%08x" \
                     $$[$(CONFIG_PAGE_OFFSET)  + \
index 47685f618ae748e504bc76a99a5f3a8b822f6534..301e6d503256da66d3e27a84ddec76d2dbe8957e 100644 (file)
@@ -23,6 +23,11 @@ IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \
 
 LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
+ifeq ($(CONFIG_FTRACE),y)
+ORIG_CFLAGS := $(KBUILD_CFLAGS)
+KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
+endif
+
 LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds
 
 $(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
index f386997e4d9c3b0c347b209b54852d3d4194e2bb..efdba6b295727a3f58c5c221e88450307df8c30e 100644 (file)
@@ -191,7 +191,7 @@ long* stack_start = &user_stack[STACK_SIZE];
 
 void decompress_kernel(void)
 {
-       output_data = 0;
+       output_data = NULL;
        output_ptr = PHYSADDR((unsigned long)&_text+PAGE_SIZE);
 #ifdef CONFIG_29BIT
        output_ptr |= P2SEG;
diff --git a/arch/sh/configs/edosk7760_defconfig b/arch/sh/configs/edosk7760_defconfig
new file mode 100644 (file)
index 0000000..bef07fa
--- /dev/null
@@ -0,0 +1,1050 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.26
+# Tue Aug 26 11:36:09 2008
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_ARCH_SUPPORTS_AOUT=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION="_edosk7760"
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_CGROUPS is not set
+# CONFIG_GROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_AS is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7751R is not set
+CONFIG_CPU_SUBTYPE_SH7760=y
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+CONFIG_SH_STORE_QUEUES=y
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+CONFIG_SH_EDOSK7760=y
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=33333333
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+CONFIG_SH_DMA_API=y
+CONFIG_SH_DMA=y
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+# CONFIG_SH_DMABRG is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+# CONFIG_HEARTBEAT is not set
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_PREEMPT_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+# CONFIG_PREEMPT_RCU is not set
+CONFIG_GUSA=y
+# CONFIG_GUSA_RB is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x02000000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="mem=64M console=ttySC2,115200 root=/dev/nfs rw nfsroot=192.168.0.3:/scripts/filesys ip=192.168.0.4"
+
+#
+# Bus options
+#
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# 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_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+CONFIG_DEBUG_DRIVER=y
+CONFIG_DEBUG_DEVRES=y
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+CONFIG_MTD_DEBUG=y
+CONFIG_MTD_DEBUG_VERBOSE=0
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_MAP_BANK_WIDTH_8=y
+CONFIG_MTD_MAP_BANK_WIDTH_16=y
+CONFIG_MTD_MAP_BANK_WIDTH_32=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI_I4=y
+CONFIG_MTD_CFI_I8=y
+# CONFIG_MTD_OTP is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_ABSENT=y
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xffffffff
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+# CONFIG_MTD_NAND is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=26000
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MISC_DEVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_STNIC is not set
+# CONFIG_SMC9194 is not set
+CONFIG_SMC91X=y
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+CONFIG_I2C_SH7760=y
+# CONFIG_I2C_SH_MOBILE is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+CONFIG_I2C_DEBUG_CORE=y
+CONFIG_I2C_DEBUG_ALGO=y
+CONFIG_I2C_DEBUG_BUS=y
+CONFIG_I2C_DEBUG_CHIP=y
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=m
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=m
+CONFIG_FB_CFB_COPYAREA=m
+CONFIG_FB_CFB_IMAGEBLIT=m
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_MB86290_640X480_16BPP is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE is not set
+# CONFIG_LOGO is not set
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+# CONFIG_SND_SUPPORT_OLD_API is not set
+# CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_SND_VERBOSE_PRINTK=y
+# CONFIG_SND_DEBUG is not set
+
+#
+# Generic devices
+#
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+
+#
+# SUPERH devices
+#
+
+#
+# System on Chip audio support
+#
+CONFIG_SND_SOC=y
+
+#
+# SoC Audio support for SuperH
+#
+
+#
+# ALSA SoC audio for Freescale SOCs
+#
+
+#
+# SoC Audio for the Texas Instruments OMAP
+#
+
+#
+# Open Sound System
+#
+# CONFIG_SOUND_PRIME is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_XIP=y
+CONFIG_FS_XIP=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS2_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+CONFIG_NLS_ISO8859_15=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_PRINTK_TIME=y
+CONFIG_ENABLE_WARN_DEPRECATED=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_UNUSED_SYMBOLS=y
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_SHIRQ=y
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/sh/configs/rts7751r2dplus_qemu_defconfig b/arch/sh/configs/rts7751r2dplus_qemu_defconfig
new file mode 100644 (file)
index 0000000..a72796c
--- /dev/null
@@ -0,0 +1,909 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.27-rc2
+# Mon Aug 18 22:17:44 2008
+#
+CONFIG_SUPERH=y
+CONFIG_SUPERH32=y
+CONFIG_ARCH_DEFCONFIG="arch/sh/configs/shx3_defconfig"
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_SYS_SUPPORTS_PCI=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_IO_TRAPPED=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CGROUPS is not set
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_HOTPLUG is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_PROFILING=y
+# CONFIG_MARKERS is not set
+CONFIG_OPROFILE=y
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
+# CONFIG_HAVE_IOREMAP_PROT is not set
+# CONFIG_HAVE_KPROBES is not set
+# CONFIG_HAVE_KRETPROBES is not set
+# CONFIG_HAVE_ARCH_TRACEHOOK is not set
+# CONFIG_HAVE_DMA_ATTRS is not set
+# CONFIG_USE_GENERIC_SMP_HELPERS is not set
+CONFIG_HAVE_CLK=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+# CONFIG_MODULE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+
+#
+# System type
+#
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7619 is not set
+# CONFIG_CPU_SUBTYPE_SH7203 is not set
+# CONFIG_CPU_SUBTYPE_SH7206 is not set
+# CONFIG_CPU_SUBTYPE_SH7263 is not set
+# CONFIG_CPU_SUBTYPE_MXG is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7706 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+# CONFIG_CPU_SUBTYPE_SH7710 is not set
+# CONFIG_CPU_SUBTYPE_SH7712 is not set
+# CONFIG_CPU_SUBTYPE_SH7720 is not set
+# CONFIG_CPU_SUBTYPE_SH7721 is not set
+# CONFIG_CPU_SUBTYPE_SH7750 is not set
+# CONFIG_CPU_SUBTYPE_SH7091 is not set
+# CONFIG_CPU_SUBTYPE_SH7750R is not set
+# CONFIG_CPU_SUBTYPE_SH7750S is not set
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+CONFIG_CPU_SUBTYPE_SH7751R=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+# CONFIG_CPU_SUBTYPE_SH7723 is not set
+# CONFIG_CPU_SUBTYPE_SH7763 is not set
+# CONFIG_CPU_SUBTYPE_SH7770 is not set
+# CONFIG_CPU_SUBTYPE_SH7780 is not set
+# CONFIG_CPU_SUBTYPE_SH7785 is not set
+# CONFIG_CPU_SUBTYPE_SHX3 is not set
+# CONFIG_CPU_SUBTYPE_SH7343 is not set
+# CONFIG_CPU_SUBTYPE_SH7722 is not set
+# CONFIG_CPU_SUBTYPE_SH7366 is not set
+# CONFIG_CPU_SUBTYPE_SH5_101 is not set
+# CONFIG_CPU_SUBTYPE_SH5_103 is not set
+
+#
+# Memory management options
+#
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_PAGE_OFFSET=0x80000000
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x04000000
+CONFIG_29BIT=y
+CONFIG_VSYSCALL=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_MAX_ACTIVE_REGIONS=1
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_PAGE_SIZE_4KB=y
+# CONFIG_PAGE_SIZE_8KB is not set
+# CONFIG_PAGE_SIZE_16KB is not set
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_ENTRY_OFFSET=0x00001000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_STATIC=y
+# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_NR_QUICK=2
+
+#
+# Cache configuration
+#
+# CONFIG_SH_DIRECT_MAPPED is not set
+CONFIG_CACHE_WRITEBACK=y
+# CONFIG_CACHE_WRITETHROUGH is not set
+# CONFIG_CACHE_OFF is not set
+
+#
+# Processor features
+#
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
+# CONFIG_SH_STORE_QUEUES is not set
+CONFIG_CPU_HAS_INTEVT=y
+CONFIG_CPU_HAS_SR_RB=y
+CONFIG_CPU_HAS_PTEA=y
+CONFIG_CPU_HAS_FPU=y
+
+#
+# Board support
+#
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+CONFIG_SH_RTS7751R2D=y
+# CONFIG_SH_LANDISK is not set
+# CONFIG_SH_TITAN is not set
+# CONFIG_SH_LBOX_RE2 is not set
+
+#
+# RTS7751R2D Board Revision
+#
+CONFIG_RTS7751R2D_PLUS=y
+# CONFIG_RTS7751R2D_1 is not set
+
+#
+# Timer and clock configuration
+#
+CONFIG_SH_TMU=y
+CONFIG_SH_TIMER_IRQ=16
+CONFIG_SH_PCLK_FREQ=60000000
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+
+#
+# Additional SuperH Device Drivers
+#
+CONFIG_HEARTBEAT=y
+# CONFIG_PUSH_SWITCH is not set
+
+#
+# Kernel features
+#
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+# CONFIG_SCHED_HRTICK is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_SECCOMP=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_GUSA=y
+# CONFIG_GUSA_RB is not set
+
+#
+# Boot options
+#
+CONFIG_ZERO_PAGE_OFFSET=0x00010000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+# CONFIG_UBC_WAKEUP is not set
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=tty0 console=ttySC0,115200 root=/dev/sda1 earlyprintk=serial"
+
+#
+# Bus options
+#
+# CONFIG_PCI is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_NET is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_SATA_PMP=y
+CONFIG_ATA_SFF=y
+# CONFIG_SATA_MV is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_MD is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=4
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=1
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_SH_SCI is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_AT25 is not set
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+
+#
+# Sonics Silicon Backplane
+#
+CONFIG_SSB_POSSIBLE=y
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+CONFIG_MFD_SM501=y
+# CONFIG_HTC_PASIC3 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_SH_MOBILE_LCDC=m
+CONFIG_FB_SM501=y
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_LOGO_SUPERH_MONO is not set
+# CONFIG_LOGO_SUPERH_VGA16 is not set
+CONFIG_LOGO_SUPERH_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SND=m
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_SPI=y
+CONFIG_SND_SUPERH=y
+# CONFIG_SND_SOC is not set
+CONFIG_SOUND_PRIME=m
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+CONFIG_RTC_DRV_R9701=y
+# CONFIG_RTC_DRV_RS5C348 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_SH is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_EXT4DEV_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=y
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+CONFIG_NLS_CODEPAGE_932=y
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SAMPLES is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+CONFIG_EARLY_SCIF_CONSOLE=y
+CONFIG_EARLY_SCIF_CONSOLE_PORT=0xffe80000
+CONFIG_EARLY_PRINTK=y
+# CONFIG_DEBUG_BOOTMEM is not set
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_4KSTACKS is not set
+# CONFIG_IRQSTACKS is not set
+# CONFIG_SH_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+CONFIG_CRYPTO_HW=y
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_GENERIC_FIND_FIRST_BIT is not set
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=y
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
index a13cb764b0b9892da9baba122e60844db4b8d776..86c0b6fb7375a3a794acf613407768c684bda699 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/io.h>
-#include <asm/lboxre2.h>
+#include <mach/lboxre2.h>
 #include "pci-sh4.h"
 
 static char lboxre2_irq_tab[] __initdata = {
index 5fdadaeed6fcc0427746ac428a7908c9e26d4470..8555238e63eb832ab797de3ff07bad4b57089363 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <asm/r7780rp.h>
+#include <mach/highlander.h>
 #include <asm/io.h>
 #include "pci-sh4.h"
 
index b3fa3e2ef184ffd24b2a3afb604254e3c03634ee..d6ca74b25d5f45e3eed5cd8fe8acb08030cc837d 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/io.h>
-#include <asm/rts7751r2d.h>
+#include <mach/r2d.h>
 #include "pci-sh4.h"
 
 static u8 rts7751r2d_irq_tab[] __initdata = {
index 66a9b4047f2669ca41e2f4a8d41d84af9898d829..4dcc64184b235e198a5c08c08a72c92cb52dff2f 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
-#include <asm/sdk7780.h>
+#include <mach/sdk7780.h>
 #include <asm/io.h>
 #include "pci-sh4.h"
 
index ac8ee2312cd8935b3f8e53e0ef07d0592d866edd..a8f7801a34afb038451daf47e2c5cc717aa592d6 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/io.h>
-#include <asm/titan.h>
+#include <mach/titan.h>
 #include "pci-sh4.h"
 
 static char titan_irq_tab[] __initdata = {
diff --git a/arch/sh/include/asm/bitops-llsc.h b/arch/sh/include/asm/bitops-llsc.h
new file mode 100644 (file)
index 0000000..43b8e1a
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef __ASM_SH_BITOPS_LLSC_H
+#define __ASM_SH_BITOPS_LLSC_H
+
+static inline void set_bit(int nr, volatile void * addr)
+{
+       int     mask;
+       volatile unsigned int *a = addr;
+       unsigned long tmp;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+
+       __asm__ __volatile__ (
+               "1:                                             \n\t"
+               "movli.l        @%1, %0 ! set_bit               \n\t"
+               "or             %3, %0                          \n\t"
+               "movco.l        %0, @%1                         \n\t"
+               "bf             1b                              \n\t"
+               : "=&z" (tmp), "=r" (a)
+               : "1" (a), "r" (mask)
+               : "t", "memory"
+       );
+}
+
+static inline void clear_bit(int nr, volatile void * addr)
+{
+       int     mask;
+       volatile unsigned int *a = addr;
+       unsigned long tmp;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+
+       __asm__ __volatile__ (
+               "1:                                             \n\t"
+               "movli.l        @%1, %0 ! clear_bit             \n\t"
+               "and            %3, %0                          \n\t"
+               "movco.l        %0, @%1                         \n\t"
+               "bf             1b                              \n\t"
+               : "=&z" (tmp), "=r" (a)
+               : "1" (a), "r" (~mask)
+               : "t", "memory"
+       );
+}
+
+static inline void change_bit(int nr, volatile void * addr)
+{
+       int     mask;
+       volatile unsigned int *a = addr;
+       unsigned long tmp;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+
+       __asm__ __volatile__ (
+               "1:                                             \n\t"
+               "movli.l        @%1, %0 ! change_bit            \n\t"
+               "xor            %3, %0                          \n\t"
+               "movco.l        %0, @%1                         \n\t"
+               "bf             1b                              \n\t"
+               : "=&z" (tmp), "=r" (a)
+               : "1" (a), "r" (mask)
+               : "t", "memory"
+       );
+}
+
+static inline int test_and_set_bit(int nr, volatile void * addr)
+{
+       int     mask, retval;
+       volatile unsigned int *a = addr;
+       unsigned long tmp;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+
+       __asm__ __volatile__ (
+               "1:                                             \n\t"
+               "movli.l        @%1, %0 ! test_and_set_bit      \n\t"
+               "mov            %0, %2                          \n\t"
+               "or             %4, %0                          \n\t"
+               "movco.l        %0, @%1                         \n\t"
+               "bf             1b                              \n\t"
+               "and            %4, %2                          \n\t"
+               : "=&z" (tmp), "=r" (a), "=&r" (retval)
+               : "1" (a), "r" (mask)
+               : "t", "memory"
+       );
+
+       return retval != 0;
+}
+
+static inline int test_and_clear_bit(int nr, volatile void * addr)
+{
+       int     mask, retval;
+       volatile unsigned int *a = addr;
+       unsigned long tmp;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+
+       __asm__ __volatile__ (
+               "1:                                             \n\t"
+               "movli.l        @%1, %0 ! test_and_clear_bit    \n\t"
+               "mov            %0, %2                          \n\t"
+               "and            %5, %0                          \n\t"
+               "movco.l        %0, @%1                         \n\t"
+               "bf             1b                              \n\t"
+               "and            %4, %2                          \n\t"
+               "synco                                          \n\t"
+               : "=&z" (tmp), "=r" (a), "=&r" (retval)
+               : "1" (a), "r" (mask), "r" (~mask)
+               : "t", "memory"
+       );
+
+       return retval != 0;
+}
+
+static inline int test_and_change_bit(int nr, volatile void * addr)
+{
+       int     mask, retval;
+       volatile unsigned int *a = addr;
+       unsigned long tmp;
+
+       a += nr >> 5;
+       mask = 1 << (nr & 0x1f);
+
+       __asm__ __volatile__ (
+               "1:                                             \n\t"
+               "movli.l        @%1, %0 ! test_and_change_bit   \n\t"
+               "mov            %0, %2                          \n\t"
+               "xor            %4, %0                          \n\t"
+               "movco.l        %0, @%1                         \n\t"
+               "bf             1b                              \n\t"
+               "and            %4, %2                          \n\t"
+               "synco                                          \n\t"
+               : "=&z" (tmp), "=r" (a), "=&r" (retval)
+               : "1" (a), "r" (mask)
+               : "t", "memory"
+       );
+
+       return retval != 0;
+}
+
+#endif /* __ASM_SH_BITOPS_LLSC_H */
index d7d382f63ee53a5c6a59a7033169ba6bc366cb8f..367930d8e5aeff378a49db60bf367af0b89bf235 100644 (file)
@@ -13,6 +13,8 @@
 
 #ifdef CONFIG_GUSA_RB
 #include <asm/bitops-grb.h>
+#elif defined(CONFIG_CPU_SH4A)
+#include <asm/bitops-llsc.h>
 #else
 #include <asm/bitops-irq.h>
 #endif
index 720dfab7b15e5b5605714a3511436fd27103e6d9..f9c88583d90aba3395c2a520ed05662056231269 100644 (file)
@@ -39,6 +39,7 @@ struct clk {
 
 /* Should be defined by processor-specific code */
 void arch_init_clk_ops(struct clk_ops **, int type);
+int __init arch_clk_init(void);
 
 /* arch/sh/kernel/cpu/clock.c */
 int clk_init(void);
diff --git a/arch/sh/include/asm/cmpxchg-llsc.h b/arch/sh/include/asm/cmpxchg-llsc.h
new file mode 100644 (file)
index 0000000..aee3bf2
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __ASM_SH_CMPXCHG_LLSC_H
+#define __ASM_SH_CMPXCHG_LLSC_H
+
+static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
+{
+       unsigned long retval;
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+               "1:                                     \n\t"
+               "movli.l        @%1, %0 ! xchg_u32      \n\t"
+               "mov            %0, %2                  \n\t"
+               "mov            %4, %0                  \n\t"
+               "movco.l        %0, @%1                 \n\t"
+               "bf             1b                      \n\t"
+               "synco                                  \n\t"
+               : "=&z"(tmp), "=r" (m), "=&r" (retval)
+               : "1" (m), "r" (val)
+               : "t", "memory"
+       );
+
+       return retval;
+}
+
+static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val)
+{
+       unsigned long retval;
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+               "1:                                     \n\t"
+               "movli.l        @%1, %0 ! xchg_u8       \n\t"
+               "mov            %0, %2                  \n\t"
+               "mov            %4, %0                  \n\t"
+               "movco.l        %0, @%1                 \n\t"
+               "bf             1b                      \n\t"
+               "synco                                  \n\t"
+               : "=&z"(tmp), "=r" (m), "=&r" (retval)
+               : "1" (m), "r" (val & 0xff)
+               : "t", "memory"
+       );
+
+       return retval;
+}
+
+static inline unsigned long
+__cmpxchg_u32(volatile int *m, unsigned long old, unsigned long new)
+{
+       unsigned long retval;
+       unsigned long tmp;
+
+       __asm__ __volatile__ (
+               "1:                                             \n\t"
+               "movli.l        @%1, %0 ! __cmpxchg_u32         \n\t"
+               "mov            %0, %2                          \n\t"
+               "cmp/eq         %2, %4                          \n\t"
+               "bf             2f                              \n\t"
+               "mov            %5, %0                          \n\t"
+               "2:                                             \n\t"
+               "movco.l        %0, @%1                         \n\t"
+               "bf             1b                              \n\t"
+               "synco                                          \n\t"
+               : "=&z" (tmp), "=r" (m), "=&r" (retval)
+               : "1" (m), "r" (old), "r" (new)
+               : "t", "memory"
+       );
+
+       return retval;
+}
+
+#endif /* __ASM_SH_CMPXCHG_LLSC_H */
index ee02db110f0da3b78aa0c5a4c66ba13c28c362a3..9eb9036a1bdc27e9a1fb50efe636ed9150e9c3f1 100644 (file)
@@ -108,6 +108,14 @@ typedef struct user_fpu_struct elf_fpregset_t;
 #define elf_check_fdpic(x)             ((x)->e_flags & EF_SH_FDPIC)
 #define elf_check_const_displacement(x)        ((x)->e_flags & EF_SH_PIC)
 
+#ifdef CONFIG_SUPERH32
+/*
+ * Enable dump using regset.
+ * This covers all of general/DSP/FPU regs.
+ */
+#define CORE_DUMP_USE_REGSET
+#endif
+
 #define USE_ELF_CORE_DUMP
 #define ELF_FDPIC_CORE_EFLAGS  EF_SH_FDPIC
 #define ELF_EXEC_PAGESIZE      PAGE_SIZE
@@ -190,12 +198,6 @@ do {                                                                       \
 #endif
 
 #define SET_PERSONALITY(ex) set_personality(PER_LINUX_32BIT)
-struct task_struct;
-extern int dump_task_regs (struct task_struct *, elf_gregset_t *);
-extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
-
-#define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs)
-#define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
 
 #ifdef CONFIG_VSYSCALL
 /* vDSO has arch_setup_additional_pages */
index 91462fea1507c69af30d42a8e2315e8730ced5b0..1d3aee04b5ccc4c3c0181ead9ca3401733a6ece2 100644 (file)
@@ -30,8 +30,15 @@ static inline void save_fpu(struct task_struct *tsk, struct pt_regs *regs)
 }
 #endif
 
+struct user_regset;
+
 extern int do_fpu_inst(unsigned short, struct pt_regs *);
 
+extern int fpregs_get(struct task_struct *target,
+                     const struct user_regset *regset,
+                     unsigned int pos, unsigned int count,
+                     void *kbuf, void __user *ubuf);
+
 static inline void unlazy_fpu(struct task_struct *tsk, struct pt_regs *regs)
 {
        preempt_disable();
@@ -50,6 +57,18 @@ static inline void clear_fpu(struct task_struct *tsk, struct pt_regs *regs)
        preempt_enable();
 }
 
+static inline int init_fpu(struct task_struct *tsk)
+{
+       if (tsk_used_math(tsk)) {
+               if ((boot_cpu_data.flags & CPU_HAS_FPU) && tsk == current)
+                       unlazy_fpu(tsk, task_pt_regs(tsk));
+               return 0;
+       }
+
+       set_stopped_child_used_math(tsk);
+       return 0;
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* __ASM_SH_FPU_H */
diff --git a/arch/sh/include/asm/ftrace.h b/arch/sh/include/asm/ftrace.h
new file mode 100644 (file)
index 0000000..3aed362
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __ASM_SH_FTRACE_H
+#define __ASM_SH_FTRACE_H
+
+#ifndef __ASSEMBLY__
+extern void mcount(void);
+#endif
+
+#endif /* __ASM_SH_FTRACE_H */
index cf32bd2df88187d7efa0a63684220a72c38e80c8..9650e7c9c39e989c5763cca1182a4c5c69f8ae9a 100644 (file)
@@ -1,9 +1,9 @@
 /*
  *  include/asm-sh/gpio.h
  *
- *  Copyright (C) 2007 Markus Brunner, Mark Jonas
+ * Generic GPIO API and pinmux table support for SuperH.
  *
- *  Addresses for the Pin Function Controller
+ * Copyright (c) 2008 Magnus Damm
  *
  * 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
 #include <cpu/gpio.h>
 #endif
 
+typedef unsigned short pinmux_enum_t;
+typedef unsigned char pinmux_flag_t;
+
+#define PINMUX_TYPE_NONE            0
+#define PINMUX_TYPE_FUNCTION        1
+#define PINMUX_TYPE_GPIO            2
+#define PINMUX_TYPE_OUTPUT          3
+#define PINMUX_TYPE_INPUT           4
+#define PINMUX_TYPE_INPUT_PULLUP    5
+#define PINMUX_TYPE_INPUT_PULLDOWN  6
+
+#define PINMUX_FLAG_TYPE            (0x7)
+#define PINMUX_FLAG_WANT_PULLUP     (1 << 3)
+#define PINMUX_FLAG_WANT_PULLDOWN   (1 << 4)
+
+struct pinmux_gpio {
+       pinmux_enum_t enum_id;
+       pinmux_flag_t flags;
+};
+
+#define PINMUX_GPIO(gpio, data_or_mark) [gpio] = { data_or_mark }
+#define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
+
+struct pinmux_cfg_reg {
+       unsigned long reg, reg_width, field_width;
+       unsigned long *cnt;
+       pinmux_enum_t *enum_ids;
+};
+
+#define PINMUX_CFG_REG(name, r, r_width, f_width) \
+       .reg = r, .reg_width = r_width, .field_width = f_width,         \
+       .cnt = (unsigned long [r_width / f_width]) {}, \
+       .enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)]) \
+
+struct pinmux_data_reg {
+       unsigned long reg, reg_width;
+       pinmux_enum_t *enum_ids;
+};
+
+#define PINMUX_DATA_REG(name, r, r_width) \
+       .reg = r, .reg_width = r_width, \
+       .enum_ids = (pinmux_enum_t [r_width]) \
+
+struct pinmux_range {
+       pinmux_enum_t begin;
+       pinmux_enum_t end;
+};
+
+struct pinmux_info {
+       char *name;
+       pinmux_enum_t reserved_id;
+       struct pinmux_range data;
+       struct pinmux_range input;
+       struct pinmux_range input_pd;
+       struct pinmux_range input_pu;
+       struct pinmux_range output;
+       struct pinmux_range mark;
+       struct pinmux_range function;
+
+       unsigned first_gpio, last_gpio;
+
+       struct pinmux_gpio *gpios;
+       struct pinmux_cfg_reg *cfg_regs;
+       struct pinmux_data_reg *data_regs;
+
+       pinmux_enum_t *gpio_data;
+       unsigned int gpio_data_size;
+
+       unsigned long *gpio_in_use;
+};
+
+int register_pinmux(struct pinmux_info *pip);
+
+int __gpio_request(unsigned gpio);
+static inline int gpio_request(unsigned gpio, const char *label)
+{
+       return __gpio_request(gpio);
+}
+void gpio_free(unsigned gpio);
+int gpio_direction_input(unsigned gpio);
+int gpio_direction_output(unsigned gpio, int value);
+int gpio_get_value(unsigned gpio);
+void gpio_set_value(unsigned gpio, int value);
+static inline int gpio_export(unsigned gpio, bool direction_may_change)
+{
+       return 0;
+}
+
 #endif /* __ASM_SH_GPIO_H */
index d557b00111bfb280a19880ae39d4afe779c7976e..603cdde813d11a2b37b94145c77db0caa06a3bd0 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_SH_HW_IRQ_H
 
 #include <linux/init.h>
+#include <linux/sh_intc.h>
 #include <asm/atomic.h>
 
 extern atomic_t irq_err_count;
@@ -23,101 +24,12 @@ struct ipr_desc {
 
 void register_ipr_controller(struct ipr_desc *);
 
-typedef unsigned char intc_enum;
-
-struct intc_vect {
-       intc_enum enum_id;
-       unsigned short vect;
-};
-
-#define INTC_VECT(enum_id, vect) { enum_id, vect }
-#define INTC_IRQ(enum_id, irq) INTC_VECT(enum_id, irq2evt(irq))
-
-struct intc_group {
-       intc_enum enum_id;
-       intc_enum enum_ids[32];
-};
-
-#define INTC_GROUP(enum_id, ids...) { enum_id, { ids } }
-
-struct intc_mask_reg {
-       unsigned long set_reg, clr_reg, reg_width;
-       intc_enum enum_ids[32];
-#ifdef CONFIG_SMP
-       unsigned long smp;
-#endif
-};
-
-struct intc_prio_reg {
-       unsigned long set_reg, clr_reg, reg_width, field_width;
-       intc_enum enum_ids[16];
-#ifdef CONFIG_SMP
-       unsigned long smp;
-#endif
-};
-
-struct intc_sense_reg {
-       unsigned long reg, reg_width, field_width;
-       intc_enum enum_ids[16];
-};
-
-#ifdef CONFIG_SMP
-#define INTC_SMP(stride, nr) .smp = (stride) | ((nr) << 8)
-#else
-#define INTC_SMP(stride, nr)
-#endif
-
-struct intc_desc {
-       struct intc_vect *vectors;
-       unsigned int nr_vectors;
-       struct intc_group *groups;
-       unsigned int nr_groups;
-       struct intc_mask_reg *mask_regs;
-       unsigned int nr_mask_regs;
-       struct intc_prio_reg *prio_regs;
-       unsigned int nr_prio_regs;
-       struct intc_sense_reg *sense_regs;
-       unsigned int nr_sense_regs;
-       char *name;
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
-       struct intc_mask_reg *ack_regs;
-       unsigned int nr_ack_regs;
-#endif
-};
-
-#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
-#define DECLARE_INTC_DESC(symbol, chipname, vectors, groups,           \
-       mask_regs, prio_regs, sense_regs)                               \
-struct intc_desc symbol __initdata = {                                 \
-       _INTC_ARRAY(vectors), _INTC_ARRAY(groups),                      \
-       _INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),                 \
-       _INTC_ARRAY(sense_regs),                                        \
-       chipname,                                                       \
-}
-
-#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
-#define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups,       \
-       mask_regs, prio_regs, sense_regs, ack_regs)                     \
-struct intc_desc symbol __initdata = {                                 \
-       _INTC_ARRAY(vectors), _INTC_ARRAY(groups),                      \
-       _INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),                 \
-       _INTC_ARRAY(sense_regs),                                        \
-       chipname,                                                       \
-       _INTC_ARRAY(ack_regs),                                          \
-}
-#endif
-
-void __init register_intc_controller(struct intc_desc *desc);
-int intc_set_priority(unsigned int irq, unsigned int prio);
-
 void __init plat_irq_setup(void);
-#ifdef CONFIG_CPU_SH3
 void __init plat_irq_setup_sh3(void);
-#endif
+void __init plat_irq_setup_pins(int mode);
 
 enum { IRQ_MODE_IRQ, IRQ_MODE_IRQ7654, IRQ_MODE_IRQ3210,
        IRQ_MODE_IRL7654_MASK, IRQ_MODE_IRL3210_MASK,
        IRQ_MODE_IRL7654, IRQ_MODE_IRL3210 };
-void __init plat_irq_setup_pins(int mode);
 
 #endif /* __ASM_SH_HW_IRQ_H */
index a4fbf0c84fb14aecf694379038d2d579c6607e2a..436c28539577ebf75e9d0aefa0514faf2351ec83 100644 (file)
@@ -1,27 +1,26 @@
 #ifndef __ASM_SH_IO_H
 #define __ASM_SH_IO_H
-
 /*
  * Convention:
- *    read{b,w,l}/write{b,w,l} are for PCI,
+ *    read{b,w,l,q}/write{b,w,l,q} are for PCI,
  *    while in{b,w,l}/out{b,w,l} are for ISA
- * These may (will) be platform specific function.
+ *
  * In addition we have 'pausing' versions: in{b,w,l}_p/out{b,w,l}_p
  * and 'string' versions: ins{b,w,l}/outs{b,w,l}
- * For read{b,w,l} and write{b,w,l} there are also __raw versions, which
- * do not have a memory barrier after them.
  *
- * In addition, we have
- *   ctrl_in{b,w,l}/ctrl_out{b,w,l} for SuperH specific I/O.
- *   which are processor specific.
- */
-
-/*
- * We follow the Alpha convention here:
- *  __inb expands to an inline function call (which calls via the mv)
- *  _inb  is a real function call (note ___raw fns are _ version of __raw)
- *  inb   by default expands to _inb, but the machine specific code may
- *        define it to __inb if it chooses.
+ * While read{b,w,l,q} and write{b,w,l,q} contain memory barriers
+ * automatically, there are also __raw versions, which do not.
+ *
+ * Historically, we have also had ctrl_in{b,w,l,q}/ctrl_out{b,w,l,q} for
+ * SuperH specific I/O (raw I/O to on-chip CPU peripherals). In practice
+ * these have the same semantics as the __raw variants, and as such, all
+ * new code should be using the __raw versions.
+ *
+ * All ISA I/O routines are wrapped through the machine vector. If a
+ * board does not provide overrides, a generic set that are copied in
+ * from the default machine vector are used instead. These are largely
+ * for old compat code for I/O offseting to SuperIOs, all of which are
+ * better handled through the machvec ioport mapping routines these days.
  */
 #include <asm/cache.h>
 #include <asm/system.h>
@@ -31,7 +30,6 @@
 #include <asm-generic/iomap.h>
 
 #ifdef __KERNEL__
-
 /*
  * Depending on which platform we are running on, we need different
  * I/O functions.
 #include <asm/io_generic.h>
 #include <asm/io_trapped.h>
 
-#define maybebadio(port) \
-  printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
-        __FUNCTION__, __LINE__, (port), (u32)__builtin_return_address(0))
-
-/*
- * Since boards are able to define their own set of I/O routines through
- * their respective machine vector, we always wrap through the mv.
- *
- * Also, in the event that a board hasn't provided its own definition for
- * a given routine, it will be wrapped to generic code at run-time.
- */
+#define inb(p)                 sh_mv.mv_inb((p))
+#define inw(p)                 sh_mv.mv_inw((p))
+#define inl(p)                 sh_mv.mv_inl((p))
+#define outb(x,p)              sh_mv.mv_outb((x),(p))
+#define outw(x,p)              sh_mv.mv_outw((x),(p))
+#define outl(x,p)              sh_mv.mv_outl((x),(p))
+
+#define inb_p(p)               sh_mv.mv_inb_p((p))
+#define inw_p(p)               sh_mv.mv_inw_p((p))
+#define inl_p(p)               sh_mv.mv_inl_p((p))
+#define outb_p(x,p)            sh_mv.mv_outb_p((x),(p))
+#define outw_p(x,p)            sh_mv.mv_outw_p((x),(p))
+#define outl_p(x,p)            sh_mv.mv_outl_p((x),(p))
+
+#define insb(p,b,c)            sh_mv.mv_insb((p), (b), (c))
+#define insw(p,b,c)            sh_mv.mv_insw((p), (b), (c))
+#define insl(p,b,c)            sh_mv.mv_insl((p), (b), (c))
+#define outsb(p,b,c)           sh_mv.mv_outsb((p), (b), (c))
+#define outsw(p,b,c)           sh_mv.mv_outsw((p), (b), (c))
+#define outsl(p,b,c)           sh_mv.mv_outsl((p), (b), (c))
+
+#define __raw_writeb(v,a)      (__chk_io_ptr(a), *(volatile u8  __force *)(a) = (v))
+#define __raw_writew(v,a)      (__chk_io_ptr(a), *(volatile u16 __force *)(a) = (v))
+#define __raw_writel(v,a)      (__chk_io_ptr(a), *(volatile u32 __force *)(a) = (v))
+#define __raw_writeq(v,a)      (__chk_io_ptr(a), *(volatile u64 __force *)(a) = (v))
+
+#define __raw_readb(a)         (__chk_io_ptr(a), *(volatile u8  __force *)(a))
+#define __raw_readw(a)         (__chk_io_ptr(a), *(volatile u16 __force *)(a))
+#define __raw_readl(a)         (__chk_io_ptr(a), *(volatile u32 __force *)(a))
+#define __raw_readq(a)         (__chk_io_ptr(a), *(volatile u64 __force *)(a))
+
+#define readb(a)               ({ u8  r_ = __raw_readb(a); mb(); r_; })
+#define readw(a)               ({ u16 r_ = __raw_readw(a); mb(); r_; })
+#define readl(a)               ({ u32 r_ = __raw_readl(a); mb(); r_; })
+#define readq(a)               ({ u64 r_ = __raw_readq(a); mb(); r_; })
+
+#define writeb(v,a)            ({ __raw_writeb((v),(a)); mb(); })
+#define writew(v,a)            ({ __raw_writew((v),(a)); mb(); })
+#define writel(v,a)            ({ __raw_writel((v),(a)); mb(); })
+#define writeq(v,a)            ({ __raw_writeq((v),(a)); mb(); })
 
-#define __inb(p)       sh_mv.mv_inb((p))
-#define __inw(p)       sh_mv.mv_inw((p))
-#define __inl(p)       sh_mv.mv_inl((p))
-#define __outb(x,p)    sh_mv.mv_outb((x),(p))
-#define __outw(x,p)    sh_mv.mv_outw((x),(p))
-#define __outl(x,p)    sh_mv.mv_outl((x),(p))
-
-#define __inb_p(p)     sh_mv.mv_inb_p((p))
-#define __inw_p(p)     sh_mv.mv_inw_p((p))
-#define __inl_p(p)     sh_mv.mv_inl_p((p))
-#define __outb_p(x,p)  sh_mv.mv_outb_p((x),(p))
-#define __outw_p(x,p)  sh_mv.mv_outw_p((x),(p))
-#define __outl_p(x,p)  sh_mv.mv_outl_p((x),(p))
-
-#define __insb(p,b,c)  sh_mv.mv_insb((p), (b), (c))
-#define __insw(p,b,c)  sh_mv.mv_insw((p), (b), (c))
-#define __insl(p,b,c)  sh_mv.mv_insl((p), (b), (c))
-#define __outsb(p,b,c) sh_mv.mv_outsb((p), (b), (c))
-#define __outsw(p,b,c) sh_mv.mv_outsw((p), (b), (c))
-#define __outsl(p,b,c) sh_mv.mv_outsl((p), (b), (c))
-
-#define __readb(a)     sh_mv.mv_readb((a))
-#define __readw(a)     sh_mv.mv_readw((a))
-#define __readl(a)     sh_mv.mv_readl((a))
-#define __writeb(v,a)  sh_mv.mv_writeb((v),(a))
-#define __writew(v,a)  sh_mv.mv_writew((v),(a))
-#define __writel(v,a)  sh_mv.mv_writel((v),(a))
-
-#define inb            __inb
-#define inw            __inw
-#define inl            __inl
-#define outb           __outb
-#define outw           __outw
-#define outl           __outl
-
-#define inb_p          __inb_p
-#define inw_p          __inw_p
-#define inl_p          __inl_p
-#define outb_p         __outb_p
-#define outw_p         __outw_p
-#define outl_p         __outl_p
-
-#define insb           __insb
-#define insw           __insw
-#define insl           __insl
-#define outsb          __outsb
-#define outsw          __outsw
-#define outsl          __outsl
-
-#define __raw_readb(a)         __readb((void __iomem *)(a))
-#define __raw_readw(a)         __readw((void __iomem *)(a))
-#define __raw_readl(a)         __readl((void __iomem *)(a))
-#define __raw_writeb(v, a)     __writeb(v, (void __iomem *)(a))
-#define __raw_writew(v, a)     __writew(v, (void __iomem *)(a))
-#define __raw_writel(v, a)     __writel(v, (void __iomem *)(a))
-
-void __raw_writesl(unsigned long addr, const void *data, int longlen);
-void __raw_readsl(unsigned long addr, void *data, int longlen);
+/* SuperH on-chip I/O functions */
+#define ctrl_inb               __raw_readb
+#define ctrl_inw               __raw_readw
+#define ctrl_inl               __raw_readl
+#define ctrl_inq               __raw_readq
 
-/*
- * The platform header files may define some of these macros to use
- * the inlined versions where appropriate.  These macros may also be
- * redefined by userlevel programs.
- */
-#ifdef __readb
-# define readb(a)      ({ unsigned int r_ = __raw_readb(a); mb(); r_; })
-#endif
-#ifdef __raw_readw
-# define readw(a)      ({ unsigned int r_ = __raw_readw(a); mb(); r_; })
-#endif
-#ifdef __raw_readl
-# define readl(a)      ({ unsigned int r_ = __raw_readl(a); mb(); r_; })
-#endif
+#define ctrl_outb              __raw_writeb
+#define ctrl_outw              __raw_writew
+#define ctrl_outl              __raw_writel
+#define ctrl_outq              __raw_writeq
 
-#ifdef __raw_writeb
-# define writeb(v,a)   ({ __raw_writeb((v),(a)); mb(); })
-#endif
-#ifdef __raw_writew
-# define writew(v,a)   ({ __raw_writew((v),(a)); mb(); })
-#endif
-#ifdef __raw_writel
-# define writel(v,a)   ({ __raw_writel((v),(a)); mb(); })
+static inline void ctrl_delay(void)
+{
+#ifdef P2SEG
+       __raw_readw(P2SEG);
 #endif
+}
 
 #define __BUILD_MEMORY_STRING(bwlq, type)                              \
                                                                        \
-static inline void writes##bwlq(volatile void __iomem *mem,            \
+static inline void __raw_writes##bwlq(volatile void __iomem *mem,      \
                                const void *addr, unsigned int count)   \
 {                                                                      \
        const volatile type *__addr = addr;                             \
@@ -149,8 +110,8 @@ static inline void writes##bwlq(volatile void __iomem *mem,         \
        }                                                               \
 }                                                                      \
                                                                        \
-static inline void reads##bwlq(volatile void __iomem *mem, void *addr, \
-                              unsigned int count)                      \
+static inline void __raw_reads##bwlq(volatile void __iomem *mem,       \
+                              void *addr, unsigned int count)          \
 {                                                                      \
        volatile type *__addr = addr;                                   \
                                                                        \
@@ -162,106 +123,71 @@ static inline void reads##bwlq(volatile void __iomem *mem, void *addr,   \
 
 __BUILD_MEMORY_STRING(b, u8)
 __BUILD_MEMORY_STRING(w, u16)
-#define writesl __raw_writesl
-#define readsl  __raw_readsl
+__BUILD_MEMORY_STRING(q, u64)
+
+void __raw_writesl(void __iomem *addr, const void *data, int longlen);
+void __raw_readsl(const void __iomem *addr, void *data, int longlen);
+
+#define writesb                        __raw_writesb
+#define writesw                        __raw_writesw
+#define writesl                        __raw_writesl
+
+#define readsb                 __raw_readsb
+#define readsw                 __raw_readsw
+#define readsl                 __raw_readsl
 
-#define readb_relaxed(a) readb(a)
-#define readw_relaxed(a) readw(a)
-#define readl_relaxed(a) readl(a)
+#define readb_relaxed(a)       readb(a)
+#define readw_relaxed(a)       readw(a)
+#define readl_relaxed(a)       readl(a)
+#define readq_relaxed(a)       readq(a)
 
 /* Simple MMIO */
-#define ioread8(a)             readb(a)
-#define ioread16(a)            readw(a)
+#define ioread8(a)             __raw_readb(a)
+#define ioread16(a)            __raw_readw(a)
 #define ioread16be(a)          be16_to_cpu(__raw_readw((a)))
-#define ioread32(a)            readl(a)
+#define ioread32(a)            __raw_readl(a)
 #define ioread32be(a)          be32_to_cpu(__raw_readl((a)))
 
-#define iowrite8(v,a)          writeb((v),(a))
-#define iowrite16(v,a)         writew((v),(a))
+#define iowrite8(v,a)          __raw_writeb((v),(a))
+#define iowrite16(v,a)         __raw_writew((v),(a))
 #define iowrite16be(v,a)       __raw_writew(cpu_to_be16((v)),(a))
-#define iowrite32(v,a)         writel((v),(a))
+#define iowrite32(v,a)         __raw_writel((v),(a))
 #define iowrite32be(v,a)       __raw_writel(cpu_to_be32((v)),(a))
 
-#define ioread8_rep(a, d, c)   readsb((a), (d), (c))
-#define ioread16_rep(a, d, c)  readsw((a), (d), (c))
-#define ioread32_rep(a, d, c)  readsl((a), (d), (c))
+#define ioread8_rep(a, d, c)   __raw_readsb((a), (d), (c))
+#define ioread16_rep(a, d, c)  __raw_readsw((a), (d), (c))
+#define ioread32_rep(a, d, c)  __raw_readsl((a), (d), (c))
 
-#define iowrite8_rep(a, s, c)  writesb((a), (s), (c))
-#define iowrite16_rep(a, s, c) writesw((a), (s), (c))
-#define iowrite32_rep(a, s, c) writesl((a), (s), (c))
+#define iowrite8_rep(a, s, c)  __raw_writesb((a), (s), (c))
+#define iowrite16_rep(a, s, c) __raw_writesw((a), (s), (c))
+#define iowrite32_rep(a, s, c) __raw_writesl((a), (s), (c))
 
-#define mmiowb()       wmb()   /* synco on SH-4A, otherwise a nop */
+/* synco on SH-4A, otherwise a nop */
+#define mmiowb()               wmb()
 
 #define IO_SPACE_LIMIT 0xffffffff
 
+extern unsigned long generic_io_base;
+
 /*
- * This function provides a method for the generic case where a board-specific
- * ioport_map simply needs to return the port + some arbitrary port base.
+ * This function provides a method for the generic case where a
+ * board-specific ioport_map simply needs to return the port + some
+ * arbitrary port base.
  *
  * We use this at board setup time to implicitly set the port base, and
  * as a result, we can use the generic ioport_map.
  */
 static inline void __set_io_port_base(unsigned long pbase)
 {
-       extern unsigned long generic_io_base;
-
        generic_io_base = pbase;
 }
 
 #define __ioport_map(p, n) sh_mv.mv_ioport_map((p), (n))
 
 /* We really want to try and get these to memcpy etc */
-extern void memcpy_fromio(void *, volatile void __iomem *, unsigned long);
-extern void memcpy_toio(volatile void __iomem *, const void *, unsigned long);
-extern void memset_io(volatile void __iomem *, int, unsigned long);
-
-/* SuperH on-chip I/O functions */
-static inline unsigned char ctrl_inb(unsigned long addr)
-{
-       return *(volatile unsigned char*)addr;
-}
-
-static inline unsigned short ctrl_inw(unsigned long addr)
-{
-       return *(volatile unsigned short*)addr;
-}
-
-static inline unsigned int ctrl_inl(unsigned long addr)
-{
-       return *(volatile unsigned long*)addr;
-}
-
-static inline unsigned long long ctrl_inq(unsigned long addr)
-{
-       return *(volatile unsigned long long*)addr;
-}
-
-static inline void ctrl_outb(unsigned char b, unsigned long addr)
-{
-       *(volatile unsigned char*)addr = b;
-}
-
-static inline void ctrl_outw(unsigned short b, unsigned long addr)
-{
-       *(volatile unsigned short*)addr = b;
-}
-
-static inline void ctrl_outl(unsigned int b, unsigned long addr)
-{
-        *(volatile unsigned long*)addr = b;
-}
-
-static inline void ctrl_outq(unsigned long long b, unsigned long addr)
-{
-       *(volatile unsigned long long*)addr = b;
-}
-
-static inline void ctrl_delay(void)
-{
-#ifdef P2SEG
-       ctrl_inw(P2SEG);
-#endif
-}
+void memcpy_fromio(void *, const volatile void __iomem *, unsigned long);
+void memcpy_toio(volatile void __iomem *, const void *, unsigned long);
+void memset_io(volatile void __iomem *, int, unsigned long);
 
 /* Quad-word real-mode I/O, don't ask.. */
 unsigned long long peek_real_address_q(unsigned long long addr);
@@ -347,9 +273,15 @@ __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags)
        __ioremap_mode((offset), (size), _PAGE_CACHABLE)
 #define p3_ioremap(offset, size, flags)                        \
        __ioremap((offset), (size), (flags))
+#define ioremap_prot(offset, size, flags)              \
+       __ioremap_mode((offset), (size), (flags))
 #define iounmap(addr)                                  \
        __iounmap((addr))
 
+#define maybebadio(port) \
+       printk(KERN_ERR "bad PC-like io %s:%u for port 0x%lx at 0x%08x\n", \
+              __func__, __LINE__, (port), (u32)__builtin_return_address(0))
+
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
  * access
index 92fc6070d7b3a8aa6affe26f09a52581d47c0148..1e5d375f55dce7e4f98236d489e021455373957c 100644 (file)
@@ -33,13 +33,6 @@ void IO_CONCAT(__IO_PREFIX,outsb)(unsigned long, const void *src, unsigned long
 void IO_CONCAT(__IO_PREFIX,outsw)(unsigned long, const void *src, unsigned long count);
 void IO_CONCAT(__IO_PREFIX,outsl)(unsigned long, const void *src, unsigned long count);
 
-u8 IO_CONCAT(__IO_PREFIX,readb)(void __iomem *);
-u16 IO_CONCAT(__IO_PREFIX,readw)(void __iomem *);
-u32 IO_CONCAT(__IO_PREFIX,readl)(void __iomem *);
-void IO_CONCAT(__IO_PREFIX,writeb)(u8, void __iomem *);
-void IO_CONCAT(__IO_PREFIX,writew)(u16, void __iomem *);
-void IO_CONCAT(__IO_PREFIX,writel)(u32, void __iomem *);
-
 void *IO_CONCAT(__IO_PREFIX,ioremap)(unsigned long offset, unsigned long size);
 void IO_CONCAT(__IO_PREFIX,iounmap)(void *addr);
 
index 6195a531c1b0c93b878519c173b87aef34c454dc..d319baaf4fbdf21a20b65cb659dcfaefd93d5f91 100644 (file)
@@ -41,6 +41,9 @@ static inline int generic_irq_demux(int irq)
 #define irq_canonicalize(irq)  (irq)
 #define irq_demux(irq)         sh_mv.mv_irq_demux(irq)
 
+void init_IRQ(void);
+asmlinkage int do_IRQ(unsigned int irq, struct pt_regs *regs);
+
 #ifdef CONFIG_IRQSTACKS
 extern void irq_ctx_init(int cpu);
 extern void irq_ctx_exit(int cpu);
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
new file mode 100644 (file)
index 0000000..6078d8e
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef __ASM_SH_KPROBES_H
+#define __ASM_SH_KPROBES_H
+
+#ifdef CONFIG_KPROBES
+
+#include <linux/types.h>
+#include <linux/ptrace.h>
+
+typedef u16 kprobe_opcode_t;
+#define BREAKPOINT_INSTRUCTION 0xc33a
+
+#define MAX_INSN_SIZE 16
+#define MAX_STACK_SIZE 64
+#define MIN_STACK_SIZE(ADDR) (((MAX_STACK_SIZE) < \
+       (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) \
+       ? (MAX_STACK_SIZE) \
+       : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))
+
+#define regs_return_value(regs)                ((regs)->regs[0])
+#define flush_insn_slot(p)             do { } while (0)
+#define kretprobe_blacklist_size       0
+
+struct kprobe;
+
+void arch_remove_kprobe(struct kprobe *);
+void kretprobe_trampoline(void);
+void jprobe_return_end(void);
+
+/* Architecture specific copy of original instruction*/
+struct arch_specific_insn {
+       /* copy of the original instruction */
+       kprobe_opcode_t insn[MAX_INSN_SIZE];
+};
+
+struct prev_kprobe {
+       struct kprobe *kp;
+       unsigned long status;
+};
+
+/* per-cpu kprobe control block */
+struct kprobe_ctlblk {
+       unsigned long kprobe_status;
+       unsigned long jprobe_saved_r15;
+       struct pt_regs jprobe_saved_regs;
+       kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
+       struct prev_kprobe prev_kprobe;
+};
+
+extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
+extern int kprobe_exceptions_notify(struct notifier_block *self,
+                                   unsigned long val, void *data);
+extern int kprobe_handle_illslot(unsigned long pc);
+#else
+
+#define kprobe_handle_illslot(pc)      (-1)
+
+#endif /* CONFIG_KPROBES */
+#endif /* __ASM_SH_KPROBES_H */
index b2e4124070aef289a724a90049bba93adfcffa64..f1bae02ef7b6398c8620a83427a51ef368c0df1d 100644 (file)
@@ -42,13 +42,6 @@ struct sh_machine_vector {
        void (*mv_outsw)(unsigned long, const void *src, unsigned long count);
        void (*mv_outsl)(unsigned long, const void *src, unsigned long count);
 
-       u8 (*mv_readb)(void __iomem *);
-       u16 (*mv_readw)(void __iomem *);
-       u32 (*mv_readl)(void __iomem *);
-       void (*mv_writeb)(u8, void __iomem *);
-       void (*mv_writew)(u16, void __iomem *);
-       void (*mv_writel)(u32, void __iomem *);
-
        int (*mv_irq_demux)(int irq);
 
        void (*mv_init_irq)(void);
index 2969253c40421a90d2da89b7856c35cf2405138d..7f5363b29ba079a33ad77d03c587fd31cfe2105e 100644 (file)
@@ -4,6 +4,8 @@
 #ifdef __KERNEL__
 
 #ifdef CONFIG_NEED_MULTIPLE_NODES
+#include <linux/numa.h>
+
 extern struct pglist_data *node_data[];
 #define NODE_DATA(nid)         (node_data[nid])
 
index 77fb8bf02e4e846b8dfcb969cac079e3009e768a..5871d78e47e529208e28a523abb30fd2e075f429 100644 (file)
@@ -104,6 +104,8 @@ typedef struct { unsigned long pgd; } pgd_t;
 
 typedef struct page *pgtable_t;
 
+#define pte_pgprot(x) __pgprot(pte_val(x) & PTE_FLAGS_MASK)
+
 #endif /* !__ASSEMBLY__ */
 
 /*
index a4a8f8b93463f000970baae167c1199ceb0005f5..52220d70a096a378f7dd9c4fbbda635177f4b808 100644 (file)
@@ -76,6 +76,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #endif
 
 #define PTE_PHYS_MASK          (PHYS_ADDR_MASK & PAGE_MASK)
+#define PTE_FLAGS_MASK         (~(PTE_PHYS_MASK) << PAGE_SHIFT)
 
 #ifdef CONFIG_SUPERH32
 #define VMALLOC_START  (P3SEG)
index 15d9f92ca383c38c35e001d27828c33d77aff09f..693364a20ad72e331a18ccdf391c01ac1b1a0a2b 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <asm/cpu-features.h>
 #include <asm/segment.h>
+#include <asm/cache.h>
 
 #ifndef __ASSEMBLY__
 /*
@@ -43,11 +44,52 @@ enum cpu_type {
        CPU_SH_NONE
 };
 
+/*
+ * TLB information structure
+ *
+ * Defined for both I and D tlb, per-processor.
+ */
+struct tlb_info {
+       unsigned long long next;
+       unsigned long long first;
+       unsigned long long last;
+
+       unsigned int entries;
+       unsigned int step;
+
+       unsigned long flags;
+};
+
+struct sh_cpuinfo {
+       unsigned int type;
+       int cut_major, cut_minor;
+       unsigned long loops_per_jiffy;
+       unsigned long asid_cache;
+
+       struct cache_info icache;       /* Primary I-cache */
+       struct cache_info dcache;       /* Primary D-cache */
+       struct cache_info scache;       /* Secondary cache */
+
+       /* TLB info */
+       struct tlb_info itlb;
+       struct tlb_info dtlb;
+
+       unsigned long flags;
+} __attribute__ ((aligned(L1_CACHE_BYTES)));
+
+extern struct sh_cpuinfo cpu_data[];
+#define boot_cpu_data cpu_data[0]
+#define current_cpu_data cpu_data[smp_processor_id()]
+#define raw_current_cpu_data cpu_data[raw_smp_processor_id()]
+
 /* Forward decl */
-struct sh_cpuinfo;
+struct seq_operations;
+
+extern struct pt_regs fake_swapper_regs;
 
 /* arch/sh/kernel/setup.c */
 const char *get_cpu_subtype(struct sh_cpuinfo *c);
+extern const struct seq_operations cpuinfo_op;
 
 #ifdef CONFIG_VSYSCALL
 int vsyscall_init(void);
index 0dadd75bd93c8cb8720e5129ed1975fc4e3517a7..a46a0207e977933469438928dee0dd0336571ab5 100644 (file)
@@ -10,9 +10,9 @@
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
+#include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/cache.h>
 #include <asm/ptrace.h>
 
 /*
 #define CCN_CVR                0xff000040
 #define CCN_PRR                0xff000044
 
-struct sh_cpuinfo {
-       unsigned int type;
-       int cut_major, cut_minor;
-       unsigned long loops_per_jiffy;
-       unsigned long asid_cache;
-
-       struct cache_info icache;       /* Primary I-cache */
-       struct cache_info dcache;       /* Primary D-cache */
-       struct cache_info scache;       /* Secondary cache */
-
-       unsigned long flags;
-} __attribute__ ((aligned(L1_CACHE_BYTES)));
-
-extern struct sh_cpuinfo cpu_data[];
-#define boot_cpu_data cpu_data[0]
-#define current_cpu_data cpu_data[smp_processor_id()]
-#define raw_current_cpu_data cpu_data[raw_smp_processor_id()]
+asmlinkage void __init sh_cpu_init(void);
 
 /*
  * User space process size: 2GB.
@@ -196,6 +180,8 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15])
 
+#define user_stack_pointer(regs)       ((regs)->regs[15])
+
 #define cpu_sleep()    __asm__ __volatile__ ("sleep" : : : "memory")
 #define cpu_relax()    barrier()
 
index 770d5169983b61e4c286e70024a3749d489dd87a..b0b4824dfc4ce9d081de5e250081681685e84252 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/compiler.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/cache.h>
 #include <asm/ptrace.h>
 #include <cpu/registers.h>
 
@@ -36,46 +35,6 @@ __asm__("gettr       tr0, %1\n\t" \
        : "1" (__dummy)); \
 pc; })
 
-/*
- * TLB information structure
- *
- * Defined for both I and D tlb, per-processor.
- */
-struct tlb_info {
-       unsigned long long next;
-       unsigned long long first;
-       unsigned long long last;
-
-       unsigned int entries;
-       unsigned int step;
-
-       unsigned long flags;
-};
-
-struct sh_cpuinfo {
-       enum cpu_type type;
-       unsigned long loops_per_jiffy;
-       unsigned long asid_cache;
-
-       unsigned int cpu_clock, master_clock, bus_clock, module_clock;
-
-       /* Cache info */
-       struct cache_info icache;
-       struct cache_info dcache;
-       struct cache_info scache;
-
-       /* TLB info */
-       struct tlb_info itlb;
-       struct tlb_info dtlb;
-
-       unsigned long flags;
-};
-
-extern struct sh_cpuinfo cpu_data[];
-#define boot_cpu_data cpu_data[0]
-#define current_cpu_data cpu_data[smp_processor_id()]
-#define raw_current_cpu_data cpu_data[raw_smp_processor_id()]
-
 #endif
 
 /*
@@ -169,8 +128,6 @@ struct thread_struct {
 #define INIT_MMAP \
 { &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
 
-extern  struct pt_regs fake_swapper_regs;
-
 #define INIT_THREAD  {                         \
        .sp             = sizeof(init_stack) +  \
                          (long) &init_stack,   \
@@ -269,6 +226,8 @@ extern unsigned long get_wchan(struct task_struct *p);
 #define KSTK_EIP(tsk)  ((tsk)->thread.pc)
 #define KSTK_ESP(tsk)  ((tsk)->thread.sp)
 
+#define user_stack_pointer(regs)       ((regs)->sp)
+
 #define cpu_relax()    barrier()
 
 #endif /* __ASSEMBLY__ */
index b86aeabba61ae4dd68a5cdf95054365b019eba73..3ad18e91bca61cfab3ac9451c0bbfa394ddc5891 100644 (file)
@@ -87,12 +87,18 @@ struct pt_dspregs {
        unsigned long   mod;
 };
 
+#define PTRACE_GETREGS         12      /* General registers */
+#define PTRACE_SETREGS         13
+
+#define PTRACE_GETFPREGS       14      /* FPU registers */
+#define PTRACE_SETFPREGS       15
+
 #define PTRACE_GETFDPIC                31      /* get the ELF fdpic loadmap address */
 
 #define PTRACE_GETFDPIC_EXEC   0       /* [addr] request the executable loadmap */
 #define PTRACE_GETFDPIC_INTERP 1       /* [addr] request the interpreter loadmap */
 
-#define        PTRACE_GETDSPREGS       55
+#define        PTRACE_GETDSPREGS       55      /* DSP registers */
 #define        PTRACE_SETDSPREGS       56
 #endif
 
@@ -117,6 +123,9 @@ extern void user_disable_single_step(struct task_struct *);
 #define task_pt_regs(task) \
        ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
                 - sizeof(struct pt_dspregs) - sizeof(unsigned long)) - 1)
+#define task_pt_dspregs(task) \
+       ((struct pt_dspregs *) (task_stack_page(task) + THREAD_SIZE \
+                - sizeof(unsigned long)) - 1)
 #else
 #define task_pt_regs(task) \
        ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
index 1813f4202a24f2a5fdb24e0e10b2e0579f69297e..f7b010d48af7b17d8c6dbf475d105f7839f816a5 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _ASM_RTC_H
 #define _ASM_RTC_H
 
+void time_init(void);
 extern void (*board_time_init)(void);
 extern void (*rtc_sh_get_time)(struct timespec *);
 extern int (*rtc_sh_set_time)(const time_t);
index 55a2bd328d990e24abc3e496641bddfd764eb3a7..d450bcf59ee2548c0db6f239ce7f4363941a02f0 100644 (file)
@@ -4,7 +4,6 @@
 #define COMMAND_LINE_SIZE 256
 
 #ifdef __KERNEL__
-
 /*
  * This is set up by the setup-routine at boot-time
  */
diff --git a/arch/sh/include/asm/sizes.h b/arch/sh/include/asm/sizes.h
new file mode 100644 (file)
index 0000000..3a1fb97
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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
+ */
+/* DO NOT EDIT!! - this file automatically generated
+ *                 from .s file by awk -f s2h.awk
+ */
+/*  Size definitions
+ *  Copyright (C) ARM Limited 1998. All rights reserved.
+ */
+
+#ifndef __sizes_h
+#define __sizes_h                       1
+
+/* handy sizes */
+#define SZ_16                          0x00000010
+#define SZ_32                          0x00000020
+#define SZ_64                          0x00000040
+#define SZ_128                         0x00000080
+#define SZ_256                         0x00000100
+#define SZ_512                         0x00000200
+
+#define SZ_1K                           0x00000400
+#define SZ_4K                           0x00001000
+#define SZ_8K                           0x00002000
+#define SZ_16K                          0x00004000
+#define SZ_32K                         0x00008000
+#define SZ_64K                          0x00010000
+#define SZ_128K                         0x00020000
+#define SZ_256K                         0x00040000
+#define SZ_512K                         0x00080000
+
+#define SZ_1M                           0x00100000
+#define SZ_2M                           0x00200000
+#define SZ_4M                           0x00400000
+#define SZ_8M                           0x00800000
+#define SZ_16M                          0x01000000
+#define SZ_26M                         0x01a00000
+#define SZ_32M                          0x02000000
+#define SZ_64M                          0x04000000
+#define SZ_128M                         0x08000000
+#define SZ_256M                         0x10000000
+#define SZ_512M                         0x20000000
+
+#define SZ_1G                           0x40000000
+#define SZ_2G                           0x80000000
+
+#endif
+
+/*         END */
index 593343cd26ee02e6ab584d23e8516ce9e8645d53..85b660c17eb070e230b7ce3e0dcac1c7f7ab27c8 100644 (file)
@@ -21,25 +21,29 @@ extern int __cpu_number_map[NR_CPUS];
 extern int __cpu_logical_map[NR_CPUS];
 #define cpu_logical_map(cpu)  __cpu_logical_map[cpu]
 
-/* I've no idea what the real meaning of this is */
-#define PROC_CHANGE_PENALTY    20
+enum {
+       SMP_MSG_FUNCTION,
+       SMP_MSG_RESCHEDULE,
+       SMP_MSG_FUNCTION_SINGLE,
+       SMP_MSG_TIMER,
 
-#define NO_PROC_ID     (-1)
+       SMP_MSG_NR,     /* must be last */
+};
 
-#define SMP_MSG_FUNCTION       0
-#define SMP_MSG_RESCHEDULE     1
-#define SMP_MSG_FUNCTION_SINGLE        2
-#define SMP_MSG_NR             3
+void smp_message_recv(unsigned int msg);
+void smp_timer_broadcast(cpumask_t mask);
+
+void local_timer_interrupt(void);
+void local_timer_setup(unsigned int cpu);
 
 void plat_smp_setup(void);
 void plat_prepare_cpus(unsigned int max_cpus);
 int plat_smp_processor_id(void);
 void plat_start_cpu(unsigned int cpu, unsigned long entry_point);
 void plat_send_ipi(unsigned int cpu, unsigned int message);
-int plat_register_ipi_handler(unsigned int message,
-                             void (*handler)(void *), void *arg);
-extern void arch_send_call_function_single_ipi(int cpu);
-extern void arch_send_call_function_ipi(cpumask_t mask);
+
+void arch_send_call_function_single_ipi(int cpu);
+void arch_send_call_function_ipi(cpumask_t mask);
 
 #else
 
diff --git a/arch/sh/include/asm/syscall.h b/arch/sh/include/asm/syscall.h
new file mode 100644 (file)
index 0000000..6a38142
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __ASM_SH_SYSCALL_H
+#define __ASM_SH_SYSCALL_H
+
+#ifdef CONFIG_SUPERH32
+# include "syscall_32.h"
+#else
+# include "syscall_64.h"
+#endif
+
+#endif /* __ASM_SH_SYSCALL_H */
diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h
new file mode 100644 (file)
index 0000000..54773f2
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __ASM_SH_SYSCALL_32_H
+#define __ASM_SH_SYSCALL_32_H
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/ptrace.h>
+
+/* The system call number is given by the user in %g1 */
+static inline long syscall_get_nr(struct task_struct *task,
+                                 struct pt_regs *regs)
+{
+       return (regs->tra >= 0) ? regs->regs[3] : -1L;
+}
+
+static inline void syscall_rollback(struct task_struct *task,
+                                   struct pt_regs *regs)
+{
+       /*
+        * XXX: This needs some thought. On SH we don't
+        * save away the original r0 value anywhere.
+        */
+}
+
+static inline bool syscall_has_error(struct pt_regs *regs)
+{
+       return (regs->sr & 0x1) ? true : false;
+}
+static inline void syscall_set_error(struct pt_regs *regs)
+{
+       regs->sr |= 0x1;
+}
+static inline void syscall_clear_error(struct pt_regs *regs)
+{
+       regs->sr &= ~0x1;
+}
+
+static inline long syscall_get_error(struct task_struct *task,
+                                    struct pt_regs *regs)
+{
+       return syscall_has_error(regs) ? regs->regs[0] : 0;
+}
+
+static inline long syscall_get_return_value(struct task_struct *task,
+                                           struct pt_regs *regs)
+{
+       return regs->regs[0];
+}
+
+static inline void syscall_set_return_value(struct task_struct *task,
+                                           struct pt_regs *regs,
+                                           int error, long val)
+{
+       if (error) {
+               syscall_set_error(regs);
+               regs->regs[0] = -error;
+       } else {
+               syscall_clear_error(regs);
+               regs->regs[0] = val;
+       }
+}
+
+static inline void syscall_get_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        unsigned long *args)
+{
+       /*
+        * Do this simply for now. If we need to start supporting
+        * fetching arguments from arbitrary indices, this will need some
+        * extra logic. Presently there are no in-tree users that depend
+        * on this behaviour.
+        */
+       BUG_ON(i);
+
+       /* Argument pattern is: R4, R5, R6, R7, R0, R1 */
+       switch (n) {
+       case 6: args[5] = regs->regs[1];
+       case 5: args[4] = regs->regs[0];
+       case 4: args[3] = regs->regs[7];
+       case 3: args[2] = regs->regs[6];
+       case 2: args[1] = regs->regs[5];
+       case 1: args[0] = regs->regs[4];
+               break;
+       default:
+               BUG();
+       }
+}
+
+static inline void syscall_set_arguments(struct task_struct *task,
+                                        struct pt_regs *regs,
+                                        unsigned int i, unsigned int n,
+                                        const unsigned long *args)
+{
+       /* Same note as above applies */
+       BUG_ON(i);
+
+       switch (n) {
+       case 6: regs->regs[1] = args[5];
+       case 5: regs->regs[0] = args[4];
+       case 4: regs->regs[7] = args[3];
+       case 3: regs->regs[6] = args[2];
+       case 2: regs->regs[5] = args[1];
+       case 1: regs->regs[4] = args[0];
+               break;
+       default:
+               BUG();
+       }
+}
+
+#endif /* __ASM_SH_SYSCALL_32_H */
diff --git a/arch/sh/include/asm/syscall_64.h b/arch/sh/include/asm/syscall_64.h
new file mode 100644 (file)
index 0000000..bcaaa8c
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __ASM_SH_SYSCALL_64_H
+#define __ASM_SH_SYSCALL_64_H
+
+#include <asm-generic/syscall.h>
+
+#endif /* __ASM_SH_SYSCALL_64_H */
diff --git a/arch/sh/include/asm/syscalls.h b/arch/sh/include/asm/syscalls.h
new file mode 100644 (file)
index 0000000..c1e2b8d
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ASM_SH_SYSCALLS_H
+#define __ASM_SH_SYSCALLS_H
+
+#ifdef __KERNEL__
+
+struct old_utsname;
+
+asmlinkage int old_mmap(unsigned long addr, unsigned long len,
+                       unsigned long prot, unsigned long flags,
+                       int fd, unsigned long off);
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+                         unsigned long prot, unsigned long flags,
+                         unsigned long fd, unsigned long pgoff);
+asmlinkage int sys_ipc(uint call, int first, int second,
+                      int third, void __user *ptr, long fifth);
+asmlinkage int sys_uname(struct old_utsname __user *name);
+
+#ifdef CONFIG_SUPERH32
+# include "syscalls_32.h"
+#else
+# include "syscalls_64.h"
+#endif
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_SYSCALLS_H */
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h
new file mode 100644 (file)
index 0000000..104c5e6
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __ASM_SH_SYSCALLS_32_H
+#define __ASM_SH_SYSCALLS_32_H
+
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+
+struct pt_regs;
+
+asmlinkage int sys_fork(unsigned long r4, unsigned long r5,
+                       unsigned long r6, unsigned long r7,
+                       struct pt_regs __regs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+                        unsigned long parent_tidptr,
+                        unsigned long child_tidptr,
+                        struct pt_regs __regs);
+asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,
+                        unsigned long r6, unsigned long r7,
+                        struct pt_regs __regs);
+asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv,
+                         char __user * __user *uenvp, unsigned long r7,
+                         struct pt_regs __regs);
+asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
+                             unsigned long r6, unsigned long r7,
+                             struct pt_regs __regs);
+asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
+                            struct old_sigaction __user *oact);
+asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
+                              unsigned long r6, unsigned long r7,
+                              struct pt_regs __regs);
+asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
+                            unsigned long r6, unsigned long r7,
+                            struct pt_regs __regs);
+asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
+                       unsigned long r6, unsigned long r7,
+                       struct pt_regs __regs);
+asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char __user *buf,
+                                    size_t count, long dummy, loff_t pos);
+asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char __user *buf,
+                                     size_t count, long dummy, loff_t pos);
+asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1,
+                                       u32 len0, u32 len1, int advice);
+
+/* Misc syscall related bits */
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
+asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);
+asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
+                                unsigned long thread_info_flags);
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_SYSCALLS_32_H */
diff --git a/arch/sh/include/asm/syscalls_64.h b/arch/sh/include/asm/syscalls_64.h
new file mode 100644 (file)
index 0000000..751fd88
--- /dev/null
@@ -0,0 +1,34 @@
+#ifndef __ASM_SH_SYSCALLS_64_H
+#define __ASM_SH_SYSCALLS_64_H
+
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <linux/linkage.h>
+#include <linux/types.h>
+
+struct pt_regs;
+
+asmlinkage int sys_fork(unsigned long r2, unsigned long r3,
+                       unsigned long r4, unsigned long r5,
+                       unsigned long r6, unsigned long r7,
+                       struct pt_regs *pregs);
+asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
+                        unsigned long r4, unsigned long r5,
+                        unsigned long r6, unsigned long r7,
+                        struct pt_regs *pregs);
+asmlinkage int sys_vfork(unsigned long r2, unsigned long r3,
+                        unsigned long r4, unsigned long r5,
+                        unsigned long r6, unsigned long r7,
+                        struct pt_regs *pregs);
+asmlinkage int sys_execve(char *ufilename, char **uargv,
+                         char **uenvp, unsigned long r5,
+                         unsigned long r6, unsigned long r7,
+                         struct pt_regs *pregs);
+
+/* Misc syscall related bits */
+asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs);
+asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_SH_SYSCALLS_64_H */
index 056d68cd21080e36b4e4a1ad56952751592b8a12..6160fe445161e12071f6daeabbca709350563da2 100644 (file)
@@ -70,6 +70,8 @@
 
 #ifdef CONFIG_GUSA_RB
 #include <asm/cmpxchg-grb.h>
+#elif defined(CONFIG_CPU_SH4A)
+#include <asm/cmpxchg-llsc.h>
 #else
 #include <asm/cmpxchg-irq.h>
 #endif
@@ -125,6 +127,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
   })
 
 extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+void free_initmem(void);
+void free_initrd_mem(unsigned long start, unsigned long end);
 
 extern void *set_exception_table_vec(unsigned int vec, void *handler);
 
@@ -177,8 +181,8 @@ BUILD_TRAP_HANDLER(fpu_state_restore);
 #define arch_align_stack(x) (x)
 
 struct mem_access {
-       unsigned long (*from)(void *dst, const void *src, unsigned long cnt);
-       unsigned long (*to)(void *dst, const void *src, unsigned long cnt);
+       unsigned long (*from)(void *dst, const void __user *src, unsigned long cnt);
+       unsigned long (*to)(void __user *dst, const void *src, unsigned long cnt);
 };
 
 #ifdef CONFIG_SUPERH32
index f11bcf0855ed59b7c5bdd521eccfd73b2416ad3a..a726d5d07277a6d53e91b90d743201c10f4fd52d 100644 (file)
@@ -58,7 +58,8 @@ do {                                                                  \
        last = __last;                                                  \
 } while (0)
 
-#define __uses_jump_to_uncached __attribute__ ((__section__ (".uncached.text")))
+#define __uses_jump_to_uncached \
+       noinline __attribute__ ((__section__ (".uncached.text")))
 
 /*
  * Jump to uncached area.
@@ -96,7 +97,48 @@ do {                                                 \
                : "=&r" (__dummy));                     \
 } while (0)
 
+#ifdef CONFIG_CPU_HAS_SR_RB
+#define lookup_exception_vector()      \
+({                                     \
+       unsigned long _vec;             \
+                                       \
+       __asm__ __volatile__ (          \
+               "stc r2_bank, %0\n\t"   \
+               : "=r" (_vec)           \
+       );                              \
+                                       \
+       _vec;                           \
+})
+#else
+#define lookup_exception_vector()      \
+({                                     \
+       unsigned long _vec;             \
+       __asm__ __volatile__ (          \
+               "mov r4, %0\n\t"        \
+               : "=r" (_vec)           \
+       );                              \
+                                       \
+       _vec;                           \
+})
+#endif
+
 int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
                            struct mem_access *ma);
 
+asmlinkage void do_address_error(struct pt_regs *regs,
+                                unsigned long writeaccess,
+                                unsigned long address);
+asmlinkage void do_divide_error(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
+                               unsigned long r6, unsigned long r7,
+                               struct pt_regs __regs);
+asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
+                                  unsigned long r6, unsigned long r7,
+                                  struct pt_regs __regs);
+
 #endif /* __ASM_SH_SYSTEM_32_H */
index 0a894cafb1ddcbc43b40303b62db4678d272ea72..f09ac4806294007a883b0a472ed2d6654a7ef19f 100644 (file)
@@ -33,20 +33,12 @@ struct thread_info {
 #define PREEMPT_ACTIVE         0x10000000
 
 #if defined(CONFIG_4KSTACKS)
-#define THREAD_SIZE_ORDER      (0)
-#elif defined(CONFIG_PAGE_SIZE_4KB)
-#define THREAD_SIZE_ORDER      (1)
-#elif defined(CONFIG_PAGE_SIZE_8KB)
-#define THREAD_SIZE_ORDER      (1)
-#elif defined(CONFIG_PAGE_SIZE_16KB)
-#define THREAD_SIZE_ORDER      (0)
-#elif defined(CONFIG_PAGE_SIZE_64KB)
-#define THREAD_SIZE_ORDER      (0)
+#define THREAD_SHIFT   12
 #else
-#error "Unknown thread size"
+#define THREAD_SHIFT   13
 #endif
 
-#define THREAD_SIZE    (PAGE_SIZE << THREAD_SIZE_ORDER)
+#define THREAD_SIZE    (1 << THREAD_SHIFT)
 #define STACK_WARN     (THREAD_SIZE >> 3)
 
 /*
@@ -94,15 +86,19 @@ static inline struct thread_info *current_thread_info(void)
        return ti;
 }
 
+/* thread information allocation */
+#if THREAD_SHIFT >= PAGE_SHIFT
+
+#define THREAD_SIZE_ORDER      (THREAD_SHIFT - PAGE_SHIFT)
+
+#else /* THREAD_SHIFT < PAGE_SHIFT */
+
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
-/* thread information allocation */
-#ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(ti)  kzalloc(THREAD_SIZE, GFP_KERNEL)
-#else
-#define alloc_thread_info(ti)  kmalloc(THREAD_SIZE, GFP_KERNEL)
-#endif
-#define free_thread_info(ti)   kfree(ti)
+extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
+extern void free_thread_info(struct thread_info *ti);
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
 
 #endif /* __ASSEMBLY__ */
 
index 5580fd471003e156b843df49f3eec236471e7335..56fd20b8cdcc16db8fbe6da757da62dec0d1d4d9 100644 (file)
@@ -26,16 +26,20 @@ do {                                                                \
        retval = 0;                                             \
        switch (size) {                                         \
        case 1:                                                 \
-               retval = __get_user_asm_b(x, ptr);              \
+               retval = __get_user_asm_b((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        case 2:                                                 \
-               retval = __get_user_asm_w(x, ptr);              \
+               retval = __get_user_asm_w((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        case 4:                                                 \
-               retval = __get_user_asm_l(x, ptr);              \
+               retval = __get_user_asm_l((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        case 8:                                                 \
-               retval = __get_user_asm_q(x, ptr);              \
+               retval = __get_user_asm_q((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        default:                                                \
                __get_user_unknown();                           \
@@ -54,16 +58,20 @@ do {                                                                \
        retval = 0;                                             \
        switch (size) {                                         \
        case 1:                                                 \
-               retval = __put_user_asm_b(x, ptr);              \
+               retval = __put_user_asm_b((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        case 2:                                                 \
-               retval = __put_user_asm_w(x, ptr);              \
+               retval = __put_user_asm_w((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        case 4:                                                 \
-               retval = __put_user_asm_l(x, ptr);              \
+               retval = __put_user_asm_l((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        case 8:                                                 \
-               retval = __put_user_asm_q(x, ptr);              \
+               retval = __put_user_asm_q((void *)&x,           \
+                                         (long)ptr);           \
                break;                                          \
        default:                                                \
                __put_user_unknown();                           \
@@ -77,5 +85,7 @@ extern long __put_user_asm_q(void *, long);
 extern void __put_user_unknown(void);
 
 extern long __strnlen_user(const char *__s, long __n);
+extern int __strncpy_from_user(unsigned long __dest,
+              unsigned long __user __src, int __count);
 
 #endif /* __ASM_SH_UACCESS_64_H */
diff --git a/arch/sh/include/cpu-sh2a/cpu/sh7203.h b/arch/sh/include/cpu-sh2a/cpu/sh7203.h
new file mode 100644 (file)
index 0000000..79f9315
--- /dev/null
@@ -0,0 +1,143 @@
+#ifndef __ASM_SH7203_H__
+#define __ASM_SH7203_H__
+
+enum {
+       /* PA */
+       GPIO_PA7, GPIO_PA6, GPIO_PA5, GPIO_PA4,
+       GPIO_PA3, GPIO_PA2, GPIO_PA1, GPIO_PA0,
+
+       /* PB */
+       GPIO_PB12,
+       GPIO_PB11, GPIO_PB10, GPIO_PB9, GPIO_PB8,
+       GPIO_PB7, GPIO_PB6, GPIO_PB5, GPIO_PB4,
+       GPIO_PB3, GPIO_PB2, GPIO_PB1, GPIO_PB0,
+
+       /* PC */
+       GPIO_PC14, GPIO_PC13, GPIO_PC12,
+       GPIO_PC11, GPIO_PC10, GPIO_PC9, GPIO_PC8,
+       GPIO_PC7, GPIO_PC6, GPIO_PC5, GPIO_PC4,
+       GPIO_PC3, GPIO_PC2, GPIO_PC1, GPIO_PC0,
+
+       /* PD */
+       GPIO_PD15, GPIO_PD14, GPIO_PD13, GPIO_PD12,
+       GPIO_PD11, GPIO_PD10, GPIO_PD9, GPIO_PD8,
+       GPIO_PD7, GPIO_PD6, GPIO_PD5, GPIO_PD4,
+       GPIO_PD3, GPIO_PD2, GPIO_PD1, GPIO_PD0,
+
+       /* PE */
+       GPIO_PE15, GPIO_PE14, GPIO_PE13, GPIO_PE12,
+       GPIO_PE11, GPIO_PE10, GPIO_PE9, GPIO_PE8,
+       GPIO_PE7, GPIO_PE6, GPIO_PE5, GPIO_PE4,
+       GPIO_PE3, GPIO_PE2, GPIO_PE1, GPIO_PE0,
+
+       /* PF */
+       GPIO_PF30, GPIO_PF29, GPIO_PF28,
+       GPIO_PF27, GPIO_PF26, GPIO_PF25, GPIO_PF24,
+       GPIO_PF23, GPIO_PF22, GPIO_PF21, GPIO_PF20,
+       GPIO_PF19, GPIO_PF18, GPIO_PF17, GPIO_PF16,
+       GPIO_PF15, GPIO_PF14, GPIO_PF13, GPIO_PF12,
+       GPIO_PF11, GPIO_PF10, GPIO_PF9, GPIO_PF8,
+       GPIO_PF7, GPIO_PF6, GPIO_PF5, GPIO_PF4,
+       GPIO_PF3, GPIO_PF2, GPIO_PF1, GPIO_PF0,
+
+       /* INTC: IRQ and PINT on PB/PD/PE */
+       GPIO_FN_PINT7_PB, GPIO_FN_PINT6_PB, GPIO_FN_PINT5_PB, GPIO_FN_PINT4_PB,
+       GPIO_FN_PINT3_PB, GPIO_FN_PINT2_PB, GPIO_FN_PINT1_PB, GPIO_FN_PINT0_PB,
+       GPIO_FN_PINT7_PD, GPIO_FN_PINT6_PD, GPIO_FN_PINT5_PD, GPIO_FN_PINT4_PD,
+       GPIO_FN_PINT3_PD, GPIO_FN_PINT2_PD, GPIO_FN_PINT1_PD, GPIO_FN_PINT0_PD,
+       GPIO_FN_IRQ7_PB, GPIO_FN_IRQ6_PB, GPIO_FN_IRQ5_PB, GPIO_FN_IRQ4_PB,
+       GPIO_FN_IRQ3_PB, GPIO_FN_IRQ2_PB, GPIO_FN_IRQ1_PB, GPIO_FN_IRQ0_PB,
+       GPIO_FN_IRQ7_PD, GPIO_FN_IRQ6_PD, GPIO_FN_IRQ5_PD, GPIO_FN_IRQ4_PD,
+       GPIO_FN_IRQ3_PD, GPIO_FN_IRQ2_PD, GPIO_FN_IRQ1_PD, GPIO_FN_IRQ0_PD,
+       GPIO_FN_IRQ7_PE, GPIO_FN_IRQ6_PE, GPIO_FN_IRQ5_PE, GPIO_FN_IRQ4_PE,
+       GPIO_FN_IRQ3_PE, GPIO_FN_IRQ2_PE, GPIO_FN_IRQ1_PE, GPIO_FN_IRQ0_PE,
+
+       GPIO_FN_WDTOVF, GPIO_FN_IRQOUT, GPIO_FN_REFOUT, GPIO_FN_IRQOUT_REFOUT,
+       GPIO_FN_UBCTRG,
+
+       /* CAN */
+       GPIO_FN_CTX1, GPIO_FN_CRX1, GPIO_FN_CTX0, GPIO_FN_CTX0_CTX1,
+       GPIO_FN_CRX0, GPIO_FN_CRX0_CRX1,
+
+       /* IIC3 */
+       GPIO_FN_SDA3, GPIO_FN_SCL3,
+       GPIO_FN_SDA2, GPIO_FN_SCL2,
+       GPIO_FN_SDA1, GPIO_FN_SCL1,
+       GPIO_FN_SDA0, GPIO_FN_SCL0,
+
+       /* DMAC */
+       GPIO_FN_TEND0_PD, GPIO_FN_TEND0_PE, GPIO_FN_DACK0_PD,
+       GPIO_FN_DACK0_PE, GPIO_FN_DREQ0_PD, GPIO_FN_DREQ0_PE,
+       GPIO_FN_TEND1_PD, GPIO_FN_TEND1_PE, GPIO_FN_DACK1_PD,
+       GPIO_FN_DACK1_PE, GPIO_FN_DREQ1_PD, GPIO_FN_DREQ1_PE,
+       GPIO_FN_DACK2, GPIO_FN_DREQ2,
+       GPIO_FN_DACK3, GPIO_FN_DREQ3,
+
+       /* ADC */
+       GPIO_FN_ADTRG_PD, GPIO_FN_ADTRG_PE,
+
+       /* BSC */
+       GPIO_FN_D31, GPIO_FN_D30, GPIO_FN_D29, GPIO_FN_D28,
+       GPIO_FN_D27, GPIO_FN_D26, GPIO_FN_D25, GPIO_FN_D24,
+       GPIO_FN_D23, GPIO_FN_D22, GPIO_FN_D21, GPIO_FN_D20,
+       GPIO_FN_D19, GPIO_FN_D18, GPIO_FN_D17, GPIO_FN_D16,
+       GPIO_FN_A25, GPIO_FN_A24, GPIO_FN_A23, GPIO_FN_A22,
+       GPIO_FN_A21, GPIO_FN_CS4, GPIO_FN_MRES, GPIO_FN_BS,
+       GPIO_FN_IOIS16, GPIO_FN_CS1, GPIO_FN_CS6_CE1B,
+       GPIO_FN_CE2B, GPIO_FN_CS5_CE1A, GPIO_FN_CE2A,
+       GPIO_FN_FRAME, GPIO_FN_WAIT, GPIO_FN_RDWR,
+       GPIO_FN_CKE, GPIO_FN_CASU, GPIO_FN_BREQ, GPIO_FN_RASU,
+       GPIO_FN_BACK, GPIO_FN_CASL, GPIO_FN_RASL,
+       GPIO_FN_WE3_DQMUU_AH_ICIO_WR, GPIO_FN_WE2_DQMUL_ICIORD,
+       GPIO_FN_WE1_DQMLU_WE, GPIO_FN_WE0_DQMLL,
+       GPIO_FN_CS3, GPIO_FN_CS2, GPIO_FN_A1, GPIO_FN_A0, GPIO_FN_CS7,
+
+       /* TMU */
+       GPIO_FN_TIOC4D, GPIO_FN_TIOC4C, GPIO_FN_TIOC4B, GPIO_FN_TIOC4A,
+       GPIO_FN_TIOC3D, GPIO_FN_TIOC3C, GPIO_FN_TIOC3B, GPIO_FN_TIOC3A,
+       GPIO_FN_TIOC2B, GPIO_FN_TIOC1B, GPIO_FN_TIOC2A, GPIO_FN_TIOC1A,
+       GPIO_FN_TIOC0D, GPIO_FN_TIOC0C, GPIO_FN_TIOC0B, GPIO_FN_TIOC0A,
+       GPIO_FN_TCLKD_PD, GPIO_FN_TCLKC_PD, GPIO_FN_TCLKB_PD, GPIO_FN_TCLKA_PD,
+       GPIO_FN_TCLKD_PF, GPIO_FN_TCLKC_PF, GPIO_FN_TCLKB_PF, GPIO_FN_TCLKA_PF,
+
+       /* SSU */
+       GPIO_FN_SCS0_PD, GPIO_FN_SSO0_PD, GPIO_FN_SSI0_PD, GPIO_FN_SSCK0_PD,
+       GPIO_FN_SCS0_PF, GPIO_FN_SSO0_PF, GPIO_FN_SSI0_PF, GPIO_FN_SSCK0_PF,
+       GPIO_FN_SCS1_PD, GPIO_FN_SSO1_PD, GPIO_FN_SSI1_PD, GPIO_FN_SSCK1_PD,
+       GPIO_FN_SCS1_PF, GPIO_FN_SSO1_PF, GPIO_FN_SSI1_PF, GPIO_FN_SSCK1_PF,
+
+       /* SCIF */
+       GPIO_FN_TXD0, GPIO_FN_RXD0, GPIO_FN_SCK0,
+       GPIO_FN_TXD1, GPIO_FN_RXD1, GPIO_FN_SCK1,
+       GPIO_FN_TXD2, GPIO_FN_RXD2, GPIO_FN_SCK2,
+       GPIO_FN_RTS3, GPIO_FN_CTS3, GPIO_FN_TXD3, GPIO_FN_RXD3, GPIO_FN_SCK3,
+
+       /* SSI */
+       GPIO_FN_AUDIO_CLK,
+       GPIO_FN_SSIDATA3, GPIO_FN_SSIWS3, GPIO_FN_SSISCK3,
+       GPIO_FN_SSIDATA2, GPIO_FN_SSIWS2, GPIO_FN_SSISCK2,
+       GPIO_FN_SSIDATA1, GPIO_FN_SSIWS1, GPIO_FN_SSISCK1,
+       GPIO_FN_SSIDATA0, GPIO_FN_SSIWS0, GPIO_FN_SSISCK0,
+
+       /* FLCTL */
+       GPIO_FN_FCE, GPIO_FN_FRB,
+       GPIO_FN_NAF7, GPIO_FN_NAF6, GPIO_FN_NAF5, GPIO_FN_NAF4,
+       GPIO_FN_NAF3, GPIO_FN_NAF2, GPIO_FN_NAF1, GPIO_FN_NAF0,
+       GPIO_FN_FSC, GPIO_FN_FOE, GPIO_FN_FCDE, GPIO_FN_FWE,
+
+       /* LCDC */
+       GPIO_FN_LCD_VEPWC, GPIO_FN_LCD_VCPWC,
+       GPIO_FN_LCD_CLK, GPIO_FN_LCD_FLM,
+       GPIO_FN_LCD_M_DISP, GPIO_FN_LCD_CL2,
+       GPIO_FN_LCD_CL1, GPIO_FN_LCD_DON,
+       GPIO_FN_LCD_DATA15, GPIO_FN_LCD_DATA14,
+       GPIO_FN_LCD_DATA13, GPIO_FN_LCD_DATA12,
+       GPIO_FN_LCD_DATA11, GPIO_FN_LCD_DATA10,
+       GPIO_FN_LCD_DATA9, GPIO_FN_LCD_DATA8,
+       GPIO_FN_LCD_DATA7, GPIO_FN_LCD_DATA6,
+       GPIO_FN_LCD_DATA5, GPIO_FN_LCD_DATA4,
+       GPIO_FN_LCD_DATA3, GPIO_FN_LCD_DATA2,
+       GPIO_FN_LCD_DATA1, GPIO_FN_LCD_DATA0,
+};
+
+#endif /* __ASM_SH7203_H__ */
diff --git a/arch/sh/include/cpu-sh3/cpu/sh7720.h b/arch/sh/include/cpu-sh3/cpu/sh7720.h
new file mode 100644 (file)
index 0000000..41c1406
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef __ASM_SH7720_H__
+#define __ASM_SH7720_H__
+
+enum {
+       /* PTA */
+       GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
+       GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+
+       /* PTB */
+       GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
+       GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+
+       /* PTC */
+       GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4,
+       GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0,
+
+       /* PTD */
+       GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
+       GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+
+       /* PTE */
+       GPIO_PTE6, GPIO_PTE5, GPIO_PTE4, GPIO_PTE3,
+       GPIO_PTE2, GPIO_PTE1, GPIO_PTE0,
+
+       /* PTF */
+       GPIO_PTF6, GPIO_PTF5, GPIO_PTF4, GPIO_PTF3,
+       GPIO_PTF2, GPIO_PTF1, GPIO_PTF0, GPIO_PTG6,
+
+       /* PTG */
+       GPIO_PTG5, GPIO_PTG4, GPIO_PTG3, GPIO_PTG2,
+       GPIO_PTG1, GPIO_PTG0,
+
+       /* PTH */
+       GPIO_PTH6, GPIO_PTH5, GPIO_PTH4, GPIO_PTH3,
+       GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+
+       /* PTJ */
+       GPIO_PTJ6, GPIO_PTJ5, GPIO_PTJ4, GPIO_PTJ3,
+       GPIO_PTJ2, GPIO_PTJ1, GPIO_PTJ0,
+
+       /* PTK */
+       GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+
+       /* PTL */
+       GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4, GPIO_PTL3,
+
+       /* PTM */
+       GPIO_PTM7, GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
+       GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+
+       /* PTP */
+       GPIO_PTP4, GPIO_PTP3, GPIO_PTP2, GPIO_PTP1, GPIO_PTP0,
+
+       /* PTR */
+       GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4,
+       GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+
+       /* PTS */
+       GPIO_PTS4, GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+
+       /* PTT */
+       GPIO_PTT4, GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0,
+
+       /* PTU */
+       GPIO_PTU4, GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0,
+
+       /* PTV */
+       GPIO_PTV4, GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+
+       /* BSC */
+       GPIO_FN_D31, GPIO_FN_D30, GPIO_FN_D29, GPIO_FN_D28,
+       GPIO_FN_D27, GPIO_FN_D26, GPIO_FN_D25, GPIO_FN_D24,
+       GPIO_FN_D23, GPIO_FN_D22, GPIO_FN_D21, GPIO_FN_D20,
+       GPIO_FN_D19, GPIO_FN_D18, GPIO_FN_D17, GPIO_FN_D16,
+       GPIO_FN_IOIS16, GPIO_FN_RAS, GPIO_FN_CAS, GPIO_FN_CKE,
+       GPIO_FN_CS5B_CE1A, GPIO_FN_CS6B_CE1B,
+       GPIO_FN_A25, GPIO_FN_A24, GPIO_FN_A23, GPIO_FN_A22,
+       GPIO_FN_A21, GPIO_FN_A20, GPIO_FN_A19, GPIO_FN_A0,
+       GPIO_FN_REFOUT, GPIO_FN_IRQOUT,
+
+       /* LCDC */
+       GPIO_FN_LCD_DATA15, GPIO_FN_LCD_DATA14,
+       GPIO_FN_LCD_DATA13, GPIO_FN_LCD_DATA12,
+       GPIO_FN_LCD_DATA11, GPIO_FN_LCD_DATA10,
+       GPIO_FN_LCD_DATA9, GPIO_FN_LCD_DATA8,
+       GPIO_FN_LCD_DATA7, GPIO_FN_LCD_DATA6,
+       GPIO_FN_LCD_DATA5, GPIO_FN_LCD_DATA4,
+       GPIO_FN_LCD_DATA3, GPIO_FN_LCD_DATA2,
+       GPIO_FN_LCD_DATA1, GPIO_FN_LCD_DATA0,
+       GPIO_FN_LCD_M_DISP,
+       GPIO_FN_LCD_CL1, GPIO_FN_LCD_CL2,
+       GPIO_FN_LCD_DON, GPIO_FN_LCD_FLM,
+       GPIO_FN_LCD_VEPWC, GPIO_FN_LCD_VCPWC,
+
+       /* AFEIF */
+       GPIO_FN_AFE_RXIN, GPIO_FN_AFE_RDET,
+       GPIO_FN_AFE_FS, GPIO_FN_AFE_TXOUT,
+       GPIO_FN_AFE_SCLK, GPIO_FN_AFE_RLYCNT,
+       GPIO_FN_AFE_HC1,
+
+       /* IIC */
+       GPIO_FN_IIC_SCL, GPIO_FN_IIC_SDA,
+
+       /* DAC */
+       GPIO_FN_DA1, GPIO_FN_DA0,
+
+       /* ADC */
+       GPIO_FN_AN3, GPIO_FN_AN2, GPIO_FN_AN1, GPIO_FN_AN0, GPIO_FN_ADTRG,
+
+       /* USB */
+       GPIO_FN_USB1D_RCV, GPIO_FN_USB1D_TXSE0,
+       GPIO_FN_USB1D_TXDPLS, GPIO_FN_USB1D_DMNS,
+       GPIO_FN_USB1D_DPLS, GPIO_FN_USB1D_SPEED,
+       GPIO_FN_USB1D_TXENL, GPIO_FN_USB2_PWR_EN,
+       GPIO_FN_USB1_PWR_EN_USBF_UPLUP, GPIO_FN_USB1D_SUSPEND,
+
+       /* INTC */
+       GPIO_FN_IRQ5, GPIO_FN_IRQ4,
+       GPIO_FN_IRQ3_IRL3, GPIO_FN_IRQ2_IRL2,
+       GPIO_FN_IRQ1_IRL1, GPIO_FN_IRQ0_IRL0,
+
+       /* PCC */
+       GPIO_FN_PCC_REG, GPIO_FN_PCC_DRV,
+       GPIO_FN_PCC_BVD2, GPIO_FN_PCC_BVD1,
+       GPIO_FN_PCC_CD2, GPIO_FN_PCC_CD1,
+       GPIO_FN_PCC_RESET, GPIO_FN_PCC_RDY,
+       GPIO_FN_PCC_VS2, GPIO_FN_PCC_VS1,
+
+       /* HUDI */
+       GPIO_FN_AUDATA3, GPIO_FN_AUDATA2, GPIO_FN_AUDATA1, GPIO_FN_AUDATA0,
+       GPIO_FN_AUDCK, GPIO_FN_AUDSYNC, GPIO_FN_ASEBRKAK, GPIO_FN_TRST,
+       GPIO_FN_TMS, GPIO_FN_TDO, GPIO_FN_TDI, GPIO_FN_TCK,
+
+       /* DMAC */
+       GPIO_FN_DACK1, GPIO_FN_DREQ1, GPIO_FN_DACK0, GPIO_FN_DREQ0,
+       GPIO_FN_TEND1, GPIO_FN_TEND0,
+
+       /* SIOF0 */
+       GPIO_FN_SIOF0_SYNC, GPIO_FN_SIOF0_MCLK,
+       GPIO_FN_SIOF0_TXD, GPIO_FN_SIOF0_RXD,
+       GPIO_FN_SIOF0_SCK,
+
+       /* SIOF1 */
+       GPIO_FN_SIOF1_SYNC, GPIO_FN_SIOF1_MCLK,
+       GPIO_FN_SIOF1_TXD, GPIO_FN_SIOF1_RXD,
+       GPIO_FN_SIOF1_SCK,
+
+       /* SCIF0 */
+       GPIO_FN_SCIF0_TXD, GPIO_FN_SCIF0_RXD,
+       GPIO_FN_SCIF0_RTS, GPIO_FN_SCIF0_CTS, GPIO_FN_SCIF0_SCK,
+
+       /* SCIF1 */
+       GPIO_FN_SCIF1_TXD, GPIO_FN_SCIF1_RXD,
+       GPIO_FN_SCIF1_RTS, GPIO_FN_SCIF1_CTS, GPIO_FN_SCIF1_SCK,
+
+       /* TPU */
+       GPIO_FN_TPU_TO1, GPIO_FN_TPU_TO0,
+       GPIO_FN_TPU_TI3B, GPIO_FN_TPU_TI3A,
+       GPIO_FN_TPU_TI2B, GPIO_FN_TPU_TI2A,
+       GPIO_FN_TPU_TO3, GPIO_FN_TPU_TO2,
+
+       /* SIM */
+       GPIO_FN_SIM_D, GPIO_FN_SIM_CLK, GPIO_FN_SIM_RST,
+
+       /* MMC */
+       GPIO_FN_MMC_DAT, GPIO_FN_MMC_CMD,
+       GPIO_FN_MMC_CLK, GPIO_FN_MMC_VDDON,
+       GPIO_FN_MMC_ODMOD,
+
+       /* SYSC */
+       GPIO_FN_STATUS0, GPIO_FN_STATUS1,
+};
+
+#endif /* __ASM_SH7720_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7722.h b/arch/sh/include/cpu-sh4/cpu/sh7722.h
new file mode 100644 (file)
index 0000000..4b3096f
--- /dev/null
@@ -0,0 +1,210 @@
+#ifndef __ASM_SH7722_H__
+#define __ASM_SH7722_H__
+
+enum {
+       /* PTA */
+       GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
+       GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+
+       /* PTB */
+       GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
+       GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+
+       /* PTC */
+       GPIO_PTC7, GPIO_PTC5, GPIO_PTC4, GPIO_PTC3,
+       GPIO_PTC2, GPIO_PTC0,
+
+       /* PTD */
+       GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
+       GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+
+       /* PTE */
+       GPIO_PTE7, GPIO_PTE6, GPIO_PTE5, GPIO_PTE4,
+       GPIO_PTE1, GPIO_PTE0,
+
+       /* PTF */
+       GPIO_PTF6, GPIO_PTF5, GPIO_PTF4, GPIO_PTF3,
+       GPIO_PTF2, GPIO_PTF1, GPIO_PTF0,
+
+       /* PTG */
+       GPIO_PTG4, GPIO_PTG3, GPIO_PTG2, GPIO_PTG1, GPIO_PTG0,
+
+       /* PTH */
+       GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4,
+       GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+
+       /* PTJ */
+       GPIO_PTJ7, GPIO_PTJ6, GPIO_PTJ5, GPIO_PTJ1, GPIO_PTJ0,
+
+       /* PTK */
+       GPIO_PTK6, GPIO_PTK5, GPIO_PTK4, GPIO_PTK3,
+       GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+
+       /* PTL */
+       GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4,
+       GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0,
+
+       /* PTM */
+       GPIO_PTM7, GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
+       GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+
+       /* PTN */
+       GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4,
+       GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
+
+       /* PTQ */
+       GPIO_PTQ7, GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
+       GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
+
+       /* PTR */
+       GPIO_PTR4, GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+
+       /* PTS */
+       GPIO_PTS4, GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+
+       /* PTT */
+       GPIO_PTT4, GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0,
+
+       /* PTU */
+       GPIO_PTU4, GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0,
+
+       /* PTV */
+       GPIO_PTV4, GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+
+       /* PTW */
+       GPIO_PTW6, GPIO_PTW5, GPIO_PTW4, GPIO_PTW3,
+       GPIO_PTW2, GPIO_PTW1, GPIO_PTW0,
+
+       /* PTX */
+       GPIO_PTX6, GPIO_PTX5, GPIO_PTX4, GPIO_PTX3,
+       GPIO_PTX2, GPIO_PTX1, GPIO_PTX0,
+
+       /* PTY */
+       GPIO_PTY5, GPIO_PTY4, GPIO_PTY3, GPIO_PTY2,
+       GPIO_PTY1, GPIO_PTY0,
+
+       /* PTZ */
+       GPIO_PTZ5, GPIO_PTZ4, GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1,
+
+       /* SCIF0 */
+       GPIO_FN_SCIF0_TXD, GPIO_FN_SCIF0_RXD,
+       GPIO_FN_SCIF0_RTS, GPIO_FN_SCIF0_CTS, GPIO_FN_SCIF0_SCK,
+
+       /* SCIF1 */
+       GPIO_FN_SCIF1_TXD, GPIO_FN_SCIF1_RXD,
+       GPIO_FN_SCIF1_RTS, GPIO_FN_SCIF1_CTS, GPIO_FN_SCIF1_SCK,
+
+       /* SCIF2 */
+       GPIO_FN_SCIF2_TXD, GPIO_FN_SCIF2_RXD,
+       GPIO_FN_SCIF2_RTS, GPIO_FN_SCIF2_CTS, GPIO_FN_SCIF2_SCK,
+
+       /* SIO */
+       GPIO_FN_SIOTXD, GPIO_FN_SIORXD,
+       GPIO_FN_SIOD, GPIO_FN_SIOSTRB0, GPIO_FN_SIOSTRB1,
+       GPIO_FN_SIOSCK, GPIO_FN_SIOMCK,
+
+       /* CEU */
+       GPIO_FN_VIO_D15, GPIO_FN_VIO_D14, GPIO_FN_VIO_D13, GPIO_FN_VIO_D12,
+       GPIO_FN_VIO_D11, GPIO_FN_VIO_D10, GPIO_FN_VIO_D9, GPIO_FN_VIO_D8,
+       GPIO_FN_VIO_D7, GPIO_FN_VIO_D6, GPIO_FN_VIO_D5, GPIO_FN_VIO_D4,
+       GPIO_FN_VIO_D3, GPIO_FN_VIO_D2, GPIO_FN_VIO_D1, GPIO_FN_VIO_D0,
+       GPIO_FN_VIO_FLD, GPIO_FN_VIO_CKO, GPIO_FN_VIO_STEX, GPIO_FN_VIO_STEM,
+       GPIO_FN_VIO_VD, GPIO_FN_VIO_HD, GPIO_FN_VIO_CLK,
+       GPIO_FN_VIO_VD2, GPIO_FN_VIO_HD2, GPIO_FN_VIO_CLK2,
+
+       /* LCDC */
+       GPIO_FN_LCDD23, GPIO_FN_LCDD22, GPIO_FN_LCDD21, GPIO_FN_LCDD20,
+       GPIO_FN_LCDD19, GPIO_FN_LCDD18, GPIO_FN_LCDD17, GPIO_FN_LCDD16,
+       GPIO_FN_LCDD15, GPIO_FN_LCDD14, GPIO_FN_LCDD13, GPIO_FN_LCDD12,
+       GPIO_FN_LCDD11, GPIO_FN_LCDD10, GPIO_FN_LCDD9, GPIO_FN_LCDD8,
+       GPIO_FN_LCDD7, GPIO_FN_LCDD6, GPIO_FN_LCDD5, GPIO_FN_LCDD4,
+       GPIO_FN_LCDD3, GPIO_FN_LCDD2, GPIO_FN_LCDD1, GPIO_FN_LCDD0,
+       GPIO_FN_LCDLCLK,
+       /* Main LCD */
+       GPIO_FN_LCDDON, GPIO_FN_LCDVCPWC, GPIO_FN_LCDVEPWC, GPIO_FN_LCDVSYN,
+       /* Main LCD - RGB Mode */
+       GPIO_FN_LCDDCK, GPIO_FN_LCDHSYN, GPIO_FN_LCDDISP,
+       /* Main LCD - SYS Mode */
+       GPIO_FN_LCDRS, GPIO_FN_LCDCS, GPIO_FN_LCDWR, GPIO_FN_LCDRD,
+       /* Sub LCD - SYS Mode */
+       GPIO_FN_LCDDON2, GPIO_FN_LCDVCPWC2, GPIO_FN_LCDVEPWC2,
+       GPIO_FN_LCDVSYN2, GPIO_FN_LCDCS2,
+
+       /* BSC */
+       GPIO_FN_IOIS16, GPIO_FN_A25, GPIO_FN_A24, GPIO_FN_A23, GPIO_FN_A22,
+       GPIO_FN_BS, GPIO_FN_CS6B_CE1B, GPIO_FN_WAIT, GPIO_FN_CS6A_CE2B,
+
+       /* SBSC */
+       GPIO_FN_HPD63, GPIO_FN_HPD62, GPIO_FN_HPD61, GPIO_FN_HPD60,
+       GPIO_FN_HPD59, GPIO_FN_HPD58, GPIO_FN_HPD57, GPIO_FN_HPD56,
+       GPIO_FN_HPD55, GPIO_FN_HPD54, GPIO_FN_HPD53, GPIO_FN_HPD52,
+       GPIO_FN_HPD51, GPIO_FN_HPD50, GPIO_FN_HPD49, GPIO_FN_HPD48,
+       GPIO_FN_HPDQM7, GPIO_FN_HPDQM6, GPIO_FN_HPDQM5, GPIO_FN_HPDQM4,
+
+       /* IRQ */
+       GPIO_FN_IRQ0, GPIO_FN_IRQ1, GPIO_FN_IRQ2, GPIO_FN_IRQ3,
+       GPIO_FN_IRQ4, GPIO_FN_IRQ5, GPIO_FN_IRQ6, GPIO_FN_IRQ7,
+
+       /* SDHI */
+       GPIO_FN_SDHICD, GPIO_FN_SDHIWP, GPIO_FN_SDHID3, GPIO_FN_SDHID2,
+       GPIO_FN_SDHID1, GPIO_FN_SDHID0, GPIO_FN_SDHICMD, GPIO_FN_SDHICLK,
+
+       /* SIU - Port A */
+       GPIO_FN_SIUAOLR, GPIO_FN_SIUAOBT, GPIO_FN_SIUAISLD, GPIO_FN_SIUAILR,
+       GPIO_FN_SIUAIBT, GPIO_FN_SIUAOSLD, GPIO_FN_SIUMCKA, GPIO_FN_SIUFCKA,
+
+       /* SIU - Port B */
+       GPIO_FN_SIUBOLR, GPIO_FN_SIUBOBT, GPIO_FN_SIUBISLD, GPIO_FN_SIUBILR,
+       GPIO_FN_SIUBIBT, GPIO_FN_SIUBOSLD, GPIO_FN_SIUMCKB, GPIO_FN_SIUFCKB,
+
+       /* AUD */
+       GPIO_FN_AUDSYNC, GPIO_FN_AUDATA3, GPIO_FN_AUDATA2, GPIO_FN_AUDATA1,
+       GPIO_FN_AUDATA0,
+
+       /* DMAC */
+       GPIO_FN_DACK, GPIO_FN_DREQ0,
+
+       /* VOU */
+       GPIO_FN_DV_CLKI, GPIO_FN_DV_CLK, GPIO_FN_DV_HSYNC, GPIO_FN_DV_VSYNC,
+       GPIO_FN_DV_D15, GPIO_FN_DV_D14, GPIO_FN_DV_D13, GPIO_FN_DV_D12,
+       GPIO_FN_DV_D11, GPIO_FN_DV_D10, GPIO_FN_DV_D9, GPIO_FN_DV_D8,
+       GPIO_FN_DV_D7, GPIO_FN_DV_D6, GPIO_FN_DV_D5, GPIO_FN_DV_D4,
+       GPIO_FN_DV_D3, GPIO_FN_DV_D2, GPIO_FN_DV_D1, GPIO_FN_DV_D0,
+
+       /* CPG */
+       GPIO_FN_STATUS0, GPIO_FN_PDSTATUS,
+
+       /* SIOF0 */
+       GPIO_FN_SIOF0_MCK, GPIO_FN_SIOF0_SCK,
+       GPIO_FN_SIOF0_SYNC, GPIO_FN_SIOF0_SS1, GPIO_FN_SIOF0_SS2,
+       GPIO_FN_SIOF0_TXD, GPIO_FN_SIOF0_RXD,
+
+       /* SIOF1 */
+       GPIO_FN_SIOF1_MCK, GPIO_FN_SIOF1_SCK,
+       GPIO_FN_SIOF1_SYNC, GPIO_FN_SIOF1_SS1, GPIO_FN_SIOF1_SS2,
+       GPIO_FN_SIOF1_TXD, GPIO_FN_SIOF1_RXD,
+
+       /* SIM */
+       GPIO_FN_SIM_D, GPIO_FN_SIM_CLK, GPIO_FN_SIM_RST,
+
+       /* TSIF */
+       GPIO_FN_TS_SDAT, GPIO_FN_TS_SCK, GPIO_FN_TS_SDEN, GPIO_FN_TS_SPSYNC,
+
+       /* IRDA */
+       GPIO_FN_IRDA_IN, GPIO_FN_IRDA_OUT,
+
+       /* TPU */
+       GPIO_FN_TPUTO,
+
+       /* FLCTL */
+       GPIO_FN_FCE, GPIO_FN_NAF7, GPIO_FN_NAF6, GPIO_FN_NAF5, GPIO_FN_NAF4,
+       GPIO_FN_NAF3, GPIO_FN_NAF2, GPIO_FN_NAF1, GPIO_FN_NAF0, GPIO_FN_FCDE,
+       GPIO_FN_FOE, GPIO_FN_FSC, GPIO_FN_FWE, GPIO_FN_FRB,
+
+       /* KEYSC */
+       GPIO_FN_KEYIN0, GPIO_FN_KEYIN1, GPIO_FN_KEYIN2, GPIO_FN_KEYIN3,
+       GPIO_FN_KEYIN4, GPIO_FN_KEYOUT0, GPIO_FN_KEYOUT1, GPIO_FN_KEYOUT2,
+       GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
+};
+
+#endif /* __ASM_SH7722_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/sh7723.h b/arch/sh/include/cpu-sh4/cpu/sh7723.h
new file mode 100644 (file)
index 0000000..9d2f6d7
--- /dev/null
@@ -0,0 +1,254 @@
+#ifndef __ASM_SH7723_H__
+#define __ASM_SH7723_H__
+
+enum {
+       /* PTA */
+       GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
+       GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+
+       /* PTB */
+       GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
+       GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+
+       /* PTC */
+       GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4,
+       GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0,
+
+       /* PTD */
+       GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
+       GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+
+       /* PTE */
+       GPIO_PTE5, GPIO_PTE4, GPIO_PTE3, GPIO_PTE2,
+       GPIO_PTE1, GPIO_PTE0,
+
+       /* PTF */
+       GPIO_PTF7, GPIO_PTF6, GPIO_PTF5, GPIO_PTF4,
+       GPIO_PTF3, GPIO_PTF2, GPIO_PTF1, GPIO_PTF0,
+
+       /* PTG */
+       GPIO_PTG5, GPIO_PTG4, GPIO_PTG3, GPIO_PTG2,
+       GPIO_PTG1, GPIO_PTG0,
+
+       /* PTH */
+       GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4,
+       GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+
+       /* PTJ */
+       GPIO_PTJ7, GPIO_PTJ5, GPIO_PTJ3, GPIO_PTJ2,
+       GPIO_PTJ1, GPIO_PTJ0,
+
+       /* PTK */
+       GPIO_PTK7, GPIO_PTK6, GPIO_PTK5, GPIO_PTK4,
+       GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+
+       /* PTL */
+       GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4,
+       GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0,
+
+       /* PTM */
+       GPIO_PTM7, GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
+       GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+
+       /* PTN */
+       GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4,
+       GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
+
+       /* PTQ */
+       GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
+
+       /* PTR */
+       GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4,
+       GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+
+       /* PTS */
+       GPIO_PTS7, GPIO_PTS6, GPIO_PTS5, GPIO_PTS4,
+       GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+
+       /* PTT */
+       GPIO_PTT5, GPIO_PTT4, GPIO_PTT3, GPIO_PTT2,
+       GPIO_PTT1, GPIO_PTT0,
+
+       /* PTU */
+       GPIO_PTU5, GPIO_PTU4, GPIO_PTU3, GPIO_PTU2,
+       GPIO_PTU1, GPIO_PTU0,
+
+       /* PTV */
+       GPIO_PTV7, GPIO_PTV6, GPIO_PTV5, GPIO_PTV4,
+       GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+
+       /* PTW */
+       GPIO_PTW7, GPIO_PTW6, GPIO_PTW5, GPIO_PTW4,
+       GPIO_PTW3, GPIO_PTW2, GPIO_PTW1, GPIO_PTW0,
+
+       /* PTX */
+       GPIO_PTX7, GPIO_PTX6, GPIO_PTX5, GPIO_PTX4,
+       GPIO_PTX3, GPIO_PTX2, GPIO_PTX1, GPIO_PTX0,
+
+       /* PTY */
+       GPIO_PTY7, GPIO_PTY6, GPIO_PTY5, GPIO_PTY4,
+       GPIO_PTY3, GPIO_PTY2, GPIO_PTY1, GPIO_PTY0,
+
+       /* PTZ */
+       GPIO_PTZ7, GPIO_PTZ6, GPIO_PTZ5, GPIO_PTZ4,
+       GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1, GPIO_PTZ0,
+
+       /* SCIF0 (SCIF: 3 pin PTT/PTU) */
+       GPIO_FN_SCIF0_PTT_TXD, GPIO_FN_SCIF0_PTT_RXD, GPIO_FN_SCIF0_PTT_SCK,
+       GPIO_FN_SCIF0_PTU_TXD, GPIO_FN_SCIF0_PTU_RXD, GPIO_FN_SCIF0_PTU_SCK,
+
+       /* SCIF1 (SCIF: 3 pin PTS/PTV) */
+       GPIO_FN_SCIF1_PTS_TXD, GPIO_FN_SCIF1_PTS_RXD, GPIO_FN_SCIF1_PTS_SCK,
+       GPIO_FN_SCIF1_PTV_TXD, GPIO_FN_SCIF1_PTV_RXD, GPIO_FN_SCIF1_PTV_SCK,
+
+       /* SCIF2 (SCIF: 3 pin PTT/PTU) */
+       GPIO_FN_SCIF2_PTT_TXD, GPIO_FN_SCIF2_PTT_RXD, GPIO_FN_SCIF2_PTT_SCK,
+       GPIO_FN_SCIF2_PTU_TXD, GPIO_FN_SCIF2_PTU_RXD, GPIO_FN_SCIF2_PTU_SCK,
+
+       /* SCIF3 (SCIFA: 5 pin PTS/PTV) */
+       GPIO_FN_SCIF3_PTS_TXD, GPIO_FN_SCIF3_PTS_RXD, GPIO_FN_SCIF3_PTS_SCK,
+       GPIO_FN_SCIF3_PTS_RTS, GPIO_FN_SCIF3_PTS_CTS,
+       GPIO_FN_SCIF3_PTV_TXD, GPIO_FN_SCIF3_PTV_RXD, GPIO_FN_SCIF3_PTV_SCK,
+       GPIO_FN_SCIF3_PTV_RTS, GPIO_FN_SCIF3_PTV_CTS,
+
+       /* SCIF4 (SCIFA: 3 pin PTE/PTN) */
+       GPIO_FN_SCIF4_PTE_TXD, GPIO_FN_SCIF4_PTE_RXD, GPIO_FN_SCIF4_PTE_SCK,
+       GPIO_FN_SCIF4_PTN_TXD, GPIO_FN_SCIF4_PTN_RXD, GPIO_FN_SCIF4_PTN_SCK,
+
+       /* SCIF5 (SCIFA: 3 pin PTE/PTN) */
+       GPIO_FN_SCIF5_PTE_TXD, GPIO_FN_SCIF5_PTE_RXD, GPIO_FN_SCIF5_PTE_SCK,
+       GPIO_FN_SCIF5_PTN_TXD, GPIO_FN_SCIF5_PTN_RXD, GPIO_FN_SCIF5_PTN_SCK,
+
+       /* CEU */
+       GPIO_FN_VIO_D15, GPIO_FN_VIO_D14, GPIO_FN_VIO_D13, GPIO_FN_VIO_D12,
+       GPIO_FN_VIO_D11, GPIO_FN_VIO_D10, GPIO_FN_VIO_D9, GPIO_FN_VIO_D8,
+       GPIO_FN_VIO_D7, GPIO_FN_VIO_D6, GPIO_FN_VIO_D5, GPIO_FN_VIO_D4,
+       GPIO_FN_VIO_D3, GPIO_FN_VIO_D2, GPIO_FN_VIO_D1, GPIO_FN_VIO_D0,
+       GPIO_FN_VIO_FLD, GPIO_FN_VIO_CKO,
+       GPIO_FN_VIO_VD1, GPIO_FN_VIO_HD1, GPIO_FN_VIO_CLK1,
+       GPIO_FN_VIO_VD2, GPIO_FN_VIO_HD2, GPIO_FN_VIO_CLK2,
+
+       /* LCDC */
+       GPIO_FN_LCDD23, GPIO_FN_LCDD22, GPIO_FN_LCDD21, GPIO_FN_LCDD20,
+       GPIO_FN_LCDD19, GPIO_FN_LCDD18, GPIO_FN_LCDD17, GPIO_FN_LCDD16,
+       GPIO_FN_LCDD15, GPIO_FN_LCDD14, GPIO_FN_LCDD13, GPIO_FN_LCDD12,
+       GPIO_FN_LCDD11, GPIO_FN_LCDD10, GPIO_FN_LCDD9, GPIO_FN_LCDD8,
+       GPIO_FN_LCDD7, GPIO_FN_LCDD6, GPIO_FN_LCDD5, GPIO_FN_LCDD4,
+       GPIO_FN_LCDD3, GPIO_FN_LCDD2, GPIO_FN_LCDD1, GPIO_FN_LCDD0,
+       GPIO_FN_LCDLCLK_PTR, GPIO_FN_LCDLCLK_PTW,
+       /* Main LCD */
+       GPIO_FN_LCDDON, GPIO_FN_LCDVCPWC, GPIO_FN_LCDVEPWC, GPIO_FN_LCDVSYN,
+       /* Main LCD - RGB Mode */
+       GPIO_FN_LCDDCK, GPIO_FN_LCDHSYN, GPIO_FN_LCDDISP,
+       /* Main LCD - SYS Mode */
+       GPIO_FN_LCDRS, GPIO_FN_LCDCS, GPIO_FN_LCDWR, GPIO_FN_LCDRD,
+
+       /* IRQ */
+       GPIO_FN_IRQ0, GPIO_FN_IRQ1, GPIO_FN_IRQ2, GPIO_FN_IRQ3,
+       GPIO_FN_IRQ4, GPIO_FN_IRQ5, GPIO_FN_IRQ6, GPIO_FN_IRQ7,
+
+       /* AUD */
+       GPIO_FN_AUDATA3, GPIO_FN_AUDATA2, GPIO_FN_AUDATA1, GPIO_FN_AUDATA0,
+       GPIO_FN_AUDCK, GPIO_FN_AUDSYNC,
+
+       /* SDHI0 (PTD) */
+       GPIO_FN_SDHI0CD_PTD, GPIO_FN_SDHI0WP_PTD,
+       GPIO_FN_SDHI0D3_PTD, GPIO_FN_SDHI0D2_PTD,
+       GPIO_FN_SDHI0D1_PTD, GPIO_FN_SDHI0D0_PTD,
+       GPIO_FN_SDHI0CMD_PTD, GPIO_FN_SDHI0CLK_PTD,
+
+       /* SDHI0 (PTS) */
+       GPIO_FN_SDHI0CD_PTS, GPIO_FN_SDHI0WP_PTS,
+       GPIO_FN_SDHI0D3_PTS, GPIO_FN_SDHI0D2_PTS,
+       GPIO_FN_SDHI0D1_PTS, GPIO_FN_SDHI0D0_PTS,
+       GPIO_FN_SDHI0CMD_PTS, GPIO_FN_SDHI0CLK_PTS,
+
+       /* SDHI1 */
+       GPIO_FN_SDHI1CD, GPIO_FN_SDHI1WP, GPIO_FN_SDHI1D3, GPIO_FN_SDHI1D2,
+       GPIO_FN_SDHI1D1, GPIO_FN_SDHI1D0, GPIO_FN_SDHI1CMD, GPIO_FN_SDHI1CLK,
+
+       /* SIUA */
+       GPIO_FN_SIUAFCK, GPIO_FN_SIUAILR, GPIO_FN_SIUAIBT, GPIO_FN_SIUAISLD,
+       GPIO_FN_SIUAOLR, GPIO_FN_SIUAOBT, GPIO_FN_SIUAOSLD, GPIO_FN_SIUAMCK,
+       GPIO_FN_SIUAISPD, GPIO_FN_SIUOSPD,
+
+       /* SIUB */
+       GPIO_FN_SIUBFCK, GPIO_FN_SIUBILR, GPIO_FN_SIUBIBT, GPIO_FN_SIUBISLD,
+       GPIO_FN_SIUBOLR, GPIO_FN_SIUBOBT, GPIO_FN_SIUBOSLD, GPIO_FN_SIUBMCK,
+
+       /* IRDA */
+       GPIO_FN_IRDA_IN, GPIO_FN_IRDA_OUT,
+
+       /* VOU */
+       GPIO_FN_DV_CLKI, GPIO_FN_DV_CLK, GPIO_FN_DV_HSYNC, GPIO_FN_DV_VSYNC,
+       GPIO_FN_DV_D15, GPIO_FN_DV_D14, GPIO_FN_DV_D13, GPIO_FN_DV_D12,
+       GPIO_FN_DV_D11, GPIO_FN_DV_D10, GPIO_FN_DV_D9, GPIO_FN_DV_D8,
+       GPIO_FN_DV_D7, GPIO_FN_DV_D6, GPIO_FN_DV_D5, GPIO_FN_DV_D4,
+       GPIO_FN_DV_D3, GPIO_FN_DV_D2, GPIO_FN_DV_D1, GPIO_FN_DV_D0,
+
+       /* KEYSC */
+       GPIO_FN_KEYIN0, GPIO_FN_KEYIN1, GPIO_FN_KEYIN2, GPIO_FN_KEYIN3,
+       GPIO_FN_KEYIN4, GPIO_FN_KEYOUT0, GPIO_FN_KEYOUT1, GPIO_FN_KEYOUT2,
+       GPIO_FN_KEYOUT3, GPIO_FN_KEYOUT4_IN6, GPIO_FN_KEYOUT5_IN5,
+
+       /* MSIOF0 (PTF) */
+       GPIO_FN_MSIOF0_PTF_TXD, GPIO_FN_MSIOF0_PTF_RXD, GPIO_FN_MSIOF0_PTF_MCK,
+       GPIO_FN_MSIOF0_PTF_TSYNC, GPIO_FN_MSIOF0_PTF_TSCK,
+       GPIO_FN_MSIOF0_PTF_RSYNC, GPIO_FN_MSIOF0_PTF_RSCK,
+       GPIO_FN_MSIOF0_PTF_SS1, GPIO_FN_MSIOF0_PTF_SS2,
+
+       /* MSIOF0 (PTT+PTX) */
+       GPIO_FN_MSIOF0_PTT_TXD, GPIO_FN_MSIOF0_PTT_RXD, GPIO_FN_MSIOF0_PTX_MCK,
+       GPIO_FN_MSIOF0_PTT_TSYNC, GPIO_FN_MSIOF0_PTT_TSCK,
+       GPIO_FN_MSIOF0_PTT_RSYNC, GPIO_FN_MSIOF0_PTT_RSCK,
+       GPIO_FN_MSIOF0_PTT_SS1, GPIO_FN_MSIOF0_PTT_SS2,
+
+       /* MSIOF1 */
+       GPIO_FN_MSIOF1_TXD, GPIO_FN_MSIOF1_RXD, GPIO_FN_MSIOF1_MCK,
+       GPIO_FN_MSIOF1_TSYNC, GPIO_FN_MSIOF1_TSCK,
+       GPIO_FN_MSIOF1_RSYNC, GPIO_FN_MSIOF1_RSCK,
+       GPIO_FN_MSIOF1_SS1, GPIO_FN_MSIOF1_SS2,
+
+       /* TSIF */
+       GPIO_FN_TS0_SDAT, GPIO_FN_TS0_SCK, GPIO_FN_TS0_SDEN, GPIO_FN_TS0_SPSYNC,
+
+       /* FLCTL */
+       GPIO_FN_FCE, GPIO_FN_NAF7, GPIO_FN_NAF6, GPIO_FN_NAF5, GPIO_FN_NAF4,
+       GPIO_FN_NAF3, GPIO_FN_NAF2, GPIO_FN_NAF1, GPIO_FN_NAF0, GPIO_FN_FCDE,
+       GPIO_FN_FOE, GPIO_FN_FSC, GPIO_FN_FWE, GPIO_FN_FRB,
+
+       /* DMAC */
+       GPIO_FN_DACK1, GPIO_FN_DREQ1, GPIO_FN_DACK0, GPIO_FN_DREQ0,
+
+       /* ADC */
+       GPIO_FN_AN3, GPIO_FN_AN2, GPIO_FN_AN1, GPIO_FN_AN0, GPIO_FN_ADTRG,
+
+       /* CPG */
+       GPIO_FN_STATUS0, GPIO_FN_PDSTATUS,
+
+       /* TPU */
+       GPIO_FN_TPUTO3, GPIO_FN_TPUTO2, GPIO_FN_TPUTO1, GPIO_FN_TPUTO0,
+
+       /* BSC */
+       GPIO_FN_D31, GPIO_FN_D30, GPIO_FN_D29, GPIO_FN_D28,
+       GPIO_FN_D27, GPIO_FN_D26, GPIO_FN_D25, GPIO_FN_D24,
+       GPIO_FN_D23, GPIO_FN_D22, GPIO_FN_D21, GPIO_FN_D20,
+       GPIO_FN_D19, GPIO_FN_D18, GPIO_FN_D17, GPIO_FN_D16,
+       GPIO_FN_IOIS16, GPIO_FN_WAIT, GPIO_FN_BS,
+       GPIO_FN_A25, GPIO_FN_A24, GPIO_FN_A23, GPIO_FN_A22,
+       GPIO_FN_CS6B_CE1B, GPIO_FN_CS6A_CE2B,
+       GPIO_FN_CS5B_CE1A, GPIO_FN_CS5A_CE2A,
+       GPIO_FN_WE3_ICIOWR, GPIO_FN_WE2_ICIORD,
+
+       /* ATAPI */
+       GPIO_FN_IDED15, GPIO_FN_IDED14, GPIO_FN_IDED13, GPIO_FN_IDED12,
+       GPIO_FN_IDED11, GPIO_FN_IDED10, GPIO_FN_IDED9, GPIO_FN_IDED8,
+       GPIO_FN_IDED7, GPIO_FN_IDED6, GPIO_FN_IDED5, GPIO_FN_IDED4,
+       GPIO_FN_IDED3, GPIO_FN_IDED2, GPIO_FN_IDED1, GPIO_FN_IDED0,
+       GPIO_FN_DIRECTION, GPIO_FN_EXBUF_ENB, GPIO_FN_IDERST, GPIO_FN_IODACK,
+       GPIO_FN_IODREQ, GPIO_FN_IDEIORDY, GPIO_FN_IDEINT, GPIO_FN_IDEIOWR,
+       GPIO_FN_IDEIORD, GPIO_FN_IDECS1, GPIO_FN_IDECS0, GPIO_FN_IDEA2,
+       GPIO_FN_IDEA1, GPIO_FN_IDEA0,
+};
+
+#endif /* __ASM_SH7723_H__ */
similarity index 94%
rename from arch/sh/include/asm/migor.h
rename to arch/sh/include/mach-common/mach/migor.h
index c12b632c540bc27a18f6d350ff9e680a23a79b9b..e451f0229e0027bea980006d7c6de21edc421186 100644 (file)
 #define PORT_HIZCRB 0xa405015a
 #define PORT_HIZCRC 0xa405015c
 
+#define BSC_CS4BCR 0xfec10010
 #define BSC_CS6ABCR 0xfec1001c
+#define BSC_CS4WCR 0xfec10030
 
-#include <asm/sh_mobile_lcdc.h>
+#include <video/sh_mobile_lcdc.h>
 
 int migor_lcd_qvga_setup(void *board_data, void *sys_ops_handle,
                         struct sh_mobile_lcdc_sys_bus_ops *sys_ops);
index 0e6905fe9fec80b54198ba4f7fd1561fac284a65..48edfb145fb4f9acdd58ca8c48081420c11e198e 100644 (file)
@@ -21,7 +21,8 @@ obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
-obj-$(CONFIG_ELF_CORE)         += dump_task.o
 obj-$(CONFIG_IO_TRAPPED)       += io_trapped.o
+obj-$(CONFIG_KPROBES)          += kprobes.o
+obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
 
 EXTRA_CFLAGS += -Werror
index 6edf53b93d940adf22f289e591337ee34de1c96d..c97660b2b48d11be65fcf440c80c841acd433bb6 100644 (file)
@@ -17,7 +17,7 @@ obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_STACKTRACE)       += stacktrace.o
-obj-$(CONFIG_BINFMT_ELF)       += dump_task.o
 obj-$(CONFIG_IO_TRAPPED)       += io_trapped.o
+obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
 
 EXTRA_CFLAGS += -Werror
index f5eb56e6bc59b8bb68e8b1552f82f64150b527ea..b7e46d5bba439057a6f503d72b509515554db89a 100644 (file)
@@ -294,9 +294,10 @@ arch_init_clk_ops(struct clk_ops **ops, int type)
 {
 }
 
-void __init __attribute__ ((weak))
+int __init __attribute__ ((weak))
 arch_clk_init(void)
 {
+       return 0;
 }
 
 static int show_clocks(char *buf, char **start, off_t off,
@@ -331,7 +332,7 @@ int __init clk_init(void)
                ret |= clk_register(clk);
        }
 
-       arch_clk_init();
+       ret |= arch_clk_init();
 
        /* Kick the child clocks.. */
        propagate_rate(&master_clk);
index 462a8f6dfee24006236cd657ddeb044d7280d3f0..f0c7025a67d117fedce5afbab43ff86227c12b5a 100644 (file)
@@ -1,8 +1,6 @@
 #
 # Makefile for the Linux/SuperH CPU-specifc IRQ handlers.
 #
-obj-y  += intc.o
-
 obj-$(CONFIG_SUPERH32)                 += imask.o
 obj-$(CONFIG_CPU_SH5)                  += intc-sh5.o
 obj-$(CONFIG_CPU_HAS_IPR_IRQ)          += ipr.o
index 56ea7b269b59c4fdc3d0503bdfc411b39cb45971..3eb17ee5540e88d5c7bd99ae133d597af9e049de 100644 (file)
@@ -33,7 +33,7 @@ static void disable_ipr_irq(unsigned int irq)
        struct ipr_data *p = get_irq_chip_data(irq);
        unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
        /* Set the priority in IPR to 0 */
-       ctrl_outw(ctrl_inw(addr) & (0xffff ^ (0xf << p->shift)), addr);
+       __raw_writew(__raw_readw(addr) & (0xffff ^ (0xf << p->shift)), addr);
 }
 
 static void enable_ipr_irq(unsigned int irq)
@@ -41,7 +41,7 @@ static void enable_ipr_irq(unsigned int irq)
        struct ipr_data *p = get_irq_chip_data(irq);
        unsigned long addr = get_ipr_desc(irq)->ipr_offsets[p->ipr_idx];
        /* Set priority in IPR back to original value */
-       ctrl_outw(ctrl_inw(addr) | (p->priority << p->shift), addr);
+       __raw_writew(__raw_readw(addr) | (p->priority << p->shift), addr);
 }
 
 /*
index 1ab1ecf4c7685d9a03d077c788c66ec85b70729b..428450cc0809d8c48476ac6ef604759d0614b64e 100644 (file)
@@ -12,3 +12,8 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7206)      += setup-sh7206.o clock-sh7206.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7203)       += setup-sh7203.o clock-sh7203.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7263)       += setup-sh7203.o clock-sh7203.o
 obj-$(CONFIG_CPU_SUBTYPE_MXG)          += setup-mxg.o clock-sh7206.o
+
+# Pinmux setup
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7203)    := pinmux-sh7203.o
+
+obj-$(CONFIG_GENERIC_GPIO)     += $(pinmux-y)
diff --git a/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c b/arch/sh/kernel/cpu/sh2a/pinmux-sh7203.c
new file mode 100644 (file)
index 0000000..39a5b88
--- /dev/null
@@ -0,0 +1,1599 @@
+/*
+ * SH7203 Pinmux
+ *
+ *  Copyright (C) 2008  Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <asm/sh7203.h>
+
+enum {
+       PINMUX_RESERVED = 0,
+
+       PINMUX_DATA_BEGIN,
+       PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+       PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
+       PB12_DATA,
+       PB11_DATA, PB10_DATA, PB9_DATA, PB8_DATA,
+       PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+       PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA,
+       PC14_DATA, PC13_DATA, PC12_DATA,
+       PC11_DATA, PC10_DATA, PC9_DATA, PC8_DATA,
+       PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+       PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+       PD15_DATA, PD14_DATA, PD13_DATA, PD12_DATA,
+       PD11_DATA, PD10_DATA, PD9_DATA, PD8_DATA,
+       PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+       PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
+       PE15_DATA, PE14_DATA, PE13_DATA, PE12_DATA,
+       PE11_DATA, PE10_DATA, PE9_DATA, PE8_DATA,
+       PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+       PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
+       PF30_DATA, PF29_DATA, PF28_DATA,
+       PF27_DATA, PF26_DATA, PF25_DATA, PF24_DATA,
+       PF23_DATA, PF22_DATA, PF21_DATA, PF20_DATA,
+       PF19_DATA, PF18_DATA, PF17_DATA, PF16_DATA,
+       PF15_DATA, PF14_DATA, PF13_DATA, PF12_DATA,
+       PF11_DATA, PF10_DATA, PF9_DATA, PF8_DATA,
+       PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+       PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
+       PINMUX_DATA_END,
+
+       PINMUX_INPUT_BEGIN,
+       PA7_IN, PA6_IN, PA5_IN, PA4_IN,
+       PA3_IN, PA2_IN, PA1_IN, PA0_IN,
+       PB11_IN, PB10_IN, PB9_IN, PB8_IN,
+       PB7_IN, PB6_IN, PB5_IN, PB4_IN,
+       PB3_IN, PB2_IN, PB1_IN, PB0_IN,
+       PC14_IN, PC13_IN, PC12_IN,
+       PC11_IN, PC10_IN, PC9_IN, PC8_IN,
+       PC7_IN, PC6_IN, PC5_IN, PC4_IN,
+       PC3_IN, PC2_IN, PC1_IN, PC0_IN,
+       PD15_IN, PD14_IN, PD13_IN, PD12_IN,
+       PD11_IN, PD10_IN, PD9_IN, PD8_IN,
+       PD7_IN, PD6_IN, PD5_IN, PD4_IN,
+       PD3_IN, PD2_IN, PD1_IN, PD0_IN,
+       PE15_IN, PE14_IN, PE13_IN, PE12_IN,
+       PE11_IN, PE10_IN, PE9_IN, PE8_IN,
+       PE7_IN, PE6_IN, PE5_IN, PE4_IN,
+       PE3_IN, PE2_IN, PE1_IN, PE0_IN,
+       PF30_IN, PF29_IN, PF28_IN,
+       PF27_IN, PF26_IN, PF25_IN, PF24_IN,
+       PF23_IN, PF22_IN, PF21_IN, PF20_IN,
+       PF19_IN, PF18_IN, PF17_IN, PF16_IN,
+       PF15_IN, PF14_IN, PF13_IN, PF12_IN,
+       PF11_IN, PF10_IN, PF9_IN, PF8_IN,
+       PF7_IN, PF6_IN, PF5_IN, PF4_IN,
+       PF3_IN, PF2_IN, PF1_IN, PF0_IN,
+       PINMUX_INPUT_END,
+
+       PINMUX_OUTPUT_BEGIN,
+       PB12_OUT,
+       PB11_OUT, PB10_OUT, PB9_OUT, PB8_OUT,
+       PC14_OUT, PC13_OUT, PC12_OUT,
+       PC11_OUT, PC10_OUT, PC9_OUT, PC8_OUT,
+       PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
+       PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
+       PD15_OUT, PD14_OUT, PD13_OUT, PD12_OUT,
+       PD11_OUT, PD10_OUT, PD9_OUT, PD8_OUT,
+       PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
+       PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
+       PE15_OUT, PE14_OUT, PE13_OUT, PE12_OUT,
+       PE11_OUT, PE10_OUT, PE9_OUT, PE8_OUT,
+       PE7_OUT, PE6_OUT, PE5_OUT, PE4_OUT,
+       PE3_OUT, PE2_OUT, PE1_OUT, PE0_OUT,
+       PF30_OUT, PF29_OUT, PF28_OUT,
+       PF27_OUT, PF26_OUT, PF25_OUT, PF24_OUT,
+       PF23_OUT, PF22_OUT, PF21_OUT, PF20_OUT,
+       PF19_OUT, PF18_OUT, PF17_OUT, PF16_OUT,
+       PF15_OUT, PF14_OUT, PF13_OUT, PF12_OUT,
+       PF11_OUT, PF10_OUT, PF9_OUT, PF8_OUT,
+       PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
+       PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
+       PINMUX_OUTPUT_END,
+
+       PINMUX_FUNCTION_BEGIN,
+       PB11_IOR_IN, PB11_IOR_OUT,
+       PB10_IOR_IN, PB10_IOR_OUT,
+       PB9_IOR_IN, PB9_IOR_OUT,
+       PB8_IOR_IN, PB8_IOR_OUT,
+       PB12MD_00, PB12MD_01, PB12MD_10, PB12MD_11,
+       PB11MD_0, PB11MD_1,
+       PB10MD_0, PB10MD_1,
+       PB9MD_00, PB9MD_01, PB9MD_10,
+       PB8MD_00, PB8MD_01, PB8MD_10,
+       PB7MD_00, PB7MD_01, PB7MD_10, PB7MD_11,
+       PB6MD_00, PB6MD_01, PB6MD_10, PB6MD_11,
+       PB5MD_00, PB5MD_01, PB5MD_10, PB5MD_11,
+       PB4MD_00, PB4MD_01, PB4MD_10, PB4MD_11,
+       PB3MD_00, PB3MD_01, PB3MD_10, PB3MD_11,
+       PB2MD_00, PB2MD_01, PB2MD_10, PB2MD_11,
+       PB1MD_00, PB1MD_01, PB1MD_10, PB1MD_11,
+       PB0MD_00, PB0MD_01, PB0MD_10, PB0MD_11,
+
+       PB12IRQ_00, PB12IRQ_01, PB12IRQ_10,
+
+       PC14MD_0, PC14MD_1,
+       PC13MD_0, PC13MD_1,
+       PC12MD_0, PC12MD_1,
+       PC11MD_00, PC11MD_01, PC11MD_10,
+       PC10MD_00, PC10MD_01, PC10MD_10,
+       PC9MD_0, PC9MD_1,
+       PC8MD_0, PC8MD_1,
+       PC7MD_0, PC7MD_1,
+       PC6MD_0, PC6MD_1,
+       PC5MD_0, PC5MD_1,
+       PC4MD_0, PC4MD_1,
+       PC3MD_0, PC3MD_1,
+       PC2MD_0, PC2MD_1,
+       PC1MD_0, PC1MD_1,
+       PC0MD_00, PC0MD_01, PC0MD_10,
+
+       PD15MD_000, PD15MD_001, PD15MD_010, PD15MD_100, PD15MD_101,
+       PD14MD_000, PD14MD_001, PD14MD_010, PD14MD_101,
+       PD13MD_000, PD13MD_001, PD13MD_010, PD13MD_100, PD13MD_101,
+       PD12MD_000, PD12MD_001, PD12MD_010, PD12MD_100, PD12MD_101,
+       PD11MD_000, PD11MD_001, PD11MD_010, PD11MD_100, PD11MD_101,
+       PD10MD_000, PD10MD_001, PD10MD_010, PD10MD_100, PD10MD_101,
+       PD9MD_000, PD9MD_001, PD9MD_010, PD9MD_100, PD9MD_101,
+       PD8MD_000, PD8MD_001, PD8MD_010, PD8MD_100, PD8MD_101,
+       PD7MD_000, PD7MD_001, PD7MD_010, PD7MD_011, PD7MD_100, PD7MD_101,
+       PD6MD_000, PD6MD_001, PD6MD_010, PD6MD_011, PD6MD_100, PD6MD_101,
+       PD5MD_000, PD5MD_001, PD5MD_010, PD5MD_011, PD5MD_100, PD5MD_101,
+       PD4MD_000, PD4MD_001, PD4MD_010, PD4MD_011, PD4MD_100, PD4MD_101,
+       PD3MD_000, PD3MD_001, PD3MD_010, PD3MD_011, PD3MD_100, PD3MD_101,
+       PD2MD_000, PD2MD_001, PD2MD_010, PD2MD_011, PD2MD_100, PD2MD_101,
+       PD1MD_000, PD1MD_001, PD1MD_010, PD1MD_011, PD1MD_100, PD1MD_101,
+       PD0MD_000, PD0MD_001, PD0MD_010, PD0MD_011, PD0MD_100, PD0MD_101,
+
+       PE15MD_00, PE15MD_01, PE15MD_11,
+       PE14MD_00, PE14MD_01, PE14MD_11,
+       PE13MD_00, PE13MD_11,
+       PE12MD_00, PE12MD_11,
+       PE11MD_000, PE11MD_001, PE11MD_010, PE11MD_100,
+       PE10MD_000, PE10MD_001, PE10MD_010, PE10MD_100,
+       PE9MD_00, PE9MD_01, PE9MD_10, PE9MD_11,
+       PE8MD_00, PE8MD_01, PE8MD_10, PE8MD_11,
+       PE7MD_000, PE7MD_001, PE7MD_010, PE7MD_011, PE7MD_100,
+       PE6MD_000, PE6MD_001, PE6MD_010, PE6MD_011, PE6MD_100,
+       PE5MD_000, PE5MD_001, PE5MD_010, PE5MD_011, PE5MD_100,
+       PE4MD_000, PE4MD_001, PE4MD_010, PE4MD_011, PE4MD_100,
+       PE3MD_00, PE3MD_01, PE3MD_11,
+       PE2MD_00, PE2MD_01, PE2MD_11,
+       PE1MD_00, PE1MD_01, PE1MD_10, PE1MD_11,
+       PE0MD_000, PE0MD_001, PE0MD_011, PE0MD_100,
+
+       PF30MD_0, PF30MD_1,
+       PF29MD_0, PF29MD_1,
+       PF28MD_0, PF28MD_1,
+       PF27MD_0, PF27MD_1,
+       PF26MD_0, PF26MD_1,
+       PF25MD_0, PF25MD_1,
+       PF24MD_0, PF24MD_1,
+       PF23MD_00, PF23MD_01, PF23MD_10,
+       PF22MD_00, PF22MD_01, PF22MD_10,
+       PF21MD_00, PF21MD_01, PF21MD_10,
+       PF20MD_00, PF20MD_01, PF20MD_10,
+       PF19MD_00, PF19MD_01, PF19MD_10,
+       PF18MD_00, PF18MD_01, PF18MD_10,
+       PF17MD_00, PF17MD_01, PF17MD_10,
+       PF16MD_00, PF16MD_01, PF16MD_10,
+       PF15MD_00, PF15MD_01, PF15MD_10,
+       PF14MD_00, PF14MD_01, PF14MD_10,
+       PF13MD_00, PF13MD_01, PF13MD_10,
+       PF12MD_00, PF12MD_01, PF12MD_10,
+       PF11MD_00, PF11MD_01, PF11MD_10,
+       PF10MD_00, PF10MD_01, PF10MD_10,
+       PF9MD_00, PF9MD_01, PF9MD_10,
+       PF8MD_00, PF8MD_01, PF8MD_10,
+       PF7MD_00, PF7MD_01, PF7MD_10, PF7MD_11,
+       PF6MD_00, PF6MD_01, PF6MD_10, PF6MD_11,
+       PF5MD_00, PF5MD_01, PF5MD_10, PF5MD_11,
+       PF4MD_00, PF4MD_01, PF4MD_10, PF4MD_11,
+       PF3MD_00, PF3MD_01, PF3MD_10, PF3MD_11,
+       PF2MD_00, PF2MD_01, PF2MD_10, PF2MD_11,
+       PF1MD_00, PF1MD_01, PF1MD_10, PF1MD_11,
+       PF0MD_00, PF0MD_01, PF0MD_10, PF0MD_11,
+       PINMUX_FUNCTION_END,
+
+       PINMUX_MARK_BEGIN,
+       PINT7_PB_MARK, PINT6_PB_MARK, PINT5_PB_MARK, PINT4_PB_MARK,
+       PINT3_PB_MARK, PINT2_PB_MARK, PINT1_PB_MARK, PINT0_PB_MARK,
+       PINT7_PD_MARK, PINT6_PD_MARK, PINT5_PD_MARK, PINT4_PD_MARK,
+       PINT3_PD_MARK, PINT2_PD_MARK, PINT1_PD_MARK, PINT0_PD_MARK,
+       IRQ7_PB_MARK, IRQ6_PB_MARK, IRQ5_PB_MARK, IRQ4_PB_MARK,
+       IRQ3_PB_MARK, IRQ2_PB_MARK, IRQ1_PB_MARK, IRQ0_PB_MARK,
+       IRQ7_PD_MARK, IRQ6_PD_MARK, IRQ5_PD_MARK, IRQ4_PD_MARK,
+       IRQ3_PD_MARK, IRQ2_PD_MARK, IRQ1_PD_MARK, IRQ0_PD_MARK,
+       IRQ7_PE_MARK, IRQ6_PE_MARK, IRQ5_PE_MARK, IRQ4_PE_MARK,
+       IRQ3_PE_MARK, IRQ2_PE_MARK, IRQ1_PE_MARK, IRQ0_PE_MARK,
+       WDTOVF_MARK, IRQOUT_MARK, REFOUT_MARK, IRQOUT_REFOUT_MARK,
+       UBCTRG_MARK,
+       CTX1_MARK, CRX1_MARK, CTX0_MARK, CTX0_CTX1_MARK,
+       CRX0_MARK, CRX0_CRX1_MARK,
+       SDA3_MARK, SCL3_MARK,
+       SDA2_MARK, SCL2_MARK,
+       SDA1_MARK, SCL1_MARK,
+       SDA0_MARK, SCL0_MARK,
+       TEND0_PD_MARK, TEND0_PE_MARK, DACK0_PD_MARK, DACK0_PE_MARK,
+       DREQ0_PD_MARK, DREQ0_PE_MARK, TEND1_PD_MARK, TEND1_PE_MARK,
+       DACK1_PD_MARK, DACK1_PE_MARK, DREQ1_PD_MARK, DREQ1_PE_MARK,
+       DACK2_MARK, DREQ2_MARK, DACK3_MARK, DREQ3_MARK,
+       ADTRG_PD_MARK, ADTRG_PE_MARK,
+       D31_MARK, D30_MARK, D29_MARK, D28_MARK,
+       D27_MARK, D26_MARK, D25_MARK, D24_MARK,
+       D23_MARK, D22_MARK, D21_MARK, D20_MARK,
+       D19_MARK, D18_MARK, D17_MARK, D16_MARK,
+       A25_MARK, A24_MARK, A23_MARK, A22_MARK,
+       A21_MARK, CS4_MARK, MRES_MARK, BS_MARK,
+       IOIS16_MARK, CS1_MARK, CS6_CE1B_MARK, CE2B_MARK,
+       CS5_CE1A_MARK, CE2A_MARK, FRAME_MARK, WAIT_MARK,
+       RDWR_MARK, CKE_MARK, CASU_MARK, BREQ_MARK,
+       RASU_MARK, BACK_MARK, CASL_MARK, RASL_MARK,
+       WE3_DQMUU_AH_ICIO_WR_MARK, WE2_DQMUL_ICIORD_MARK,
+       WE1_DQMLU_WE_MARK, WE0_DQMLL_MARK,
+       CS3_MARK, CS2_MARK, A1_MARK, A0_MARK, CS7_MARK,
+       TIOC4D_MARK, TIOC4C_MARK, TIOC4B_MARK, TIOC4A_MARK,
+       TIOC3D_MARK, TIOC3C_MARK, TIOC3B_MARK, TIOC3A_MARK,
+       TIOC2B_MARK, TIOC1B_MARK, TIOC2A_MARK, TIOC1A_MARK,
+       TIOC0D_MARK, TIOC0C_MARK, TIOC0B_MARK, TIOC0A_MARK,
+       TCLKD_PD_MARK, TCLKC_PD_MARK, TCLKB_PD_MARK, TCLKA_PD_MARK,
+       TCLKD_PF_MARK, TCLKC_PF_MARK, TCLKB_PF_MARK, TCLKA_PF_MARK,
+       SCS0_PD_MARK, SSO0_PD_MARK, SSI0_PD_MARK, SSCK0_PD_MARK,
+       SCS0_PF_MARK, SSO0_PF_MARK, SSI0_PF_MARK, SSCK0_PF_MARK,
+       SCS1_PD_MARK, SSO1_PD_MARK, SSI1_PD_MARK, SSCK1_PD_MARK,
+       SCS1_PF_MARK, SSO1_PF_MARK, SSI1_PF_MARK, SSCK1_PF_MARK,
+       TXD0_MARK, RXD0_MARK, SCK0_MARK,
+       TXD1_MARK, RXD1_MARK, SCK1_MARK,
+       TXD2_MARK, RXD2_MARK, SCK2_MARK,
+       RTS3_MARK, CTS3_MARK, TXD3_MARK,
+       RXD3_MARK, SCK3_MARK,
+       AUDIO_CLK_MARK,
+       SSIDATA3_MARK, SSIWS3_MARK, SSISCK3_MARK,
+       SSIDATA2_MARK, SSIWS2_MARK, SSISCK2_MARK,
+       SSIDATA1_MARK, SSIWS1_MARK, SSISCK1_MARK,
+       SSIDATA0_MARK, SSIWS0_MARK, SSISCK0_MARK,
+       FCE_MARK, FRB_MARK,
+       NAF7_MARK, NAF6_MARK, NAF5_MARK, NAF4_MARK,
+       NAF3_MARK, NAF2_MARK, NAF1_MARK, NAF0_MARK,
+       FSC_MARK, FOE_MARK, FCDE_MARK, FWE_MARK,
+       LCD_VEPWC_MARK, LCD_VCPWC_MARK, LCD_CLK_MARK, LCD_FLM_MARK,
+       LCD_M_DISP_MARK, LCD_CL2_MARK, LCD_CL1_MARK, LCD_DON_MARK,
+       LCD_DATA15_MARK, LCD_DATA14_MARK, LCD_DATA13_MARK, LCD_DATA12_MARK,
+       LCD_DATA11_MARK, LCD_DATA10_MARK, LCD_DATA9_MARK, LCD_DATA8_MARK,
+       LCD_DATA7_MARK, LCD_DATA6_MARK, LCD_DATA5_MARK, LCD_DATA4_MARK,
+       LCD_DATA3_MARK, LCD_DATA2_MARK, LCD_DATA1_MARK, LCD_DATA0_MARK,
+       PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+
+       /* PA */
+       PINMUX_DATA(PA7_DATA, PA7_IN),
+       PINMUX_DATA(PA6_DATA, PA6_IN),
+       PINMUX_DATA(PA5_DATA, PA5_IN),
+       PINMUX_DATA(PA4_DATA, PA4_IN),
+       PINMUX_DATA(PA3_DATA, PA3_IN),
+       PINMUX_DATA(PA2_DATA, PA2_IN),
+       PINMUX_DATA(PA1_DATA, PA1_IN),
+       PINMUX_DATA(PA0_DATA, PA0_IN),
+
+       /* PB */
+       PINMUX_DATA(PB12_DATA, PB12MD_00, PB12_OUT),
+       PINMUX_DATA(WDTOVF_MARK, PB12MD_01),
+       PINMUX_DATA(IRQOUT_MARK, PB12MD_10, PB12IRQ_00),
+       PINMUX_DATA(REFOUT_MARK, PB12MD_10, PB12IRQ_01),
+       PINMUX_DATA(IRQOUT_REFOUT_MARK, PB12MD_10, PB12IRQ_10),
+       PINMUX_DATA(UBCTRG_MARK, PB12MD_11),
+
+       PINMUX_DATA(PB11_DATA, PB11MD_0, PB11_IN, PB11_OUT),
+       PINMUX_DATA(CTX1_MARK, PB11MD_1),
+
+       PINMUX_DATA(PB10_DATA, PB10MD_0, PB10_IN, PB10_OUT),
+       PINMUX_DATA(CRX1_MARK, PB10MD_1),
+
+       PINMUX_DATA(PB9_DATA, PB9MD_00, PB9_IN, PB9_OUT),
+       PINMUX_DATA(CTX0_MARK, PB9MD_01),
+       PINMUX_DATA(CTX0_CTX1_MARK, PB9MD_10),
+
+       PINMUX_DATA(PB8_DATA, PB8MD_00, PB8_IN, PB8_OUT),
+       PINMUX_DATA(CRX0_MARK, PB8MD_01),
+       PINMUX_DATA(CRX0_CRX1_MARK, PB8MD_10),
+
+       PINMUX_DATA(PB7_DATA, PB7MD_00, PB7_IN),
+       PINMUX_DATA(SDA3_MARK, PB7MD_01),
+       PINMUX_DATA(PINT7_PB_MARK, PB7MD_10),
+       PINMUX_DATA(IRQ7_PB_MARK, PB7MD_11),
+
+       PINMUX_DATA(PB6_DATA, PB6MD_00, PB6_IN),
+       PINMUX_DATA(SCL3_MARK, PB6MD_01),
+       PINMUX_DATA(PINT6_PB_MARK, PB6MD_10),
+       PINMUX_DATA(IRQ6_PB_MARK, PB6MD_11),
+
+       PINMUX_DATA(PB5_DATA, PB5MD_00, PB5_IN),
+       PINMUX_DATA(SDA2_MARK, PB6MD_01),
+       PINMUX_DATA(PINT5_PB_MARK, PB6MD_10),
+       PINMUX_DATA(IRQ5_PB_MARK, PB6MD_11),
+
+       PINMUX_DATA(PB4_DATA, PB4MD_00, PB4_IN),
+       PINMUX_DATA(SCL2_MARK, PB4MD_01),
+       PINMUX_DATA(PINT4_PB_MARK, PB4MD_10),
+       PINMUX_DATA(IRQ4_PB_MARK, PB4MD_11),
+
+       PINMUX_DATA(PB3_DATA, PB3MD_00, PB3_IN),
+       PINMUX_DATA(SDA1_MARK, PB3MD_01),
+       PINMUX_DATA(PINT3_PB_MARK, PB3MD_10),
+       PINMUX_DATA(IRQ3_PB_MARK, PB3MD_11),
+
+       PINMUX_DATA(PB2_DATA, PB2MD_00, PB2_IN),
+       PINMUX_DATA(SCL1_MARK, PB2MD_01),
+       PINMUX_DATA(PINT2_PB_MARK, PB2MD_10),
+       PINMUX_DATA(IRQ2_PB_MARK, PB2MD_11),
+
+       PINMUX_DATA(PB1_DATA, PB1MD_00, PB1_IN),
+       PINMUX_DATA(SDA0_MARK, PB1MD_01),
+       PINMUX_DATA(PINT1_PB_MARK, PB1MD_10),
+       PINMUX_DATA(IRQ1_PB_MARK, PB1MD_11),
+
+       PINMUX_DATA(PB0_DATA, PB0MD_00, PB0_IN),
+       PINMUX_DATA(SCL0_MARK, PB0MD_01),
+       PINMUX_DATA(PINT0_PB_MARK, PB0MD_10),
+       PINMUX_DATA(IRQ0_PB_MARK, PB0MD_11),
+
+       /* PC */
+       PINMUX_DATA(PC14_DATA, PC14MD_0, PC14_IN, PC14_OUT),
+       PINMUX_DATA(WAIT_MARK, PC14MD_1),
+
+       PINMUX_DATA(PC13_DATA, PC13MD_0, PC13_IN, PC13_OUT),
+       PINMUX_DATA(RDWR_MARK, PC13MD_1),
+
+       PINMUX_DATA(PC12_DATA, PC12MD_0, PC12_IN, PC12_OUT),
+       PINMUX_DATA(CKE_MARK, PC12MD_1),
+
+       PINMUX_DATA(PC11_DATA, PC11MD_00, PC11_IN, PC11_OUT),
+       PINMUX_DATA(CASU_MARK, PC11MD_01),
+       PINMUX_DATA(BREQ_MARK, PC11MD_10),
+
+       PINMUX_DATA(PC10_DATA, PC10MD_00, PC10_IN, PC10_OUT),
+       PINMUX_DATA(RASU_MARK, PC10MD_01),
+       PINMUX_DATA(BACK_MARK, PC10MD_10),
+
+       PINMUX_DATA(PC9_DATA, PC9MD_0, PC9_IN, PC9_OUT),
+       PINMUX_DATA(CASL_MARK, PC9MD_1),
+
+       PINMUX_DATA(PC8_DATA, PC8MD_0, PC8_IN, PC8_OUT),
+       PINMUX_DATA(RASL_MARK, PC8MD_1),
+
+       PINMUX_DATA(PC7_DATA, PC7MD_0, PC7_IN, PC7_OUT),
+       PINMUX_DATA(WE3_DQMUU_AH_ICIO_WR_MARK, PC7MD_1),
+
+       PINMUX_DATA(PC6_DATA, PC6MD_0, PC6_IN, PC6_OUT),
+       PINMUX_DATA(WE2_DQMUL_ICIORD_MARK, PC6MD_1),
+
+       PINMUX_DATA(PC5_DATA, PC5MD_0, PC5_IN, PC5_OUT),
+       PINMUX_DATA(WE1_DQMLU_WE_MARK, PC5MD_1),
+
+       PINMUX_DATA(PC4_DATA, PC4MD_0, PC4_IN, PC4_OUT),
+       PINMUX_DATA(WE0_DQMLL_MARK, PC4MD_1),
+
+       PINMUX_DATA(PC3_DATA, PC3MD_0, PC3_IN, PC3_OUT),
+       PINMUX_DATA(CS3_MARK, PC3MD_1),
+
+       PINMUX_DATA(PC2_DATA, PC2MD_0, PC2_IN, PC2_OUT),
+       PINMUX_DATA(CS2_MARK, PC2MD_1),
+
+       PINMUX_DATA(PC1_DATA, PC1MD_0, PC1_IN, PC1_OUT),
+       PINMUX_DATA(A1_MARK, PC1MD_1),
+
+       PINMUX_DATA(PC0_DATA, PC0MD_00, PC0_IN, PC0_OUT),
+       PINMUX_DATA(A0_MARK, PC0MD_01),
+       PINMUX_DATA(CS7_MARK, PC0MD_10),
+
+       /* PD */
+       PINMUX_DATA(PD15_DATA, PD15MD_000, PD15_IN, PD15_OUT),
+       PINMUX_DATA(D31_MARK, PD15MD_001),
+       PINMUX_DATA(PINT7_PD_MARK, PD15MD_010),
+       PINMUX_DATA(ADTRG_PD_MARK, PD15MD_100),
+       PINMUX_DATA(TIOC4D_MARK, PD15MD_101),
+
+       PINMUX_DATA(PD14_DATA, PD14MD_000, PD14_IN, PD14_OUT),
+       PINMUX_DATA(D30_MARK, PD14MD_001),
+       PINMUX_DATA(PINT6_PD_MARK, PD14MD_010),
+       PINMUX_DATA(TIOC4C_MARK, PD14MD_101),
+
+       PINMUX_DATA(PD13_DATA, PD13MD_000, PD13_IN, PD13_OUT),
+       PINMUX_DATA(D29_MARK, PD13MD_001),
+       PINMUX_DATA(PINT5_PD_MARK, PD13MD_010),
+       PINMUX_DATA(TEND1_PD_MARK, PD13MD_100),
+       PINMUX_DATA(TIOC4B_MARK, PD13MD_101),
+
+       PINMUX_DATA(PD12_DATA, PD12MD_000, PD12_IN, PD12_OUT),
+       PINMUX_DATA(D28_MARK, PD12MD_001),
+       PINMUX_DATA(PINT4_PD_MARK, PD12MD_010),
+       PINMUX_DATA(DACK1_PD_MARK, PD12MD_100),
+       PINMUX_DATA(TIOC4A_MARK, PD12MD_101),
+
+       PINMUX_DATA(PD11_DATA, PD11MD_000, PD11_IN, PD11_OUT),
+       PINMUX_DATA(D27_MARK, PD11MD_001),
+       PINMUX_DATA(PINT3_PD_MARK, PD11MD_010),
+       PINMUX_DATA(DREQ1_PD_MARK, PD11MD_100),
+       PINMUX_DATA(TIOC3D_MARK, PD11MD_101),
+
+       PINMUX_DATA(PD10_DATA, PD10MD_000, PD10_IN, PD10_OUT),
+       PINMUX_DATA(D26_MARK, PD10MD_001),
+       PINMUX_DATA(PINT2_PD_MARK, PD10MD_010),
+       PINMUX_DATA(TEND0_PD_MARK, PD10MD_100),
+       PINMUX_DATA(TIOC3C_MARK, PD10MD_101),
+
+       PINMUX_DATA(PD9_DATA, PD9MD_000, PD9_IN, PD9_OUT),
+       PINMUX_DATA(D25_MARK, PD9MD_001),
+       PINMUX_DATA(PINT1_PD_MARK, PD9MD_010),
+       PINMUX_DATA(DACK0_PD_MARK, PD9MD_100),
+       PINMUX_DATA(TIOC3B_MARK, PD9MD_101),
+
+       PINMUX_DATA(PD8_DATA, PD8MD_000, PD8_IN, PD8_OUT),
+       PINMUX_DATA(D24_MARK, PD8MD_001),
+       PINMUX_DATA(PINT0_PD_MARK, PD8MD_010),
+       PINMUX_DATA(DREQ0_PD_MARK, PD8MD_100),
+       PINMUX_DATA(TIOC3A_MARK, PD8MD_101),
+
+       PINMUX_DATA(PD7_DATA, PD7MD_000, PD7_IN, PD7_OUT),
+       PINMUX_DATA(D23_MARK, PD7MD_001),
+       PINMUX_DATA(IRQ7_PD_MARK, PD7MD_010),
+       PINMUX_DATA(SCS1_PD_MARK, PD7MD_011),
+       PINMUX_DATA(TCLKD_PD_MARK, PD7MD_100),
+       PINMUX_DATA(TIOC2B_MARK, PD7MD_101),
+
+       PINMUX_DATA(PD6_DATA, PD6MD_000, PD6_IN, PD6_OUT),
+       PINMUX_DATA(D22_MARK, PD6MD_001),
+       PINMUX_DATA(IRQ6_PD_MARK, PD6MD_010),
+       PINMUX_DATA(SSO1_PD_MARK, PD6MD_011),
+       PINMUX_DATA(TCLKC_PD_MARK, PD6MD_100),
+       PINMUX_DATA(TIOC2A_MARK, PD6MD_101),
+
+       PINMUX_DATA(PD5_DATA, PD5MD_000, PD5_IN, PD5_OUT),
+       PINMUX_DATA(D21_MARK, PD5MD_001),
+       PINMUX_DATA(IRQ5_PD_MARK, PD5MD_010),
+       PINMUX_DATA(SSI1_PD_MARK, PD5MD_011),
+       PINMUX_DATA(TCLKB_PD_MARK, PD5MD_100),
+       PINMUX_DATA(TIOC1B_MARK, PD5MD_101),
+
+       PINMUX_DATA(PD4_DATA, PD4MD_000, PD4_IN, PD4_OUT),
+       PINMUX_DATA(D20_MARK, PD4MD_001),
+       PINMUX_DATA(IRQ4_PD_MARK, PD4MD_010),
+       PINMUX_DATA(SSCK1_PD_MARK, PD4MD_011),
+       PINMUX_DATA(TCLKA_PD_MARK, PD4MD_100),
+       PINMUX_DATA(TIOC1A_MARK, PD4MD_101),
+
+       PINMUX_DATA(PD3_DATA, PD3MD_000, PD3_IN, PD3_OUT),
+       PINMUX_DATA(D19_MARK, PD3MD_001),
+       PINMUX_DATA(IRQ3_PD_MARK, PD3MD_010),
+       PINMUX_DATA(SCS0_PD_MARK, PD3MD_011),
+       PINMUX_DATA(DACK3_MARK, PD3MD_100),
+       PINMUX_DATA(TIOC0D_MARK, PD3MD_101),
+
+       PINMUX_DATA(PD2_DATA, PD2MD_000, PD2_IN, PD2_OUT),
+       PINMUX_DATA(D18_MARK, PD2MD_001),
+       PINMUX_DATA(IRQ2_PD_MARK, PD2MD_010),
+       PINMUX_DATA(SSO0_PD_MARK, PD2MD_011),
+       PINMUX_DATA(DREQ3_MARK, PD2MD_100),
+       PINMUX_DATA(TIOC0C_MARK, PD2MD_101),
+
+       PINMUX_DATA(PD1_DATA, PD1MD_000, PD1_IN, PD1_OUT),
+       PINMUX_DATA(D17_MARK, PD1MD_001),
+       PINMUX_DATA(IRQ1_PD_MARK, PD1MD_010),
+       PINMUX_DATA(SSI0_PD_MARK, PD1MD_011),
+       PINMUX_DATA(DACK2_MARK, PD1MD_100),
+       PINMUX_DATA(TIOC0B_MARK, PD1MD_101),
+
+       PINMUX_DATA(PD0_DATA, PD0MD_000, PD0_IN, PD0_OUT),
+       PINMUX_DATA(D16_MARK, PD0MD_001),
+       PINMUX_DATA(IRQ0_PD_MARK, PD0MD_010),
+       PINMUX_DATA(SSCK0_PD_MARK, PD0MD_011),
+       PINMUX_DATA(DREQ2_MARK, PD0MD_100),
+       PINMUX_DATA(TIOC0A_MARK, PD0MD_101),
+
+       /* PE */
+       PINMUX_DATA(PE15_DATA, PE15MD_00, PE15_IN, PE15_OUT),
+       PINMUX_DATA(IOIS16_MARK, PE15MD_01),
+       PINMUX_DATA(RTS3_MARK, PE15MD_11),
+
+       PINMUX_DATA(PE14_DATA, PE14MD_00, PE14_IN, PE14_OUT),
+       PINMUX_DATA(CS1_MARK, PE14MD_01),
+       PINMUX_DATA(CTS3_MARK, PE14MD_11),
+
+       PINMUX_DATA(PE13_DATA, PE13MD_00, PE13_IN, PE13_OUT),
+       PINMUX_DATA(TXD3_MARK, PE13MD_11),
+
+       PINMUX_DATA(PE12_DATA, PE12MD_00, PE12_IN, PE12_OUT),
+       PINMUX_DATA(RXD3_MARK, PE12MD_11),
+
+       PINMUX_DATA(PE11_DATA, PE11MD_000, PE11_IN, PE11_OUT),
+       PINMUX_DATA(CS6_CE1B_MARK, PE11MD_001),
+       PINMUX_DATA(IRQ7_PE_MARK, PE11MD_010),
+       PINMUX_DATA(TEND1_PE_MARK, PE11MD_100),
+
+       PINMUX_DATA(PE10_DATA, PE10MD_000, PE10_IN, PE10_OUT),
+       PINMUX_DATA(CE2B_MARK, PE10MD_001),
+       PINMUX_DATA(IRQ6_PE_MARK, PE10MD_010),
+       PINMUX_DATA(TEND0_PE_MARK, PE10MD_100),
+
+       PINMUX_DATA(PE9_DATA, PE9MD_00, PE9_IN, PE9_OUT),
+       PINMUX_DATA(CS5_CE1A_MARK, PE9MD_01),
+       PINMUX_DATA(IRQ5_PE_MARK, PE9MD_10),
+       PINMUX_DATA(SCK3_MARK, PE9MD_11),
+
+       PINMUX_DATA(PE8_DATA, PE8MD_00, PE8_IN, PE8_OUT),
+       PINMUX_DATA(CE2A_MARK, PE8MD_01),
+       PINMUX_DATA(IRQ4_PE_MARK, PE8MD_10),
+       PINMUX_DATA(SCK2_MARK, PE8MD_11),
+
+       PINMUX_DATA(PE7_DATA, PE7MD_000, PE7_IN, PE7_OUT),
+       PINMUX_DATA(FRAME_MARK, PE7MD_001),
+       PINMUX_DATA(IRQ3_PE_MARK, PE7MD_010),
+       PINMUX_DATA(TXD2_MARK, PE7MD_011),
+       PINMUX_DATA(DACK1_PE_MARK, PE7MD_100),
+
+       PINMUX_DATA(PE6_DATA, PE6MD_000, PE6_IN, PE6_OUT),
+       PINMUX_DATA(A25_MARK, PE6MD_001),
+       PINMUX_DATA(IRQ2_PE_MARK, PE6MD_010),
+       PINMUX_DATA(RXD2_MARK, PE6MD_011),
+       PINMUX_DATA(DREQ1_PE_MARK, PE6MD_100),
+
+       PINMUX_DATA(PE5_DATA, PE5MD_000, PE5_IN, PE5_OUT),
+       PINMUX_DATA(A24_MARK, PE5MD_001),
+       PINMUX_DATA(IRQ1_PE_MARK, PE5MD_010),
+       PINMUX_DATA(TXD1_MARK, PE5MD_011),
+       PINMUX_DATA(DACK0_PE_MARK, PE5MD_100),
+
+       PINMUX_DATA(PE4_DATA, PE4MD_000, PE4_IN, PE4_OUT),
+       PINMUX_DATA(A23_MARK, PE4MD_001),
+       PINMUX_DATA(IRQ0_PE_MARK, PE4MD_010),
+       PINMUX_DATA(RXD1_MARK, PE4MD_011),
+       PINMUX_DATA(DREQ0_PE_MARK, PE4MD_100),
+
+       PINMUX_DATA(PE3_DATA, PE3MD_00, PE3_IN, PE3_OUT),
+       PINMUX_DATA(A22_MARK, PE3MD_01),
+       PINMUX_DATA(SCK1_MARK, PE3MD_11),
+
+       PINMUX_DATA(PE2_DATA, PE2MD_00, PE2_IN, PE2_OUT),
+       PINMUX_DATA(A21_MARK, PE2MD_01),
+       PINMUX_DATA(SCK0_MARK, PE2MD_11),
+
+       PINMUX_DATA(PE1_DATA, PE1MD_00, PE1_IN, PE1_OUT),
+       PINMUX_DATA(CS4_MARK, PE1MD_01),
+       PINMUX_DATA(MRES_MARK, PE1MD_10),
+       PINMUX_DATA(TXD0_MARK, PE1MD_11),
+
+       PINMUX_DATA(PE0_DATA, PE0MD_000, PE0_IN, PE0_OUT),
+       PINMUX_DATA(BS_MARK, PE0MD_001),
+       PINMUX_DATA(RXD0_MARK, PE0MD_011),
+       PINMUX_DATA(ADTRG_PE_MARK, PE0MD_100),
+
+       /* PF */
+       PINMUX_DATA(PF30_DATA, PF30MD_0, PF30_IN, PF30_OUT),
+       PINMUX_DATA(AUDIO_CLK_MARK, PF30MD_1),
+
+       PINMUX_DATA(PF29_DATA, PF29MD_0, PF29_IN, PF29_OUT),
+       PINMUX_DATA(SSIDATA3_MARK, PF29MD_1),
+
+       PINMUX_DATA(PF28_DATA, PF28MD_0, PF28_IN, PF28_OUT),
+       PINMUX_DATA(SSIWS3_MARK, PF28MD_1),
+
+       PINMUX_DATA(PF27_DATA, PF27MD_0, PF27_IN, PF27_OUT),
+       PINMUX_DATA(SSISCK3_MARK, PF27MD_1),
+
+       PINMUX_DATA(PF26_DATA, PF26MD_0, PF26_IN, PF26_OUT),
+       PINMUX_DATA(SSIDATA2_MARK, PF26MD_1),
+
+       PINMUX_DATA(PF25_DATA, PF25MD_0, PF25_IN, PF25_OUT),
+       PINMUX_DATA(SSIWS2_MARK, PF25MD_1),
+
+       PINMUX_DATA(PF24_DATA, PF24MD_0, PF24_IN, PF24_OUT),
+       PINMUX_DATA(SSISCK2_MARK, PF24MD_1),
+
+       PINMUX_DATA(PF23_DATA, PF23MD_00, PF23_IN, PF23_OUT),
+       PINMUX_DATA(SSIDATA1_MARK, PF23MD_01),
+       PINMUX_DATA(LCD_VEPWC_MARK, PF23MD_10),
+
+       PINMUX_DATA(PF22_DATA, PF22MD_00, PF22_IN, PF22_OUT),
+       PINMUX_DATA(SSIWS1_MARK, PF22MD_01),
+       PINMUX_DATA(LCD_VCPWC_MARK, PF22MD_10),
+
+       PINMUX_DATA(PF21_DATA, PF21MD_00, PF21_IN, PF21_OUT),
+       PINMUX_DATA(SSISCK1_MARK, PF21MD_01),
+       PINMUX_DATA(LCD_CLK_MARK, PF21MD_10),
+
+       PINMUX_DATA(PF20_DATA, PF20MD_00, PF20_IN, PF20_OUT),
+       PINMUX_DATA(SSIDATA0_MARK, PF20MD_01),
+       PINMUX_DATA(LCD_FLM_MARK, PF20MD_10),
+
+       PINMUX_DATA(PF19_DATA, PF19MD_00, PF19_IN, PF19_OUT),
+       PINMUX_DATA(SSIWS0_MARK, PF19MD_01),
+       PINMUX_DATA(LCD_M_DISP_MARK, PF19MD_10),
+
+       PINMUX_DATA(PF18_DATA, PF18MD_00, PF18_IN, PF18_OUT),
+       PINMUX_DATA(SSISCK0_MARK, PF18MD_01),
+       PINMUX_DATA(LCD_CL2_MARK, PF18MD_10),
+
+       PINMUX_DATA(PF17_DATA, PF17MD_00, PF17_IN, PF17_OUT),
+       PINMUX_DATA(FCE_MARK, PF17MD_01),
+       PINMUX_DATA(LCD_CL1_MARK, PF17MD_10),
+
+       PINMUX_DATA(PF16_DATA, PF16MD_00, PF16_IN, PF16_OUT),
+       PINMUX_DATA(FRB_MARK, PF16MD_01),
+       PINMUX_DATA(LCD_DON_MARK, PF16MD_10),
+
+       PINMUX_DATA(PF15_DATA, PF15MD_00, PF15_IN, PF15_OUT),
+       PINMUX_DATA(NAF7_MARK, PF15MD_01),
+       PINMUX_DATA(LCD_DATA15_MARK, PF15MD_10),
+
+       PINMUX_DATA(PF14_DATA, PF14MD_00, PF14_IN, PF14_OUT),
+       PINMUX_DATA(NAF6_MARK, PF14MD_01),
+       PINMUX_DATA(LCD_DATA14_MARK, PF14MD_10),
+
+       PINMUX_DATA(PF13_DATA, PF13MD_00, PF13_IN, PF13_OUT),
+       PINMUX_DATA(NAF5_MARK, PF13MD_01),
+       PINMUX_DATA(LCD_DATA13_MARK, PF13MD_10),
+
+       PINMUX_DATA(PF12_DATA, PF12MD_00, PF12_IN, PF12_OUT),
+       PINMUX_DATA(NAF4_MARK, PF12MD_01),
+       PINMUX_DATA(LCD_DATA12_MARK, PF12MD_10),
+
+       PINMUX_DATA(PF11_DATA, PF11MD_00, PF11_IN, PF11_OUT),
+       PINMUX_DATA(NAF3_MARK, PF11MD_01),
+       PINMUX_DATA(LCD_DATA11_MARK, PF11MD_10),
+
+       PINMUX_DATA(PF10_DATA, PF10MD_00, PF10_IN, PF10_OUT),
+       PINMUX_DATA(NAF2_MARK, PF10MD_01),
+       PINMUX_DATA(LCD_DATA10_MARK, PF10MD_10),
+
+       PINMUX_DATA(PF9_DATA, PF9MD_00, PF9_IN, PF9_OUT),
+       PINMUX_DATA(NAF1_MARK, PF9MD_01),
+       PINMUX_DATA(LCD_DATA9_MARK, PF9MD_10),
+
+       PINMUX_DATA(PF8_DATA, PF8MD_00, PF8_IN, PF8_OUT),
+       PINMUX_DATA(NAF0_MARK, PF8MD_01),
+       PINMUX_DATA(LCD_DATA8_MARK, PF8MD_10),
+
+       PINMUX_DATA(PF7_DATA, PF7MD_00, PF7_IN, PF7_OUT),
+       PINMUX_DATA(FSC_MARK, PF7MD_01),
+       PINMUX_DATA(LCD_DATA7_MARK, PF7MD_10),
+       PINMUX_DATA(SCS1_PF_MARK, PF7MD_11),
+
+       PINMUX_DATA(PF6_DATA, PF6MD_00, PF6_IN, PF6_OUT),
+       PINMUX_DATA(FOE_MARK, PF6MD_01),
+       PINMUX_DATA(LCD_DATA6_MARK, PF6MD_10),
+       PINMUX_DATA(SSO1_PF_MARK, PF6MD_11),
+
+       PINMUX_DATA(PF5_DATA, PF5MD_00, PF5_IN, PF5_OUT),
+       PINMUX_DATA(FCDE_MARK, PF5MD_01),
+       PINMUX_DATA(LCD_DATA5_MARK, PF5MD_10),
+       PINMUX_DATA(SSI1_PF_MARK, PF5MD_11),
+
+       PINMUX_DATA(PF4_DATA, PF4MD_00, PF4_IN, PF4_OUT),
+       PINMUX_DATA(FWE_MARK, PF4MD_01),
+       PINMUX_DATA(LCD_DATA4_MARK, PF4MD_10),
+       PINMUX_DATA(SSCK1_PF_MARK, PF4MD_11),
+
+       PINMUX_DATA(PF3_DATA, PF3MD_00, PF3_IN, PF3_OUT),
+       PINMUX_DATA(TCLKD_PF_MARK, PF3MD_01),
+       PINMUX_DATA(LCD_DATA3_MARK, PF3MD_10),
+       PINMUX_DATA(SCS0_PF_MARK, PF3MD_11),
+
+       PINMUX_DATA(PF2_DATA, PF2MD_00, PF2_IN, PF2_OUT),
+       PINMUX_DATA(TCLKC_PF_MARK, PF2MD_01),
+       PINMUX_DATA(LCD_DATA2_MARK, PF2MD_10),
+       PINMUX_DATA(SSO0_PF_MARK, PF2MD_11),
+
+       PINMUX_DATA(PF1_DATA, PF1MD_00, PF1_IN, PF1_OUT),
+       PINMUX_DATA(TCLKB_PF_MARK, PF1MD_01),
+       PINMUX_DATA(LCD_DATA1_MARK, PF1MD_10),
+       PINMUX_DATA(SSI0_PF_MARK, PF1MD_11),
+
+       PINMUX_DATA(PF0_DATA, PF0MD_00, PF0_IN, PF0_OUT),
+       PINMUX_DATA(TCLKA_PF_MARK, PF0MD_01),
+       PINMUX_DATA(LCD_DATA0_MARK, PF0MD_10),
+       PINMUX_DATA(SSCK0_PF_MARK, PF0MD_11),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+
+       /* PA */
+       PINMUX_GPIO(GPIO_PA7, PA7_DATA),
+       PINMUX_GPIO(GPIO_PA6, PA6_DATA),
+       PINMUX_GPIO(GPIO_PA5, PA5_DATA),
+       PINMUX_GPIO(GPIO_PA4, PA4_DATA),
+       PINMUX_GPIO(GPIO_PA3, PA3_DATA),
+       PINMUX_GPIO(GPIO_PA2, PA2_DATA),
+       PINMUX_GPIO(GPIO_PA1, PA1_DATA),
+       PINMUX_GPIO(GPIO_PA0, PA0_DATA),
+
+       /* PB */
+       PINMUX_GPIO(GPIO_PB12, PB12_DATA),
+       PINMUX_GPIO(GPIO_PB11, PB11_DATA),
+       PINMUX_GPIO(GPIO_PB10, PB10_DATA),
+       PINMUX_GPIO(GPIO_PB9, PB9_DATA),
+       PINMUX_GPIO(GPIO_PB8, PB8_DATA),
+       PINMUX_GPIO(GPIO_PB7, PB7_DATA),
+       PINMUX_GPIO(GPIO_PB6, PB6_DATA),
+       PINMUX_GPIO(GPIO_PB5, PB5_DATA),
+       PINMUX_GPIO(GPIO_PB4, PB4_DATA),
+       PINMUX_GPIO(GPIO_PB3, PB3_DATA),
+       PINMUX_GPIO(GPIO_PB2, PB2_DATA),
+       PINMUX_GPIO(GPIO_PB1, PB1_DATA),
+       PINMUX_GPIO(GPIO_PB0, PB0_DATA),
+
+       /* PC */
+       PINMUX_GPIO(GPIO_PC14, PC14_DATA),
+       PINMUX_GPIO(GPIO_PC13, PC13_DATA),
+       PINMUX_GPIO(GPIO_PC12, PC12_DATA),
+       PINMUX_GPIO(GPIO_PC11, PC11_DATA),
+       PINMUX_GPIO(GPIO_PC10, PC10_DATA),
+       PINMUX_GPIO(GPIO_PC9, PC9_DATA),
+       PINMUX_GPIO(GPIO_PC8, PC8_DATA),
+       PINMUX_GPIO(GPIO_PC7, PC7_DATA),
+       PINMUX_GPIO(GPIO_PC6, PC6_DATA),
+       PINMUX_GPIO(GPIO_PC5, PC5_DATA),
+       PINMUX_GPIO(GPIO_PC4, PC4_DATA),
+       PINMUX_GPIO(GPIO_PC3, PC3_DATA),
+       PINMUX_GPIO(GPIO_PC2, PC2_DATA),
+       PINMUX_GPIO(GPIO_PC1, PC1_DATA),
+       PINMUX_GPIO(GPIO_PC0, PC0_DATA),
+
+       /* PD */
+       PINMUX_GPIO(GPIO_PD15, PD15_DATA),
+       PINMUX_GPIO(GPIO_PD14, PD14_DATA),
+       PINMUX_GPIO(GPIO_PD13, PD13_DATA),
+       PINMUX_GPIO(GPIO_PD12, PD12_DATA),
+       PINMUX_GPIO(GPIO_PD11, PD11_DATA),
+       PINMUX_GPIO(GPIO_PD10, PD10_DATA),
+       PINMUX_GPIO(GPIO_PD9, PD9_DATA),
+       PINMUX_GPIO(GPIO_PD8, PD8_DATA),
+       PINMUX_GPIO(GPIO_PD7, PD7_DATA),
+       PINMUX_GPIO(GPIO_PD6, PD6_DATA),
+       PINMUX_GPIO(GPIO_PD5, PD5_DATA),
+       PINMUX_GPIO(GPIO_PD4, PD4_DATA),
+       PINMUX_GPIO(GPIO_PD3, PD3_DATA),
+       PINMUX_GPIO(GPIO_PD2, PD2_DATA),
+       PINMUX_GPIO(GPIO_PD1, PD1_DATA),
+       PINMUX_GPIO(GPIO_PD0, PD0_DATA),
+
+       /* PE */
+       PINMUX_GPIO(GPIO_PE15, PE15_DATA),
+       PINMUX_GPIO(GPIO_PE14, PE14_DATA),
+       PINMUX_GPIO(GPIO_PE13, PE13_DATA),
+       PINMUX_GPIO(GPIO_PE12, PE12_DATA),
+       PINMUX_GPIO(GPIO_PE11, PE11_DATA),
+       PINMUX_GPIO(GPIO_PE10, PE10_DATA),
+       PINMUX_GPIO(GPIO_PE9, PE9_DATA),
+       PINMUX_GPIO(GPIO_PE8, PE8_DATA),
+       PINMUX_GPIO(GPIO_PE7, PE7_DATA),
+       PINMUX_GPIO(GPIO_PE6, PE6_DATA),
+       PINMUX_GPIO(GPIO_PE5, PE5_DATA),
+       PINMUX_GPIO(GPIO_PE4, PE4_DATA),
+       PINMUX_GPIO(GPIO_PE3, PE3_DATA),
+       PINMUX_GPIO(GPIO_PE2, PE2_DATA),
+       PINMUX_GPIO(GPIO_PE1, PE1_DATA),
+       PINMUX_GPIO(GPIO_PE0, PE0_DATA),
+
+       /* PF */
+       PINMUX_GPIO(GPIO_PF30, PF30_DATA),
+       PINMUX_GPIO(GPIO_PF29, PF29_DATA),
+       PINMUX_GPIO(GPIO_PF28, PF28_DATA),
+       PINMUX_GPIO(GPIO_PF27, PF27_DATA),
+       PINMUX_GPIO(GPIO_PF26, PF26_DATA),
+       PINMUX_GPIO(GPIO_PF25, PF25_DATA),
+       PINMUX_GPIO(GPIO_PF24, PF24_DATA),
+       PINMUX_GPIO(GPIO_PF23, PF23_DATA),
+       PINMUX_GPIO(GPIO_PF22, PF22_DATA),
+       PINMUX_GPIO(GPIO_PF21, PF21_DATA),
+       PINMUX_GPIO(GPIO_PF20, PF20_DATA),
+       PINMUX_GPIO(GPIO_PF19, PF19_DATA),
+       PINMUX_GPIO(GPIO_PF18, PF18_DATA),
+       PINMUX_GPIO(GPIO_PF17, PF17_DATA),
+       PINMUX_GPIO(GPIO_PF16, PF16_DATA),
+       PINMUX_GPIO(GPIO_PF15, PF15_DATA),
+       PINMUX_GPIO(GPIO_PF14, PF14_DATA),
+       PINMUX_GPIO(GPIO_PF13, PF13_DATA),
+       PINMUX_GPIO(GPIO_PF12, PF12_DATA),
+       PINMUX_GPIO(GPIO_PF11, PF11_DATA),
+       PINMUX_GPIO(GPIO_PF10, PF10_DATA),
+       PINMUX_GPIO(GPIO_PF9, PF9_DATA),
+       PINMUX_GPIO(GPIO_PF8, PF8_DATA),
+       PINMUX_GPIO(GPIO_PF7, PF7_DATA),
+       PINMUX_GPIO(GPIO_PF6, PF6_DATA),
+       PINMUX_GPIO(GPIO_PF5, PF5_DATA),
+       PINMUX_GPIO(GPIO_PF4, PF4_DATA),
+       PINMUX_GPIO(GPIO_PF3, PF3_DATA),
+       PINMUX_GPIO(GPIO_PF2, PF2_DATA),
+       PINMUX_GPIO(GPIO_PF1, PF1_DATA),
+       PINMUX_GPIO(GPIO_PF0, PF0_DATA),
+
+       /* INTC */
+       PINMUX_GPIO(GPIO_FN_PINT7_PB, PINT7_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT6_PB, PINT6_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT5_PB, PINT5_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT4_PB, PINT4_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT3_PB, PINT3_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT2_PB, PINT2_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT1_PB, PINT1_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT0_PB, PINT0_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT7_PD, PINT7_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT6_PD, PINT6_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT5_PD, PINT5_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT4_PD, PINT4_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT3_PD, PINT3_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT2_PD, PINT2_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT1_PD, PINT1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_PINT0_PD, PINT0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ7_PB, IRQ7_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ6_PB, IRQ6_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ5_PB, IRQ5_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ4_PB, IRQ4_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3_PB, IRQ3_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2_PB, IRQ2_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1_PB, IRQ1_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ0_PB, IRQ0_PB_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ7_PD, IRQ7_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ6_PD, IRQ6_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ5_PD, IRQ5_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ4_PD, IRQ4_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3_PD, IRQ3_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2_PD, IRQ2_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1_PD, IRQ1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ0_PD, IRQ0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ7_PE, IRQ7_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ6_PE, IRQ6_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ5_PE, IRQ5_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ4_PE, IRQ4_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3_PE, IRQ3_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2_PE, IRQ2_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1_PE, IRQ1_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ0_PE, IRQ0_PE_MARK),
+
+       PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQOUT, IRQOUT_MARK),
+       PINMUX_GPIO(GPIO_FN_REFOUT, REFOUT_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQOUT_REFOUT, IRQOUT_REFOUT_MARK),
+       PINMUX_GPIO(GPIO_FN_UBCTRG, UBCTRG_MARK),
+
+       /* CAN */
+       PINMUX_GPIO(GPIO_FN_CTX1, CTX1_MARK),
+       PINMUX_GPIO(GPIO_FN_CRX1, CRX1_MARK),
+       PINMUX_GPIO(GPIO_FN_CTX0, CTX0_MARK),
+       PINMUX_GPIO(GPIO_FN_CTX0_CTX1, CTX0_CTX1_MARK),
+       PINMUX_GPIO(GPIO_FN_CRX0, CRX0_MARK),
+       PINMUX_GPIO(GPIO_FN_CRX0_CRX1, CRX0_CRX1_MARK),
+
+       /* IIC3 */
+       PINMUX_GPIO(GPIO_FN_SDA3, SDA3_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL3, SCL3_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA2, SDA2_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL2, SCL2_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA1, SDA1_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL1, SCL1_MARK),
+       PINMUX_GPIO(GPIO_FN_SDA0, SDA0_MARK),
+       PINMUX_GPIO(GPIO_FN_SCL0, SCL0_MARK),
+
+       /* DMAC */
+       PINMUX_GPIO(GPIO_FN_TEND0_PD, TEND0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND0_PE, TEND0_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0_PD, DACK0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0_PE, DACK0_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0_PD, DREQ0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0_PE, DREQ0_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND1_PD, TEND1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND1_PE, TEND1_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK1_PD, DACK1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK1_PE, DACK1_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1_PD, DREQ1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1_PE, DREQ1_PE_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK2, DACK2_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ2, DREQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK3, DACK3_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ3, DREQ3_MARK),
+
+       /* ADC */
+       PINMUX_GPIO(GPIO_FN_ADTRG_PD, ADTRG_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG_PE, ADTRG_PE_MARK),
+
+       /* BSC */
+       PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
+       PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
+       PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
+       PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
+       PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
+       PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
+       PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
+       PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
+       PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
+       PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
+       PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
+       PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
+       PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
+       PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
+       PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
+       PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
+       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+       PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+       PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+       PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
+       PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
+       PINMUX_GPIO(GPIO_FN_MRES, MRES_MARK),
+       PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
+       PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+       PINMUX_GPIO(GPIO_FN_CS1, CS1_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6_CE1B, CS6_CE1B_MARK),
+       PINMUX_GPIO(GPIO_FN_CE2B, CE2B_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5_CE1A, CS5_CE1A_MARK),
+       PINMUX_GPIO(GPIO_FN_CE2A, CE2A_MARK),
+       PINMUX_GPIO(GPIO_FN_FRAME, FRAME_MARK),
+       PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
+       PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
+       PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
+       PINMUX_GPIO(GPIO_FN_CASU, CASU_MARK),
+       PINMUX_GPIO(GPIO_FN_BREQ, BREQ_MARK),
+       PINMUX_GPIO(GPIO_FN_RASU, RASU_MARK),
+       PINMUX_GPIO(GPIO_FN_BACK, BACK_MARK),
+       PINMUX_GPIO(GPIO_FN_CASL, CASL_MARK),
+       PINMUX_GPIO(GPIO_FN_RASL, RASL_MARK),
+       PINMUX_GPIO(GPIO_FN_WE3_DQMUU_AH_ICIO_WR, WE3_DQMUU_AH_ICIO_WR_MARK),
+       PINMUX_GPIO(GPIO_FN_WE2_DQMUL_ICIORD, WE2_DQMUL_ICIORD_MARK),
+       PINMUX_GPIO(GPIO_FN_WE1_DQMLU_WE, WE1_DQMLU_WE_MARK),
+       PINMUX_GPIO(GPIO_FN_WE0_DQMLL, WE0_DQMLL_MARK),
+       PINMUX_GPIO(GPIO_FN_CS3, CS3_MARK),
+       PINMUX_GPIO(GPIO_FN_CS2, CS2_MARK),
+       PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
+       PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
+       PINMUX_GPIO(GPIO_FN_CS7, CS7_MARK),
+
+       /* TMU */
+       PINMUX_GPIO(GPIO_FN_TIOC4D, TIOC4D_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC4C, TIOC4C_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC4B, TIOC4B_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC4A, TIOC4A_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC3D, TIOC3D_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC3C, TIOC3C_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC3B, TIOC3B_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC3A, TIOC3A_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC2B, TIOC2B_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC1B, TIOC1B_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC2A, TIOC2A_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC1A, TIOC1A_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC0D, TIOC0D_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC0C, TIOC0C_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC0B, TIOC0B_MARK),
+       PINMUX_GPIO(GPIO_FN_TIOC0A, TIOC0A_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKD_PD, TCLKD_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKC_PD, TCLKC_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKB_PD, TCLKB_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKA_PD, TCLKA_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKD_PF, TCLKD_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKC_PF, TCLKC_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKB_PF, TCLKB_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLKA_PF, TCLKA_PF_MARK),
+
+       /* SSU */
+       PINMUX_GPIO(GPIO_FN_SCS0_PD, SCS0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SSO0_PD, SSO0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SSI0_PD, SSI0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SSCK0_PD, SSCK0_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCS0_PF, SCS0_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_SSO0_PF, SSO0_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_SSI0_PF, SSI0_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_SSCK0_PF, SSCK0_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_SCS1_PD, SCS1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SSO1_PD, SSO1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SSI1_PD, SSI1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SSCK1_PD, SSCK1_PD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCS1_PF, SCS1_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_SSO1_PF, SSO1_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_SSI1_PF, SSI1_PF_MARK),
+       PINMUX_GPIO(GPIO_FN_SSCK1_PF, SSCK1_PF_MARK),
+
+       /* SCIF */
+       PINMUX_GPIO(GPIO_FN_TXD0, TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD0, RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK0, SCK0_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD1, TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD1, RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK1, SCK1_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD3, TXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+
+       /* SSI */
+       PINMUX_GPIO(GPIO_FN_AUDIO_CLK, AUDIO_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIDATA3, SSIDATA3_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIWS3, SSIWS3_MARK),
+       PINMUX_GPIO(GPIO_FN_SSISCK3, SSISCK3_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIDATA2, SSIDATA2_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIWS2, SSIWS2_MARK),
+       PINMUX_GPIO(GPIO_FN_SSISCK2, SSISCK2_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIDATA1, SSIDATA1_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIWS1, SSIWS1_MARK),
+       PINMUX_GPIO(GPIO_FN_SSISCK1, SSISCK1_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIDATA0, SSIDATA0_MARK),
+       PINMUX_GPIO(GPIO_FN_SSIWS0, SSIWS0_MARK),
+       PINMUX_GPIO(GPIO_FN_SSISCK0, SSISCK0_MARK),
+
+       /* FLCTL */
+       PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
+       PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF7, NAF7_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF6, NAF6_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF5, NAF5_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF4, NAF4_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF3, NAF3_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF2, NAF2_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF1, NAF1_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF0, NAF0_MARK),
+       PINMUX_GPIO(GPIO_FN_FSC, FSC_MARK),
+       PINMUX_GPIO(GPIO_FN_FOE, FOE_MARK),
+       PINMUX_GPIO(GPIO_FN_FCDE, FCDE_MARK),
+       PINMUX_GPIO(GPIO_FN_FWE, FWE_MARK),
+
+       /* LCDC */
+       PINMUX_GPIO(GPIO_FN_LCD_VEPWC, LCD_VEPWC_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_VCPWC, LCD_VCPWC_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_CLK, LCD_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_FLM, LCD_FLM_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_CL2, LCD_CL2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_CL1, LCD_CL1_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DON, LCD_DON_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+       { PINMUX_CFG_REG("PBIORL", 0xfffe3886, 16, 1) {
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PB11_IN, PB11_OUT,
+               PB10_IN, PB10_OUT,
+               PB9_IN, PB9_OUT,
+               PB8_IN, PB8_OUT,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0 }
+       },
+       { PINMUX_CFG_REG("PBCRL4", 0xfffe3890, 16, 4) {
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB12MD_00, PB12MD_01, PB12MD_10, PB12MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PBCRL3", 0xfffe3892, 16, 4) {
+               PB11MD_0, PB11MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB10MD_0, PB10MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB9MD_00, PB9MD_01, PB9MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB8MD_00, PB8MD_01, PB8MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PBCRL2", 0xfffe3894, 16, 4) {
+               PB7MD_00, PB7MD_01, PB7MD_10, PB7MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB6MD_00, PB6MD_01, PB6MD_10, PB6MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB5MD_00, PB5MD_01, PB5MD_10, PB5MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB4MD_00, PB4MD_01, PB4MD_10, PB4MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PBCRL1", 0xfffe3896, 16, 4) {
+               PB3MD_00, PB3MD_01, PB3MD_10, PB3MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB2MD_00, PB2MD_01, PB2MD_10, PB2MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB1MD_00, PB1MD_01, PB1MD_10, PB1MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB0MD_00, PB0MD_01, PB0MD_10, PB0MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("IFCR", 0xfffe38a2, 16, 4) {
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PB12IRQ_00, PB12IRQ_01, PB12IRQ_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PCIORL", 0xfffe3906, 16, 1) {
+               0, 0,
+               PC14_IN, PC14_OUT,
+               PC13_IN, PC13_OUT,
+               PC12_IN, PC12_OUT,
+               PC11_IN, PC11_OUT,
+               PC10_IN, PC10_OUT,
+               PC9_IN, PC9_OUT,
+               PC8_IN, PC8_OUT,
+               PC7_IN, PC7_OUT,
+               PC6_IN, PC6_OUT,
+               PC5_IN, PC5_OUT,
+               PC4_IN, PC4_OUT,
+               PC3_IN, PC3_OUT,
+               PC2_IN, PC2_OUT,
+               PC1_IN, PC1_OUT,
+               PC0_IN, PC0_OUT }
+       },
+       { PINMUX_CFG_REG("PCCRL4", 0xfffe3910, 16, 4) {
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC14MD_0, PC14MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC13MD_0, PC13MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC12MD_0, PC12MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PCCRL3", 0xfffe3912, 16, 4) {
+               PC11MD_00, PC11MD_01, PC11MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC10MD_00, PC10MD_01, PC10MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC9MD_0, PC9MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC8MD_0, PC8MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PCCRL2", 0xfffe3914, 16, 4) {
+               PC7MD_0, PC7MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC6MD_0, PC6MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC5MD_0, PC5MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC4MD_0, PC4MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PCCRL1", 0xfffe3916, 16, 4) {
+               PC3MD_0, PC3MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC2MD_0, PC2MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC1MD_0, PC1MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PC0MD_00, PC0MD_01, PC0MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PDIORL", 0xfffe3986, 16, 1) {
+               PD15_IN, PD15_OUT,
+               PD14_IN, PD14_OUT,
+               PD13_IN, PD13_OUT,
+               PD12_IN, PD12_OUT,
+               PD11_IN, PD11_OUT,
+               PD10_IN, PD10_OUT,
+               PD9_IN, PD9_OUT,
+               PD8_IN, PD8_OUT,
+               PD7_IN, PD7_OUT,
+               PD6_IN, PD6_OUT,
+               PD5_IN, PD5_OUT,
+               PD4_IN, PD4_OUT,
+               PD3_IN, PD3_OUT,
+               PD2_IN, PD2_OUT,
+               PD1_IN, PD1_OUT,
+               PD0_IN, PD0_OUT }
+       },
+       { PINMUX_CFG_REG("PDCRL4", 0xfffe3990, 16, 4) {
+               PD15MD_000, PD15MD_001, PD15MD_010, 0,
+               PD15MD_100, PD15MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD14MD_000, PD14MD_001, PD14MD_010, 0,
+               0, PD14MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD13MD_000, PD13MD_001, PD13MD_010, 0,
+               PD13MD_100, PD13MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD12MD_000, PD12MD_001, PD12MD_010, 0,
+               PD12MD_100, PD12MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PDCRL3", 0xfffe3992, 16, 4) {
+               PD11MD_000, PD11MD_001, PD11MD_010, 0,
+               PD11MD_100, PD11MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD10MD_000, PD10MD_001, PD10MD_010, 0,
+               PD10MD_100, PD10MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD9MD_000, PD9MD_001, PD9MD_010, 0,
+               PD9MD_100, PD9MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD8MD_000, PD8MD_001, PD8MD_010, 0,
+               PD8MD_100, PD8MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PDCRL2", 0xfffe3994, 16, 4) {
+               PD7MD_000, PD7MD_001, PD7MD_010, PD7MD_011,
+               PD7MD_100, PD7MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD6MD_000, PD6MD_001, PD6MD_010, PD6MD_011,
+               PD6MD_100, PD6MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD5MD_000, PD5MD_001, PD5MD_010, PD5MD_011,
+               PD5MD_100, PD5MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD4MD_000, PD4MD_001, PD4MD_010, PD4MD_011,
+               PD4MD_100, PD4MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PDCRL1", 0xfffe3996, 16, 4) {
+               PD3MD_000, PD3MD_001, PD3MD_010, PD3MD_011,
+               PD3MD_100, PD3MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD2MD_000, PD2MD_001, PD2MD_010, PD2MD_011,
+               PD2MD_100, PD2MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD1MD_000, PD1MD_001, PD1MD_010, PD1MD_011,
+               PD1MD_100, PD1MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PD0MD_000, PD0MD_001, PD0MD_010, PD0MD_011,
+               PD0MD_100, PD0MD_101, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PEIORL", 0xfffe3a06, 16, 1) {
+               PE15_IN, PE15_OUT,
+               PE14_IN, PE14_OUT,
+               PE13_IN, PE13_OUT,
+               PE12_IN, PE12_OUT,
+               PE11_IN, PE11_OUT,
+               PE10_IN, PE10_OUT,
+               PE9_IN, PE9_OUT,
+               PE8_IN, PE8_OUT,
+               PE7_IN, PE7_OUT,
+               PE6_IN, PE6_OUT,
+               PE5_IN, PE5_OUT,
+               PE4_IN, PE4_OUT,
+               PE3_IN, PE3_OUT,
+               PE2_IN, PE2_OUT,
+               PE1_IN, PE1_OUT,
+               PE0_IN, PE0_OUT }
+       },
+       { PINMUX_CFG_REG("PECRL4", 0xfffe3a10, 16, 4) {
+               PE15MD_00, PE15MD_01, 0, PE15MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE14MD_00, PE14MD_01, 0, PE14MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE13MD_00, 0, 0, PE13MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE12MD_00, 0, 0, PE12MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PECRL3", 0xfffe3a12, 16, 4) {
+               PE11MD_000, PE11MD_001, PE11MD_010, 0,
+               PE11MD_100, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE10MD_000, PE10MD_001, PE10MD_010, 0,
+               PE10MD_100, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE9MD_00, PE9MD_01, PE9MD_10, PE9MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE8MD_00, PE8MD_01, PE8MD_10, PE8MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PECRL2", 0xfffe3a14, 16, 4) {
+               PE7MD_000, PE7MD_001, PE7MD_010, PE7MD_011,
+               PE7MD_100, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE6MD_000, PE6MD_001, PE6MD_010, PE6MD_011,
+               PE6MD_100, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE5MD_000, PE5MD_001, PE5MD_010, PE5MD_011,
+               PE5MD_100, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE4MD_000, PE4MD_001, PE4MD_010, PE4MD_011,
+               PE4MD_100, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PECRL1", 0xfffe3a16, 16, 4) {
+               PE3MD_00, PE3MD_01, 0, PE3MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE2MD_00, PE2MD_01, 0, PE2MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE1MD_00, PE1MD_01, PE1MD_10, PE1MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PE0MD_000, PE0MD_001, 0, PE0MD_011,
+               PE0MD_100, 0, 0, 0,
+               0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFIORH", 0xfffe3a84, 16, 1) {
+               0, 0,
+               PF30_IN, PF30_OUT,
+               PF29_IN, PF29_OUT,
+               PF28_IN, PF28_OUT,
+               PF27_IN, PF27_OUT,
+               PF26_IN, PF26_OUT,
+               PF25_IN, PF25_OUT,
+               PF24_IN, PF24_OUT,
+               PF23_IN, PF23_OUT,
+               PF22_IN, PF22_OUT,
+               PF21_IN, PF21_OUT,
+               PF20_IN, PF20_OUT,
+               PF19_IN, PF19_OUT,
+               PF18_IN, PF18_OUT,
+               PF17_IN, PF17_OUT,
+               PF16_IN, PF16_OUT }
+       },
+       { PINMUX_CFG_REG("PFIORL", 0xfffe3a86, 16, 1) {
+               PF15_IN, PF15_OUT,
+               PF14_IN, PF14_OUT,
+               PF13_IN, PF13_OUT,
+               PF12_IN, PF12_OUT,
+               PF11_IN, PF11_OUT,
+               PF10_IN, PF10_OUT,
+               PF9_IN, PF9_OUT,
+               PF8_IN, PF8_OUT,
+               PF7_IN, PF7_OUT,
+               PF6_IN, PF6_OUT,
+               PF5_IN, PF5_OUT,
+               PF4_IN, PF4_OUT,
+               PF3_IN, PF3_OUT,
+               PF2_IN, PF2_OUT,
+               PF1_IN, PF1_OUT,
+               PF0_IN, PF0_OUT }
+       },
+       { PINMUX_CFG_REG("PFCRH4", 0xfffe3a88, 16, 4) {
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF30MD_0, PF30MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF29MD_0, PF29MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF28MD_0, PF28MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFCRH3", 0xfffe3a8a, 16, 4) {
+               PF27MD_0, PF27MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF26MD_0, PF26MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF25MD_0, PF25MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF24MD_0, PF24MD_1,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFCRH2", 0xfffe3a8c, 16, 4) {
+               PF23MD_00, PF23MD_01, PF23MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF22MD_00, PF22MD_01, PF22MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF21MD_00, PF21MD_01, PF21MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF20MD_00, PF20MD_01, PF20MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFCRH1", 0xfffe3a8e, 16, 4) {
+               PF19MD_00, PF19MD_01, PF19MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF18MD_00, PF18MD_01, PF18MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF17MD_00, PF17MD_01, PF17MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF16MD_00, PF16MD_01, PF16MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFCRL4", 0xfffe3a90, 16, 4) {
+               PF15MD_00, PF15MD_01, PF15MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF14MD_00, PF14MD_01, PF14MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF13MD_00, PF13MD_01, PF13MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF12MD_00, PF12MD_01, PF12MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFCRL3", 0xfffe3a92, 16, 4) {
+               PF11MD_00, PF11MD_01, PF11MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF10MD_00, PF10MD_01, PF10MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF9MD_00, PF9MD_01, PF9MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF8MD_00, PF8MD_01, PF8MD_10, 0,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFCRL2", 0xfffe3a94, 16, 4) {
+               PF7MD_00, PF7MD_01, PF7MD_10, PF7MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF6MD_00, PF6MD_01, PF6MD_10, PF6MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF5MD_00, PF5MD_01, PF5MD_10, PF5MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF4MD_00, PF4MD_01, PF4MD_10, PF4MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PFCRL1", 0xfffe3a96, 16, 4) {
+               PF3MD_00, PF3MD_01, PF3MD_10, PF3MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF2MD_00, PF2MD_01, PF2MD_10, PF2MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF1MD_00, PF1MD_01, PF1MD_10, PF1MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+
+               PF0MD_00, PF0MD_01, PF0MD_10, PF0MD_11,
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+       },
+       {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+       { PINMUX_DATA_REG("PADRL", 0xfffe3802, 16) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+               PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA }
+       },
+       { PINMUX_DATA_REG("PBDRL", 0xfffe3882, 16) {
+               0, 0, 0, PB12_DATA,
+               PB11_DATA, PB10_DATA, PB9_DATA, PB8_DATA,
+               PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+               PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA }
+       },
+       { PINMUX_DATA_REG("PCDRL", 0xfffe3902, 16) {
+               0, PC14_DATA, PC13_DATA, PC12_DATA,
+               PC11_DATA, PC10_DATA, PC9_DATA, PC8_DATA,
+               PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+               PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA }
+       },
+       { PINMUX_DATA_REG("PDDRL", 0xfffe3982, 16) {
+               PD15_DATA, PD14_DATA, PD13_DATA, PD12_DATA,
+               PD11_DATA, PD10_DATA, PD9_DATA, PD8_DATA,
+               PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+               PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA }
+       },
+       { PINMUX_DATA_REG("PEDRL", 0xfffe3a02, 16) {
+               PE15_DATA, PE14_DATA, PE13_DATA, PE12_DATA,
+               PE11_DATA, PE10_DATA, PE9_DATA, PE8_DATA,
+               PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+               PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA }
+       },
+       { PINMUX_DATA_REG("PFDRH", 0xfffe3a80, 16) {
+               0, PF30_DATA, PF29_DATA, PF28_DATA,
+               PF27_DATA, PF26_DATA, PF25_DATA, PF24_DATA,
+               PF23_DATA, PF22_DATA, PF21_DATA, PF20_DATA,
+               PF19_DATA, PF18_DATA, PF17_DATA, PF16_DATA }
+       },
+       { PINMUX_DATA_REG("PFDRL", 0xfffe3a82, 16) {
+               PF15_DATA, PF14_DATA, PF13_DATA, PF12_DATA,
+               PF11_DATA, PF10_DATA, PF9_DATA, PF8_DATA,
+               PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+               PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA }
+       },
+       { },
+};
+
+static struct pinmux_info sh7203_pinmux_info = {
+       .name = "sh7203_pfc",
+       .reserved_id = PINMUX_RESERVED,
+       .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+       .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+       .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+       .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+       .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+       .first_gpio = GPIO_PA7,
+       .last_gpio = GPIO_FN_LCD_DATA0,
+
+       .gpios = pinmux_gpios,
+       .cfg_regs = pinmux_config_regs,
+       .data_regs = pinmux_data_regs,
+
+       .gpio_data = pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+       return register_pinmux(&sh7203_pinmux_info);
+}
+
+arch_initcall(plat_pinmux_setup);
index 511de55af8321c0d982d827d7987a6c85c45c0c6..e07c69e16d9b5202fff76d06e90773df0f374d1b 100644 (file)
@@ -24,4 +24,8 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7710)    := clock-sh7710.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7720)     := clock-sh7710.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7712)     := clock-sh7712.o
 
+# Pinmux setup
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7720)    := pinmux-sh7720.o
+
 obj-y  += $(clock-y)
+obj-$(CONFIG_GENERIC_GPIO)     += $(pinmux-y)
diff --git a/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c b/arch/sh/kernel/cpu/sh3/pinmux-sh7720.c
new file mode 100644 (file)
index 0000000..9ca1546
--- /dev/null
@@ -0,0 +1,1242 @@
+/*
+ * SH7720 Pinmux
+ *
+ *  Copyright (C) 2008  Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7720.h>
+
+enum {
+       PINMUX_RESERVED = 0,
+
+       PINMUX_DATA_BEGIN,
+       PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+       PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA,
+       PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+       PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA,
+       PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+       PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA,
+       PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+       PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA,
+       PTE6_DATA, PTE5_DATA, PTE4_DATA,
+       PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA,
+       PTF6_DATA, PTF5_DATA, PTF4_DATA,
+       PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA,
+       PTG6_DATA, PTG5_DATA, PTG4_DATA,
+       PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA,
+       PTH6_DATA, PTH5_DATA, PTH4_DATA,
+       PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
+       PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+       PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA,
+       PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA,
+       PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA, PTL3_DATA,
+       PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+       PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA,
+       PTP4_DATA, PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA,
+       PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+       PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA,
+       PTS4_DATA, PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA,
+       PTT4_DATA, PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
+       PTU4_DATA, PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
+       PTV4_DATA, PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA,
+       PINMUX_DATA_END,
+
+       PINMUX_INPUT_BEGIN,
+       PTA7_IN, PTA6_IN, PTA5_IN, PTA4_IN,
+       PTA3_IN, PTA2_IN, PTA1_IN, PTA0_IN,
+       PTB7_IN, PTB6_IN, PTB5_IN, PTB4_IN,
+       PTB3_IN, PTB2_IN, PTB1_IN, PTB0_IN,
+       PTC7_IN, PTC6_IN, PTC5_IN, PTC4_IN,
+       PTC3_IN, PTC2_IN, PTC1_IN, PTC0_IN,
+       PTD7_IN, PTD6_IN, PTD5_IN, PTD4_IN,
+       PTD3_IN, PTD2_IN, PTD1_IN, PTD0_IN,
+       PTE6_IN, PTE5_IN, PTE4_IN,
+       PTE3_IN, PTE2_IN, PTE1_IN, PTE0_IN,
+       PTF6_IN, PTF5_IN, PTF4_IN,
+       PTF3_IN, PTF2_IN, PTF1_IN, PTF0_IN,
+       PTG6_IN, PTG5_IN, PTG4_IN,
+       PTG3_IN, PTG2_IN, PTG1_IN, PTG0_IN,
+       PTH6_IN, PTH5_IN, PTH4_IN,
+       PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN,
+       PTJ6_IN, PTJ5_IN, PTJ4_IN,
+       PTJ3_IN, PTJ2_IN, PTJ1_IN, PTJ0_IN,
+       PTK3_IN, PTK2_IN, PTK1_IN, PTK0_IN,
+       PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN, PTL3_IN,
+       PTM7_IN, PTM6_IN, PTM5_IN, PTM4_IN,
+       PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN,
+       PTP4_IN, PTP3_IN, PTP2_IN, PTP1_IN, PTP0_IN,
+       PTR7_IN, PTR6_IN, PTR5_IN, PTR4_IN,
+       PTR3_IN, PTR2_IN, PTR1_IN, PTR0_IN,
+       PTS4_IN, PTS3_IN, PTS2_IN, PTS1_IN, PTS0_IN,
+       PTT4_IN, PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN,
+       PTU4_IN, PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
+       PTV4_IN, PTV3_IN, PTV2_IN, PTV1_IN, PTV0_IN,
+       PINMUX_INPUT_END,
+
+       PINMUX_INPUT_PULLUP_BEGIN,
+       PTA7_IN_PU, PTA6_IN_PU, PTA5_IN_PU, PTA4_IN_PU,
+       PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
+       PTB7_IN_PU, PTB6_IN_PU, PTB5_IN_PU, PTB4_IN_PU,
+       PTB3_IN_PU, PTB2_IN_PU, PTB1_IN_PU, PTB0_IN_PU,
+       PTC7_IN_PU, PTC6_IN_PU, PTC5_IN_PU, PTC4_IN_PU,
+       PTC3_IN_PU, PTC2_IN_PU, PTC1_IN_PU, PTC0_IN_PU,
+       PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
+       PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
+       PTE4_IN_PU, PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
+       PTF0_IN_PU,
+       PTG6_IN_PU, PTG5_IN_PU, PTG4_IN_PU,
+       PTG3_IN_PU, PTG2_IN_PU, PTG1_IN_PU, PTG0_IN_PU,
+       PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
+       PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
+       PTJ6_IN_PU, PTJ5_IN_PU, PTJ4_IN_PU,
+       PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
+       PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
+       PTL7_IN_PU, PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU, PTL3_IN_PU,
+       PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
+       PTM3_IN_PU, PTM2_IN_PU, PTM1_IN_PU, PTM0_IN_PU,
+       PTP4_IN_PU, PTP3_IN_PU, PTP2_IN_PU, PTP1_IN_PU, PTP0_IN_PU,
+       PTR7_IN_PU, PTR6_IN_PU, PTR5_IN_PU, PTR4_IN_PU,
+       PTR3_IN_PU, PTR2_IN_PU, PTR1_IN_PU, PTR0_IN_PU,
+       PTS4_IN_PU, PTS3_IN_PU, PTS2_IN_PU, PTS1_IN_PU, PTS0_IN_PU,
+       PTT4_IN_PU, PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
+       PTU4_IN_PU, PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
+       PTV4_IN_PU, PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
+       PINMUX_INPUT_PULLUP_END,
+
+       PINMUX_OUTPUT_BEGIN,
+       PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
+       PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
+       PTB7_OUT, PTB6_OUT, PTB5_OUT, PTB4_OUT,
+       PTB3_OUT, PTB2_OUT, PTB1_OUT, PTB0_OUT,
+       PTC7_OUT, PTC6_OUT, PTC5_OUT, PTC4_OUT,
+       PTC3_OUT, PTC2_OUT, PTC1_OUT, PTC0_OUT,
+       PTD7_OUT, PTD6_OUT, PTD5_OUT, PTD4_OUT,
+       PTD3_OUT, PTD2_OUT, PTD1_OUT, PTD0_OUT,
+       PTE4_OUT, PTE3_OUT, PTE2_OUT, PTE1_OUT, PTE0_OUT,
+       PTF0_OUT,
+       PTG6_OUT, PTG5_OUT, PTG4_OUT,
+       PTG3_OUT, PTG2_OUT, PTG1_OUT, PTG0_OUT,
+       PTH6_OUT, PTH5_OUT, PTH4_OUT,
+       PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
+       PTJ6_OUT, PTJ5_OUT, PTJ4_OUT,
+       PTJ3_OUT, PTJ2_OUT, PTJ1_OUT, PTJ0_OUT,
+       PTK3_OUT, PTK2_OUT, PTK1_OUT, PTK0_OUT,
+       PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT, PTL3_OUT,
+       PTM7_OUT, PTM6_OUT, PTM5_OUT, PTM4_OUT,
+       PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT,
+       PTP4_OUT, PTP3_OUT, PTP2_OUT, PTP1_OUT, PTP0_OUT,
+       PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT,
+       PTR3_OUT, PTR2_OUT, PTR1_OUT, PTR0_OUT,
+       PTS4_OUT, PTS3_OUT, PTS2_OUT, PTS1_OUT, PTS0_OUT,
+       PTT4_OUT, PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT,
+       PTU4_OUT, PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT,
+       PTV4_OUT, PTV3_OUT, PTV2_OUT, PTV1_OUT, PTV0_OUT,
+       PINMUX_OUTPUT_END,
+
+       PINMUX_FUNCTION_BEGIN,
+       PTA7_FN, PTA6_FN, PTA5_FN, PTA4_FN,
+       PTA3_FN, PTA2_FN, PTA1_FN, PTA0_FN,
+       PTB7_FN, PTB6_FN, PTB5_FN, PTB4_FN,
+       PTB3_FN, PTB2_FN, PTB1_FN, PTB0_FN,
+       PTC7_FN, PTC6_FN, PTC5_FN, PTC4_FN,
+       PTC3_FN, PTC2_FN, PTC1_FN, PTC0_FN,
+       PTD7_FN, PTD6_FN, PTD5_FN, PTD4_FN,
+       PTD3_FN, PTD2_FN, PTD1_FN, PTD0_FN,
+       PTE6_FN, PTE5_FN, PTE4_FN,
+       PTE3_FN, PTE2_FN, PTE1_FN, PTE0_FN,
+       PTF6_FN, PTF5_FN, PTF4_FN,
+       PTF3_FN, PTF2_FN, PTF1_FN, PTF0_FN,
+       PTG6_FN, PTG5_FN, PTG4_FN,
+       PTG3_FN, PTG2_FN, PTG1_FN, PTG0_FN,
+       PTH6_FN, PTH5_FN, PTH4_FN,
+       PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN,
+       PTJ6_FN, PTJ5_FN, PTJ4_FN,
+       PTJ3_FN, PTJ2_FN, PTJ1_FN, PTJ0_FN,
+       PTK3_FN, PTK2_FN, PTK1_FN, PTK0_FN,
+       PTL7_FN, PTL6_FN, PTL5_FN, PTL4_FN, PTL3_FN,
+       PTM7_FN, PTM6_FN, PTM5_FN, PTM4_FN,
+       PTM3_FN, PTM2_FN, PTM1_FN, PTM0_FN,
+       PTP4_FN, PTP3_FN, PTP2_FN, PTP1_FN, PTP0_FN,
+       PTR7_FN, PTR6_FN, PTR5_FN, PTR4_FN,
+       PTR3_FN, PTR2_FN, PTR1_FN, PTR0_FN,
+       PTS4_FN, PTS3_FN, PTS2_FN, PTS1_FN, PTS0_FN,
+       PTT4_FN, PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN,
+       PTU4_FN, PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN,
+       PTV4_FN, PTV3_FN, PTV2_FN, PTV1_FN, PTV0_FN,
+
+       PSELA_1_0_00, PSELA_1_0_01, PSELA_1_0_10,
+       PSELA_3_2_00, PSELA_3_2_01, PSELA_3_2_10, PSELA_3_2_11,
+       PSELA_5_4_00, PSELA_5_4_01, PSELA_5_4_10, PSELA_5_4_11,
+       PSELA_7_6_00, PSELA_7_6_01, PSELA_7_6_10,
+       PSELA_9_8_00, PSELA_9_8_01, PSELA_9_8_10,
+       PSELA_11_10_00, PSELA_11_10_01, PSELA_11_10_10,
+       PSELA_13_12_00, PSELA_13_12_10,
+       PSELA_15_14_00, PSELA_15_14_10,
+       PSELB_9_8_00, PSELB_9_8_11,
+       PSELB_11_10_00, PSELB_11_10_01, PSELB_11_10_10, PSELB_11_10_11,
+       PSELB_13_12_00, PSELB_13_12_01, PSELB_13_12_10, PSELB_13_12_11,
+       PSELB_15_14_00, PSELB_15_14_11,
+       PSELC_9_8_00, PSELC_9_8_10,
+       PSELC_11_10_00, PSELC_11_10_10,
+       PSELC_13_12_00, PSELC_13_12_01, PSELC_13_12_10,
+       PSELC_15_14_00, PSELC_15_14_01, PSELC_15_14_10,
+       PSELD_1_0_00, PSELD_1_0_10,
+       PSELD_11_10_00, PSELD_11_10_01,
+       PSELD_15_14_00, PSELD_15_14_01, PSELD_15_14_10,
+       PINMUX_FUNCTION_END,
+
+       PINMUX_MARK_BEGIN,
+       D31_MARK, D30_MARK, D29_MARK, D28_MARK,
+       D27_MARK, D26_MARK, D25_MARK, D24_MARK,
+       D23_MARK, D22_MARK, D21_MARK, D20_MARK,
+       D19_MARK, D18_MARK, D17_MARK, D16_MARK,
+       IOIS16_MARK, RAS_MARK, CAS_MARK, CKE_MARK,
+       CS5B_CE1A_MARK, CS6B_CE1B_MARK,
+       A25_MARK, A24_MARK, A23_MARK, A22_MARK,
+       A21_MARK, A20_MARK, A19_MARK, A0_MARK,
+       REFOUT_MARK, IRQOUT_MARK,
+       LCD_DATA15_MARK, LCD_DATA14_MARK,
+       LCD_DATA13_MARK, LCD_DATA12_MARK,
+       LCD_DATA11_MARK, LCD_DATA10_MARK,
+       LCD_DATA9_MARK, LCD_DATA8_MARK,
+       LCD_DATA7_MARK, LCD_DATA6_MARK,
+       LCD_DATA5_MARK, LCD_DATA4_MARK,
+       LCD_DATA3_MARK, LCD_DATA2_MARK,
+       LCD_DATA1_MARK, LCD_DATA0_MARK,
+       LCD_M_DISP_MARK,
+       LCD_CL1_MARK, LCD_CL2_MARK,
+       LCD_DON_MARK, LCD_FLM_MARK,
+       LCD_VEPWC_MARK, LCD_VCPWC_MARK,
+       AFE_RXIN_MARK, AFE_RDET_MARK,
+       AFE_FS_MARK, AFE_TXOUT_MARK,
+       AFE_SCLK_MARK, AFE_RLYCNT_MARK,
+       AFE_HC1_MARK,
+       IIC_SCL_MARK, IIC_SDA_MARK,
+       DA1_MARK, DA0_MARK,
+       AN3_MARK, AN2_MARK, AN1_MARK, AN0_MARK, ADTRG_MARK,
+       USB1D_RCV_MARK, USB1D_TXSE0_MARK,
+       USB1D_TXDPLS_MARK, USB1D_DMNS_MARK,
+       USB1D_DPLS_MARK, USB1D_SPEED_MARK,
+       USB1D_TXENL_MARK,
+       USB2_PWR_EN_MARK, USB1_PWR_EN_USBF_UPLUP_MARK, USB1D_SUSPEND_MARK,
+       IRQ5_MARK, IRQ4_MARK,
+       IRQ3_IRL3_MARK, IRQ2_IRL2_MARK,
+       IRQ1_IRL1_MARK, IRQ0_IRL0_MARK,
+       PCC_REG_MARK, PCC_DRV_MARK,
+       PCC_BVD2_MARK, PCC_BVD1_MARK,
+       PCC_CD2_MARK, PCC_CD1_MARK,
+       PCC_RESET_MARK, PCC_RDY_MARK,
+       PCC_VS2_MARK, PCC_VS1_MARK,
+       AUDATA3_MARK, AUDATA2_MARK, AUDATA1_MARK, AUDATA0_MARK,
+       AUDCK_MARK, AUDSYNC_MARK, ASEBRKAK_MARK, TRST_MARK,
+       TMS_MARK, TDO_MARK, TDI_MARK, TCK_MARK,
+       DACK1_MARK, DREQ1_MARK, DACK0_MARK, DREQ0_MARK,
+       TEND1_MARK, TEND0_MARK,
+       SIOF0_SYNC_MARK, SIOF0_MCLK_MARK,
+       SIOF0_TXD_MARK, SIOF0_RXD_MARK,
+       SIOF0_SCK_MARK,
+       SIOF1_SYNC_MARK, SIOF1_MCLK_MARK,
+       SIOF1_TXD_MARK, SIOF1_RXD_MARK,
+       SIOF1_SCK_MARK,
+       SCIF0_TXD_MARK, SCIF0_RXD_MARK,
+       SCIF0_RTS_MARK, SCIF0_CTS_MARK, SCIF0_SCK_MARK,
+       SCIF1_TXD_MARK, SCIF1_RXD_MARK,
+       SCIF1_RTS_MARK, SCIF1_CTS_MARK, SCIF1_SCK_MARK,
+       TPU_TO1_MARK, TPU_TO0_MARK,
+       TPU_TI3B_MARK, TPU_TI3A_MARK,
+       TPU_TI2B_MARK, TPU_TI2A_MARK,
+       TPU_TO3_MARK, TPU_TO2_MARK,
+       SIM_D_MARK, SIM_CLK_MARK, SIM_RST_MARK,
+       MMC_DAT_MARK, MMC_CMD_MARK,
+       MMC_CLK_MARK, MMC_VDDON_MARK,
+       MMC_ODMOD_MARK,
+       STATUS0_MARK, STATUS1_MARK,
+       PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+       /* PTA GPIO */
+       PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT, PTA7_IN_PU),
+       PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT, PTA6_IN_PU),
+       PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT, PTA5_IN_PU),
+       PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT, PTA4_IN_PU),
+       PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT, PTA3_IN_PU),
+       PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT, PTA2_IN_PU),
+       PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT, PTA1_IN_PU),
+       PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT, PTA0_IN_PU),
+
+       /* PTB GPIO */
+       PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT, PTB7_IN_PU),
+       PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT, PTB6_IN_PU),
+       PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT, PTB5_IN_PU),
+       PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT, PTB4_IN_PU),
+       PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT, PTB3_IN_PU),
+       PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT, PTB2_IN_PU),
+       PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT, PTB1_IN_PU),
+       PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT, PTB0_IN_PU),
+
+       /* PTC GPIO */
+       PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT, PTC7_IN_PU),
+       PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT, PTC6_IN_PU),
+       PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT, PTC5_IN_PU),
+       PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT, PTC4_IN_PU),
+       PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT, PTC3_IN_PU),
+       PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT, PTC2_IN_PU),
+       PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT, PTC1_IN_PU),
+       PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT, PTC0_IN_PU),
+
+       /* PTD GPIO */
+       PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT, PTD7_IN_PU),
+       PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT, PTD6_IN_PU),
+       PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT, PTD5_IN_PU),
+       PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT, PTD4_IN_PU),
+       PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT, PTD3_IN_PU),
+       PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT, PTD2_IN_PU),
+       PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT, PTD1_IN_PU),
+       PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT, PTD0_IN_PU),
+
+       /* PTE GPIO */
+       PINMUX_DATA(PTE6_DATA, PTE6_IN),
+       PINMUX_DATA(PTE5_DATA, PTE5_IN),
+       PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT, PTE4_IN_PU),
+       PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT, PTE3_IN_PU),
+       PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT, PTE2_IN_PU),
+       PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT, PTE1_IN_PU),
+       PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT, PTE0_IN_PU),
+
+       /* PTF GPIO */
+       PINMUX_DATA(PTF6_DATA, PTF6_IN),
+       PINMUX_DATA(PTF5_DATA, PTF5_IN),
+       PINMUX_DATA(PTF4_DATA, PTF4_IN),
+       PINMUX_DATA(PTF3_DATA, PTF3_IN),
+       PINMUX_DATA(PTF2_DATA, PTF2_IN),
+       PINMUX_DATA(PTF1_DATA, PTF1_IN),
+       PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT, PTF0_IN_PU),
+
+       /* PTG GPIO */
+       PINMUX_DATA(PTG6_DATA, PTG6_IN, PTG6_OUT, PTG6_IN_PU),
+       PINMUX_DATA(PTG5_DATA, PTG5_IN, PTG5_OUT, PTG5_IN_PU),
+       PINMUX_DATA(PTG4_DATA, PTG4_IN, PTG4_OUT, PTG4_IN_PU),
+       PINMUX_DATA(PTG3_DATA, PTG3_IN, PTG3_OUT, PTG3_IN_PU),
+       PINMUX_DATA(PTG2_DATA, PTG2_IN, PTG2_OUT, PTG2_IN_PU),
+       PINMUX_DATA(PTG1_DATA, PTG1_IN, PTG1_OUT, PTG1_IN_PU),
+       PINMUX_DATA(PTG0_DATA, PTG0_IN, PTG0_OUT, PTG0_IN_PU),
+
+       /* PTH GPIO */
+       PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT, PTH6_IN_PU),
+       PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT, PTH5_IN_PU),
+       PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT, PTH4_IN_PU),
+       PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT, PTH3_IN_PU),
+       PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT, PTH2_IN_PU),
+       PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT, PTH1_IN_PU),
+       PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT, PTH0_IN_PU),
+
+       /* PTJ GPIO */
+       PINMUX_DATA(PTJ6_DATA, PTJ6_IN, PTJ6_OUT, PTJ6_IN_PU),
+       PINMUX_DATA(PTJ5_DATA, PTJ5_IN, PTJ5_OUT, PTJ5_IN_PU),
+       PINMUX_DATA(PTJ4_DATA, PTJ4_IN, PTJ4_OUT, PTJ4_IN_PU),
+       PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT, PTJ3_IN_PU),
+       PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT, PTJ2_IN_PU),
+       PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT, PTJ1_IN_PU),
+       PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT, PTJ0_IN_PU),
+
+       /* PTK GPIO */
+       PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT, PTK3_IN_PU),
+       PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT, PTK2_IN_PU),
+       PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT, PTK1_IN_PU),
+       PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT, PTK0_IN_PU),
+
+       /* PTL GPIO */
+       PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT, PTL7_IN_PU),
+       PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT, PTL6_IN_PU),
+       PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT, PTL5_IN_PU),
+       PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT, PTL4_IN_PU),
+       PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT, PTL3_IN_PU),
+
+       /* PTM GPIO */
+       PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT, PTM7_IN_PU),
+       PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT, PTM6_IN_PU),
+       PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT, PTM5_IN_PU),
+       PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT, PTM4_IN_PU),
+       PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT, PTM3_IN_PU),
+       PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT, PTM2_IN_PU),
+       PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT, PTM1_IN_PU),
+       PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT, PTM0_IN_PU),
+
+       /* PTP GPIO */
+       PINMUX_DATA(PTP4_DATA, PTP4_IN, PTP4_OUT, PTP4_IN_PU),
+       PINMUX_DATA(PTP3_DATA, PTP3_IN, PTP3_OUT, PTP3_IN_PU),
+       PINMUX_DATA(PTP2_DATA, PTP2_IN, PTP2_OUT, PTP2_IN_PU),
+       PINMUX_DATA(PTP1_DATA, PTP1_IN, PTP1_OUT, PTP1_IN_PU),
+       PINMUX_DATA(PTP0_DATA, PTP0_IN, PTP0_OUT, PTP0_IN_PU),
+
+       /* PTR GPIO */
+       PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT, PTR7_IN_PU),
+       PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT, PTR6_IN_PU),
+       PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT, PTR5_IN_PU),
+       PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT, PTR4_IN_PU),
+       PINMUX_DATA(PTR3_DATA, PTR3_IN, PTR3_OUT, PTR3_IN_PU),
+       PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_OUT, PTR2_IN_PU),
+       PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT, PTR1_IN_PU),
+       PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT, PTR0_IN_PU),
+
+       /* PTS GPIO */
+       PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT, PTS4_IN_PU),
+       PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT, PTS3_IN_PU),
+       PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT, PTS2_IN_PU),
+       PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT, PTS1_IN_PU),
+       PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT, PTS0_IN_PU),
+
+       /* PTT GPIO */
+       PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT, PTT4_IN_PU),
+       PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT, PTT3_IN_PU),
+       PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT, PTT2_IN_PU),
+       PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT, PTT1_IN_PU),
+       PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT, PTT0_IN_PU),
+
+       /* PTU GPIO */
+       PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT, PTU4_IN_PU),
+       PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT, PTU3_IN_PU),
+       PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT, PTU2_IN_PU),
+       PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT, PTU1_IN_PU),
+       PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT, PTU0_IN_PU),
+
+       /* PTV GPIO */
+       PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT, PTV4_IN_PU),
+       PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT, PTV3_IN_PU),
+       PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT, PTV2_IN_PU),
+       PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT, PTV1_IN_PU),
+       PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT, PTV0_IN_PU),
+
+       /* PTA FN */
+       PINMUX_DATA(D23_MARK, PTA7_FN),
+       PINMUX_DATA(D22_MARK, PTA6_FN),
+       PINMUX_DATA(D21_MARK, PTA5_FN),
+       PINMUX_DATA(D20_MARK, PTA4_FN),
+       PINMUX_DATA(D19_MARK, PTA3_FN),
+       PINMUX_DATA(D18_MARK, PTA2_FN),
+       PINMUX_DATA(D17_MARK, PTA1_FN),
+       PINMUX_DATA(D16_MARK, PTA0_FN),
+
+       /* PTB FN */
+       PINMUX_DATA(D31_MARK, PTB7_FN),
+       PINMUX_DATA(D30_MARK, PTB6_FN),
+       PINMUX_DATA(D29_MARK, PTB5_FN),
+       PINMUX_DATA(D28_MARK, PTB4_FN),
+       PINMUX_DATA(D27_MARK, PTB3_FN),
+       PINMUX_DATA(D26_MARK, PTB2_FN),
+       PINMUX_DATA(D25_MARK, PTB1_FN),
+       PINMUX_DATA(D24_MARK, PTB0_FN),
+
+       /* PTC FN */
+       PINMUX_DATA(LCD_DATA7_MARK, PTC7_FN),
+       PINMUX_DATA(LCD_DATA6_MARK, PTC6_FN),
+       PINMUX_DATA(LCD_DATA5_MARK, PTC5_FN),
+       PINMUX_DATA(LCD_DATA4_MARK, PTC4_FN),
+       PINMUX_DATA(LCD_DATA3_MARK, PTC3_FN),
+       PINMUX_DATA(LCD_DATA2_MARK, PTC2_FN),
+       PINMUX_DATA(LCD_DATA1_MARK, PTC1_FN),
+       PINMUX_DATA(LCD_DATA0_MARK, PTC0_FN),
+
+       /* PTD FN */
+       PINMUX_DATA(LCD_DATA15_MARK, PTD7_FN),
+       PINMUX_DATA(LCD_DATA14_MARK, PTD6_FN),
+       PINMUX_DATA(LCD_DATA13_MARK, PTD5_FN),
+       PINMUX_DATA(LCD_DATA12_MARK, PTD4_FN),
+       PINMUX_DATA(LCD_DATA11_MARK, PTD3_FN),
+       PINMUX_DATA(LCD_DATA10_MARK, PTD2_FN),
+       PINMUX_DATA(LCD_DATA9_MARK, PTD1_FN),
+       PINMUX_DATA(LCD_DATA8_MARK, PTD0_FN),
+
+       /* PTE FN */
+       PINMUX_DATA(IIC_SCL_MARK, PSELB_9_8_00, PTE6_FN),
+       PINMUX_DATA(AFE_RXIN_MARK, PSELB_9_8_11, PTE6_FN),
+       PINMUX_DATA(IIC_SDA_MARK, PSELB_9_8_00, PTE5_FN),
+       PINMUX_DATA(AFE_RDET_MARK, PSELB_9_8_11, PTE5_FN),
+       PINMUX_DATA(LCD_M_DISP_MARK, PTE4_FN),
+       PINMUX_DATA(LCD_CL1_MARK, PTE3_FN),
+       PINMUX_DATA(LCD_CL2_MARK, PTE2_FN),
+       PINMUX_DATA(LCD_DON_MARK, PTE1_FN),
+       PINMUX_DATA(LCD_FLM_MARK, PTE0_FN),
+
+       /* PTF FN */
+       PINMUX_DATA(DA1_MARK, PTF6_FN),
+       PINMUX_DATA(DA0_MARK, PTF5_FN),
+       PINMUX_DATA(AN3_MARK, PTF4_FN),
+       PINMUX_DATA(AN2_MARK, PTF3_FN),
+       PINMUX_DATA(AN1_MARK, PTF2_FN),
+       PINMUX_DATA(AN0_MARK, PTF1_FN),
+       PINMUX_DATA(ADTRG_MARK, PTF0_FN),
+
+       /* PTG FN */
+       PINMUX_DATA(USB1D_RCV_MARK, PSELA_3_2_00, PTG6_FN),
+       PINMUX_DATA(AFE_FS_MARK, PSELA_3_2_01, PTG6_FN),
+       PINMUX_DATA(PCC_REG_MARK, PSELA_3_2_10, PTG6_FN),
+       PINMUX_DATA(IRQ5_MARK, PSELA_3_2_11, PTG6_FN),
+       PINMUX_DATA(USB1D_TXSE0_MARK, PSELA_5_4_00, PTG5_FN),
+       PINMUX_DATA(AFE_TXOUT_MARK, PSELA_5_4_01, PTG5_FN),
+       PINMUX_DATA(PCC_DRV_MARK, PSELA_5_4_10, PTG5_FN),
+       PINMUX_DATA(IRQ4_MARK, PSELA_5_4_11, PTG5_FN),
+       PINMUX_DATA(USB1D_TXDPLS_MARK, PSELA_7_6_00, PTG4_FN),
+       PINMUX_DATA(AFE_SCLK_MARK, PSELA_7_6_01, PTG4_FN),
+       PINMUX_DATA(IOIS16_MARK, PSELA_7_6_10, PTG4_FN),
+       PINMUX_DATA(USB1D_DMNS_MARK, PSELA_9_8_00, PTG3_FN),
+       PINMUX_DATA(AFE_RLYCNT_MARK, PSELA_9_8_01, PTG3_FN),
+       PINMUX_DATA(PCC_BVD2_MARK, PSELA_9_8_10, PTG3_FN),
+       PINMUX_DATA(USB1D_DPLS_MARK, PSELA_11_10_00, PTG2_FN),
+       PINMUX_DATA(AFE_HC1_MARK, PSELA_11_10_01, PTG2_FN),
+       PINMUX_DATA(PCC_BVD1_MARK, PSELA_11_10_10, PTG2_FN),
+       PINMUX_DATA(USB1D_SPEED_MARK, PSELA_13_12_00, PTG1_FN),
+       PINMUX_DATA(PCC_CD2_MARK, PSELA_13_12_10, PTG1_FN),
+       PINMUX_DATA(USB1D_TXENL_MARK, PSELA_15_14_00, PTG0_FN),
+       PINMUX_DATA(PCC_CD1_MARK, PSELA_15_14_10, PTG0_FN),
+
+       /* PTH FN */
+       PINMUX_DATA(RAS_MARK, PTH6_FN),
+       PINMUX_DATA(CAS_MARK, PTH5_FN),
+       PINMUX_DATA(CKE_MARK, PTH4_FN),
+       PINMUX_DATA(STATUS1_MARK, PTH3_FN),
+       PINMUX_DATA(STATUS0_MARK, PTH2_FN),
+       PINMUX_DATA(USB2_PWR_EN_MARK, PTH1_FN),
+       PINMUX_DATA(USB1_PWR_EN_USBF_UPLUP_MARK, PTH0_FN),
+
+       /* PTJ FN */
+       PINMUX_DATA(AUDCK_MARK, PTJ6_FN),
+       PINMUX_DATA(ASEBRKAK_MARK, PTJ5_FN),
+       PINMUX_DATA(AUDATA3_MARK, PTJ4_FN),
+       PINMUX_DATA(AUDATA2_MARK, PTJ3_FN),
+       PINMUX_DATA(AUDATA1_MARK, PTJ2_FN),
+       PINMUX_DATA(AUDATA0_MARK, PTJ1_FN),
+       PINMUX_DATA(AUDSYNC_MARK, PTJ0_FN),
+
+       /* PTK FN */
+       PINMUX_DATA(PCC_RESET_MARK, PTK3_FN),
+       PINMUX_DATA(PCC_RDY_MARK, PTK2_FN),
+       PINMUX_DATA(PCC_VS2_MARK, PTK1_FN),
+       PINMUX_DATA(PCC_VS1_MARK, PTK0_FN),
+
+       /* PTL FN */
+       PINMUX_DATA(TRST_MARK, PTL7_FN),
+       PINMUX_DATA(TMS_MARK, PTL6_FN),
+       PINMUX_DATA(TDO_MARK, PTL5_FN),
+       PINMUX_DATA(TDI_MARK, PTL4_FN),
+       PINMUX_DATA(TCK_MARK, PTL3_FN),
+
+       /* PTM FN */
+       PINMUX_DATA(DREQ1_MARK, PTM7_FN),
+       PINMUX_DATA(DREQ0_MARK, PTM6_FN),
+       PINMUX_DATA(DACK1_MARK, PTM5_FN),
+       PINMUX_DATA(DACK0_MARK, PTM4_FN),
+       PINMUX_DATA(TEND1_MARK, PTM3_FN),
+       PINMUX_DATA(TEND0_MARK, PTM2_FN),
+       PINMUX_DATA(CS5B_CE1A_MARK, PTM1_FN),
+       PINMUX_DATA(CS6B_CE1B_MARK, PTM0_FN),
+
+       /* PTP FN */
+       PINMUX_DATA(USB1D_SUSPEND_MARK, PSELA_1_0_00, PTP4_FN),
+       PINMUX_DATA(REFOUT_MARK, PSELA_1_0_01, PTP4_FN),
+       PINMUX_DATA(IRQOUT_MARK, PSELA_1_0_10, PTP4_FN),
+       PINMUX_DATA(IRQ3_IRL3_MARK, PTP3_FN),
+       PINMUX_DATA(IRQ2_IRL2_MARK, PTP2_FN),
+       PINMUX_DATA(IRQ1_IRL1_MARK, PTP1_FN),
+       PINMUX_DATA(IRQ0_IRL0_MARK, PTP0_FN),
+
+       /* PTR FN */
+       PINMUX_DATA(A25_MARK, PTR7_FN),
+       PINMUX_DATA(A24_MARK, PTR6_FN),
+       PINMUX_DATA(A23_MARK, PTR5_FN),
+       PINMUX_DATA(A22_MARK, PTR4_FN),
+       PINMUX_DATA(A21_MARK, PTR3_FN),
+       PINMUX_DATA(A20_MARK, PTR2_FN),
+       PINMUX_DATA(A19_MARK, PTR1_FN),
+       PINMUX_DATA(A0_MARK, PTR0_FN),
+
+       /* PTS FN */
+       PINMUX_DATA(SIOF0_SYNC_MARK, PTS4_FN),
+       PINMUX_DATA(SIOF0_MCLK_MARK, PTS3_FN),
+       PINMUX_DATA(SIOF0_TXD_MARK, PTS2_FN),
+       PINMUX_DATA(SIOF0_RXD_MARK, PTS1_FN),
+       PINMUX_DATA(SIOF0_SCK_MARK, PTS0_FN),
+
+       /* PTT FN */
+       PINMUX_DATA(SCIF0_CTS_MARK, PSELB_15_14_00, PTT4_FN),
+       PINMUX_DATA(TPU_TO1_MARK, PSELB_15_14_11, PTT4_FN),
+       PINMUX_DATA(SCIF0_RTS_MARK, PSELB_15_14_00, PTT3_FN),
+       PINMUX_DATA(TPU_TO0_MARK, PSELB_15_14_11, PTT3_FN),
+       PINMUX_DATA(SCIF0_TXD_MARK, PTT2_FN),
+       PINMUX_DATA(SCIF0_RXD_MARK, PTT1_FN),
+       PINMUX_DATA(SCIF0_SCK_MARK, PTT0_FN),
+
+       /* PTU FN */
+       PINMUX_DATA(SIOF1_SYNC_MARK, PTU4_FN),
+       PINMUX_DATA(SIOF1_MCLK_MARK, PSELD_11_10_00, PTU3_FN),
+       PINMUX_DATA(TPU_TI3B_MARK, PSELD_11_10_01, PTU3_FN),
+       PINMUX_DATA(SIOF1_TXD_MARK, PSELD_15_14_00, PTU2_FN),
+       PINMUX_DATA(TPU_TI3A_MARK, PSELD_15_14_01, PTU2_FN),
+       PINMUX_DATA(MMC_DAT_MARK, PSELD_15_14_10, PTU2_FN),
+       PINMUX_DATA(SIOF1_RXD_MARK, PSELC_13_12_00, PTU1_FN),
+       PINMUX_DATA(TPU_TI2B_MARK, PSELC_13_12_01, PTU1_FN),
+       PINMUX_DATA(MMC_CMD_MARK, PSELC_13_12_10, PTU1_FN),
+       PINMUX_DATA(SIOF1_SCK_MARK, PSELC_15_14_00, PTU0_FN),
+       PINMUX_DATA(TPU_TI2A_MARK, PSELC_15_14_01, PTU0_FN),
+       PINMUX_DATA(MMC_CLK_MARK, PSELC_15_14_10, PTU0_FN),
+
+       /* PTV FN */
+       PINMUX_DATA(SCIF1_CTS_MARK, PSELB_11_10_00, PTV4_FN),
+       PINMUX_DATA(TPU_TO3_MARK, PSELB_11_10_01, PTV4_FN),
+       PINMUX_DATA(MMC_VDDON_MARK, PSELB_11_10_10, PTV4_FN),
+       PINMUX_DATA(LCD_VEPWC_MARK, PSELB_11_10_11, PTV4_FN),
+       PINMUX_DATA(SCIF1_RTS_MARK, PSELB_13_12_00, PTV3_FN),
+       PINMUX_DATA(TPU_TO2_MARK, PSELB_13_12_01, PTV3_FN),
+       PINMUX_DATA(MMC_ODMOD_MARK, PSELB_13_12_10, PTV3_FN),
+       PINMUX_DATA(LCD_VCPWC_MARK, PSELB_13_12_11, PTV3_FN),
+       PINMUX_DATA(SCIF1_TXD_MARK, PSELC_9_8_00, PTV2_FN),
+       PINMUX_DATA(SIM_D_MARK, PSELC_9_8_10, PTV2_FN),
+       PINMUX_DATA(SCIF1_RXD_MARK, PSELC_11_10_00, PTV1_FN),
+       PINMUX_DATA(SIM_RST_MARK, PSELC_11_10_10, PTV1_FN),
+       PINMUX_DATA(SCIF1_SCK_MARK, PSELD_1_0_00, PTV0_FN),
+       PINMUX_DATA(SIM_CLK_MARK, PSELD_1_0_10, PTV0_FN),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+       /* PTA */
+       PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
+       PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
+       PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
+       PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
+       PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
+       PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
+       PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
+       PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+
+       /* PTB */
+       PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
+       PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
+       PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
+       PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
+       PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
+       PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
+       PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
+       PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+
+       /* PTC */
+       PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
+       PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
+       PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
+       PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
+       PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
+       PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
+       PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
+       PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+
+       /* PTD */
+       PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
+       PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
+       PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
+       PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
+       PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
+       PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
+       PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
+       PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+
+       /* PTE */
+       PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
+       PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
+       PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
+       PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
+       PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
+       PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
+       PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+
+       /* PTF */
+       PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
+       PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
+       PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
+       PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
+       PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
+       PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
+       PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+
+       /* PTG */
+       PINMUX_GPIO(GPIO_PTG6, PTG6_DATA),
+       PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
+       PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
+       PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
+       PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
+       PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
+       PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+
+       /* PTH */
+       PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
+       PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
+       PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
+       PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
+       PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
+       PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
+       PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+
+       /* PTJ */
+       PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
+       PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
+       PINMUX_GPIO(GPIO_PTJ4, PTJ4_DATA),
+       PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
+       PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
+       PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
+       PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+
+       /* PTK */
+       PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
+       PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
+       PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
+       PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+
+       /* PTL */
+       PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
+       PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
+       PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
+       PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
+       PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
+
+       /* PTM */
+       PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
+       PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
+       PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
+       PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
+       PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
+       PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
+       PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
+       PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+
+       /* PTP */
+       PINMUX_GPIO(GPIO_PTP4, PTP4_DATA),
+       PINMUX_GPIO(GPIO_PTP3, PTP3_DATA),
+       PINMUX_GPIO(GPIO_PTP2, PTP2_DATA),
+       PINMUX_GPIO(GPIO_PTP1, PTP1_DATA),
+       PINMUX_GPIO(GPIO_PTP0, PTP0_DATA),
+
+       /* PTR */
+       PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
+       PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
+       PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
+       PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
+       PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
+       PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
+       PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
+       PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+
+       /* PTS */
+       PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
+       PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
+       PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
+       PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
+       PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+
+       /* PTT */
+       PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
+       PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
+       PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
+       PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
+       PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+
+       /* PTU */
+       PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
+       PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
+       PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
+       PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
+       PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+
+       /* PTV */
+       PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
+       PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
+       PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
+       PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
+       PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+
+       /* BSC */
+       PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
+       PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
+       PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
+       PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
+       PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
+       PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
+       PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
+       PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
+       PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
+       PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
+       PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
+       PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
+       PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
+       PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
+       PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
+       PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
+       PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+       PINMUX_GPIO(GPIO_FN_RAS, RAS_MARK),
+       PINMUX_GPIO(GPIO_FN_CAS, CAS_MARK),
+       PINMUX_GPIO(GPIO_FN_CKE, CKE_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5B_CE1A, CS5B_CE1A_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6B_CE1B, CS6B_CE1B_MARK),
+       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+       PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+       PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+       PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
+       PINMUX_GPIO(GPIO_FN_A20, A20_MARK),
+       PINMUX_GPIO(GPIO_FN_A19, A19_MARK),
+       PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
+       PINMUX_GPIO(GPIO_FN_REFOUT, REFOUT_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQOUT, IRQOUT_MARK),
+
+       /* LCDC */
+       PINMUX_GPIO(GPIO_FN_LCD_DATA15, LCD_DATA15_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA14, LCD_DATA14_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA13, LCD_DATA13_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA12, LCD_DATA12_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA11, LCD_DATA11_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA10, LCD_DATA10_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA9, LCD_DATA9_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA8, LCD_DATA8_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA7, LCD_DATA7_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA6, LCD_DATA6_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA5, LCD_DATA5_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA4, LCD_DATA4_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA3, LCD_DATA3_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA2, LCD_DATA2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA1, LCD_DATA1_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DATA0, LCD_DATA0_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_M_DISP, LCD_M_DISP_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_CL1, LCD_CL1_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_CL2, LCD_CL2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_DON, LCD_DON_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_FLM, LCD_FLM_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_VEPWC, LCD_VEPWC_MARK),
+       PINMUX_GPIO(GPIO_FN_LCD_VCPWC, LCD_VCPWC_MARK),
+
+       /* AFEIF */
+       PINMUX_GPIO(GPIO_FN_AFE_RXIN, AFE_RXIN_MARK),
+       PINMUX_GPIO(GPIO_FN_AFE_RDET, AFE_RDET_MARK),
+       PINMUX_GPIO(GPIO_FN_AFE_FS, AFE_FS_MARK),
+       PINMUX_GPIO(GPIO_FN_AFE_TXOUT, AFE_TXOUT_MARK),
+       PINMUX_GPIO(GPIO_FN_AFE_SCLK, AFE_SCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_AFE_RLYCNT, AFE_RLYCNT_MARK),
+       PINMUX_GPIO(GPIO_FN_AFE_HC1, AFE_HC1_MARK),
+
+       /* IIC */
+       PINMUX_GPIO(GPIO_FN_IIC_SCL, IIC_SCL_MARK),
+       PINMUX_GPIO(GPIO_FN_IIC_SDA, IIC_SDA_MARK),
+
+       /* DAC */
+       PINMUX_GPIO(GPIO_FN_DA1, DA1_MARK),
+       PINMUX_GPIO(GPIO_FN_DA0, DA0_MARK),
+
+       /* ADC */
+       PINMUX_GPIO(GPIO_FN_AN3, AN3_MARK),
+       PINMUX_GPIO(GPIO_FN_AN2, AN2_MARK),
+       PINMUX_GPIO(GPIO_FN_AN1, AN1_MARK),
+       PINMUX_GPIO(GPIO_FN_AN0, AN0_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+
+       /* USB */
+       PINMUX_GPIO(GPIO_FN_USB1D_RCV, USB1D_RCV_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1D_TXSE0, USB1D_TXSE0_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1D_TXDPLS, USB1D_TXDPLS_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1D_DMNS, USB1D_DMNS_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1D_DPLS, USB1D_DPLS_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1D_SPEED, USB1D_SPEED_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1D_TXENL, USB1D_TXENL_MARK),
+
+       PINMUX_GPIO(GPIO_FN_USB2_PWR_EN, USB2_PWR_EN_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1_PWR_EN_USBF_UPLUP,
+                   USB1_PWR_EN_USBF_UPLUP_MARK),
+       PINMUX_GPIO(GPIO_FN_USB1D_SUSPEND, USB1D_SUSPEND_MARK),
+
+       /* INTC */
+       PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3_IRL3, IRQ3_IRL3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2_IRL2, IRQ2_IRL2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1_IRL1, IRQ1_IRL1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ0_IRL0, IRQ0_IRL0_MARK),
+
+       /* PCC */
+       PINMUX_GPIO(GPIO_FN_PCC_REG, PCC_REG_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_DRV, PCC_DRV_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_BVD2, PCC_BVD2_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_BVD1, PCC_BVD1_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_CD2, PCC_CD2_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_CD1, PCC_CD1_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_RESET, PCC_RESET_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_RDY, PCC_RDY_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_VS2, PCC_VS2_MARK),
+       PINMUX_GPIO(GPIO_FN_PCC_VS1, PCC_VS1_MARK),
+
+       /* HUDI */
+       PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_ASEBRKAK, ASEBRKAK_MARK),
+       PINMUX_GPIO(GPIO_FN_TRST, TRST_MARK),
+       PINMUX_GPIO(GPIO_FN_TMS, TMS_MARK),
+       PINMUX_GPIO(GPIO_FN_TDO, TDO_MARK),
+       PINMUX_GPIO(GPIO_FN_TDI, TDI_MARK),
+       PINMUX_GPIO(GPIO_FN_TCK, TCK_MARK),
+
+       /* DMAC */
+       PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
+
+       /* SIOF0 */
+       PINMUX_GPIO(GPIO_FN_SIOF0_SYNC, SIOF0_SYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_MCLK, SIOF0_MCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_TXD, SIOF0_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_RXD, SIOF0_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_SCK, SIOF0_SCK_MARK),
+
+       /* SIOF1 */
+       PINMUX_GPIO(GPIO_FN_SIOF1_SYNC, SIOF1_SYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_MCLK, SIOF1_MCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_TXD, SIOF1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_RXD, SIOF1_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_SCK, SIOF1_SCK_MARK),
+
+       /* SCIF0 */
+       PINMUX_GPIO(GPIO_FN_SCIF0_TXD, SCIF0_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_RXD, SCIF0_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_RTS, SCIF0_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_CTS, SCIF0_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_SCK, SCIF0_SCK_MARK),
+
+       /* SCIF1 */
+       PINMUX_GPIO(GPIO_FN_SCIF1_TXD, SCIF1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_RXD, SCIF1_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_RTS, SCIF1_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_CTS, SCIF1_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_SCK, SCIF1_SCK_MARK),
+
+       /* TPU */
+       PINMUX_GPIO(GPIO_FN_TPU_TO1, TPU_TO1_MARK),
+       PINMUX_GPIO(GPIO_FN_TPU_TO0, TPU_TO0_MARK),
+       PINMUX_GPIO(GPIO_FN_TPU_TI3B, TPU_TI3B_MARK),
+       PINMUX_GPIO(GPIO_FN_TPU_TI3A, TPU_TI3A_MARK),
+       PINMUX_GPIO(GPIO_FN_TPU_TI2B, TPU_TI2B_MARK),
+       PINMUX_GPIO(GPIO_FN_TPU_TI2A, TPU_TI2A_MARK),
+       PINMUX_GPIO(GPIO_FN_TPU_TO3, TPU_TO3_MARK),
+       PINMUX_GPIO(GPIO_FN_TPU_TO2, TPU_TO2_MARK),
+
+       /* SIM */
+       PINMUX_GPIO(GPIO_FN_SIM_D, SIM_D_MARK),
+       PINMUX_GPIO(GPIO_FN_SIM_CLK, SIM_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIM_RST, SIM_RST_MARK),
+
+       /* MMC */
+       PINMUX_GPIO(GPIO_FN_MMC_DAT, MMC_DAT_MARK),
+       PINMUX_GPIO(GPIO_FN_MMC_CMD, MMC_CMD_MARK),
+       PINMUX_GPIO(GPIO_FN_MMC_CLK, MMC_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_MMC_VDDON, MMC_VDDON_MARK),
+       PINMUX_GPIO(GPIO_FN_MMC_ODMOD, MMC_ODMOD_MARK),
+
+       /* SYSC */
+       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+       { PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
+               PTA7_FN, PTA7_OUT, PTA7_IN_PU, PTA7_IN,
+               PTA6_FN, PTA6_OUT, PTA6_IN_PU, PTA6_IN,
+               PTA5_FN, PTA5_OUT, PTA5_IN_PU, PTA5_IN,
+               PTA4_FN, PTA4_OUT, PTA4_IN_PU, PTA4_IN,
+               PTA3_FN, PTA3_OUT, PTA3_IN_PU, PTA3_IN,
+               PTA2_FN, PTA2_OUT, PTA2_IN_PU, PTA2_IN,
+               PTA1_FN, PTA1_OUT, PTA1_IN_PU, PTA1_IN,
+               PTA0_FN, PTA0_OUT, PTA0_IN_PU, PTA0_IN }
+       },
+       { PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
+               PTB7_FN, PTB7_OUT, PTB7_IN_PU, PTB7_IN,
+               PTB6_FN, PTB6_OUT, PTB6_IN_PU, PTB6_IN,
+               PTB5_FN, PTB5_OUT, PTB5_IN_PU, PTB5_IN,
+               PTB4_FN, PTB4_OUT, PTB4_IN_PU, PTB4_IN,
+               PTB3_FN, PTB3_OUT, PTB3_IN_PU, PTB3_IN,
+               PTB2_FN, PTB2_OUT, PTB2_IN_PU, PTB2_IN,
+               PTB1_FN, PTB1_OUT, PTB1_IN_PU, PTB1_IN,
+               PTB0_FN, PTB0_OUT, PTB0_IN_PU, PTB0_IN }
+       },
+       { PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
+               PTC7_FN, PTC7_OUT, PTC7_IN_PU, PTC7_IN,
+               PTC6_FN, PTC6_OUT, PTC6_IN_PU, PTC6_IN,
+               PTC5_FN, PTC5_OUT, PTC5_IN_PU, PTC5_IN,
+               PTC4_FN, PTC4_OUT, PTC4_IN_PU, PTC4_IN,
+               PTC3_FN, PTC3_OUT, PTC3_IN_PU, PTC3_IN,
+               PTC2_FN, PTC2_OUT, PTC2_IN_PU, PTC2_IN,
+               PTC1_FN, PTC1_OUT, PTC1_IN_PU, PTC1_IN,
+               PTC0_FN, PTC0_OUT, PTC0_IN_PU, PTC0_IN }
+       },
+       { PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
+               PTD7_FN, PTD7_OUT, PTD7_IN_PU, PTD7_IN,
+               PTD6_FN, PTD6_OUT, PTD6_IN_PU, PTD6_IN,
+               PTD5_FN, PTD5_OUT, PTD5_IN_PU, PTD5_IN,
+               PTD4_FN, PTD4_OUT, PTD4_IN_PU, PTD4_IN,
+               PTD3_FN, PTD3_OUT, PTD3_IN_PU, PTD3_IN,
+               PTD2_FN, PTD2_OUT, PTD2_IN_PU, PTD2_IN,
+               PTD1_FN, PTD1_OUT, PTD1_IN_PU, PTD1_IN,
+               PTD0_FN, PTD0_OUT, PTD0_IN_PU, PTD0_IN }
+       },
+       { PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
+               0, 0, 0, 0,
+               PTE6_FN, 0, 0, PTE6_IN,
+               PTE5_FN, 0, 0, PTE5_IN,
+               PTE4_FN, PTE4_OUT, PTE4_IN_PU, PTE4_IN,
+               PTE3_FN, PTE3_OUT, PTE3_IN_PU, PTE3_IN,
+               PTE2_FN, PTE2_OUT, PTE2_IN_PU, PTE2_IN,
+               PTE1_FN, PTE1_OUT, PTE1_IN_PU, PTE1_IN,
+               PTE0_FN, PTE0_OUT, PTE0_IN_PU, PTE0_IN }
+       },
+       { PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
+               0, 0, 0, 0,
+               PTF6_FN, 0, 0, PTF6_IN,
+               PTF5_FN, 0, 0, PTF5_IN,
+               PTF4_FN, 0, 0, PTF4_IN,
+               PTF3_FN, 0, 0, PTF3_IN,
+               PTF2_FN, 0, 0, PTF2_IN,
+               PTF1_FN, 0, 0, PTF1_IN,
+               PTF0_FN, 0, 0, PTF0_IN }
+       },
+       { PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
+               0, 0, 0, 0,
+               PTG6_FN, PTG6_OUT, PTG6_IN_PU, PTG6_IN,
+               PTG5_FN, PTG5_OUT, PTG5_IN_PU, PTG5_IN,
+               PTG4_FN, PTG4_OUT, PTG4_IN_PU, PTG4_IN,
+               PTG3_FN, PTG3_OUT, PTG3_IN_PU, PTG3_IN,
+               PTG2_FN, PTG2_OUT, PTG2_IN_PU, PTG2_IN,
+               PTG1_FN, PTG1_OUT, PTG1_IN_PU, PTG1_IN,
+               PTG0_FN, PTG0_OUT, PTG0_IN_PU, PTG0_IN }
+       },
+       { PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
+               0, 0, 0, 0,
+               PTH6_FN, PTH6_OUT, PTH6_IN_PU, PTH6_IN,
+               PTH5_FN, PTH5_OUT, PTH5_IN_PU, PTH5_IN,
+               PTH4_FN, PTH4_OUT, PTH4_IN_PU, PTH4_IN,
+               PTH3_FN, PTH3_OUT, PTH3_IN_PU, PTH3_IN,
+               PTH2_FN, PTH2_OUT, PTH2_IN_PU, PTH2_IN,
+               PTH1_FN, PTH1_OUT, PTH1_IN_PU, PTH1_IN,
+               PTH0_FN, PTH0_OUT, PTH0_IN_PU, PTH0_IN }
+       },
+       { PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
+               0, 0, 0, 0,
+               PTJ6_FN, PTJ6_OUT, PTJ6_IN_PU, PTJ6_IN,
+               PTJ5_FN, PTJ5_OUT, PTJ5_IN_PU, PTJ5_IN,
+               PTJ4_FN, PTJ4_OUT, PTJ4_IN_PU, PTJ4_IN,
+               PTJ3_FN, PTJ3_OUT, PTJ3_IN_PU, PTJ3_IN,
+               PTJ2_FN, PTJ2_OUT, PTJ2_IN_PU, PTJ2_IN,
+               PTJ1_FN, PTJ1_OUT, PTJ1_IN_PU, PTJ1_IN,
+               PTJ0_FN, PTJ0_OUT, PTJ0_IN_PU, PTJ0_IN }
+       },
+       { PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTK3_FN, PTK3_OUT, PTK3_IN_PU, PTK3_IN,
+               PTK2_FN, PTK2_OUT, PTK2_IN_PU, PTK2_IN,
+               PTK1_FN, PTK1_OUT, PTK1_IN_PU, PTK1_IN,
+               PTK0_FN, PTK0_OUT, PTK0_IN_PU, PTK0_IN }
+       },
+       { PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
+               PTL7_FN, PTL7_OUT, PTL7_IN_PU, PTL7_IN,
+               PTL6_FN, PTL6_OUT, PTL6_IN_PU, PTL6_IN,
+               PTL5_FN, PTL5_OUT, PTL5_IN_PU, PTL5_IN,
+               PTL4_FN, PTL4_OUT, PTL4_IN_PU, PTL4_IN,
+               PTL3_FN, PTL3_OUT, PTL3_IN_PU, PTL3_IN,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
+               PTM7_FN, PTM7_OUT, PTM7_IN_PU, PTM7_IN,
+               PTM6_FN, PTM6_OUT, PTM6_IN_PU, PTM6_IN,
+               PTM5_FN, PTM5_OUT, PTM5_IN_PU, PTM5_IN,
+               PTM4_FN, PTM4_OUT, PTM4_IN_PU, PTM4_IN,
+               PTM3_FN, PTM3_OUT, PTM3_IN_PU, PTM3_IN,
+               PTM2_FN, PTM2_OUT, PTM2_IN_PU, PTM2_IN,
+               PTM1_FN, PTM1_OUT, PTM1_IN_PU, PTM1_IN,
+               PTM0_FN, PTM0_OUT, PTM0_IN_PU, PTM0_IN }
+       },
+       { PINMUX_CFG_REG("PPCR", 0xa4050118, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTP4_FN, PTP4_OUT, PTP4_IN_PU, PTP4_IN,
+               PTP3_FN, PTP3_OUT, PTP3_IN_PU, PTP3_IN,
+               PTP2_FN, PTP2_OUT, PTP2_IN_PU, PTP2_IN,
+               PTP1_FN, PTP1_OUT, PTP1_IN_PU, PTP1_IN,
+               PTP0_FN, PTP0_OUT, PTP0_IN_PU, PTP0_IN }
+       },
+       { PINMUX_CFG_REG("PRCR", 0xa405011a, 16, 2) {
+               PTR7_FN, PTR7_OUT, PTR7_IN_PU, PTR7_IN,
+               PTR6_FN, PTR6_OUT, PTR6_IN_PU, PTR6_IN,
+               PTR5_FN, PTR5_OUT, PTR5_IN_PU, PTR5_IN,
+               PTR4_FN, PTR4_OUT, PTR4_IN_PU, PTR4_IN,
+               PTR3_FN, PTR3_OUT, PTR3_IN_PU, PTR3_IN,
+               PTR2_FN, PTR2_OUT, PTR2_IN_PU, PTR2_IN,
+               PTR1_FN, PTR1_OUT, PTR1_IN_PU, PTR1_IN,
+               PTR0_FN, PTR0_OUT, PTR0_IN_PU, PTR0_IN }
+       },
+       { PINMUX_CFG_REG("PSCR", 0xa405011c, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTS4_FN, PTS4_OUT, PTS4_IN_PU, PTS4_IN,
+               PTS3_FN, PTS3_OUT, PTS3_IN_PU, PTS3_IN,
+               PTS2_FN, PTS2_OUT, PTS2_IN_PU, PTS2_IN,
+               PTS1_FN, PTS1_OUT, PTS1_IN_PU, PTS1_IN,
+               PTS0_FN, PTS0_OUT, PTS0_IN_PU, PTS0_IN }
+       },
+       { PINMUX_CFG_REG("PTCR", 0xa405011e, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTT4_FN, PTT4_OUT, PTT4_IN_PU, PTT4_IN,
+               PTT3_FN, PTT3_OUT, PTT3_IN_PU, PTT3_IN,
+               PTT2_FN, PTT2_OUT, PTT2_IN_PU, PTT2_IN,
+               PTT1_FN, PTT1_OUT, PTT1_IN_PU, PTT1_IN,
+               PTT0_FN, PTT0_OUT, PTT0_IN_PU, PTT0_IN }
+       },
+       { PINMUX_CFG_REG("PUCR", 0xa4050120, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTU4_FN, PTU4_OUT, PTU4_IN_PU, PTU4_IN,
+               PTU3_FN, PTU3_OUT, PTU3_IN_PU, PTU3_IN,
+               PTU2_FN, PTU2_OUT, PTU2_IN_PU, PTU2_IN,
+               PTU1_FN, PTU1_OUT, PTU1_IN_PU, PTU1_IN,
+               PTU0_FN, PTU0_OUT, PTU0_IN_PU, PTU0_IN }
+       },
+       { PINMUX_CFG_REG("PVCR", 0xa4050122, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTV4_FN, PTV4_OUT, PTV4_IN_PU, PTV4_IN,
+               PTV3_FN, PTV3_OUT, PTV3_IN_PU, PTV3_IN,
+               PTV2_FN, PTV2_OUT, PTV2_IN_PU, PTV2_IN,
+               PTV1_FN, PTV1_OUT, PTV1_IN_PU, PTV1_IN,
+               PTV0_FN, PTV0_OUT, PTV0_IN_PU, PTV0_IN }
+       },
+       {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+       { PINMUX_DATA_REG("PADR", 0xa4050140, 8) {
+               PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+               PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
+       },
+       { PINMUX_DATA_REG("PBDR", 0xa4050142, 8) {
+               PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+               PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA }
+       },
+       { PINMUX_DATA_REG("PCDR", 0xa4050144, 8) {
+               PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+               PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA }
+       },
+       { PINMUX_DATA_REG("PDDR", 0xa4050126, 8) {
+               PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+               PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA }
+       },
+       { PINMUX_DATA_REG("PEDR", 0xa4050148, 8) {
+               0, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+               PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA }
+       },
+       { PINMUX_DATA_REG("PFDR", 0xa405014a, 8) {
+               0, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+               PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA }
+       },
+       { PINMUX_DATA_REG("PGDR", 0xa405014c, 8) {
+               0, PTG6_DATA, PTG5_DATA, PTG4_DATA,
+               PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA }
+       },
+       { PINMUX_DATA_REG("PHDR", 0xa405014e, 8) {
+               0, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+               PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA }
+       },
+       { PINMUX_DATA_REG("PJDR", 0xa4050150, 8) {
+               0, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+               PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA }
+       },
+       { PINMUX_DATA_REG("PKDR", 0xa4050152, 8) {
+               0, 0, 0, 0,
+               PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
+       },
+       { PINMUX_DATA_REG("PLDR", 0xa4050154, 8) {
+               PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+               PTL3_DATA, 0, 0, 0 }
+       },
+       { PINMUX_DATA_REG("PMDR", 0xa4050156, 8) {
+               PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+               PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
+       },
+       { PINMUX_DATA_REG("PPDR", 0xa4050158, 8) {
+               0, 0, 0, PTP4_DATA,
+               PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA }
+       },
+       { PINMUX_DATA_REG("PRDR", 0xa405015a, 8) {
+               PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+               PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA }
+       },
+       { PINMUX_DATA_REG("PSDR", 0xa405015c, 8) {
+               0, 0, 0, PTS4_DATA,
+               PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
+       },
+       { PINMUX_DATA_REG("PTDR", 0xa405015e, 8) {
+               0, 0, 0, PTT4_DATA,
+               PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
+       },
+       { PINMUX_DATA_REG("PUDR", 0xa4050160, 8) {
+               0, 0, 0, PTU4_DATA,
+               PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA }
+       },
+       { PINMUX_DATA_REG("PVDR", 0xa4050162, 8) {
+               0, 0, 0, PTV4_DATA,
+               PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA }
+       },
+       { },
+};
+
+static struct pinmux_info sh7720_pinmux_info = {
+       .name = "sh7720_pfc",
+       .reserved_id = PINMUX_RESERVED,
+       .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+       .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+       .input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+       .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+       .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+       .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+       .first_gpio = GPIO_PTA7,
+       .last_gpio = GPIO_FN_STATUS1,
+
+       .gpios = pinmux_gpios,
+       .cfg_regs = pinmux_config_regs,
+       .data_regs = pinmux_data_regs,
+
+       .gpio_data = pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+       return register_pinmux(&sh7720_pinmux_info);
+}
+
+arch_initcall(plat_pinmux_setup);
index 2d452f67fb87dcc9535b088d6c101c7069641272..2780917c0088c410491c4729e92727e4ec019d0e 100644 (file)
@@ -36,7 +36,7 @@ extern unsigned long int float32_add(unsigned long int a, unsigned long int b);
 extern unsigned long long float64_sub(unsigned long long a,
                                      unsigned long long b);
 extern unsigned long int float32_sub(unsigned long int a, unsigned long int b);
-
+extern unsigned long int float64_to_float32(unsigned long long a);
 static unsigned int fpu_exception_flags;
 
 /*
@@ -415,6 +415,29 @@ static int ieee_fpe_handler(struct pt_regs *regs)
                } else
                        return 0;
 
+               regs->pc = nextpc;
+               return 1;
+       } else if ((finsn & 0xf0bd) == 0xf0bd) {
+               /* fcnvds - double to single precision convert */
+               struct task_struct *tsk = current;
+               int m;
+               unsigned int hx;
+
+               m = (finsn >> 9) & 0x7;
+               hx = tsk->thread.fpu.hard.fp_regs[m];
+
+               if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)
+                       && ((hx & 0x7fffffff) < 0x00100000)) {
+                       /* subnormal double to float conversion */
+                       long long llx;
+
+                       llx = ((long long)tsk->thread.fpu.hard.fp_regs[m] << 32)
+                           | tsk->thread.fpu.hard.fp_regs[m + 1];
+
+                       tsk->thread.fpu.hard.fpul = float64_to_float32(llx);
+               } else
+                       return 0;
+
                regs->pc = nextpc;
                return 1;
        }
index 254c5c55ab9170b846d9a9f5b0ac52db0f31e5fa..d9bdc931ac09138f84b007fc3d0f9ff92f5f900e 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/init.h>
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
+#include <linux/io.h>
 
 enum {
        UNUSED = 0,
@@ -178,10 +179,14 @@ static int __init sh7760_devices_setup(void)
 }
 __initcall(sh7760_devices_setup);
 
+#define INTC_ICR       0xffd00000UL
+#define INTC_ICR_IRLM  (1 << 7)
+
 void __init plat_irq_setup_pins(int mode)
 {
        switch (mode) {
        case IRQ_MODE_IRQ:
+               ctrl_outw(ctrl_inw(INTC_ICR) | INTC_ICR_IRLM, INTC_ICR);
                register_intc_controller(&intc_desc_irq);
                break;
        default:
index 828cb57cb9591efe1c8a2e3003caa7c15b3cbc8f..2b747f3b02bd34d22290eab0ec5e9ca2a948ea10 100644 (file)
@@ -85,6 +85,7 @@ float64 float64_div(float64 a, float64 b);
 float32 float32_div(float32 a, float32 b);
 float32 float32_mul(float32 a, float32 b);
 float64 float64_mul(float64 a, float64 b);
+float32 float64_to_float32(float64 a);
 inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
                   bits64 * z1Ptr);
 inline void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr,
@@ -890,3 +891,31 @@ float64 float64_mul(float64 a, float64 b)
        }
        return roundAndPackFloat64(zSign, zExp, zSig0);
 }
+
+/*
+ * -------------------------------------------------------------------------------
+ *  Returns the result of converting the double-precision floating-point value
+ *  `a' to the single-precision floating-point format.  The conversion is
+ *  performed according to the IEC/IEEE Standard for Binary Floating-point
+ *  Arithmetic.
+ *  -------------------------------------------------------------------------------
+ *  */
+float32 float64_to_float32(float64 a)
+{
+    flag aSign;
+    int16 aExp;
+    bits64 aSig;
+    bits32 zSig;
+
+    aSig = extractFloat64Frac( a );
+    aExp = extractFloat64Exp( a );
+    aSign = extractFloat64Sign( a );
+
+    shift64RightJamming( aSig, 22, &aSig );
+    zSig = aSig;
+    if ( aExp || zSig ) {
+        zSig |= 0x40000000;
+        aExp -= 0x381;
+    }
+    return roundAndPackFloat32(aSign, aExp, zSig);
+}
index 9381ad8da263825164922874529c794d2ebb8223..be9a0c185958375585c3f4ac9de363cce18e375c 100644 (file)
@@ -27,5 +27,10 @@ clock-$(CONFIG_CPU_SUBTYPE_SH7723)   := clock-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SH7366)     := clock-sh7722.o
 clock-$(CONFIG_CPU_SUBTYPE_SHX3)       := clock-shx3.o
 
+# Pinmux setup
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7722)    := pinmux-sh7722.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SH7723)    := pinmux-sh7723.o
+
 obj-y                  += $(clock-y)
 obj-$(CONFIG_SMP)      += $(smp-y)
+obj-$(CONFIG_GENERIC_GPIO)     += $(pinmux-y)
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7722.c
new file mode 100644 (file)
index 0000000..cb9d07b
--- /dev/null
@@ -0,0 +1,1783 @@
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7722.h>
+
+enum {
+       PINMUX_RESERVED = 0,
+
+       PINMUX_DATA_BEGIN,
+       PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+       PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA,
+       PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+       PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA,
+       PTC7_DATA, PTC5_DATA, PTC4_DATA, PTC3_DATA, PTC2_DATA, PTC0_DATA,
+       PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+       PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA,
+       PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA, PTE1_DATA, PTE0_DATA,
+       PTF6_DATA, PTF5_DATA, PTF4_DATA,
+       PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA,
+       PTG4_DATA, PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA,
+       PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+       PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
+       PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ1_DATA, PTJ0_DATA,
+       PTK6_DATA, PTK5_DATA, PTK4_DATA,
+       PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA,
+       PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+       PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA,
+       PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+       PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA,
+       PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+       PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA,
+       PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+       PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA,
+       PTR4_DATA, PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA,
+       PTS4_DATA, PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA,
+       PTT4_DATA, PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
+       PTU4_DATA, PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
+       PTV4_DATA, PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA,
+       PTW6_DATA, PTW5_DATA, PTW4_DATA,
+       PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA,
+       PTX6_DATA, PTX5_DATA, PTX4_DATA,
+       PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA,
+       PTY6_DATA, PTY5_DATA, PTY4_DATA,
+       PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA,
+       PTZ5_DATA, PTZ4_DATA, PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA,
+       PINMUX_DATA_END,
+
+       PINMUX_INPUT_BEGIN,
+       PTA7_IN, PTA6_IN, PTA5_IN, PTA4_IN,
+       PTA3_IN, PTA2_IN, PTA1_IN, PTA0_IN,
+       PTB7_IN, PTB6_IN, PTB5_IN, PTB4_IN,
+       PTB3_IN, PTB2_IN, PTB1_IN, PTB0_IN,
+       PTC7_IN, PTC5_IN, PTC4_IN, PTC3_IN, PTC2_IN, PTC0_IN,
+       PTD7_IN, PTD6_IN, PTD5_IN, PTD4_IN, PTD3_IN, PTD2_IN, PTD1_IN,
+       PTE7_IN, PTE6_IN, PTE5_IN, PTE4_IN, PTE1_IN, PTE0_IN,
+       PTF6_IN, PTF5_IN, PTF4_IN, PTF3_IN, PTF2_IN, PTF1_IN,
+       PTH6_IN, PTH5_IN, PTH1_IN, PTH0_IN,
+       PTJ1_IN, PTJ0_IN,
+       PTK6_IN, PTK5_IN, PTK4_IN, PTK3_IN, PTK2_IN, PTK0_IN,
+       PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN,
+       PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN,
+       PTM7_IN, PTM6_IN, PTM5_IN, PTM4_IN,
+       PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN,
+       PTN7_IN, PTN6_IN, PTN5_IN, PTN4_IN,
+       PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN,
+       PTQ5_IN, PTQ4_IN, PTQ3_IN, PTQ2_IN, PTQ0_IN,
+       PTR2_IN,
+       PTS4_IN, PTS2_IN, PTS1_IN,
+       PTT4_IN, PTT3_IN, PTT2_IN, PTT1_IN,
+       PTU4_IN, PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
+       PTV4_IN, PTV3_IN, PTV2_IN, PTV1_IN, PTV0_IN,
+       PTW6_IN, PTW4_IN, PTW3_IN, PTW2_IN, PTW1_IN, PTW0_IN,
+       PTX6_IN, PTX5_IN, PTX4_IN, PTX3_IN, PTX2_IN, PTX1_IN, PTX0_IN,
+       PTY5_IN, PTY4_IN, PTY3_IN, PTY2_IN, PTY0_IN,
+       PTZ5_IN, PTZ4_IN, PTZ3_IN, PTZ2_IN, PTZ1_IN,
+       PINMUX_INPUT_END,
+
+       PINMUX_INPUT_PULLDOWN_BEGIN,
+       PTA7_IN_PD, PTA6_IN_PD, PTA5_IN_PD, PTA4_IN_PD,
+       PTA3_IN_PD, PTA2_IN_PD, PTA1_IN_PD, PTA0_IN_PD,
+       PTE7_IN_PD, PTE6_IN_PD, PTE5_IN_PD, PTE4_IN_PD, PTE1_IN_PD, PTE0_IN_PD,
+       PTF6_IN_PD, PTF5_IN_PD, PTF4_IN_PD, PTF3_IN_PD, PTF2_IN_PD, PTF1_IN_PD,
+       PTH6_IN_PD, PTH5_IN_PD, PTH1_IN_PD, PTH0_IN_PD,
+       PTK6_IN_PD, PTK5_IN_PD, PTK4_IN_PD, PTK3_IN_PD, PTK2_IN_PD, PTK0_IN_PD,
+       PTL7_IN_PD, PTL6_IN_PD, PTL5_IN_PD, PTL4_IN_PD,
+       PTL3_IN_PD, PTL2_IN_PD, PTL1_IN_PD, PTL0_IN_PD,
+       PTM7_IN_PD, PTM6_IN_PD, PTM5_IN_PD, PTM4_IN_PD,
+       PTM3_IN_PD, PTM2_IN_PD, PTM1_IN_PD, PTM0_IN_PD,
+       PTQ5_IN_PD, PTQ4_IN_PD, PTQ3_IN_PD, PTQ2_IN_PD,
+       PTS4_IN_PD, PTS2_IN_PD, PTS1_IN_PD,
+       PTT4_IN_PD, PTT3_IN_PD, PTT2_IN_PD, PTT1_IN_PD,
+       PTU4_IN_PD, PTU3_IN_PD, PTU2_IN_PD, PTU1_IN_PD, PTU0_IN_PD,
+       PTV4_IN_PD, PTV3_IN_PD, PTV2_IN_PD, PTV1_IN_PD, PTV0_IN_PD,
+       PTW6_IN_PD, PTW4_IN_PD, PTW3_IN_PD, PTW2_IN_PD, PTW1_IN_PD, PTW0_IN_PD,
+       PTX6_IN_PD, PTX5_IN_PD, PTX4_IN_PD,
+       PTX3_IN_PD, PTX2_IN_PD, PTX1_IN_PD, PTX0_IN_PD,
+       PINMUX_INPUT_PULLDOWN_END,
+
+       PINMUX_INPUT_PULLUP_BEGIN,
+       PTC7_IN_PU, PTC5_IN_PU,
+       PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
+       PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU,
+       PTJ1_IN_PU, PTJ0_IN_PU,
+       PTQ0_IN_PU,
+       PTR2_IN_PU,
+       PTX6_IN_PU,
+       PTY5_IN_PU, PTY4_IN_PU, PTY3_IN_PU, PTY2_IN_PU, PTY0_IN_PU,
+       PTZ5_IN_PU, PTZ4_IN_PU, PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU,
+       PINMUX_INPUT_PULLUP_END,
+
+       PINMUX_OUTPUT_BEGIN,
+       PTA7_OUT, PTA5_OUT,
+       PTB7_OUT, PTB6_OUT, PTB5_OUT, PTB4_OUT,
+       PTB3_OUT, PTB2_OUT, PTB1_OUT, PTB0_OUT,
+       PTC4_OUT, PTC3_OUT, PTC2_OUT, PTC0_OUT,
+       PTD6_OUT, PTD5_OUT, PTD4_OUT,
+       PTD3_OUT, PTD2_OUT, PTD1_OUT, PTD0_OUT,
+       PTE7_OUT, PTE6_OUT, PTE5_OUT, PTE4_OUT, PTE1_OUT, PTE0_OUT,
+       PTF6_OUT, PTF5_OUT, PTF4_OUT, PTF3_OUT, PTF2_OUT, PTF0_OUT,
+       PTG4_OUT, PTG3_OUT, PTG2_OUT, PTG1_OUT, PTG0_OUT,
+       PTH7_OUT, PTH6_OUT, PTH5_OUT, PTH4_OUT,
+       PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
+       PTJ7_OUT, PTJ6_OUT, PTJ5_OUT, PTJ1_OUT, PTJ0_OUT,
+       PTK6_OUT, PTK5_OUT, PTK4_OUT, PTK3_OUT, PTK1_OUT, PTK0_OUT,
+       PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT,
+       PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT,
+       PTM7_OUT, PTM6_OUT, PTM5_OUT, PTM4_OUT,
+       PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT,
+       PTN7_OUT, PTN6_OUT, PTN5_OUT, PTN4_OUT,
+       PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT, PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
+       PTQ3_OUT, PTQ2_OUT, PTQ1_OUT, PTQ0_OUT,
+       PTR4_OUT, PTR3_OUT, PTR1_OUT, PTR0_OUT,
+       PTS3_OUT, PTS2_OUT, PTS0_OUT,
+       PTT4_OUT, PTT3_OUT, PTT2_OUT, PTT0_OUT,
+       PTU4_OUT, PTU3_OUT, PTU2_OUT, PTU0_OUT,
+       PTV4_OUT, PTV3_OUT, PTV2_OUT, PTV1_OUT, PTV0_OUT,
+       PTW5_OUT, PTW4_OUT, PTW3_OUT, PTW2_OUT, PTW1_OUT, PTW0_OUT,
+       PTX6_OUT, PTX5_OUT, PTX4_OUT, PTX3_OUT, PTX2_OUT, PTX1_OUT, PTX0_OUT,
+       PTY5_OUT, PTY4_OUT, PTY3_OUT, PTY2_OUT, PTY1_OUT, PTY0_OUT,
+       PINMUX_OUTPUT_END,
+
+       PINMUX_MARK_BEGIN,
+       SCIF0_TXD_MARK, SCIF0_RXD_MARK,
+       SCIF0_RTS_MARK, SCIF0_CTS_MARK, SCIF0_SCK_MARK,
+       SCIF1_TXD_MARK, SCIF1_RXD_MARK,
+       SCIF1_RTS_MARK, SCIF1_CTS_MARK, SCIF1_SCK_MARK,
+       SCIF2_TXD_MARK, SCIF2_RXD_MARK,
+       SCIF2_RTS_MARK, SCIF2_CTS_MARK, SCIF2_SCK_MARK,
+       SIOTXD_MARK, SIORXD_MARK,
+       SIOD_MARK, SIOSTRB0_MARK, SIOSTRB1_MARK,
+       SIOSCK_MARK, SIOMCK_MARK,
+       VIO_D15_MARK, VIO_D14_MARK, VIO_D13_MARK, VIO_D12_MARK,
+       VIO_D11_MARK, VIO_D10_MARK, VIO_D9_MARK, VIO_D8_MARK,
+       VIO_D7_MARK, VIO_D6_MARK, VIO_D5_MARK, VIO_D4_MARK,
+       VIO_D3_MARK, VIO_D2_MARK, VIO_D1_MARK, VIO_D0_MARK,
+       VIO_CLK_MARK, VIO_VD_MARK, VIO_HD_MARK, VIO_FLD_MARK,
+       VIO_CKO_MARK, VIO_STEX_MARK, VIO_STEM_MARK, VIO_VD2_MARK,
+       VIO_HD2_MARK, VIO_CLK2_MARK,
+       LCDD23_MARK, LCDD22_MARK, LCDD21_MARK, LCDD20_MARK,
+       LCDD19_MARK, LCDD18_MARK, LCDD17_MARK, LCDD16_MARK,
+       LCDD15_MARK, LCDD14_MARK, LCDD13_MARK, LCDD12_MARK,
+       LCDD11_MARK, LCDD10_MARK, LCDD9_MARK, LCDD8_MARK,
+       LCDD7_MARK, LCDD6_MARK, LCDD5_MARK, LCDD4_MARK,
+       LCDD3_MARK, LCDD2_MARK, LCDD1_MARK, LCDD0_MARK,
+       LCDLCLK_MARK, LCDDON_MARK, LCDVCPWC_MARK, LCDVEPWC_MARK,
+       LCDVSYN_MARK, LCDDCK_MARK, LCDHSYN_MARK, LCDDISP_MARK,
+       LCDRS_MARK, LCDCS_MARK, LCDWR_MARK, LCDRD_MARK,
+       LCDDON2_MARK, LCDVCPWC2_MARK, LCDVEPWC2_MARK, LCDVSYN2_MARK,
+       LCDCS2_MARK,
+       IOIS16_MARK, A25_MARK, A24_MARK, A23_MARK, A22_MARK,
+       BS_MARK, CS6B_CE1B_MARK, WAIT_MARK, CS6A_CE2B_MARK,
+       HPD63_MARK, HPD62_MARK, HPD61_MARK, HPD60_MARK,
+       HPD59_MARK, HPD58_MARK, HPD57_MARK, HPD56_MARK,
+       HPD55_MARK, HPD54_MARK, HPD53_MARK, HPD52_MARK,
+       HPD51_MARK, HPD50_MARK, HPD49_MARK, HPD48_MARK,
+       HPDQM7_MARK, HPDQM6_MARK, HPDQM5_MARK, HPDQM4_MARK,
+       IRQ0_MARK, IRQ1_MARK, IRQ2_MARK, IRQ3_MARK,
+       IRQ4_MARK, IRQ5_MARK, IRQ6_MARK, IRQ7_MARK,
+       SDHICD_MARK, SDHIWP_MARK, SDHID3_MARK, SDHID2_MARK,
+       SDHID1_MARK, SDHID0_MARK, SDHICMD_MARK, SDHICLK_MARK,
+       SIUAOLR_MARK, SIUAOBT_MARK, SIUAISLD_MARK, SIUAILR_MARK,
+       SIUAIBT_MARK, SIUAOSLD_MARK, SIUMCKA_MARK, SIUFCKA_MARK,
+       SIUBOLR_MARK, SIUBOBT_MARK, SIUBISLD_MARK, SIUBILR_MARK,
+       SIUBIBT_MARK, SIUBOSLD_MARK, SIUMCKB_MARK, SIUFCKB_MARK,
+       AUDSYNC_MARK, AUDATA3_MARK, AUDATA2_MARK, AUDATA1_MARK, AUDATA0_MARK,
+       DACK_MARK, DREQ0_MARK,
+       DV_CLKI_MARK, DV_CLK_MARK, DV_HSYNC_MARK, DV_VSYNC_MARK,
+       DV_D15_MARK, DV_D14_MARK, DV_D13_MARK, DV_D12_MARK,
+       DV_D11_MARK, DV_D10_MARK, DV_D9_MARK, DV_D8_MARK,
+       DV_D7_MARK, DV_D6_MARK, DV_D5_MARK, DV_D4_MARK,
+       DV_D3_MARK, DV_D2_MARK, DV_D1_MARK, DV_D0_MARK,
+       STATUS0_MARK, PDSTATUS_MARK,
+       SIOF0_MCK_MARK, SIOF0_SCK_MARK,
+       SIOF0_SYNC_MARK, SIOF0_SS1_MARK, SIOF0_SS2_MARK,
+       SIOF0_TXD_MARK, SIOF0_RXD_MARK,
+       SIOF1_MCK_MARK, SIOF1_SCK_MARK,
+       SIOF1_SYNC_MARK, SIOF1_SS1_MARK, SIOF1_SS2_MARK,
+       SIOF1_TXD_MARK, SIOF1_RXD_MARK,
+       SIM_D_MARK, SIM_CLK_MARK, SIM_RST_MARK,
+       TS_SDAT_MARK, TS_SCK_MARK, TS_SDEN_MARK, TS_SPSYNC_MARK,
+       IRDA_IN_MARK, IRDA_OUT_MARK,
+       TPUTO_MARK,
+       FCE_MARK, NAF7_MARK, NAF6_MARK, NAF5_MARK, NAF4_MARK,
+       NAF3_MARK, NAF2_MARK, NAF1_MARK, NAF0_MARK, FCDE_MARK,
+       FOE_MARK, FSC_MARK, FWE_MARK, FRB_MARK,
+       KEYIN0_MARK, KEYIN1_MARK, KEYIN2_MARK, KEYIN3_MARK, KEYIN4_MARK,
+       KEYOUT0_MARK, KEYOUT1_MARK, KEYOUT2_MARK, KEYOUT3_MARK,
+       KEYOUT4_IN6_MARK, KEYOUT5_IN5_MARK,
+       PINMUX_MARK_END,
+
+       PINMUX_FUNCTION_BEGIN,
+       VIO_D7_SCIF1_SCK, VIO_D6_SCIF1_RXD, VIO_D5_SCIF1_TXD, VIO_D4,
+       VIO_D3, VIO_D2, VIO_D1, VIO_D0_LCDLCLK,
+       HPD55, HPD54, HPD53, HPD52, HPD51, HPD50, HPD49, HPD48,
+       IOIS16, HPDQM7, HPDQM6, HPDQM5, HPDQM4,
+       SDHICD, SDHIWP, SDHID3, IRQ2_SDHID2, SDHID1, SDHID0, SDHICMD, SDHICLK,
+       A25, A24, A23, A22, IRQ5, IRQ4_BS,
+       PTF6, SIOSCK_SIUBOBT, SIOSTRB1_SIUBOLR,
+       SIOSTRB0_SIUBIBT, SIOD_SIUBILR, SIORXD_SIUBISLD, SIOTXD_SIUBOSLD,
+       AUDSYNC, AUDATA3, AUDATA2, AUDATA1, AUDATA0,
+       LCDVCPWC_LCDVCPWC2, LCDVSYN2_DACK, LCDVSYN, LCDDISP_LCDRS,
+       LCDHSYN_LCDCS, LCDDON_LCDDON2, LCDD17_DV_HSYNC, LCDD16_DV_VSYNC,
+       STATUS0, PDSTATUS, IRQ1, IRQ0,
+       SIUAILR_SIOF1_SS2, SIUAIBT_SIOF1_SS1, SIUAOLR_SIOF1_SYNC,
+       SIUAOBT_SIOF1_SCK, SIUAISLD_SIOF1_RXD, SIUAOSLD_SIOF1_TXD, PTK0,
+       LCDD15_DV_D15, LCDD14_DV_D14, LCDD13_DV_D13, LCDD12_DV_D12,
+       LCDD11_DV_D11, LCDD10_DV_D10, LCDD9_DV_D9, LCDD8_DV_D8,
+       LCDD7_DV_D7, LCDD6_DV_D6, LCDD5_DV_D5, LCDD4_DV_D4,
+       LCDD3_DV_D3, LCDD2_DV_D2, LCDD1_DV_D1, LCDD0_DV_D0,
+       HPD63, HPD62, HPD61, HPD60, HPD59, HPD58, HPD57, HPD56,
+       SIOF0_SS2_SIM_RST, SIOF0_SS1_TS_SPSYNC, SIOF0_SYNC_TS_SDEN,
+       SIOF0_SCK_TS_SCK, PTQ2, PTQ1, PTQ0,
+       LCDRD, CS6B_CE1B_LCDCS2, WAIT, LCDDCK_LCDWR, LCDVEPWC_LCDVEPWC2,
+       SCIF0_CTS_SIUAISPD, SCIF0_RTS_SIUAOSPD,
+       SCIF0_SCK_TPUTO, SCIF0_RXD, SCIF0_TXD,
+       FOE_VIO_VD2, FWE, FSC, DREQ0, FCDE,
+       NAF2_VIO_D10, NAF1_VIO_D9, NAF0_VIO_D8,
+       FRB_VIO_CLK2, FCE_VIO_HD2,
+       NAF7_VIO_D15, NAF6_VIO_D14, NAF5_VIO_D13, NAF4_VIO_D12, NAF3_VIO_D11,
+       VIO_FLD_SCIF2_CTS, VIO_CKO_SCIF2_RTS, VIO_STEX_SCIF2_SCK,
+       VIO_STEM_SCIF2_TXD, VIO_HD_SCIF2_RXD,
+       VIO_VD_SCIF1_CTS, VIO_CLK_SCIF1_RTS,
+       CS6A_CE2B, LCDD23, LCDD22, LCDD21, LCDD20,
+       LCDD19_DV_CLKI, LCDD18_DV_CLK,
+       KEYOUT5_IN5, KEYOUT4_IN6, KEYOUT3, KEYOUT2, KEYOUT1, KEYOUT0,
+       KEYIN4_IRQ7, KEYIN3, KEYIN2, KEYIN1, KEYIN0_IRQ6,
+
+       PSA15_KEYIN0, PSA15_IRQ6, PSA14_KEYIN4, PSA14_IRQ7,
+       PSA9_IRQ4, PSA9_BS, PSA4_IRQ2, PSA4_SDHID2,
+       PSB15_SIOTXD, PSB15_SIUBOSLD, PSB14_SIORXD, PSB14_SIUBISLD,
+       PSB13_SIOD, PSB13_SIUBILR, PSB12_SIOSTRB0, PSB12_SIUBIBT,
+       PSB11_SIOSTRB1, PSB11_SIUBOLR, PSB10_SIOSCK, PSB10_SIUBOBT,
+       PSB9_SIOMCK, PSB9_SIUMCKB, PSB8_SIOF0_MCK, PSB8_IRQ3,
+       PSB7_SIOF0_TXD, PSB7_IRDA_OUT, PSB6_SIOF0_RXD, PSB6_IRDA_IN,
+       PSB5_SIOF0_SCK, PSB5_TS_SCK, PSB4_SIOF0_SYNC, PSB4_TS_SDEN,
+       PSB3_SIOF0_SS1, PSB3_TS_SPSYNC, PSB2_SIOF0_SS2, PSB2_SIM_RST,
+       PSB1_SIUMCKA, PSB1_SIOF1_MCK, PSB0_SIUAOSLD, PSB0_SIOF1_TXD,
+       PSC15_SIUAISLD, PSC15_SIOF1_RXD, PSC14_SIUAOBT, PSC14_SIOF1_SCK,
+       PSC13_SIUAOLR, PSC13_SIOF1_SYNC, PSC12_SIUAIBT, PSC12_SIOF1_SS1,
+       PSC11_SIUAILR, PSC11_SIOF1_SS2, PSC0_NAF, PSC0_VIO,
+       PSD13_VIO, PSD13_SCIF2, PSD12_VIO, PSD12_SCIF1,
+       PSD11_VIO, PSD11_SCIF1, PSD10_VIO_D0, PSD10_LCDLCLK,
+       PSD9_SIOMCK_SIUMCKB, PSD9_SIUFCKB, PSD8_SCIF0_SCK, PSD8_TPUTO,
+       PSD7_SCIF0_RTS, PSD7_SIUAOSPD, PSD6_SCIF0_CTS, PSD6_SIUAISPD,
+       PSD5_CS6B_CE1B, PSD5_LCDCS2,
+       PSD3_LCDVEPWC_LCDVCPWC, PSD3_LCDVEPWC2_LCDVCPWC2,
+       PSD2_LCDDON, PSD2_LCDDON2, PSD0_LCDD19_LCDD0, PSD0_DV,
+       PSE15_SIOF0_MCK_IRQ3, PSE15_SIM_D,
+       PSE14_SIOF0_TXD_IRDA_OUT, PSE14_SIM_CLK,
+       PSE13_SIOF0_RXD_IRDA_IN, PSE13_TS_SDAT, PSE12_LCDVSYN2, PSE12_DACK,
+       PSE11_SIUMCKA_SIOF1_MCK, PSE11_SIUFCKA,
+       PSE3_FLCTL, PSE3_VIO, PSE2_NAF2, PSE2_VIO_D10,
+       PSE1_NAF1, PSE1_VIO_D9, PSE0_NAF0, PSE0_VIO_D8,
+
+       HIZA14_KEYSC, HIZA14_HIZ,
+       HIZA10_NAF, HIZA10_HIZ,
+       HIZA9_VIO, HIZA9_HIZ,
+       HIZA8_LCDC, HIZA8_HIZ,
+       HIZA7_LCDC, HIZA7_HIZ,
+       HIZA6_LCDC, HIZA6_HIZ,
+       HIZB1_VIO, HIZB1_HIZ,
+       HIZB0_VIO, HIZB0_HIZ,
+       HIZC15_IRQ7, HIZC15_HIZ,
+       HIZC14_IRQ6, HIZC14_HIZ,
+       HIZC13_IRQ5, HIZC13_HIZ,
+       HIZC12_IRQ4, HIZC12_HIZ,
+       HIZC11_IRQ3, HIZC11_HIZ,
+       HIZC10_IRQ2, HIZC10_HIZ,
+       HIZC9_IRQ1, HIZC9_HIZ,
+       HIZC8_IRQ0, HIZC8_HIZ,
+       MSELB9_VIO, MSELB9_VIO2,
+       MSELB8_RGB, MSELB8_SYS,
+       PINMUX_FUNCTION_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+       /* PTA */
+       PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_IN_PD, PTA7_OUT),
+       PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_IN_PD),
+       PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_IN_PD, PTA5_OUT),
+       PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_IN_PD),
+       PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_IN_PD),
+       PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_IN_PD),
+       PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_IN_PD),
+       PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_IN_PD),
+
+       /* PTB */
+       PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT),
+       PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT),
+       PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT),
+       PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT),
+       PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT),
+       PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT),
+       PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT),
+       PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT),
+
+       /* PTC */
+       PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_IN_PU),
+       PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_IN_PU),
+       PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT),
+       PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT),
+       PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT),
+       PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT),
+
+       /* PTD */
+       PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_IN_PU),
+       PINMUX_DATA(PTD6_DATA, PTD6_OUT, PTD6_IN, PTD6_IN_PU),
+       PINMUX_DATA(PTD5_DATA, PTD5_OUT, PTD5_IN, PTD5_IN_PU),
+       PINMUX_DATA(PTD4_DATA, PTD4_OUT, PTD4_IN, PTD4_IN_PU),
+       PINMUX_DATA(PTD3_DATA, PTD3_OUT, PTD3_IN, PTD3_IN_PU),
+       PINMUX_DATA(PTD2_DATA, PTD2_OUT, PTD2_IN, PTD2_IN_PU),
+       PINMUX_DATA(PTD1_DATA, PTD1_OUT, PTD1_IN, PTD1_IN_PU),
+       PINMUX_DATA(PTD0_DATA, PTD0_OUT),
+
+       /* PTE */
+       PINMUX_DATA(PTE7_DATA, PTE7_OUT, PTE7_IN, PTE7_IN_PD),
+       PINMUX_DATA(PTE6_DATA, PTE6_OUT, PTE6_IN, PTE6_IN_PD),
+       PINMUX_DATA(PTE5_DATA, PTE5_OUT, PTE5_IN, PTE5_IN_PD),
+       PINMUX_DATA(PTE4_DATA, PTE4_OUT, PTE4_IN, PTE4_IN_PD),
+       PINMUX_DATA(PTE1_DATA, PTE1_OUT, PTE1_IN, PTE1_IN_PD),
+       PINMUX_DATA(PTE0_DATA, PTE0_OUT, PTE0_IN, PTE0_IN_PD),
+
+       /* PTF */
+       PINMUX_DATA(PTF6_DATA, PTF6_OUT, PTF6_IN, PTF6_IN_PD),
+       PINMUX_DATA(PTF5_DATA, PTF5_OUT, PTF5_IN, PTF5_IN_PD),
+       PINMUX_DATA(PTF4_DATA, PTF4_OUT, PTF4_IN, PTF4_IN_PD),
+       PINMUX_DATA(PTF3_DATA, PTF3_OUT, PTF3_IN, PTF3_IN_PD),
+       PINMUX_DATA(PTF2_DATA, PTF2_OUT, PTF2_IN, PTF2_IN_PD),
+       PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_IN_PD),
+       PINMUX_DATA(PTF0_DATA, PTF0_OUT),
+
+       /* PTG */
+       PINMUX_DATA(PTG4_DATA, PTG4_OUT),
+       PINMUX_DATA(PTG3_DATA, PTG3_OUT),
+       PINMUX_DATA(PTG2_DATA, PTG2_OUT),
+       PINMUX_DATA(PTG1_DATA, PTG1_OUT),
+       PINMUX_DATA(PTG0_DATA, PTG0_OUT),
+
+       /* PTH */
+       PINMUX_DATA(PTH7_DATA, PTH7_OUT),
+       PINMUX_DATA(PTH6_DATA, PTH6_OUT, PTH6_IN, PTH6_IN_PD),
+       PINMUX_DATA(PTH5_DATA, PTH5_OUT, PTH5_IN, PTH5_IN_PD),
+       PINMUX_DATA(PTH4_DATA, PTH4_OUT),
+       PINMUX_DATA(PTH3_DATA, PTH3_OUT),
+       PINMUX_DATA(PTH2_DATA, PTH2_OUT),
+       PINMUX_DATA(PTH1_DATA, PTH1_OUT, PTH1_IN, PTH1_IN_PD),
+       PINMUX_DATA(PTH0_DATA, PTH0_OUT, PTH0_IN, PTH0_IN_PD),
+
+       /* PTJ */
+       PINMUX_DATA(PTJ7_DATA, PTJ7_OUT),
+       PINMUX_DATA(PTJ6_DATA, PTJ6_OUT),
+       PINMUX_DATA(PTJ5_DATA, PTJ5_OUT),
+       PINMUX_DATA(PTJ1_DATA, PTJ1_OUT, PTJ1_IN, PTJ1_IN_PU),
+       PINMUX_DATA(PTJ0_DATA, PTJ0_OUT, PTJ0_IN, PTJ0_IN_PU),
+
+       /* PTK */
+       PINMUX_DATA(PTK6_DATA, PTK6_OUT, PTK6_IN, PTK6_IN_PD),
+       PINMUX_DATA(PTK5_DATA, PTK5_OUT, PTK5_IN, PTK5_IN_PD),
+       PINMUX_DATA(PTK4_DATA, PTK4_OUT, PTK4_IN, PTK4_IN_PD),
+       PINMUX_DATA(PTK3_DATA, PTK3_OUT, PTK3_IN, PTK3_IN_PD),
+       PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_IN_PD),
+       PINMUX_DATA(PTK1_DATA, PTK1_OUT),
+       PINMUX_DATA(PTK0_DATA, PTK0_OUT, PTK0_IN, PTK0_IN_PD),
+
+       /* PTL */
+       PINMUX_DATA(PTL7_DATA, PTL7_OUT, PTL7_IN, PTL7_IN_PD),
+       PINMUX_DATA(PTL6_DATA, PTL6_OUT, PTL6_IN, PTL6_IN_PD),
+       PINMUX_DATA(PTL5_DATA, PTL5_OUT, PTL5_IN, PTL5_IN_PD),
+       PINMUX_DATA(PTL4_DATA, PTL4_OUT, PTL4_IN, PTL4_IN_PD),
+       PINMUX_DATA(PTL3_DATA, PTL3_OUT, PTL3_IN, PTL3_IN_PD),
+       PINMUX_DATA(PTL2_DATA, PTL2_OUT, PTL2_IN, PTL2_IN_PD),
+       PINMUX_DATA(PTL1_DATA, PTL1_OUT, PTL1_IN, PTL1_IN_PD),
+       PINMUX_DATA(PTL0_DATA, PTL0_OUT, PTL0_IN, PTL0_IN_PD),
+
+       /* PTM */
+       PINMUX_DATA(PTM7_DATA, PTM7_OUT, PTM7_IN, PTM7_IN_PD),
+       PINMUX_DATA(PTM6_DATA, PTM6_OUT, PTM6_IN, PTM6_IN_PD),
+       PINMUX_DATA(PTM5_DATA, PTM5_OUT, PTM5_IN, PTM5_IN_PD),
+       PINMUX_DATA(PTM4_DATA, PTM4_OUT, PTM4_IN, PTM4_IN_PD),
+       PINMUX_DATA(PTM3_DATA, PTM3_OUT, PTM3_IN, PTM3_IN_PD),
+       PINMUX_DATA(PTM2_DATA, PTM2_OUT, PTM2_IN, PTM2_IN_PD),
+       PINMUX_DATA(PTM1_DATA, PTM1_OUT, PTM1_IN, PTM1_IN_PD),
+       PINMUX_DATA(PTM0_DATA, PTM0_OUT, PTM0_IN, PTM0_IN_PD),
+
+       /* PTN */
+       PINMUX_DATA(PTN7_DATA, PTN7_OUT, PTN7_IN),
+       PINMUX_DATA(PTN6_DATA, PTN6_OUT, PTN6_IN),
+       PINMUX_DATA(PTN5_DATA, PTN5_OUT, PTN5_IN),
+       PINMUX_DATA(PTN4_DATA, PTN4_OUT, PTN4_IN),
+       PINMUX_DATA(PTN3_DATA, PTN3_OUT, PTN3_IN),
+       PINMUX_DATA(PTN2_DATA, PTN2_OUT, PTN2_IN),
+       PINMUX_DATA(PTN1_DATA, PTN1_OUT, PTN1_IN),
+       PINMUX_DATA(PTN0_DATA, PTN0_OUT, PTN0_IN),
+
+       /* PTQ */
+       PINMUX_DATA(PTQ6_DATA, PTQ6_OUT),
+       PINMUX_DATA(PTQ5_DATA, PTQ5_OUT, PTQ5_IN, PTQ5_IN_PD),
+       PINMUX_DATA(PTQ4_DATA, PTQ4_OUT, PTQ4_IN, PTQ4_IN_PD),
+       PINMUX_DATA(PTQ3_DATA, PTQ3_OUT, PTQ3_IN, PTQ3_IN_PD),
+       PINMUX_DATA(PTQ2_DATA, PTQ2_IN, PTQ2_IN_PD),
+       PINMUX_DATA(PTQ1_DATA, PTQ1_OUT),
+       PINMUX_DATA(PTQ0_DATA, PTQ0_OUT, PTQ0_IN, PTQ0_IN_PU),
+
+       /* PTR */
+       PINMUX_DATA(PTR4_DATA, PTR4_OUT),
+       PINMUX_DATA(PTR3_DATA, PTR3_OUT),
+       PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_IN_PU),
+       PINMUX_DATA(PTR1_DATA, PTR1_OUT),
+       PINMUX_DATA(PTR0_DATA, PTR0_OUT),
+
+       /* PTS */
+       PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_IN_PD),
+       PINMUX_DATA(PTS3_DATA, PTS3_OUT),
+       PINMUX_DATA(PTS2_DATA, PTS2_OUT, PTS2_IN, PTS2_IN_PD),
+       PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_IN_PD),
+       PINMUX_DATA(PTS0_DATA, PTS0_OUT),
+
+       /* PTT */
+       PINMUX_DATA(PTT4_DATA, PTT4_OUT, PTT4_IN, PTT4_IN_PD),
+       PINMUX_DATA(PTT3_DATA, PTT3_OUT, PTT3_IN, PTT3_IN_PD),
+       PINMUX_DATA(PTT2_DATA, PTT2_OUT, PTT2_IN, PTT2_IN_PD),
+       PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_IN_PD),
+       PINMUX_DATA(PTT0_DATA, PTT0_OUT),
+
+       /* PTU */
+       PINMUX_DATA(PTU4_DATA, PTU4_OUT, PTU4_IN, PTU4_IN_PD),
+       PINMUX_DATA(PTU3_DATA, PTU3_OUT, PTU3_IN, PTU3_IN_PD),
+       PINMUX_DATA(PTU2_DATA, PTU2_OUT, PTU2_IN, PTU2_IN_PD),
+       PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_IN_PD),
+       PINMUX_DATA(PTU0_DATA, PTU0_OUT, PTU0_IN, PTU0_IN_PD),
+
+       /* PTV */
+       PINMUX_DATA(PTV4_DATA, PTV4_OUT, PTV4_IN, PTV4_IN_PD),
+       PINMUX_DATA(PTV3_DATA, PTV3_OUT, PTV3_IN, PTV3_IN_PD),
+       PINMUX_DATA(PTV2_DATA, PTV2_OUT, PTV2_IN, PTV2_IN_PD),
+       PINMUX_DATA(PTV1_DATA, PTV1_OUT, PTV1_IN, PTV1_IN_PD),
+       PINMUX_DATA(PTV0_DATA, PTV0_OUT, PTV0_IN, PTV0_IN_PD),
+
+       /* PTW */
+       PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_IN_PD),
+       PINMUX_DATA(PTW5_DATA, PTW5_OUT),
+       PINMUX_DATA(PTW4_DATA, PTW4_OUT, PTW4_IN, PTW4_IN_PD),
+       PINMUX_DATA(PTW3_DATA, PTW3_OUT, PTW3_IN, PTW3_IN_PD),
+       PINMUX_DATA(PTW2_DATA, PTW2_OUT, PTW2_IN, PTW2_IN_PD),
+       PINMUX_DATA(PTW1_DATA, PTW1_OUT, PTW1_IN, PTW1_IN_PD),
+       PINMUX_DATA(PTW0_DATA, PTW0_OUT, PTW0_IN, PTW0_IN_PD),
+
+       /* PTX */
+       PINMUX_DATA(PTX6_DATA, PTX6_OUT, PTX6_IN, PTX6_IN_PD),
+       PINMUX_DATA(PTX5_DATA, PTX5_OUT, PTX5_IN, PTX5_IN_PD),
+       PINMUX_DATA(PTX4_DATA, PTX4_OUT, PTX4_IN, PTX4_IN_PD),
+       PINMUX_DATA(PTX3_DATA, PTX3_OUT, PTX3_IN, PTX3_IN_PD),
+       PINMUX_DATA(PTX2_DATA, PTX2_OUT, PTX2_IN, PTX2_IN_PD),
+       PINMUX_DATA(PTX1_DATA, PTX1_OUT, PTX1_IN, PTX1_IN_PD),
+       PINMUX_DATA(PTX0_DATA, PTX0_OUT, PTX0_IN, PTX0_IN_PD),
+
+       /* PTY */
+       PINMUX_DATA(PTY5_DATA, PTY5_OUT, PTY5_IN, PTY5_IN_PU),
+       PINMUX_DATA(PTY4_DATA, PTY4_OUT, PTY4_IN, PTY4_IN_PU),
+       PINMUX_DATA(PTY3_DATA, PTY3_OUT, PTY3_IN, PTY3_IN_PU),
+       PINMUX_DATA(PTY2_DATA, PTY2_OUT, PTY2_IN, PTY2_IN_PU),
+       PINMUX_DATA(PTY1_DATA, PTY1_OUT),
+       PINMUX_DATA(PTY0_DATA, PTY0_OUT, PTY0_IN, PTY0_IN_PU),
+
+       /* PTZ */
+       PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_IN_PU),
+       PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_IN_PU),
+       PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_IN_PU),
+       PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_IN_PU),
+       PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_IN_PU),
+
+       /* SCIF0 */
+       PINMUX_DATA(SCIF0_TXD_MARK, SCIF0_TXD),
+       PINMUX_DATA(SCIF0_RXD_MARK, SCIF0_RXD),
+       PINMUX_DATA(SCIF0_RTS_MARK, PSD7_SCIF0_RTS, SCIF0_RTS_SIUAOSPD),
+       PINMUX_DATA(SCIF0_CTS_MARK, PSD6_SCIF0_CTS, SCIF0_CTS_SIUAISPD),
+       PINMUX_DATA(SCIF0_SCK_MARK, PSD8_SCIF0_SCK, SCIF0_SCK_TPUTO),
+
+       /* SCIF1 */
+       PINMUX_DATA(SCIF1_TXD_MARK, PSD11_SCIF1, VIO_D5_SCIF1_TXD),
+       PINMUX_DATA(SCIF1_RXD_MARK, PSD11_SCIF1, VIO_D6_SCIF1_RXD),
+       PINMUX_DATA(SCIF1_RTS_MARK, PSD12_SCIF1, VIO_CLK_SCIF1_RTS),
+       PINMUX_DATA(SCIF1_CTS_MARK, PSD12_SCIF1, VIO_VD_SCIF1_CTS),
+       PINMUX_DATA(SCIF1_SCK_MARK, PSD11_SCIF1, VIO_D7_SCIF1_SCK),
+
+       /* SCIF2 */
+       PINMUX_DATA(SCIF2_TXD_MARK, PSD13_SCIF2, VIO_STEM_SCIF2_TXD),
+       PINMUX_DATA(SCIF2_RXD_MARK, PSD13_SCIF2, VIO_HD_SCIF2_RXD),
+       PINMUX_DATA(SCIF2_RTS_MARK, PSD13_SCIF2, VIO_CKO_SCIF2_RTS),
+       PINMUX_DATA(SCIF2_CTS_MARK, PSD13_SCIF2, VIO_FLD_SCIF2_CTS),
+       PINMUX_DATA(SCIF2_SCK_MARK, PSD13_SCIF2, VIO_STEX_SCIF2_SCK),
+
+       /* SIO */
+       PINMUX_DATA(SIOTXD_MARK, PSB15_SIOTXD, SIOTXD_SIUBOSLD),
+       PINMUX_DATA(SIORXD_MARK, PSB14_SIORXD, SIORXD_SIUBISLD),
+       PINMUX_DATA(SIOD_MARK, PSB13_SIOD, SIOD_SIUBILR),
+       PINMUX_DATA(SIOSTRB0_MARK, PSB12_SIOSTRB0, SIOSTRB0_SIUBIBT),
+       PINMUX_DATA(SIOSTRB1_MARK, PSB11_SIOSTRB1, SIOSTRB1_SIUBOLR),
+       PINMUX_DATA(SIOSCK_MARK, PSB10_SIOSCK, SIOSCK_SIUBOBT),
+       PINMUX_DATA(SIOMCK_MARK, PSD9_SIOMCK_SIUMCKB, PSB9_SIOMCK, PTF6),
+
+       /* CEU */
+       PINMUX_DATA(VIO_D15_MARK, PSC0_VIO, HIZA10_NAF, NAF7_VIO_D15),
+       PINMUX_DATA(VIO_D14_MARK, PSC0_VIO, HIZA10_NAF, NAF6_VIO_D14),
+       PINMUX_DATA(VIO_D13_MARK, PSC0_VIO, HIZA10_NAF, NAF5_VIO_D13),
+       PINMUX_DATA(VIO_D12_MARK, PSC0_VIO, HIZA10_NAF, NAF4_VIO_D12),
+       PINMUX_DATA(VIO_D11_MARK, PSC0_VIO, HIZA10_NAF, NAF3_VIO_D11),
+       PINMUX_DATA(VIO_D10_MARK, PSE2_VIO_D10, HIZB0_VIO, NAF2_VIO_D10),
+       PINMUX_DATA(VIO_D9_MARK, PSE1_VIO_D9, HIZB0_VIO, NAF1_VIO_D9),
+       PINMUX_DATA(VIO_D8_MARK, PSE0_VIO_D8, HIZB0_VIO, NAF0_VIO_D8),
+       PINMUX_DATA(VIO_D7_MARK, PSD11_VIO, VIO_D7_SCIF1_SCK),
+       PINMUX_DATA(VIO_D6_MARK, PSD11_VIO, VIO_D6_SCIF1_RXD),
+       PINMUX_DATA(VIO_D5_MARK, PSD11_VIO, VIO_D5_SCIF1_TXD),
+       PINMUX_DATA(VIO_D4_MARK, VIO_D4),
+       PINMUX_DATA(VIO_D3_MARK, VIO_D3),
+       PINMUX_DATA(VIO_D2_MARK, VIO_D2),
+       PINMUX_DATA(VIO_D1_MARK, VIO_D1),
+       PINMUX_DATA(VIO_D0_MARK, PSD10_VIO_D0, VIO_D0_LCDLCLK),
+       PINMUX_DATA(VIO_CLK_MARK, PSD12_VIO, MSELB9_VIO, VIO_CLK_SCIF1_RTS),
+       PINMUX_DATA(VIO_VD_MARK, PSD12_VIO, MSELB9_VIO, VIO_VD_SCIF1_CTS),
+       PINMUX_DATA(VIO_HD_MARK, PSD13_VIO, MSELB9_VIO, VIO_HD_SCIF2_RXD),
+       PINMUX_DATA(VIO_FLD_MARK, PSD13_VIO, HIZA9_VIO, VIO_FLD_SCIF2_CTS),
+       PINMUX_DATA(VIO_CKO_MARK, PSD13_VIO, HIZA9_VIO, VIO_CKO_SCIF2_RTS),
+       PINMUX_DATA(VIO_STEX_MARK, PSD13_VIO, HIZA9_VIO, VIO_STEX_SCIF2_SCK),
+       PINMUX_DATA(VIO_STEM_MARK, PSD13_VIO, HIZA9_VIO, VIO_STEM_SCIF2_TXD),
+       PINMUX_DATA(VIO_VD2_MARK, PSE3_VIO, MSELB9_VIO2,
+                   HIZB0_VIO, FOE_VIO_VD2),
+       PINMUX_DATA(VIO_HD2_MARK, PSE3_VIO, MSELB9_VIO2,
+                   HIZB1_VIO, HIZB1_VIO, FCE_VIO_HD2),
+       PINMUX_DATA(VIO_CLK2_MARK, PSE3_VIO, MSELB9_VIO2,
+                   HIZB1_VIO, FRB_VIO_CLK2),
+
+       /* LCDC */
+       PINMUX_DATA(LCDD23_MARK, HIZA8_LCDC, LCDD23),
+       PINMUX_DATA(LCDD22_MARK, HIZA8_LCDC, LCDD22),
+       PINMUX_DATA(LCDD21_MARK, HIZA8_LCDC, LCDD21),
+       PINMUX_DATA(LCDD20_MARK, HIZA8_LCDC, LCDD20),
+       PINMUX_DATA(LCDD19_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD19_DV_CLKI),
+       PINMUX_DATA(LCDD18_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD18_DV_CLK),
+       PINMUX_DATA(LCDD17_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC,
+                   LCDD17_DV_HSYNC),
+       PINMUX_DATA(LCDD16_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC,
+                   LCDD16_DV_VSYNC),
+       PINMUX_DATA(LCDD15_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD15_DV_D15),
+       PINMUX_DATA(LCDD14_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD14_DV_D14),
+       PINMUX_DATA(LCDD13_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD13_DV_D13),
+       PINMUX_DATA(LCDD12_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD12_DV_D12),
+       PINMUX_DATA(LCDD11_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD11_DV_D11),
+       PINMUX_DATA(LCDD10_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD10_DV_D10),
+       PINMUX_DATA(LCDD9_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD9_DV_D9),
+       PINMUX_DATA(LCDD8_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD8_DV_D8),
+       PINMUX_DATA(LCDD7_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD7_DV_D7),
+       PINMUX_DATA(LCDD6_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD6_DV_D6),
+       PINMUX_DATA(LCDD5_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD5_DV_D5),
+       PINMUX_DATA(LCDD4_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD4_DV_D4),
+       PINMUX_DATA(LCDD3_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD3_DV_D3),
+       PINMUX_DATA(LCDD2_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD2_DV_D2),
+       PINMUX_DATA(LCDD1_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD1_DV_D1),
+       PINMUX_DATA(LCDD0_MARK, PSD0_LCDD19_LCDD0, HIZA8_LCDC, LCDD0_DV_D0),
+       PINMUX_DATA(LCDLCLK_MARK, PSD10_LCDLCLK, VIO_D0_LCDLCLK),
+       /* Main LCD */
+       PINMUX_DATA(LCDDON_MARK, PSD2_LCDDON, HIZA7_LCDC, LCDDON_LCDDON2),
+       PINMUX_DATA(LCDVCPWC_MARK, PSD3_LCDVEPWC_LCDVCPWC,
+                   HIZA6_LCDC, LCDVCPWC_LCDVCPWC2),
+       PINMUX_DATA(LCDVEPWC_MARK, PSD3_LCDVEPWC_LCDVCPWC,
+                   HIZA6_LCDC, LCDVEPWC_LCDVEPWC2),
+       PINMUX_DATA(LCDVSYN_MARK, HIZA7_LCDC, LCDVSYN),
+       /* Main LCD - RGB Mode */
+       PINMUX_DATA(LCDDCK_MARK, MSELB8_RGB, HIZA8_LCDC, LCDDCK_LCDWR),
+       PINMUX_DATA(LCDHSYN_MARK, MSELB8_RGB, HIZA7_LCDC, LCDHSYN_LCDCS),
+       PINMUX_DATA(LCDDISP_MARK, MSELB8_RGB, HIZA7_LCDC, LCDDISP_LCDRS),
+       /* Main LCD - SYS Mode */
+       PINMUX_DATA(LCDRS_MARK, MSELB8_SYS, HIZA7_LCDC, LCDDISP_LCDRS),
+       PINMUX_DATA(LCDCS_MARK, MSELB8_SYS, HIZA7_LCDC, LCDHSYN_LCDCS),
+       PINMUX_DATA(LCDWR_MARK, MSELB8_SYS, HIZA8_LCDC, LCDDCK_LCDWR),
+       PINMUX_DATA(LCDRD_MARK, HIZA7_LCDC, LCDRD),
+       /* Sub LCD - SYS Mode */
+       PINMUX_DATA(LCDDON2_MARK, PSD2_LCDDON2, HIZA7_LCDC, LCDDON_LCDDON2),
+       PINMUX_DATA(LCDVCPWC2_MARK, PSD3_LCDVEPWC2_LCDVCPWC2,
+                   HIZA6_LCDC, LCDVCPWC_LCDVCPWC2),
+       PINMUX_DATA(LCDVEPWC2_MARK, PSD3_LCDVEPWC2_LCDVCPWC2,
+                   HIZA6_LCDC, LCDVEPWC_LCDVEPWC2),
+       PINMUX_DATA(LCDVSYN2_MARK, PSE12_LCDVSYN2, HIZA8_LCDC, LCDVSYN2_DACK),
+       PINMUX_DATA(LCDCS2_MARK, PSD5_LCDCS2, CS6B_CE1B_LCDCS2),
+
+       /* BSC */
+       PINMUX_DATA(IOIS16_MARK, IOIS16),
+       PINMUX_DATA(A25_MARK, A25),
+       PINMUX_DATA(A24_MARK, A24),
+       PINMUX_DATA(A23_MARK, A23),
+       PINMUX_DATA(A22_MARK, A22),
+       PINMUX_DATA(BS_MARK, PSA9_BS, IRQ4_BS),
+       PINMUX_DATA(CS6B_CE1B_MARK, PSD5_CS6B_CE1B, CS6B_CE1B_LCDCS2),
+       PINMUX_DATA(WAIT_MARK, WAIT),
+       PINMUX_DATA(CS6A_CE2B_MARK, CS6A_CE2B),
+
+       /* SBSC */
+       PINMUX_DATA(HPD63_MARK, HPD63),
+       PINMUX_DATA(HPD62_MARK, HPD62),
+       PINMUX_DATA(HPD61_MARK, HPD61),
+       PINMUX_DATA(HPD60_MARK, HPD60),
+       PINMUX_DATA(HPD59_MARK, HPD59),
+       PINMUX_DATA(HPD58_MARK, HPD58),
+       PINMUX_DATA(HPD57_MARK, HPD57),
+       PINMUX_DATA(HPD56_MARK, HPD56),
+       PINMUX_DATA(HPD55_MARK, HPD55),
+       PINMUX_DATA(HPD54_MARK, HPD54),
+       PINMUX_DATA(HPD53_MARK, HPD53),
+       PINMUX_DATA(HPD52_MARK, HPD52),
+       PINMUX_DATA(HPD51_MARK, HPD51),
+       PINMUX_DATA(HPD50_MARK, HPD50),
+       PINMUX_DATA(HPD49_MARK, HPD49),
+       PINMUX_DATA(HPD48_MARK, HPD48),
+       PINMUX_DATA(HPDQM7_MARK, HPDQM7),
+       PINMUX_DATA(HPDQM6_MARK, HPDQM6),
+       PINMUX_DATA(HPDQM5_MARK, HPDQM5),
+       PINMUX_DATA(HPDQM4_MARK, HPDQM4),
+
+       /* IRQ */
+       PINMUX_DATA(IRQ0_MARK, HIZC8_IRQ0, IRQ0),
+       PINMUX_DATA(IRQ1_MARK, HIZC9_IRQ1, IRQ1),
+       PINMUX_DATA(IRQ2_MARK, PSA4_IRQ2, HIZC10_IRQ2, IRQ2_SDHID2),
+       PINMUX_DATA(IRQ3_MARK, PSE15_SIOF0_MCK_IRQ3, PSB8_IRQ3,
+                   HIZC11_IRQ3, PTQ0),
+       PINMUX_DATA(IRQ4_MARK, PSA9_IRQ4, HIZC12_IRQ4, IRQ4_BS),
+       PINMUX_DATA(IRQ5_MARK, HIZC13_IRQ5, IRQ5),
+       PINMUX_DATA(IRQ6_MARK, PSA15_IRQ6, HIZC14_IRQ6, KEYIN0_IRQ6),
+       PINMUX_DATA(IRQ7_MARK, PSA14_IRQ7, HIZC15_IRQ7, KEYIN4_IRQ7),
+
+       /* SDHI */
+       PINMUX_DATA(SDHICD_MARK, SDHICD),
+       PINMUX_DATA(SDHIWP_MARK, SDHIWP),
+       PINMUX_DATA(SDHID3_MARK, SDHID3),
+       PINMUX_DATA(SDHID2_MARK, PSA4_SDHID2, IRQ2_SDHID2),
+       PINMUX_DATA(SDHID1_MARK, SDHID1),
+       PINMUX_DATA(SDHID0_MARK, SDHID0),
+       PINMUX_DATA(SDHICMD_MARK, SDHICMD),
+       PINMUX_DATA(SDHICLK_MARK, SDHICLK),
+
+       /* SIU - Port A */
+       PINMUX_DATA(SIUAOLR_MARK, PSC13_SIUAOLR, SIUAOLR_SIOF1_SYNC),
+       PINMUX_DATA(SIUAOBT_MARK, PSC14_SIUAOBT, SIUAOBT_SIOF1_SCK),
+       PINMUX_DATA(SIUAISLD_MARK, PSC15_SIUAISLD, SIUAISLD_SIOF1_RXD),
+       PINMUX_DATA(SIUAILR_MARK, PSC11_SIUAILR, SIUAILR_SIOF1_SS2),
+       PINMUX_DATA(SIUAIBT_MARK, PSC12_SIUAIBT, SIUAIBT_SIOF1_SS1),
+       PINMUX_DATA(SIUAOSLD_MARK, PSB0_SIUAOSLD, SIUAOSLD_SIOF1_TXD),
+       PINMUX_DATA(SIUMCKA_MARK, PSE11_SIUMCKA_SIOF1_MCK, PSB1_SIUMCKA, PTK0),
+       PINMUX_DATA(SIUFCKA_MARK, PSE11_SIUFCKA, PTK0),
+
+       /* SIU - Port B */
+       PINMUX_DATA(SIUBOLR_MARK, PSB11_SIUBOLR, SIOSTRB1_SIUBOLR),
+       PINMUX_DATA(SIUBOBT_MARK, PSB10_SIUBOBT, SIOSCK_SIUBOBT),
+       PINMUX_DATA(SIUBISLD_MARK, PSB14_SIUBISLD, SIORXD_SIUBISLD),
+       PINMUX_DATA(SIUBILR_MARK, PSB13_SIUBILR, SIOD_SIUBILR),
+       PINMUX_DATA(SIUBIBT_MARK, PSB12_SIUBIBT, SIOSTRB0_SIUBIBT),
+       PINMUX_DATA(SIUBOSLD_MARK, PSB15_SIUBOSLD, SIOTXD_SIUBOSLD),
+       PINMUX_DATA(SIUMCKB_MARK, PSD9_SIOMCK_SIUMCKB, PSB9_SIUMCKB, PTF6),
+       PINMUX_DATA(SIUFCKB_MARK, PSD9_SIUFCKB, PTF6),
+
+       /* AUD */
+       PINMUX_DATA(AUDSYNC_MARK, AUDSYNC),
+       PINMUX_DATA(AUDATA3_MARK, AUDATA3),
+       PINMUX_DATA(AUDATA2_MARK, AUDATA2),
+       PINMUX_DATA(AUDATA1_MARK, AUDATA1),
+       PINMUX_DATA(AUDATA0_MARK, AUDATA0),
+
+       /* DMAC */
+       PINMUX_DATA(DACK_MARK, PSE12_DACK, LCDVSYN2_DACK),
+       PINMUX_DATA(DREQ0_MARK, DREQ0),
+
+       /* VOU */
+       PINMUX_DATA(DV_CLKI_MARK, PSD0_DV, LCDD19_DV_CLKI),
+       PINMUX_DATA(DV_CLK_MARK, PSD0_DV, LCDD18_DV_CLK),
+       PINMUX_DATA(DV_HSYNC_MARK, PSD0_DV, LCDD17_DV_HSYNC),
+       PINMUX_DATA(DV_VSYNC_MARK, PSD0_DV, LCDD16_DV_VSYNC),
+       PINMUX_DATA(DV_D15_MARK, PSD0_DV, LCDD15_DV_D15),
+       PINMUX_DATA(DV_D14_MARK, PSD0_DV, LCDD14_DV_D14),
+       PINMUX_DATA(DV_D13_MARK, PSD0_DV, LCDD13_DV_D13),
+       PINMUX_DATA(DV_D12_MARK, PSD0_DV, LCDD12_DV_D12),
+       PINMUX_DATA(DV_D11_MARK, PSD0_DV, LCDD11_DV_D11),
+       PINMUX_DATA(DV_D10_MARK, PSD0_DV, LCDD10_DV_D10),
+       PINMUX_DATA(DV_D9_MARK, PSD0_DV, LCDD9_DV_D9),
+       PINMUX_DATA(DV_D8_MARK, PSD0_DV, LCDD8_DV_D8),
+       PINMUX_DATA(DV_D7_MARK, PSD0_DV, LCDD7_DV_D7),
+       PINMUX_DATA(DV_D6_MARK, PSD0_DV, LCDD6_DV_D6),
+       PINMUX_DATA(DV_D5_MARK, PSD0_DV, LCDD5_DV_D5),
+       PINMUX_DATA(DV_D4_MARK, PSD0_DV, LCDD4_DV_D4),
+       PINMUX_DATA(DV_D3_MARK, PSD0_DV, LCDD3_DV_D3),
+       PINMUX_DATA(DV_D2_MARK, PSD0_DV, LCDD2_DV_D2),
+       PINMUX_DATA(DV_D1_MARK, PSD0_DV, LCDD1_DV_D1),
+       PINMUX_DATA(DV_D0_MARK, PSD0_DV, LCDD0_DV_D0),
+
+       /* CPG */
+       PINMUX_DATA(STATUS0_MARK, STATUS0),
+       PINMUX_DATA(PDSTATUS_MARK, PDSTATUS),
+
+       /* SIOF0 */
+       PINMUX_DATA(SIOF0_MCK_MARK, PSE15_SIOF0_MCK_IRQ3, PSB8_SIOF0_MCK, PTQ0),
+       PINMUX_DATA(SIOF0_SCK_MARK, PSB5_SIOF0_SCK, SIOF0_SCK_TS_SCK),
+       PINMUX_DATA(SIOF0_SYNC_MARK, PSB4_SIOF0_SYNC, SIOF0_SYNC_TS_SDEN),
+       PINMUX_DATA(SIOF0_SS1_MARK, PSB3_SIOF0_SS1, SIOF0_SS1_TS_SPSYNC),
+       PINMUX_DATA(SIOF0_SS2_MARK, PSB2_SIOF0_SS2, SIOF0_SS2_SIM_RST),
+       PINMUX_DATA(SIOF0_TXD_MARK, PSE14_SIOF0_TXD_IRDA_OUT,
+                   PSB7_SIOF0_TXD, PTQ1),
+       PINMUX_DATA(SIOF0_RXD_MARK, PSE13_SIOF0_RXD_IRDA_IN,
+                   PSB6_SIOF0_RXD, PTQ2),
+
+       /* SIOF1 */
+       PINMUX_DATA(SIOF1_MCK_MARK, PSE11_SIUMCKA_SIOF1_MCK,
+                   PSB1_SIOF1_MCK, PTK0),
+       PINMUX_DATA(SIOF1_SCK_MARK, PSC14_SIOF1_SCK, SIUAOBT_SIOF1_SCK),
+       PINMUX_DATA(SIOF1_SYNC_MARK, PSC13_SIOF1_SYNC, SIUAOLR_SIOF1_SYNC),
+       PINMUX_DATA(SIOF1_SS1_MARK, PSC12_SIOF1_SS1, SIUAIBT_SIOF1_SS1),
+       PINMUX_DATA(SIOF1_SS2_MARK, PSC11_SIOF1_SS2, SIUAILR_SIOF1_SS2),
+       PINMUX_DATA(SIOF1_TXD_MARK, PSB0_SIOF1_TXD, SIUAOSLD_SIOF1_TXD),
+       PINMUX_DATA(SIOF1_RXD_MARK, PSC15_SIOF1_RXD, SIUAISLD_SIOF1_RXD),
+
+       /* SIM */
+       PINMUX_DATA(SIM_D_MARK, PSE15_SIM_D, PTQ0),
+       PINMUX_DATA(SIM_CLK_MARK, PSE14_SIM_CLK, PTQ1),
+       PINMUX_DATA(SIM_RST_MARK, PSB2_SIM_RST, SIOF0_SS2_SIM_RST),
+
+       /* TSIF */
+       PINMUX_DATA(TS_SDAT_MARK, PSE13_TS_SDAT, PTQ2),
+       PINMUX_DATA(TS_SCK_MARK, PSB5_TS_SCK, SIOF0_SCK_TS_SCK),
+       PINMUX_DATA(TS_SDEN_MARK, PSB4_TS_SDEN, SIOF0_SYNC_TS_SDEN),
+       PINMUX_DATA(TS_SPSYNC_MARK, PSB3_TS_SPSYNC, SIOF0_SS1_TS_SPSYNC),
+
+       /* IRDA */
+       PINMUX_DATA(IRDA_IN_MARK, PSE13_SIOF0_RXD_IRDA_IN, PSB6_IRDA_IN, PTQ2),
+       PINMUX_DATA(IRDA_OUT_MARK, PSE14_SIOF0_TXD_IRDA_OUT,
+                   PSB7_IRDA_OUT, PTQ1),
+
+       /* TPU */
+       PINMUX_DATA(TPUTO_MARK, PSD8_TPUTO, SCIF0_SCK_TPUTO),
+
+       /* FLCTL */
+       PINMUX_DATA(FCE_MARK, PSE3_FLCTL, FCE_VIO_HD2),
+       PINMUX_DATA(NAF7_MARK, PSC0_NAF, HIZA10_NAF, NAF7_VIO_D15),
+       PINMUX_DATA(NAF6_MARK, PSC0_NAF, HIZA10_NAF, NAF6_VIO_D14),
+       PINMUX_DATA(NAF5_MARK, PSC0_NAF, HIZA10_NAF, NAF5_VIO_D13),
+       PINMUX_DATA(NAF4_MARK, PSC0_NAF, HIZA10_NAF, NAF4_VIO_D12),
+       PINMUX_DATA(NAF3_MARK, PSC0_NAF, HIZA10_NAF, NAF3_VIO_D11),
+       PINMUX_DATA(NAF2_MARK, PSE2_NAF2, HIZB0_VIO, NAF2_VIO_D10),
+       PINMUX_DATA(NAF1_MARK, PSE1_NAF1, HIZB0_VIO, NAF1_VIO_D9),
+       PINMUX_DATA(NAF0_MARK, PSE0_NAF0, HIZB0_VIO, NAF0_VIO_D8),
+       PINMUX_DATA(FCDE_MARK, FCDE),
+       PINMUX_DATA(FOE_MARK, PSE3_FLCTL, HIZB0_VIO, FOE_VIO_VD2),
+       PINMUX_DATA(FSC_MARK, FSC),
+       PINMUX_DATA(FWE_MARK, FWE),
+       PINMUX_DATA(FRB_MARK, PSE3_FLCTL, FRB_VIO_CLK2),
+
+       /* KEYSC */
+       PINMUX_DATA(KEYIN0_MARK, PSA15_KEYIN0, HIZC14_IRQ6, KEYIN0_IRQ6),
+       PINMUX_DATA(KEYIN1_MARK, HIZA14_KEYSC, KEYIN1),
+       PINMUX_DATA(KEYIN2_MARK, HIZA14_KEYSC, KEYIN2),
+       PINMUX_DATA(KEYIN3_MARK, HIZA14_KEYSC, KEYIN3),
+       PINMUX_DATA(KEYIN4_MARK, PSA14_KEYIN4, HIZC15_IRQ7, KEYIN4_IRQ7),
+       PINMUX_DATA(KEYOUT0_MARK, HIZA14_KEYSC, KEYOUT0),
+       PINMUX_DATA(KEYOUT1_MARK, HIZA14_KEYSC, KEYOUT1),
+       PINMUX_DATA(KEYOUT2_MARK, HIZA14_KEYSC, KEYOUT2),
+       PINMUX_DATA(KEYOUT3_MARK, HIZA14_KEYSC, KEYOUT3),
+       PINMUX_DATA(KEYOUT4_IN6_MARK, HIZA14_KEYSC, KEYOUT4_IN6),
+       PINMUX_DATA(KEYOUT5_IN5_MARK, HIZA14_KEYSC, KEYOUT5_IN5),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+       /* PTA */
+       PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
+       PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
+       PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
+       PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
+       PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
+       PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
+       PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
+       PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+
+       /* PTB */
+       PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
+       PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
+       PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
+       PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
+       PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
+       PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
+       PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
+       PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+
+       /* PTC */
+       PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
+       PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
+       PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
+       PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
+       PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
+       PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+
+       /* PTD */
+       PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
+       PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
+       PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
+       PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
+       PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
+       PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
+       PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
+       PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+
+       /* PTE */
+       PINMUX_GPIO(GPIO_PTE7, PTE7_DATA),
+       PINMUX_GPIO(GPIO_PTE6, PTE6_DATA),
+       PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
+       PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
+       PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
+       PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+
+       /* PTF */
+       PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
+       PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
+       PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
+       PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
+       PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
+       PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
+       PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+
+       /* PTG */
+       PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
+       PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
+       PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
+       PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
+       PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+
+       /* PTH */
+       PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
+       PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
+       PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
+       PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
+       PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
+       PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
+       PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
+       PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+
+       /* PTJ */
+       PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
+       PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
+       PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
+       PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
+       PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+
+       /* PTK */
+       PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
+       PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
+       PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
+       PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
+       PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
+       PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
+       PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+
+       /* PTL */
+       PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
+       PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
+       PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
+       PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
+       PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
+       PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
+       PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
+       PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+
+       /* PTM */
+       PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
+       PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
+       PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
+       PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
+       PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
+       PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
+       PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
+       PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+
+       /* PTN */
+       PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
+       PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
+       PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
+       PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
+       PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
+       PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
+       PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
+       PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+
+       /* PTQ */
+       PINMUX_GPIO(GPIO_PTQ6, PTQ6_DATA),
+       PINMUX_GPIO(GPIO_PTQ5, PTQ5_DATA),
+       PINMUX_GPIO(GPIO_PTQ4, PTQ4_DATA),
+       PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
+       PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
+       PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
+       PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+
+       /* PTR */
+       PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
+       PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
+       PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
+       PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
+       PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+
+       /* PTS */
+       PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
+       PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
+       PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
+       PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
+       PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+
+       /* PTT */
+       PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
+       PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
+       PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
+       PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
+       PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+
+       /* PTU */
+       PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
+       PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
+       PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
+       PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
+       PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+
+       /* PTV */
+       PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
+       PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
+       PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
+       PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
+       PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+
+       /* PTW */
+       PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
+       PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
+       PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
+       PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
+       PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
+       PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
+       PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+
+       /* PTX */
+       PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
+       PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
+       PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
+       PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
+       PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
+       PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
+       PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+
+       /* PTY */
+       PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
+       PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
+       PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
+       PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
+       PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
+       PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+
+       /* PTZ */
+       PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
+       PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
+       PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
+       PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
+       PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
+
+       /* SCIF0 */
+       PINMUX_GPIO(GPIO_FN_SCIF0_TXD, SCIF0_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_RXD, SCIF0_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_RTS, SCIF0_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_CTS, SCIF0_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_SCK, SCIF0_SCK_MARK),
+
+       /* SCIF1 */
+       PINMUX_GPIO(GPIO_FN_SCIF1_TXD, SCIF1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_RXD, SCIF1_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_RTS, SCIF1_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_CTS, SCIF1_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_SCK, SCIF1_SCK_MARK),
+
+       /* SCIF2 */
+       PINMUX_GPIO(GPIO_FN_SCIF2_TXD, SCIF2_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_RXD, SCIF2_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_RTS, SCIF2_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_CTS, SCIF2_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_SCK, SCIF2_SCK_MARK),
+
+       /* SIO */
+       PINMUX_GPIO(GPIO_FN_SIOTXD, SIOTXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIORXD, SIORXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOD, SIOD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOSTRB0, SIOSTRB0_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOSTRB1, SIOSTRB1_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOSCK, SIOSCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOMCK, SIOMCK_MARK),
+
+       /* CEU */
+       PINMUX_GPIO(GPIO_FN_VIO_D15, VIO_D15_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D14, VIO_D14_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D13, VIO_D13_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D12, VIO_D12_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D11, VIO_D11_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D10, VIO_D10_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D9, VIO_D9_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D8, VIO_D8_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D7, VIO_D7_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D6, VIO_D6_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D5, VIO_D5_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D4, VIO_D4_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D3, VIO_D3_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D2, VIO_D2_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D1, VIO_D1_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D0, VIO_D0_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_CLK, VIO_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_VD, VIO_VD_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_HD, VIO_HD_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_FLD, VIO_FLD_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_CKO, VIO_CKO_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_STEX, VIO_STEX_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_STEM, VIO_STEM_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_VD2, VIO_VD2_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_HD2, VIO_HD2_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_CLK2, VIO_CLK2_MARK),
+
+       /* LCDC */
+       PINMUX_GPIO(GPIO_FN_LCDD23, LCDD23_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD22, LCDD22_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD21, LCDD21_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD20, LCDD20_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD19, LCDD19_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD18, LCDD18_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD17, LCDD17_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD16, LCDD16_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD15, LCDD15_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD14, LCDD14_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD13, LCDD13_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD12, LCDD12_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD11, LCDD11_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD10, LCDD10_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD9, LCDD9_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD8, LCDD8_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD7, LCDD7_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD6, LCDD6_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD5, LCDD5_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD4, LCDD4_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD3, LCDD3_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD2, LCDD2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD1, LCDD1_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD0, LCDD0_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDLCLK, LCDLCLK_MARK),
+       /* Main LCD */
+       PINMUX_GPIO(GPIO_FN_LCDDON, LCDDON_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVCPWC, LCDVCPWC_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVEPWC, LCDVEPWC_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVSYN, LCDVSYN_MARK),
+       /* Main LCD - RGB Mode */
+       PINMUX_GPIO(GPIO_FN_LCDDCK, LCDDCK_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDHSYN, LCDHSYN_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDDISP, LCDDISP_MARK),
+       /* Main LCD - SYS Mode */
+       PINMUX_GPIO(GPIO_FN_LCDRS, LCDRS_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDCS, LCDCS_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDWR, LCDWR_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDRD, LCDRD_MARK),
+       /* Sub LCD - SYS Mode */
+       PINMUX_GPIO(GPIO_FN_LCDDON2, LCDDON2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVCPWC2, LCDVCPWC2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVEPWC2, LCDVEPWC2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVSYN2, LCDVSYN2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDCS2, LCDCS2_MARK),
+
+       /* BSC */
+       PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+       PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+       PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+       PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6B_CE1B, CS6B_CE1B_MARK),
+       PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6A_CE2B, CS6A_CE2B_MARK),
+
+       /* SBSC */
+       PINMUX_GPIO(GPIO_FN_HPD63, HPD63_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD62, HPD62_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD61, HPD61_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD60, HPD60_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD59, HPD59_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD58, HPD58_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD57, HPD57_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD56, HPD56_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD55, HPD55_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD54, HPD54_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD53, HPD53_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD52, HPD52_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD51, HPD51_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD50, HPD50_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD49, HPD49_MARK),
+       PINMUX_GPIO(GPIO_FN_HPD48, HPD48_MARK),
+       PINMUX_GPIO(GPIO_FN_HPDQM7, HPDQM7_MARK),
+       PINMUX_GPIO(GPIO_FN_HPDQM6, HPDQM6_MARK),
+       PINMUX_GPIO(GPIO_FN_HPDQM5, HPDQM5_MARK),
+       PINMUX_GPIO(GPIO_FN_HPDQM4, HPDQM4_MARK),
+
+       /* IRQ */
+       PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3, IRQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
+
+       /* SDHI */
+       PINMUX_GPIO(GPIO_FN_SDHICD, SDHICD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHIWP, SDHIWP_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHID3, SDHID3_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHID2, SDHID2_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHID1, SDHID1_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHID0, SDHID0_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHICMD, SDHICMD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHICLK, SDHICLK_MARK),
+
+       /* SIU - Port A */
+       PINMUX_GPIO(GPIO_FN_SIUAOLR, SIUAOLR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAOBT, SIUAOBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAISLD, SIUAISLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAILR, SIUAILR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAIBT, SIUAIBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAOSLD, SIUAOSLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUMCKA, SIUMCKA_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUFCKA, SIUFCKA_MARK),
+
+       /* SIU - Port B */
+       PINMUX_GPIO(GPIO_FN_SIUBOLR, SIUBOLR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBOBT, SIUBOBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBISLD, SIUBISLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBILR, SIUBILR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBIBT, SIUBIBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBOSLD, SIUBOSLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUMCKB, SIUMCKB_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUFCKB, SIUFCKB_MARK),
+
+       /* AUD */
+       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
+
+       /* DMAC */
+       PINMUX_GPIO(GPIO_FN_DACK, DACK_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+
+       /* VOU */
+       PINMUX_GPIO(GPIO_FN_DV_CLKI, DV_CLKI_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D15, DV_D15_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D14, DV_D14_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D13, DV_D13_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D12, DV_D12_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D11, DV_D11_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D10, DV_D10_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D9, DV_D9_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D8, DV_D8_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D7, DV_D7_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D6, DV_D6_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D5, DV_D5_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D4, DV_D4_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D3, DV_D3_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D2, DV_D2_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D1, DV_D1_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D0, DV_D0_MARK),
+
+       /* CPG */
+       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
+       PINMUX_GPIO(GPIO_FN_PDSTATUS, PDSTATUS_MARK),
+
+       /* SIOF0 */
+       PINMUX_GPIO(GPIO_FN_SIOF0_MCK, SIOF0_MCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_SCK, SIOF0_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_SYNC, SIOF0_SYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_SS1, SIOF0_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_SS2, SIOF0_SS2_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_TXD, SIOF0_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF0_RXD, SIOF0_RXD_MARK),
+
+       /* SIOF1 */
+       PINMUX_GPIO(GPIO_FN_SIOF1_MCK, SIOF1_MCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_SCK, SIOF1_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_SYNC, SIOF1_SYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_SS1, SIOF1_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_SS2, SIOF1_SS2_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_TXD, SIOF1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIOF1_RXD, SIOF1_RXD_MARK),
+
+       /* SIM */
+       PINMUX_GPIO(GPIO_FN_SIM_D, SIM_D_MARK),
+       PINMUX_GPIO(GPIO_FN_SIM_CLK, SIM_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIM_RST, SIM_RST_MARK),
+
+       /* TSIF */
+       PINMUX_GPIO(GPIO_FN_TS_SDAT, TS_SDAT_MARK),
+       PINMUX_GPIO(GPIO_FN_TS_SCK, TS_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_TS_SDEN, TS_SDEN_MARK),
+       PINMUX_GPIO(GPIO_FN_TS_SPSYNC, TS_SPSYNC_MARK),
+
+       /* IRDA */
+       PINMUX_GPIO(GPIO_FN_IRDA_IN, IRDA_IN_MARK),
+       PINMUX_GPIO(GPIO_FN_IRDA_OUT, IRDA_OUT_MARK),
+
+       /* TPU */
+       PINMUX_GPIO(GPIO_FN_TPUTO, TPUTO_MARK),
+
+       /* FLCTL */
+       PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF7, NAF7_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF6, NAF6_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF5, NAF5_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF4, NAF4_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF3, NAF3_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF2, NAF2_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF1, NAF1_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF0, NAF0_MARK),
+       PINMUX_GPIO(GPIO_FN_FCDE, FCDE_MARK),
+       PINMUX_GPIO(GPIO_FN_FOE, FOE_MARK),
+       PINMUX_GPIO(GPIO_FN_FSC, FSC_MARK),
+       PINMUX_GPIO(GPIO_FN_FWE, FWE_MARK),
+       PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+
+       /* KEYSC */
+       PINMUX_GPIO(GPIO_FN_KEYIN0, KEYIN0_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN1, KEYIN1_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN2, KEYIN2_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN3, KEYIN3_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN4, KEYIN4_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT0, KEYOUT0_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT1, KEYOUT1_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT2, KEYOUT2_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT3, KEYOUT3_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT4_IN6, KEYOUT4_IN6_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT5_IN5, KEYOUT5_IN5_MARK),
+};
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+       { PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
+               VIO_D7_SCIF1_SCK, PTA7_OUT, PTA7_IN_PD, PTA7_IN,
+               VIO_D6_SCIF1_RXD, 0, PTA6_IN_PD, PTA6_IN,
+               VIO_D5_SCIF1_TXD, PTA5_OUT, PTA5_IN_PD, PTA5_IN,
+               VIO_D4, 0, PTA4_IN_PD, PTA4_IN,
+               VIO_D3, 0, PTA3_IN_PD, PTA3_IN,
+               VIO_D2, 0, PTA2_IN_PD, PTA2_IN,
+               VIO_D1, 0, PTA1_IN_PD, PTA1_IN,
+               VIO_D0_LCDLCLK, 0, PTA0_IN_PD, PTA0_IN }
+       },
+       { PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
+               HPD55, PTB7_OUT, 0, PTB7_IN,
+               HPD54, PTB6_OUT, 0, PTB6_IN,
+               HPD53, PTB5_OUT, 0, PTB5_IN,
+               HPD52, PTB4_OUT, 0, PTB4_IN,
+               HPD51, PTB3_OUT, 0, PTB3_IN,
+               HPD50, PTB2_OUT, 0, PTB2_IN,
+               HPD49, PTB1_OUT, 0, PTB1_IN,
+               HPD48, PTB0_OUT, 0, PTB0_IN }
+       },
+       { PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
+               0, 0, PTC7_IN_PU, PTC7_IN,
+               0, 0, 0, 0,
+               IOIS16, 0, PTC5_IN_PU, PTC5_IN,
+               HPDQM7, PTC4_OUT, 0, PTC4_IN,
+               HPDQM6, PTC3_OUT, 0, PTC3_IN,
+               HPDQM5, PTC2_OUT, 0, PTC2_IN,
+               0, 0, 0, 0,
+               HPDQM4, PTC0_OUT, 0, PTC0_IN }
+       },
+       { PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
+               SDHICD, 0, PTD7_IN_PU, PTD7_IN,
+               SDHIWP, PTD6_OUT, PTD6_IN_PU, PTD6_IN,
+               SDHID3, PTD5_OUT, PTD5_IN_PU, PTD5_IN,
+               IRQ2_SDHID2, PTD4_OUT, PTD4_IN_PU, PTD4_IN,
+               SDHID1, PTD3_OUT, PTD3_IN_PU, PTD3_IN,
+               SDHID0, PTD2_OUT, PTD2_IN_PU, PTD2_IN,
+               SDHICMD, PTD1_OUT, PTD1_IN_PU, PTD1_IN,
+               SDHICLK, PTD0_OUT, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
+               A25, PTE7_OUT, PTE7_IN_PD, PTE7_IN,
+               A24, PTE6_OUT, PTE6_IN_PD, PTE6_IN,
+               A23, PTE5_OUT, PTE5_IN_PD, PTE5_IN,
+               A22, PTE4_OUT, PTE4_IN_PD, PTE4_IN,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               IRQ5, PTE1_OUT, PTE1_IN_PD, PTE1_IN,
+               IRQ4_BS, PTE0_OUT, PTE0_IN_PD, PTE0_IN }
+       },
+       { PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
+               0, 0, 0, 0,
+               PTF6, PTF6_OUT, PTF6_IN_PD, PTF6_IN,
+               SIOSCK_SIUBOBT, PTF5_OUT, PTF5_IN_PD, PTF5_IN,
+               SIOSTRB1_SIUBOLR, PTF4_OUT, PTF4_IN_PD, PTF4_IN,
+               SIOSTRB0_SIUBIBT, PTF3_OUT, PTF3_IN_PD, PTF3_IN,
+               SIOD_SIUBILR, PTF2_OUT, PTF2_IN_PD, PTF2_IN,
+               SIORXD_SIUBISLD, 0, PTF1_IN_PD, PTF1_IN,
+               SIOTXD_SIUBOSLD, PTF0_OUT, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               AUDSYNC, PTG4_OUT, 0, 0,
+               AUDATA3, PTG3_OUT, 0, 0,
+               AUDATA2, PTG2_OUT, 0, 0,
+               AUDATA1, PTG1_OUT, 0, 0,
+               AUDATA0, PTG0_OUT, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
+               LCDVCPWC_LCDVCPWC2, PTH7_OUT, 0, 0,
+               LCDVSYN2_DACK, PTH6_OUT, PTH6_IN_PD, PTH6_IN,
+               LCDVSYN, PTH5_OUT, PTH5_IN_PD, PTH5_IN,
+               LCDDISP_LCDRS, PTH4_OUT, 0, 0,
+               LCDHSYN_LCDCS, PTH3_OUT, 0, 0,
+               LCDDON_LCDDON2, PTH2_OUT, 0, 0,
+               LCDD17_DV_HSYNC, PTH1_OUT, PTH1_IN_PD, PTH1_IN,
+               LCDD16_DV_VSYNC, PTH0_OUT, PTH0_IN_PD, PTH0_IN }
+       },
+       { PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
+               STATUS0, PTJ7_OUT, 0, 0,
+               0, PTJ6_OUT, 0, 0,
+               PDSTATUS, PTJ5_OUT, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               IRQ1, PTJ1_OUT, PTJ1_IN_PU, PTJ1_IN,
+               IRQ0, PTJ0_OUT, PTJ0_IN_PU, PTJ0_IN }
+       },
+       { PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
+               0, 0, 0, 0,
+               SIUAILR_SIOF1_SS2, PTK6_OUT, PTK6_IN_PD, PTK6_IN,
+               SIUAIBT_SIOF1_SS1, PTK5_OUT, PTK5_IN_PD, PTK5_IN,
+               SIUAOLR_SIOF1_SYNC, PTK4_OUT, PTK4_IN_PD, PTK4_IN,
+               SIUAOBT_SIOF1_SCK, PTK3_OUT, PTK3_IN_PD, PTK3_IN,
+               SIUAISLD_SIOF1_RXD, 0, PTK2_IN_PD, PTK2_IN,
+               SIUAOSLD_SIOF1_TXD, PTK1_OUT, 0, 0,
+               PTK0, PTK0_OUT, PTK0_IN_PD, PTK0_IN }
+       },
+       { PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
+               LCDD15_DV_D15, PTL7_OUT, PTL7_IN_PD, PTL7_IN,
+               LCDD14_DV_D14, PTL6_OUT, PTL6_IN_PD, PTL6_IN,
+               LCDD13_DV_D13, PTL5_OUT, PTL5_IN_PD, PTL5_IN,
+               LCDD12_DV_D12, PTL4_OUT, PTL4_IN_PD, PTL4_IN,
+               LCDD11_DV_D11, PTL3_OUT, PTL3_IN_PD, PTL3_IN,
+               LCDD10_DV_D10, PTL2_OUT, PTL2_IN_PD, PTL2_IN,
+               LCDD9_DV_D9, PTL1_OUT, PTL1_IN_PD, PTL1_IN,
+               LCDD8_DV_D8, PTL0_OUT, PTL0_IN_PD, PTL0_IN }
+       },
+       { PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
+               LCDD7_DV_D7, PTM7_OUT, PTM7_IN_PD, PTM7_IN,
+               LCDD6_DV_D6, PTM6_OUT, PTM6_IN_PD, PTM6_IN,
+               LCDD5_DV_D5, PTM5_OUT, PTM5_IN_PD, PTM5_IN,
+               LCDD4_DV_D4, PTM4_OUT, PTM4_IN_PD, PTM4_IN,
+               LCDD3_DV_D3, PTM3_OUT, PTM3_IN_PD, PTM3_IN,
+               LCDD2_DV_D2, PTM2_OUT, PTM2_IN_PD, PTM2_IN,
+               LCDD1_DV_D1, PTM1_OUT, PTM1_IN_PD, PTM1_IN,
+               LCDD0_DV_D0, PTM0_OUT, PTM0_IN_PD, PTM0_IN }
+       },
+       { PINMUX_CFG_REG("PNCR", 0xa4050118, 16, 2) {
+               HPD63, PTN7_OUT, 0, PTN7_IN,
+               HPD62, PTN6_OUT, 0, PTN6_IN,
+               HPD61, PTN5_OUT, 0, PTN5_IN,
+               HPD60, PTN4_OUT, 0, PTN4_IN,
+               HPD59, PTN3_OUT, 0, PTN3_IN,
+               HPD58, PTN2_OUT, 0, PTN2_IN,
+               HPD57, PTN1_OUT, 0, PTN1_IN,
+               HPD56, PTN0_OUT, 0, PTN0_IN }
+       },
+       { PINMUX_CFG_REG("PQCR", 0xa405011a, 16, 2) {
+               0, 0, 0, 0,
+               SIOF0_SS2_SIM_RST, PTQ6_OUT, 0, 0,
+               SIOF0_SS1_TS_SPSYNC, PTQ5_OUT, PTQ5_IN_PD, PTQ5_IN,
+               SIOF0_SYNC_TS_SDEN, PTQ4_OUT, PTQ4_IN_PD, PTQ4_IN,
+               SIOF0_SCK_TS_SCK, PTQ3_OUT, PTQ3_IN_PD, PTQ3_IN,
+               PTQ2, 0, PTQ2_IN_PD, PTQ2_IN,
+               PTQ1, PTQ1_OUT, 0, 0,
+               PTQ0, PTQ0_OUT, PTQ0_IN_PU, PTQ0_IN }
+       },
+       { PINMUX_CFG_REG("PRCR", 0xa405011c, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               LCDRD, PTR4_OUT, 0, 0,
+               CS6B_CE1B_LCDCS2, PTR3_OUT, 0, 0,
+               WAIT, 0, PTR2_IN_PU, PTR2_IN,
+               LCDDCK_LCDWR, PTR1_OUT, 0, 0,
+               LCDVEPWC_LCDVEPWC2, PTR0_OUT, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PSCR", 0xa405011e, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               SCIF0_CTS_SIUAISPD, 0, PTS4_IN_PD, PTS4_IN,
+               SCIF0_RTS_SIUAOSPD, PTS3_OUT, 0, 0,
+               SCIF0_SCK_TPUTO, PTS2_OUT, PTS2_IN_PD, PTS2_IN,
+               SCIF0_RXD, 0, PTS1_IN_PD, PTS1_IN,
+               SCIF0_TXD, PTS0_OUT, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               FOE_VIO_VD2, PTT4_OUT, PTT4_IN_PD, PTT4_IN,
+               FWE, PTT3_OUT, PTT3_IN_PD, PTT3_IN,
+               FSC, PTT2_OUT, PTT2_IN_PD, PTT2_IN,
+               DREQ0, 0, PTT1_IN_PD, PTT1_IN,
+               FCDE, PTT0_OUT, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               NAF2_VIO_D10, PTU4_OUT, PTU4_IN_PD, PTU4_IN,
+               NAF1_VIO_D9, PTU3_OUT, PTU3_IN_PD, PTU3_IN,
+               NAF0_VIO_D8, PTU2_OUT, PTU2_IN_PD, PTU2_IN,
+               FRB_VIO_CLK2, 0, PTU1_IN_PD, PTU1_IN,
+               FCE_VIO_HD2, PTU0_OUT, PTU0_IN_PD, PTU0_IN }
+       },
+       { PINMUX_CFG_REG("PVCR", 0xa4050144, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               NAF7_VIO_D15, PTV4_OUT, PTV4_IN_PD, PTV4_IN,
+               NAF6_VIO_D14, PTV3_OUT, PTV3_IN_PD, PTV3_IN,
+               NAF5_VIO_D13, PTV2_OUT, PTV2_IN_PD, PTV2_IN,
+               NAF4_VIO_D12, PTV1_OUT, PTV1_IN_PD, PTV1_IN,
+               NAF3_VIO_D11, PTV0_OUT, PTV0_IN_PD, PTV0_IN }
+       },
+       { PINMUX_CFG_REG("PWCR", 0xa4050146, 16, 2) {
+               0, 0, 0, 0,
+               VIO_FLD_SCIF2_CTS, 0, PTW6_IN_PD, PTW6_IN,
+               VIO_CKO_SCIF2_RTS, PTW5_OUT, 0, 0,
+               VIO_STEX_SCIF2_SCK, PTW4_OUT, PTW4_IN_PD, PTW4_IN,
+               VIO_STEM_SCIF2_TXD, PTW3_OUT, PTW3_IN_PD, PTW3_IN,
+               VIO_HD_SCIF2_RXD, PTW2_OUT, PTW2_IN_PD, PTW2_IN,
+               VIO_VD_SCIF1_CTS, PTW1_OUT, PTW1_IN_PD, PTW1_IN,
+               VIO_CLK_SCIF1_RTS, PTW0_OUT, PTW0_IN_PD, PTW0_IN }
+       },
+       { PINMUX_CFG_REG("PXCR", 0xa4050148, 16, 2) {
+               0, 0, 0, 0,
+               CS6A_CE2B, PTX6_OUT, PTX6_IN_PU, PTX6_IN,
+               LCDD23, PTX5_OUT, PTX5_IN_PD, PTX5_IN,
+               LCDD22, PTX4_OUT, PTX4_IN_PD, PTX4_IN,
+               LCDD21, PTX3_OUT, PTX3_IN_PD, PTX3_IN,
+               LCDD20, PTX2_OUT, PTX2_IN_PD, PTX2_IN,
+               LCDD19_DV_CLKI, PTX1_OUT, PTX1_IN_PD, PTX1_IN,
+               LCDD18_DV_CLK, PTX0_OUT, PTX0_IN_PD, PTX0_IN }
+       },
+       { PINMUX_CFG_REG("PYCR", 0xa405014a, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               KEYOUT5_IN5, PTY5_OUT, PTY5_IN_PU, PTY5_IN,
+               KEYOUT4_IN6, PTY4_OUT, PTY4_IN_PU, PTY4_IN,
+               KEYOUT3, PTY3_OUT, PTY3_IN_PU, PTY3_IN,
+               KEYOUT2, PTY2_OUT, PTY2_IN_PU, PTY2_IN,
+               KEYOUT1, PTY1_OUT, 0, 0,
+               KEYOUT0, PTY0_OUT, PTY0_IN_PU, PTY0_IN }
+       },
+       { PINMUX_CFG_REG("PZCR", 0xa405014c, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               KEYIN4_IRQ7, 0, PTZ5_IN_PU, PTZ5_IN,
+               KEYIN3, 0, PTZ4_IN_PU, PTZ4_IN,
+               KEYIN2, 0, PTZ3_IN_PU, PTZ3_IN,
+               KEYIN1, 0, PTZ2_IN_PU, PTZ2_IN,
+               KEYIN0_IRQ6, 0, PTZ1_IN_PU, PTZ1_IN,
+               0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 1) {
+               PSA15_KEYIN0, PSA15_IRQ6,
+               PSA14_KEYIN4, PSA14_IRQ7,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PSA9_IRQ4, PSA9_BS,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PSA4_IRQ2, PSA4_SDHID2,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0 }
+       },
+       { PINMUX_CFG_REG("PSELB", 0xa4050150, 16, 1) {
+               PSB15_SIOTXD, PSB15_SIUBOSLD,
+               PSB14_SIORXD, PSB14_SIUBISLD,
+               PSB13_SIOD, PSB13_SIUBILR,
+               PSB12_SIOSTRB0, PSB12_SIUBIBT,
+               PSB11_SIOSTRB1, PSB11_SIUBOLR,
+               PSB10_SIOSCK, PSB10_SIUBOBT,
+               PSB9_SIOMCK, PSB9_SIUMCKB,
+               PSB8_SIOF0_MCK, PSB8_IRQ3,
+               PSB7_SIOF0_TXD, PSB7_IRDA_OUT,
+               PSB6_SIOF0_RXD, PSB6_IRDA_IN,
+               PSB5_SIOF0_SCK, PSB5_TS_SCK,
+               PSB4_SIOF0_SYNC, PSB4_TS_SDEN,
+               PSB3_SIOF0_SS1, PSB3_TS_SPSYNC,
+               PSB2_SIOF0_SS2, PSB2_SIM_RST,
+               PSB1_SIUMCKA, PSB1_SIOF1_MCK,
+               PSB0_SIUAOSLD, PSB0_SIOF1_TXD }
+       },
+       { PINMUX_CFG_REG("PSELC", 0xa4050152, 16, 1) {
+               PSC15_SIUAISLD, PSC15_SIOF1_RXD,
+               PSC14_SIUAOBT, PSC14_SIOF1_SCK,
+               PSC13_SIUAOLR, PSC13_SIOF1_SYNC,
+               PSC12_SIUAIBT, PSC12_SIOF1_SS1,
+               PSC11_SIUAILR, PSC11_SIOF1_SS2,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PSC0_NAF, PSC0_VIO }
+       },
+       { PINMUX_CFG_REG("PSELD", 0xa4050154, 16, 1) {
+               0, 0,
+               0, 0,
+               PSD13_VIO, PSD13_SCIF2,
+               PSD12_VIO, PSD12_SCIF1,
+               PSD11_VIO, PSD11_SCIF1,
+               PSD10_VIO_D0, PSD10_LCDLCLK,
+               PSD9_SIOMCK_SIUMCKB, PSD9_SIUFCKB,
+               PSD8_SCIF0_SCK, PSD8_TPUTO,
+               PSD7_SCIF0_RTS, PSD7_SIUAOSPD,
+               PSD6_SCIF0_CTS, PSD6_SIUAISPD,
+               PSD5_CS6B_CE1B, PSD5_LCDCS2,
+               0, 0,
+               PSD3_LCDVEPWC_LCDVCPWC, PSD3_LCDVEPWC2_LCDVCPWC2,
+               PSD2_LCDDON, PSD2_LCDDON2,
+               0, 0,
+               PSD0_LCDD19_LCDD0, PSD0_DV }
+       },
+       { PINMUX_CFG_REG("PSELE", 0xa4050156, 16, 1) {
+               PSE15_SIOF0_MCK_IRQ3, PSE15_SIM_D,
+               PSE14_SIOF0_TXD_IRDA_OUT, PSE14_SIM_CLK,
+               PSE13_SIOF0_RXD_IRDA_IN, PSE13_TS_SDAT,
+               PSE12_LCDVSYN2, PSE12_DACK,
+               PSE11_SIUMCKA_SIOF1_MCK, PSE11_SIUFCKA,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               PSE3_FLCTL, PSE3_VIO,
+               PSE2_NAF2, PSE2_VIO_D10,
+               PSE1_NAF1, PSE1_VIO_D9,
+               PSE0_NAF0, PSE0_VIO_D8 }
+       },
+       { PINMUX_CFG_REG("HIZCRA", 0xa4050158, 16, 1) {
+               0, 0,
+               HIZA14_KEYSC, HIZA14_HIZ,
+               0, 0,
+               0, 0,
+               0, 0,
+               HIZA10_NAF, HIZA10_HIZ,
+               HIZA9_VIO, HIZA9_HIZ,
+               HIZA8_LCDC, HIZA8_HIZ,
+               HIZA7_LCDC, HIZA7_HIZ,
+               HIZA6_LCDC, HIZA6_HIZ,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0 }
+       },
+       { PINMUX_CFG_REG("HIZCRB", 0xa405015a, 16, 1) {
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               HIZB1_VIO, HIZB1_HIZ,
+               HIZB0_VIO, HIZB0_HIZ }
+       },
+       { PINMUX_CFG_REG("HIZCRC", 0xa405015c, 16, 1) {
+               HIZC15_IRQ7, HIZC15_HIZ,
+               HIZC14_IRQ6, HIZC14_HIZ,
+               HIZC13_IRQ5, HIZC13_HIZ,
+               HIZC12_IRQ4, HIZC12_HIZ,
+               HIZC11_IRQ3, HIZC11_HIZ,
+               HIZC10_IRQ2, HIZC10_HIZ,
+               HIZC9_IRQ1, HIZC9_HIZ,
+               HIZC8_IRQ0, HIZC8_HIZ,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0 }
+       },
+       { PINMUX_CFG_REG("MSELCRB", 0xa4050182, 16, 1) {
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               MSELB9_VIO, MSELB9_VIO2,
+               MSELB8_RGB, MSELB8_SYS,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0,
+               0, 0 }
+       },
+       {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+       { PINMUX_DATA_REG("PADR", 0xa4050120, 8) {
+               PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+               PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
+       },
+       { PINMUX_DATA_REG("PBDR", 0xa4050122, 8) {
+               PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+               PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA }
+       },
+       { PINMUX_DATA_REG("PCDR", 0xa4050124, 8) {
+               PTC7_DATA, 0, PTC5_DATA, PTC4_DATA,
+               PTC3_DATA, PTC2_DATA, 0, PTC0_DATA }
+       },
+       { PINMUX_DATA_REG("PDDR", 0xa4050126, 8) {
+               PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+               PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA }
+       },
+       { PINMUX_DATA_REG("PEDR", 0xa4050128, 8) {
+               PTE7_DATA, PTE6_DATA, PTE5_DATA, PTE4_DATA,
+               0, 0, PTE1_DATA, PTE0_DATA }
+       },
+       { PINMUX_DATA_REG("PFDR", 0xa405012a, 8) {
+               0, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+               PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA }
+       },
+       { PINMUX_DATA_REG("PGDR", 0xa405012c, 8) {
+               0, 0, 0, PTG4_DATA,
+               PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA }
+       },
+       { PINMUX_DATA_REG("PHDR", 0xa405012e, 8) {
+               PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+               PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA }
+       },
+       { PINMUX_DATA_REG("PJDR", 0xa4050130, 8) {
+               PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, 0,
+               0, 0, PTJ1_DATA, PTJ0_DATA }
+       },
+       { PINMUX_DATA_REG("PKDR", 0xa4050132, 8) {
+               0, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+               PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
+       },
+       { PINMUX_DATA_REG("PLDR", 0xa4050134, 8) {
+               PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+               PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA }
+       },
+       { PINMUX_DATA_REG("PMDR", 0xa4050136, 8) {
+               PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+               PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
+       },
+       { PINMUX_DATA_REG("PNDR", 0xa4050138, 8) {
+               PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+               PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA }
+       },
+       { PINMUX_DATA_REG("PQDR", 0xa405013a, 8) {
+               0, PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+               PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA }
+       },
+       { PINMUX_DATA_REG("PRDR", 0xa405013c, 8) {
+               0, 0, 0, PTR4_DATA,
+               PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA }
+       },
+       { PINMUX_DATA_REG("PSDR", 0xa405013e, 8) {
+               0, 0, 0, PTS4_DATA,
+               PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
+       },
+       { PINMUX_DATA_REG("PTDR", 0xa4050160, 8) {
+               0, 0, 0, PTT4_DATA,
+               PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
+       },
+       { PINMUX_DATA_REG("PUDR", 0xa4050162, 8) {
+               0, 0, 0, PTU4_DATA,
+               PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA }
+       },
+       { PINMUX_DATA_REG("PVDR", 0xa4050164, 8) {
+               0, 0, 0, PTV4_DATA,
+               PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA }
+       },
+       { PINMUX_DATA_REG("PWDR", 0xa4050166, 8) {
+               0, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+               PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA }
+       },
+       { PINMUX_DATA_REG("PXDR", 0xa4050168, 8) {
+               0, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+               PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA }
+       },
+       { PINMUX_DATA_REG("PYDR", 0xa405016a, 8) {
+               0, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+               PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA }
+       },
+       { PINMUX_DATA_REG("PZDR", 0xa405016c, 8) {
+               0, 0, PTZ5_DATA, PTZ4_DATA,
+               PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA }
+       },
+       { },
+};
+
+static struct pinmux_info sh7722_pinmux_info = {
+       .name = "sh7722_pfc",
+       .reserved_id = PINMUX_RESERVED,
+       .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+       .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+       .input_pd = { PINMUX_INPUT_PULLDOWN_BEGIN, PINMUX_INPUT_PULLDOWN_END },
+       .input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+       .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+       .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+       .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+       .first_gpio = GPIO_PTA7,
+       .last_gpio = GPIO_FN_KEYOUT5_IN5,
+
+       .gpios = pinmux_gpios,
+       .cfg_regs = pinmux_config_regs,
+       .data_regs = pinmux_data_regs,
+
+       .gpio_data = pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+       return register_pinmux(&sh7722_pinmux_info);
+}
+
+arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c b/arch/sh/kernel/cpu/sh4a/pinmux-sh7723.c
new file mode 100644 (file)
index 0000000..88bf5ec
--- /dev/null
@@ -0,0 +1,1909 @@
+/*
+ * SH7723 Pinmux
+ *
+ *  Copyright (C) 2008  Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <cpu/sh7723.h>
+
+enum {
+       PINMUX_RESERVED = 0,
+
+       PINMUX_DATA_BEGIN,
+       PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+       PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA,
+       PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+       PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA,
+       PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+       PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA,
+       PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+       PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA,
+       PTE5_DATA, PTE4_DATA, PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA,
+       PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+       PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA,
+       PTG5_DATA, PTG4_DATA, PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA,
+       PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+       PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
+       PTJ7_DATA, PTJ5_DATA, PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA,
+       PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+       PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA,
+       PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+       PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA,
+       PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+       PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA,
+       PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+       PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA,
+       PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA,
+       PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+       PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA,
+       PTS7_DATA, PTS6_DATA, PTS5_DATA, PTS4_DATA,
+       PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA,
+       PTT5_DATA, PTT4_DATA, PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
+       PTU5_DATA, PTU4_DATA, PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
+       PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+       PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA,
+       PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+       PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA,
+       PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+       PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA,
+       PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+       PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA,
+       PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+       PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA,
+       PINMUX_DATA_END,
+
+       PINMUX_INPUT_BEGIN,
+       PTA7_IN, PTA6_IN, PTA5_IN, PTA4_IN,
+       PTA3_IN, PTA2_IN, PTA1_IN, PTA0_IN,
+       PTB7_IN, PTB6_IN, PTB5_IN, PTB4_IN,
+       PTB3_IN, PTB2_IN, PTB1_IN, PTB0_IN,
+       PTC7_IN, PTC6_IN, PTC5_IN, PTC4_IN,
+       PTC3_IN, PTC2_IN, PTC1_IN, PTC0_IN,
+       PTD7_IN, PTD6_IN, PTD5_IN, PTD4_IN,
+       PTD3_IN, PTD2_IN, PTD1_IN, PTD0_IN,
+       PTE5_IN, PTE4_IN, PTE3_IN, PTE2_IN, PTE1_IN, PTE0_IN,
+       PTF7_IN, PTF6_IN, PTF5_IN, PTF4_IN,
+       PTF3_IN, PTF2_IN, PTF1_IN, PTF0_IN,
+       PTH7_IN, PTH6_IN, PTH5_IN, PTH4_IN,
+       PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN,
+       PTJ3_IN, PTJ2_IN, PTJ1_IN, PTJ0_IN,
+       PTK7_IN, PTK6_IN, PTK5_IN, PTK4_IN,
+       PTK3_IN, PTK2_IN, PTK1_IN, PTK0_IN,
+       PTL7_IN, PTL6_IN, PTL5_IN, PTL4_IN,
+       PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN,
+       PTM7_IN, PTM6_IN, PTM5_IN, PTM4_IN,
+       PTM3_IN, PTM2_IN, PTM1_IN, PTM0_IN,
+       PTN7_IN, PTN6_IN, PTN5_IN, PTN4_IN,
+       PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN,
+       PTQ3_IN, PTQ2_IN, PTQ1_IN, PTQ0_IN,
+       PTR7_IN, PTR6_IN, PTR5_IN, PTR4_IN,
+       PTR3_IN, PTR2_IN, PTR1_IN, PTR0_IN,
+       PTS7_IN, PTS6_IN, PTS5_IN, PTS4_IN,
+       PTS3_IN, PTS2_IN, PTS1_IN, PTS0_IN,
+       PTT5_IN, PTT4_IN, PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN,
+       PTU5_IN, PTU4_IN, PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
+       PTV7_IN, PTV6_IN, PTV5_IN, PTV4_IN,
+       PTV3_IN, PTV2_IN, PTV1_IN, PTV0_IN,
+       PTW7_IN, PTW6_IN, PTW5_IN, PTW4_IN,
+       PTW3_IN, PTW2_IN, PTW1_IN, PTW0_IN,
+       PTX7_IN, PTX6_IN, PTX5_IN, PTX4_IN,
+       PTX3_IN, PTX2_IN, PTX1_IN, PTX0_IN,
+       PTY7_IN, PTY6_IN, PTY5_IN, PTY4_IN,
+       PTY3_IN, PTY2_IN, PTY1_IN, PTY0_IN,
+       PTZ7_IN, PTZ6_IN, PTZ5_IN, PTZ4_IN,
+       PTZ3_IN, PTZ2_IN, PTZ1_IN, PTZ0_IN,
+       PINMUX_INPUT_END,
+
+       PINMUX_INPUT_PULLUP_BEGIN,
+       PTA4_IN_PU, PTA3_IN_PU, PTA2_IN_PU, PTA1_IN_PU, PTA0_IN_PU,
+       PTB2_IN_PU, PTB1_IN_PU,
+       PTR2_IN_PU,
+       PINMUX_INPUT_PULLUP_END,
+
+       PINMUX_OUTPUT_BEGIN,
+       PTA7_OUT, PTA6_OUT, PTA5_OUT, PTA4_OUT,
+       PTA3_OUT, PTA2_OUT, PTA1_OUT, PTA0_OUT,
+       PTB7_OUT, PTB6_OUT, PTB5_OUT, PTB4_OUT,
+       PTB3_OUT, PTB2_OUT, PTB1_OUT, PTB0_OUT,
+       PTC7_OUT, PTC6_OUT, PTC5_OUT, PTC4_OUT,
+       PTC3_OUT, PTC2_OUT, PTC1_OUT, PTC0_OUT,
+       PTD7_OUT, PTD6_OUT, PTD5_OUT, PTD4_OUT,
+       PTD3_OUT, PTD2_OUT, PTD1_OUT, PTD0_OUT,
+       PTE5_OUT, PTE4_OUT, PTE3_OUT, PTE2_OUT, PTE1_OUT, PTE0_OUT,
+       PTF7_OUT, PTF6_OUT, PTF5_OUT, PTF4_OUT,
+       PTF3_OUT, PTF2_OUT, PTF1_OUT, PTF0_OUT,
+       PTG5_OUT, PTG4_OUT, PTG3_OUT, PTG2_OUT, PTG1_OUT, PTG0_OUT,
+       PTH7_OUT, PTH6_OUT, PTH5_OUT, PTH4_OUT,
+       PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
+       PTJ7_OUT, PTJ5_OUT, PTJ3_OUT, PTJ2_OUT, PTJ1_OUT, PTJ0_OUT,
+       PTK7_OUT, PTK6_OUT, PTK5_OUT, PTK4_OUT,
+       PTK3_OUT, PTK2_OUT, PTK1_OUT, PTK0_OUT,
+       PTL7_OUT, PTL6_OUT, PTL5_OUT, PTL4_OUT,
+       PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT,
+       PTM7_OUT, PTM6_OUT, PTM5_OUT, PTM4_OUT,
+       PTM3_OUT, PTM2_OUT, PTM1_OUT, PTM0_OUT,
+       PTN7_OUT, PTN6_OUT, PTN5_OUT, PTN4_OUT,
+       PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT,
+       PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT,
+       PTR1_OUT, PTR0_OUT,
+       PTS7_OUT, PTS6_OUT, PTS5_OUT, PTS4_OUT,
+       PTS3_OUT, PTS2_OUT, PTS1_OUT, PTS0_OUT,
+       PTT5_OUT, PTT4_OUT, PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT,
+       PTU5_OUT, PTU4_OUT, PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT,
+       PTV7_OUT, PTV6_OUT, PTV5_OUT, PTV4_OUT,
+       PTV3_OUT, PTV2_OUT, PTV1_OUT, PTV0_OUT,
+       PTW7_OUT, PTW6_OUT, PTW5_OUT, PTW4_OUT,
+       PTW3_OUT, PTW2_OUT, PTW1_OUT, PTW0_OUT,
+       PTX7_OUT, PTX6_OUT, PTX5_OUT, PTX4_OUT,
+       PTX3_OUT, PTX2_OUT, PTX1_OUT, PTX0_OUT,
+       PTY7_OUT, PTY6_OUT, PTY5_OUT, PTY4_OUT,
+       PTY3_OUT, PTY2_OUT, PTY1_OUT, PTY0_OUT,
+       PTZ7_OUT, PTZ6_OUT, PTZ5_OUT, PTZ4_OUT,
+       PTZ3_OUT, PTZ2_OUT, PTZ1_OUT, PTZ0_OUT,
+       PINMUX_OUTPUT_END,
+
+       PINMUX_FUNCTION_BEGIN,
+       PTA7_FN, PTA6_FN, PTA5_FN, PTA4_FN,
+       PTA3_FN, PTA2_FN, PTA1_FN, PTA0_FN,
+       PTB7_FN, PTB6_FN, PTB5_FN, PTB4_FN,
+       PTB3_FN, PTB2_FN, PTB1_FN, PTB0_FN,
+       PTC7_FN, PTC6_FN, PTC5_FN, PTC4_FN,
+       PTC3_FN, PTC2_FN, PTC1_FN, PTC0_FN,
+       PTD7_FN, PTD6_FN, PTD5_FN, PTD4_FN,
+       PTD3_FN, PTD2_FN, PTD1_FN, PTD0_FN,
+       PTE5_FN, PTE4_FN, PTE3_FN, PTE2_FN, PTE1_FN, PTE0_FN,
+       PTF7_FN, PTF6_FN, PTF5_FN, PTF4_FN,
+       PTF3_FN, PTF2_FN, PTF1_FN, PTF0_FN,
+       PTG5_FN, PTG4_FN, PTG3_FN, PTG2_FN, PTG1_FN, PTG0_FN,
+       PTH7_FN, PTH6_FN, PTH5_FN, PTH4_FN,
+       PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN,
+       PTJ7_FN, PTJ5_FN, PTJ3_FN, PTJ2_FN, PTJ1_FN, PTJ0_FN,
+       PTK7_FN, PTK6_FN, PTK5_FN, PTK4_FN,
+       PTK3_FN, PTK2_FN, PTK1_FN, PTK0_FN,
+       PTL7_FN, PTL6_FN, PTL5_FN, PTL4_FN,
+       PTL3_FN, PTL2_FN, PTL1_FN, PTL0_FN,
+       PTM7_FN, PTM6_FN, PTM5_FN, PTM4_FN,
+       PTM3_FN, PTM2_FN, PTM1_FN, PTM0_FN,
+       PTN7_FN, PTN6_FN, PTN5_FN, PTN4_FN,
+       PTN3_FN, PTN2_FN, PTN1_FN, PTN0_FN,
+       PTQ3_FN, PTQ2_FN, PTQ1_FN, PTQ0_FN,
+       PTR7_FN, PTR6_FN, PTR5_FN, PTR4_FN,
+       PTR3_FN, PTR2_FN, PTR1_FN, PTR0_FN,
+       PTS7_FN, PTS6_FN, PTS5_FN, PTS4_FN,
+       PTS3_FN, PTS2_FN, PTS1_FN, PTS0_FN,
+       PTT5_FN, PTT4_FN, PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN,
+       PTU5_FN, PTU4_FN, PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN,
+       PTV7_FN, PTV6_FN, PTV5_FN, PTV4_FN,
+       PTV3_FN, PTV2_FN, PTV1_FN, PTV0_FN,
+       PTW7_FN, PTW6_FN, PTW5_FN, PTW4_FN,
+       PTW3_FN, PTW2_FN, PTW1_FN, PTW0_FN,
+       PTX7_FN, PTX6_FN, PTX5_FN, PTX4_FN,
+       PTX3_FN, PTX2_FN, PTX1_FN, PTX0_FN,
+       PTY7_FN, PTY6_FN, PTY5_FN, PTY4_FN,
+       PTY3_FN, PTY2_FN, PTY1_FN, PTY0_FN,
+       PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN,
+       PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN,
+
+
+       PSA15_PSA14_FN1, PSA15_PSA14_FN2,
+       PSA13_PSA12_FN1, PSA13_PSA12_FN2,
+       PSA11_PSA10_FN1, PSA11_PSA10_FN2,
+       PSA5_PSA4_FN1, PSA5_PSA4_FN2, PSA5_PSA4_FN3,
+       PSA3_PSA2_FN1, PSA3_PSA2_FN2,
+       PSB15_PSB14_FN1, PSB15_PSB14_FN2,
+       PSB13_PSB12_LCDC_RGB, PSB13_PSB12_LCDC_SYS,
+       PSB9_PSB8_FN1, PSB9_PSB8_FN2, PSB9_PSB8_FN3,
+       PSB7_PSB6_FN1, PSB7_PSB6_FN2,
+       PSB5_PSB4_FN1, PSB5_PSB4_FN2,
+       PSB3_PSB2_FN1, PSB3_PSB2_FN2,
+       PSC15_PSC14_FN1, PSC15_PSC14_FN2,
+       PSC13_PSC12_FN1, PSC13_PSC12_FN2,
+       PSC11_PSC10_FN1, PSC11_PSC10_FN2, PSC11_PSC10_FN3,
+       PSC9_PSC8_FN1, PSC9_PSC8_FN2,
+       PSC7_PSC6_FN1, PSC7_PSC6_FN2, PSC7_PSC6_FN3,
+       PSD15_PSD14_FN1, PSD15_PSD14_FN2,
+       PSD13_PSD12_FN1, PSD13_PSD12_FN2,
+       PSD11_PSD10_FN1, PSD11_PSD10_FN2, PSD11_PSD10_FN3,
+       PSD9_PSD8_FN1, PSD9_PSD8_FN2,
+       PSD7_PSD6_FN1, PSD7_PSD6_FN2,
+       PSD5_PSD4_FN1, PSD5_PSD4_FN2,
+       PSD3_PSD2_FN1, PSD3_PSD2_FN2,
+       PSD1_PSD0_FN1, PSD1_PSD0_FN2,
+       PINMUX_FUNCTION_END,
+
+       PINMUX_MARK_BEGIN,
+       SCIF0_PTT_TXD_MARK, SCIF0_PTT_RXD_MARK,
+       SCIF0_PTT_SCK_MARK, SCIF0_PTU_TXD_MARK,
+       SCIF0_PTU_RXD_MARK, SCIF0_PTU_SCK_MARK,
+
+       SCIF1_PTS_TXD_MARK, SCIF1_PTS_RXD_MARK,
+       SCIF1_PTS_SCK_MARK, SCIF1_PTV_TXD_MARK,
+       SCIF1_PTV_RXD_MARK, SCIF1_PTV_SCK_MARK,
+
+       SCIF2_PTT_TXD_MARK, SCIF2_PTT_RXD_MARK,
+       SCIF2_PTT_SCK_MARK, SCIF2_PTU_TXD_MARK,
+       SCIF2_PTU_RXD_MARK, SCIF2_PTU_SCK_MARK,
+
+       SCIF3_PTS_TXD_MARK, SCIF3_PTS_RXD_MARK,
+       SCIF3_PTS_SCK_MARK, SCIF3_PTS_RTS_MARK,
+       SCIF3_PTS_CTS_MARK, SCIF3_PTV_TXD_MARK,
+       SCIF3_PTV_RXD_MARK, SCIF3_PTV_SCK_MARK,
+       SCIF3_PTV_RTS_MARK, SCIF3_PTV_CTS_MARK,
+
+       SCIF4_PTE_TXD_MARK, SCIF4_PTE_RXD_MARK,
+       SCIF4_PTE_SCK_MARK, SCIF4_PTN_TXD_MARK,
+       SCIF4_PTN_RXD_MARK, SCIF4_PTN_SCK_MARK,
+
+       SCIF5_PTE_TXD_MARK, SCIF5_PTE_RXD_MARK,
+       SCIF5_PTE_SCK_MARK, SCIF5_PTN_TXD_MARK,
+       SCIF5_PTN_RXD_MARK, SCIF5_PTN_SCK_MARK,
+
+       VIO_D15_MARK, VIO_D14_MARK, VIO_D13_MARK, VIO_D12_MARK,
+       VIO_D11_MARK, VIO_D10_MARK, VIO_D9_MARK, VIO_D8_MARK,
+       VIO_D7_MARK, VIO_D6_MARK, VIO_D5_MARK, VIO_D4_MARK,
+       VIO_D3_MARK, VIO_D2_MARK, VIO_D1_MARK, VIO_D0_MARK,
+       VIO_FLD_MARK, VIO_CKO_MARK,
+       VIO_VD1_MARK, VIO_HD1_MARK, VIO_CLK1_MARK,
+       VIO_HD2_MARK, VIO_VD2_MARK, VIO_CLK2_MARK,
+
+       LCDD23_MARK, LCDD22_MARK, LCDD21_MARK, LCDD20_MARK,
+       LCDD19_MARK, LCDD18_MARK, LCDD17_MARK, LCDD16_MARK,
+       LCDD15_MARK, LCDD14_MARK, LCDD13_MARK, LCDD12_MARK,
+       LCDD11_MARK, LCDD10_MARK, LCDD9_MARK, LCDD8_MARK,
+       LCDD7_MARK, LCDD6_MARK, LCDD5_MARK, LCDD4_MARK,
+       LCDD3_MARK, LCDD2_MARK, LCDD1_MARK, LCDD0_MARK,
+       LCDDON_MARK, LCDVCPWC_MARK, LCDVEPWC_MARK,
+       LCDVSYN_MARK, LCDDCK_MARK, LCDHSYN_MARK, LCDDISP_MARK,
+       LCDRS_MARK, LCDCS_MARK, LCDWR_MARK, LCDRD_MARK,
+       LCDLCLK_PTR_MARK, LCDLCLK_PTW_MARK,
+
+       IRQ0_MARK, IRQ1_MARK, IRQ2_MARK, IRQ3_MARK,
+       IRQ4_MARK, IRQ5_MARK, IRQ6_MARK, IRQ7_MARK,
+
+       AUDATA3_MARK, AUDATA2_MARK, AUDATA1_MARK, AUDATA0_MARK,
+       AUDCK_MARK, AUDSYNC_MARK,
+
+       SDHI0CD_PTD_MARK, SDHI0WP_PTD_MARK,
+       SDHI0D3_PTD_MARK, SDHI0D2_PTD_MARK,
+       SDHI0D1_PTD_MARK, SDHI0D0_PTD_MARK,
+       SDHI0CMD_PTD_MARK, SDHI0CLK_PTD_MARK,
+
+       SDHI0CD_PTS_MARK, SDHI0WP_PTS_MARK,
+       SDHI0D3_PTS_MARK, SDHI0D2_PTS_MARK,
+       SDHI0D1_PTS_MARK, SDHI0D0_PTS_MARK,
+       SDHI0CMD_PTS_MARK, SDHI0CLK_PTS_MARK,
+
+       SDHI1CD_MARK, SDHI1WP_MARK, SDHI1D3_MARK, SDHI1D2_MARK,
+       SDHI1D1_MARK, SDHI1D0_MARK, SDHI1CMD_MARK, SDHI1CLK_MARK,
+
+       SIUAFCK_MARK, SIUAILR_MARK, SIUAIBT_MARK, SIUAISLD_MARK,
+       SIUAOLR_MARK, SIUAOBT_MARK, SIUAOSLD_MARK, SIUAMCK_MARK,
+       SIUAISPD_MARK, SIUAOSPD_MARK,
+
+       SIUBFCK_MARK, SIUBILR_MARK, SIUBIBT_MARK, SIUBISLD_MARK,
+       SIUBOLR_MARK, SIUBOBT_MARK, SIUBOSLD_MARK, SIUBMCK_MARK,
+
+       IRDA_IN_MARK, IRDA_OUT_MARK,
+
+       DV_CLKI_MARK, DV_CLK_MARK, DV_HSYNC_MARK, DV_VSYNC_MARK,
+       DV_D15_MARK, DV_D14_MARK, DV_D13_MARK, DV_D12_MARK,
+       DV_D11_MARK, DV_D10_MARK, DV_D9_MARK, DV_D8_MARK,
+       DV_D7_MARK, DV_D6_MARK, DV_D5_MARK, DV_D4_MARK,
+       DV_D3_MARK, DV_D2_MARK, DV_D1_MARK, DV_D0_MARK,
+
+       KEYIN0_MARK, KEYIN1_MARK, KEYIN2_MARK, KEYIN3_MARK, KEYIN4_MARK,
+       KEYOUT0_MARK, KEYOUT1_MARK, KEYOUT2_MARK, KEYOUT3_MARK,
+       KEYOUT4_IN6_MARK, KEYOUT5_IN5_MARK,
+
+       MSIOF0_PTF_TXD_MARK, MSIOF0_PTF_RXD_MARK, MSIOF0_PTF_MCK_MARK,
+       MSIOF0_PTF_TSYNC_MARK, MSIOF0_PTF_TSCK_MARK, MSIOF0_PTF_RSYNC_MARK,
+       MSIOF0_PTF_RSCK_MARK, MSIOF0_PTF_SS1_MARK, MSIOF0_PTF_SS2_MARK,
+
+       MSIOF0_PTT_TXD_MARK, MSIOF0_PTT_RXD_MARK, MSIOF0_PTX_MCK_MARK,
+       MSIOF0_PTT_TSYNC_MARK, MSIOF0_PTT_TSCK_MARK, MSIOF0_PTT_RSYNC_MARK,
+       MSIOF0_PTT_RSCK_MARK, MSIOF0_PTT_SS1_MARK, MSIOF0_PTT_SS2_MARK,
+
+       MSIOF1_TXD_MARK, MSIOF1_RXD_MARK, MSIOF1_MCK_MARK,
+       MSIOF1_TSYNC_MARK, MSIOF1_TSCK_MARK, MSIOF1_RSYNC_MARK,
+       MSIOF1_RSCK_MARK, MSIOF1_SS1_MARK, MSIOF1_SS2_MARK,
+
+       TS0_SDAT_MARK, TS0_SCK_MARK, TS0_SDEN_MARK, TS0_SPSYNC_MARK,
+
+       FCE_MARK, NAF7_MARK, NAF6_MARK, NAF5_MARK, NAF4_MARK,
+       NAF3_MARK, NAF2_MARK, NAF1_MARK, NAF0_MARK, FCDE_MARK,
+       FOE_MARK, FSC_MARK, FWE_MARK, FRB_MARK,
+
+       DACK1_MARK, DREQ1_MARK, DACK0_MARK, DREQ0_MARK,
+
+       AN3_MARK, AN2_MARK, AN1_MARK, AN0_MARK, ADTRG_MARK,
+
+       STATUS0_MARK, PDSTATUS_MARK,
+
+       TPUTO3_MARK, TPUTO2_MARK, TPUTO1_MARK, TPUTO0_MARK,
+
+       D31_MARK, D30_MARK, D29_MARK, D28_MARK,
+       D27_MARK, D26_MARK, D25_MARK, D24_MARK,
+       D23_MARK, D22_MARK, D21_MARK, D20_MARK,
+       D19_MARK, D18_MARK, D17_MARK, D16_MARK,
+       IOIS16_MARK, WAIT_MARK, BS_MARK,
+       A25_MARK, A24_MARK, A23_MARK, A22_MARK,
+       CS6B_CE1B_MARK, CS6A_CE2B_MARK,
+       CS5B_CE1A_MARK, CS5A_CE2A_MARK,
+       WE3_ICIOWR_MARK, WE2_ICIORD_MARK,
+
+       IDED15_MARK, IDED14_MARK, IDED13_MARK, IDED12_MARK,
+       IDED11_MARK, IDED10_MARK, IDED9_MARK, IDED8_MARK,
+       IDED7_MARK, IDED6_MARK, IDED5_MARK, IDED4_MARK,
+       IDED3_MARK, IDED2_MARK, IDED1_MARK, IDED0_MARK,
+       DIRECTION_MARK, EXBUF_ENB_MARK, IDERST_MARK, IODACK_MARK,
+       IODREQ_MARK, IDEIORDY_MARK, IDEINT_MARK, IDEIOWR_MARK,
+       IDEIORD_MARK, IDECS1_MARK, IDECS0_MARK, IDEA2_MARK,
+       IDEA1_MARK, IDEA0_MARK,
+       PINMUX_MARK_END,
+};
+
+static pinmux_enum_t pinmux_data[] = {
+       /* PTA GPIO */
+       PINMUX_DATA(PTA7_DATA, PTA7_IN, PTA7_OUT),
+       PINMUX_DATA(PTA6_DATA, PTA6_IN, PTA6_OUT),
+       PINMUX_DATA(PTA5_DATA, PTA5_IN, PTA5_OUT),
+       PINMUX_DATA(PTA4_DATA, PTA4_IN, PTA4_OUT, PTA4_IN_PU),
+       PINMUX_DATA(PTA3_DATA, PTA3_IN, PTA3_OUT, PTA3_IN_PU),
+       PINMUX_DATA(PTA2_DATA, PTA2_IN, PTA2_OUT, PTA2_IN_PU),
+       PINMUX_DATA(PTA1_DATA, PTA1_IN, PTA1_OUT, PTA1_IN_PU),
+       PINMUX_DATA(PTA0_DATA, PTA0_IN, PTA0_OUT, PTA0_IN_PU),
+
+       /* PTB GPIO */
+       PINMUX_DATA(PTB7_DATA, PTB7_IN, PTB7_OUT),
+       PINMUX_DATA(PTB6_DATA, PTB6_IN, PTB6_OUT),
+       PINMUX_DATA(PTB5_DATA, PTB5_IN, PTB5_OUT),
+       PINMUX_DATA(PTB4_DATA, PTB4_IN, PTB4_OUT),
+       PINMUX_DATA(PTB3_DATA, PTB3_IN, PTB3_OUT),
+       PINMUX_DATA(PTB2_DATA, PTB2_IN, PTB2_OUT, PTB2_IN_PU),
+       PINMUX_DATA(PTB1_DATA, PTB1_IN, PTB1_OUT, PTB1_IN_PU),
+       PINMUX_DATA(PTB0_DATA, PTB0_IN, PTB0_OUT),
+
+       /* PTC GPIO */
+       PINMUX_DATA(PTC7_DATA, PTC7_IN, PTC7_OUT),
+       PINMUX_DATA(PTC6_DATA, PTC6_IN, PTC6_OUT),
+       PINMUX_DATA(PTC5_DATA, PTC5_IN, PTC5_OUT),
+       PINMUX_DATA(PTC4_DATA, PTC4_IN, PTC4_OUT),
+       PINMUX_DATA(PTC3_DATA, PTC3_IN, PTC3_OUT),
+       PINMUX_DATA(PTC2_DATA, PTC2_IN, PTC2_OUT),
+       PINMUX_DATA(PTC1_DATA, PTC1_IN, PTC1_OUT),
+       PINMUX_DATA(PTC0_DATA, PTC0_IN, PTC0_OUT),
+
+       /* PTD GPIO */
+       PINMUX_DATA(PTD7_DATA, PTD7_IN, PTD7_OUT),
+       PINMUX_DATA(PTD6_DATA, PTD6_IN, PTD6_OUT),
+       PINMUX_DATA(PTD5_DATA, PTD5_IN, PTD5_OUT),
+       PINMUX_DATA(PTD4_DATA, PTD4_IN, PTD4_OUT),
+       PINMUX_DATA(PTD3_DATA, PTD3_IN, PTD3_OUT),
+       PINMUX_DATA(PTD2_DATA, PTD2_IN, PTD2_OUT),
+       PINMUX_DATA(PTD1_DATA, PTD1_IN, PTD1_OUT),
+       PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT),
+
+       /* PTE GPIO */
+       PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT),
+       PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT),
+       PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT),
+       PINMUX_DATA(PTE2_DATA, PTE2_IN, PTE2_OUT),
+       PINMUX_DATA(PTE1_DATA, PTE1_IN, PTE1_OUT),
+       PINMUX_DATA(PTE0_DATA, PTE0_IN, PTE0_OUT),
+
+       /* PTF GPIO */
+       PINMUX_DATA(PTF7_DATA, PTF7_IN, PTF7_OUT),
+       PINMUX_DATA(PTF6_DATA, PTF6_IN, PTF6_OUT),
+       PINMUX_DATA(PTF5_DATA, PTF5_IN, PTF5_OUT),
+       PINMUX_DATA(PTF4_DATA, PTF4_IN, PTF4_OUT),
+       PINMUX_DATA(PTF3_DATA, PTF3_IN, PTF3_OUT),
+       PINMUX_DATA(PTF2_DATA, PTF2_IN, PTF2_OUT),
+       PINMUX_DATA(PTF1_DATA, PTF1_IN, PTF1_OUT),
+       PINMUX_DATA(PTF0_DATA, PTF0_IN, PTF0_OUT),
+
+       /* PTG GPIO */
+       PINMUX_DATA(PTG5_DATA, PTG5_OUT),
+       PINMUX_DATA(PTG4_DATA, PTG4_OUT),
+       PINMUX_DATA(PTG3_DATA, PTG3_OUT),
+       PINMUX_DATA(PTG2_DATA, PTG2_OUT),
+       PINMUX_DATA(PTG1_DATA, PTG1_OUT),
+       PINMUX_DATA(PTG0_DATA, PTG0_OUT),
+
+       /* PTH GPIO */
+       PINMUX_DATA(PTH7_DATA, PTH7_IN, PTH7_OUT),
+       PINMUX_DATA(PTH6_DATA, PTH6_IN, PTH6_OUT),
+       PINMUX_DATA(PTH5_DATA, PTH5_IN, PTH5_OUT),
+       PINMUX_DATA(PTH4_DATA, PTH4_IN, PTH4_OUT),
+       PINMUX_DATA(PTH3_DATA, PTH3_IN, PTH3_OUT),
+       PINMUX_DATA(PTH2_DATA, PTH2_IN, PTH2_OUT),
+       PINMUX_DATA(PTH1_DATA, PTH1_IN, PTH1_OUT),
+       PINMUX_DATA(PTH0_DATA, PTH0_IN, PTH0_OUT),
+
+       /* PTJ GPIO */
+       PINMUX_DATA(PTJ7_DATA, PTJ7_OUT),
+       PINMUX_DATA(PTJ5_DATA, PTJ5_OUT),
+       PINMUX_DATA(PTJ3_DATA, PTJ3_IN, PTJ3_OUT),
+       PINMUX_DATA(PTJ2_DATA, PTJ2_IN, PTJ2_OUT),
+       PINMUX_DATA(PTJ1_DATA, PTJ1_IN, PTJ1_OUT),
+       PINMUX_DATA(PTJ0_DATA, PTJ0_IN, PTJ0_OUT),
+
+       /* PTK GPIO */
+       PINMUX_DATA(PTK7_DATA, PTK7_IN, PTK7_OUT),
+       PINMUX_DATA(PTK6_DATA, PTK6_IN, PTK6_OUT),
+       PINMUX_DATA(PTK5_DATA, PTK5_IN, PTK5_OUT),
+       PINMUX_DATA(PTK4_DATA, PTK4_IN, PTK4_OUT),
+       PINMUX_DATA(PTK3_DATA, PTK3_IN, PTK3_OUT),
+       PINMUX_DATA(PTK2_DATA, PTK2_IN, PTK2_OUT),
+       PINMUX_DATA(PTK1_DATA, PTK1_IN, PTK1_OUT),
+       PINMUX_DATA(PTK0_DATA, PTK0_IN, PTK0_OUT),
+
+       /* PTL GPIO */
+       PINMUX_DATA(PTL7_DATA, PTL7_IN, PTL7_OUT),
+       PINMUX_DATA(PTL6_DATA, PTL6_IN, PTL6_OUT),
+       PINMUX_DATA(PTL5_DATA, PTL5_IN, PTL5_OUT),
+       PINMUX_DATA(PTL4_DATA, PTL4_IN, PTL4_OUT),
+       PINMUX_DATA(PTL3_DATA, PTL3_IN, PTL3_OUT),
+       PINMUX_DATA(PTL2_DATA, PTL2_IN, PTL2_OUT),
+       PINMUX_DATA(PTL1_DATA, PTL1_IN, PTL1_OUT),
+       PINMUX_DATA(PTL0_DATA, PTL0_IN, PTL0_OUT),
+
+       /* PTM GPIO */
+       PINMUX_DATA(PTM7_DATA, PTM7_IN, PTM7_OUT),
+       PINMUX_DATA(PTM6_DATA, PTM6_IN, PTM6_OUT),
+       PINMUX_DATA(PTM5_DATA, PTM5_IN, PTM5_OUT),
+       PINMUX_DATA(PTM4_DATA, PTM4_IN, PTM4_OUT),
+       PINMUX_DATA(PTM3_DATA, PTM3_IN, PTM3_OUT),
+       PINMUX_DATA(PTM2_DATA, PTM2_IN, PTM2_OUT),
+       PINMUX_DATA(PTM1_DATA, PTM1_IN, PTM1_OUT),
+       PINMUX_DATA(PTM0_DATA, PTM0_IN, PTM0_OUT),
+
+       /* PTN GPIO */
+       PINMUX_DATA(PTN7_DATA, PTN7_IN, PTN7_OUT),
+       PINMUX_DATA(PTN6_DATA, PTN6_IN, PTN6_OUT),
+       PINMUX_DATA(PTN5_DATA, PTN5_IN, PTN5_OUT),
+       PINMUX_DATA(PTN4_DATA, PTN4_IN, PTN4_OUT),
+       PINMUX_DATA(PTN3_DATA, PTN3_IN, PTN3_OUT),
+       PINMUX_DATA(PTN2_DATA, PTN2_IN, PTN2_OUT),
+       PINMUX_DATA(PTN1_DATA, PTN1_IN, PTN1_OUT),
+       PINMUX_DATA(PTN0_DATA, PTN0_IN, PTN0_OUT),
+
+       /* PTQ GPIO */
+       PINMUX_DATA(PTQ3_DATA, PTQ3_IN),
+       PINMUX_DATA(PTQ2_DATA, PTQ2_IN),
+       PINMUX_DATA(PTQ1_DATA, PTQ1_IN),
+       PINMUX_DATA(PTQ0_DATA, PTQ0_IN),
+
+       /* PTR GPIO */
+       PINMUX_DATA(PTR7_DATA, PTR7_IN, PTR7_OUT),
+       PINMUX_DATA(PTR6_DATA, PTR6_IN, PTR6_OUT),
+       PINMUX_DATA(PTR5_DATA, PTR5_IN, PTR5_OUT),
+       PINMUX_DATA(PTR4_DATA, PTR4_IN, PTR4_OUT),
+       PINMUX_DATA(PTR3_DATA, PTR3_IN),
+       PINMUX_DATA(PTR2_DATA, PTR2_IN, PTR2_IN_PU),
+       PINMUX_DATA(PTR1_DATA, PTR1_IN, PTR1_OUT),
+       PINMUX_DATA(PTR0_DATA, PTR0_IN, PTR0_OUT),
+
+       /* PTS GPIO */
+       PINMUX_DATA(PTS7_DATA, PTS7_IN, PTS7_OUT),
+       PINMUX_DATA(PTS6_DATA, PTS6_IN, PTS6_OUT),
+       PINMUX_DATA(PTS5_DATA, PTS5_IN, PTS5_OUT),
+       PINMUX_DATA(PTS4_DATA, PTS4_IN, PTS4_OUT),
+       PINMUX_DATA(PTS3_DATA, PTS3_IN, PTS3_OUT),
+       PINMUX_DATA(PTS2_DATA, PTS2_IN, PTS2_OUT),
+       PINMUX_DATA(PTS1_DATA, PTS1_IN, PTS1_OUT),
+       PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT),
+
+       /* PTT GPIO */
+       PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT),
+       PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT),
+       PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT),
+       PINMUX_DATA(PTT2_DATA, PTT2_IN, PTT2_OUT),
+       PINMUX_DATA(PTT1_DATA, PTT1_IN, PTT1_OUT),
+       PINMUX_DATA(PTT0_DATA, PTT0_IN, PTT0_OUT),
+
+       /* PTU GPIO */
+       PINMUX_DATA(PTU5_DATA, PTU5_IN, PTU5_OUT),
+       PINMUX_DATA(PTU4_DATA, PTU4_IN, PTU4_OUT),
+       PINMUX_DATA(PTU3_DATA, PTU3_IN, PTU3_OUT),
+       PINMUX_DATA(PTU2_DATA, PTU2_IN, PTU2_OUT),
+       PINMUX_DATA(PTU1_DATA, PTU1_IN, PTU1_OUT),
+       PINMUX_DATA(PTU0_DATA, PTU0_IN, PTU0_OUT),
+
+       /* PTV GPIO */
+       PINMUX_DATA(PTV7_DATA, PTV7_IN, PTV7_OUT),
+       PINMUX_DATA(PTV6_DATA, PTV6_IN, PTV6_OUT),
+       PINMUX_DATA(PTV5_DATA, PTV5_IN, PTV5_OUT),
+       PINMUX_DATA(PTV4_DATA, PTV4_IN, PTV4_OUT),
+       PINMUX_DATA(PTV3_DATA, PTV3_IN, PTV3_OUT),
+       PINMUX_DATA(PTV2_DATA, PTV2_IN, PTV2_OUT),
+       PINMUX_DATA(PTV1_DATA, PTV1_IN, PTV1_OUT),
+       PINMUX_DATA(PTV0_DATA, PTV0_IN, PTV0_OUT),
+
+       /* PTW GPIO */
+       PINMUX_DATA(PTW7_DATA, PTW7_IN, PTW7_OUT),
+       PINMUX_DATA(PTW6_DATA, PTW6_IN, PTW6_OUT),
+       PINMUX_DATA(PTW5_DATA, PTW5_IN, PTW5_OUT),
+       PINMUX_DATA(PTW4_DATA, PTW4_IN, PTW4_OUT),
+       PINMUX_DATA(PTW3_DATA, PTW3_IN, PTW3_OUT),
+       PINMUX_DATA(PTW2_DATA, PTW2_IN, PTW2_OUT),
+       PINMUX_DATA(PTW1_DATA, PTW1_IN, PTW1_OUT),
+       PINMUX_DATA(PTW0_DATA, PTW0_IN, PTW0_OUT),
+
+       /* PTX GPIO */
+       PINMUX_DATA(PTX7_DATA, PTX7_IN, PTX7_OUT),
+       PINMUX_DATA(PTX6_DATA, PTX6_IN, PTX6_OUT),
+       PINMUX_DATA(PTX5_DATA, PTX5_IN, PTX5_OUT),
+       PINMUX_DATA(PTX4_DATA, PTX4_IN, PTX4_OUT),
+       PINMUX_DATA(PTX3_DATA, PTX3_IN, PTX3_OUT),
+       PINMUX_DATA(PTX2_DATA, PTX2_IN, PTX2_OUT),
+       PINMUX_DATA(PTX1_DATA, PTX1_IN, PTX1_OUT),
+       PINMUX_DATA(PTX0_DATA, PTX0_IN, PTX0_OUT),
+
+       /* PTY GPIO */
+       PINMUX_DATA(PTY7_DATA, PTY7_IN, PTY7_OUT),
+       PINMUX_DATA(PTY6_DATA, PTY6_IN, PTY6_OUT),
+       PINMUX_DATA(PTY5_DATA, PTY5_IN, PTY5_OUT),
+       PINMUX_DATA(PTY4_DATA, PTY4_IN, PTY4_OUT),
+       PINMUX_DATA(PTY3_DATA, PTY3_IN, PTY3_OUT),
+       PINMUX_DATA(PTY2_DATA, PTY2_IN, PTY2_OUT),
+       PINMUX_DATA(PTY1_DATA, PTY1_IN, PTY1_OUT),
+       PINMUX_DATA(PTY0_DATA, PTY0_IN, PTY0_OUT),
+
+       /* PTZ GPIO */
+       PINMUX_DATA(PTZ7_DATA, PTZ7_IN, PTZ7_OUT),
+       PINMUX_DATA(PTZ6_DATA, PTZ6_IN, PTZ6_OUT),
+       PINMUX_DATA(PTZ5_DATA, PTZ5_IN, PTZ5_OUT),
+       PINMUX_DATA(PTZ4_DATA, PTZ4_IN, PTZ4_OUT),
+       PINMUX_DATA(PTZ3_DATA, PTZ3_IN, PTZ3_OUT),
+       PINMUX_DATA(PTZ2_DATA, PTZ2_IN, PTZ2_OUT),
+       PINMUX_DATA(PTZ1_DATA, PTZ1_IN, PTZ1_OUT),
+       PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT),
+
+       /* PTA FN */
+       PINMUX_DATA(D23_MARK, PSA15_PSA14_FN1, PTA7_FN),
+       PINMUX_DATA(KEYOUT2_MARK, PSA15_PSA14_FN2, PTA7_FN),
+       PINMUX_DATA(D22_MARK, PSA15_PSA14_FN1, PTA6_FN),
+       PINMUX_DATA(KEYOUT1_MARK, PSA15_PSA14_FN2, PTA6_FN),
+       PINMUX_DATA(D21_MARK, PSA15_PSA14_FN1, PTA5_FN),
+       PINMUX_DATA(KEYOUT0_MARK, PSA15_PSA14_FN2, PTA5_FN),
+       PINMUX_DATA(D20_MARK, PSA15_PSA14_FN1, PTA4_FN),
+       PINMUX_DATA(KEYIN4_MARK, PSA15_PSA14_FN2, PTA4_FN),
+       PINMUX_DATA(D19_MARK, PSA15_PSA14_FN1, PTA3_FN),
+       PINMUX_DATA(KEYIN3_MARK, PSA15_PSA14_FN2, PTA3_FN),
+       PINMUX_DATA(D18_MARK, PSA15_PSA14_FN1, PTA2_FN),
+       PINMUX_DATA(KEYIN2_MARK, PSA15_PSA14_FN2, PTA2_FN),
+       PINMUX_DATA(D17_MARK, PSA15_PSA14_FN1, PTA1_FN),
+       PINMUX_DATA(KEYIN1_MARK, PSA15_PSA14_FN2, PTA1_FN),
+       PINMUX_DATA(D16_MARK, PSA15_PSA14_FN1, PTA0_FN),
+       PINMUX_DATA(KEYIN0_MARK, PSA15_PSA14_FN2, PTA0_FN),
+
+       /* PTB FN */
+       PINMUX_DATA(D31_MARK, PTB7_FN),
+       PINMUX_DATA(D30_MARK, PTB6_FN),
+       PINMUX_DATA(D29_MARK, PTB5_FN),
+       PINMUX_DATA(D28_MARK, PTB4_FN),
+       PINMUX_DATA(D27_MARK, PTB3_FN),
+       PINMUX_DATA(D26_MARK, PSA15_PSA14_FN1, PTB2_FN),
+       PINMUX_DATA(KEYOUT5_IN5_MARK, PSA15_PSA14_FN2, PTB2_FN),
+       PINMUX_DATA(D25_MARK, PSA15_PSA14_FN1, PTB1_FN),
+       PINMUX_DATA(KEYOUT4_IN6_MARK, PSA15_PSA14_FN2, PTB1_FN),
+       PINMUX_DATA(D24_MARK, PSA15_PSA14_FN1, PTB0_FN),
+       PINMUX_DATA(KEYOUT3_MARK, PSA15_PSA14_FN2, PTB0_FN),
+
+       /* PTC FN */
+       PINMUX_DATA(IDED15_MARK, PSA11_PSA10_FN1, PTC7_FN),
+       PINMUX_DATA(SDHI1CD_MARK, PSA11_PSA10_FN2, PTC7_FN),
+       PINMUX_DATA(IDED14_MARK, PSA11_PSA10_FN1, PTC6_FN),
+       PINMUX_DATA(SDHI1WP_MARK, PSA11_PSA10_FN2, PTC6_FN),
+       PINMUX_DATA(IDED13_MARK, PSA11_PSA10_FN1, PTC5_FN),
+       PINMUX_DATA(SDHI1D3_MARK, PSA11_PSA10_FN2, PTC5_FN),
+       PINMUX_DATA(IDED12_MARK, PSA11_PSA10_FN1, PTC4_FN),
+       PINMUX_DATA(SDHI1D2_MARK, PSA11_PSA10_FN2, PTC4_FN),
+       PINMUX_DATA(IDED11_MARK, PSA11_PSA10_FN1, PTC3_FN),
+       PINMUX_DATA(SDHI1D1_MARK, PSA11_PSA10_FN2, PTC3_FN),
+       PINMUX_DATA(IDED10_MARK, PSA11_PSA10_FN1, PTC2_FN),
+       PINMUX_DATA(SDHI1D0_MARK, PSA11_PSA10_FN2, PTC2_FN),
+       PINMUX_DATA(IDED9_MARK, PSA11_PSA10_FN1, PTC1_FN),
+       PINMUX_DATA(SDHI1CMD_MARK, PSA11_PSA10_FN2, PTC1_FN),
+       PINMUX_DATA(IDED8_MARK, PSA11_PSA10_FN1, PTC0_FN),
+       PINMUX_DATA(SDHI1CLK_MARK, PSA11_PSA10_FN2, PTC0_FN),
+
+       /* PTD FN */
+       PINMUX_DATA(IDED7_MARK, PSA11_PSA10_FN1, PTD7_FN),
+       PINMUX_DATA(SDHI0CD_PTD_MARK, PSA11_PSA10_FN2, PTD7_FN),
+       PINMUX_DATA(IDED6_MARK, PSA11_PSA10_FN1, PTD6_FN),
+       PINMUX_DATA(SDHI0WP_PTD_MARK, PSA11_PSA10_FN2, PTD6_FN),
+       PINMUX_DATA(IDED5_MARK, PSA11_PSA10_FN1, PTD5_FN),
+       PINMUX_DATA(SDHI0D3_PTD_MARK, PSA11_PSA10_FN2, PTD5_FN),
+       PINMUX_DATA(IDED4_MARK, PSA11_PSA10_FN1, PTD4_FN),
+       PINMUX_DATA(SDHI0D2_PTD_MARK, PSA11_PSA10_FN2, PTD4_FN),
+       PINMUX_DATA(IDED3_MARK, PSA11_PSA10_FN1, PTD3_FN),
+       PINMUX_DATA(SDHI0D1_PTD_MARK, PSA11_PSA10_FN2, PTD3_FN),
+       PINMUX_DATA(IDED2_MARK, PSA11_PSA10_FN1, PTD2_FN),
+       PINMUX_DATA(SDHI0D0_PTD_MARK, PSA11_PSA10_FN2, PTD2_FN),
+       PINMUX_DATA(IDED1_MARK, PSA11_PSA10_FN1, PTD1_FN),
+       PINMUX_DATA(SDHI0CMD_PTD_MARK, PSA11_PSA10_FN2, PTD1_FN),
+       PINMUX_DATA(IDED0_MARK, PSA11_PSA10_FN1, PTD0_FN),
+       PINMUX_DATA(SDHI0CLK_PTD_MARK, PSA11_PSA10_FN2, PTD0_FN),
+
+       /* PTE FN */
+       PINMUX_DATA(DIRECTION_MARK, PSA11_PSA10_FN1, PTE5_FN),
+       PINMUX_DATA(SCIF5_PTE_SCK_MARK, PSA11_PSA10_FN2, PTE5_FN),
+       PINMUX_DATA(EXBUF_ENB_MARK, PSA11_PSA10_FN1, PTE4_FN),
+       PINMUX_DATA(SCIF5_PTE_RXD_MARK, PSA11_PSA10_FN2, PTE4_FN),
+       PINMUX_DATA(IDERST_MARK, PSA11_PSA10_FN1, PTE3_FN),
+       PINMUX_DATA(SCIF5_PTE_TXD_MARK, PSA11_PSA10_FN2, PTE3_FN),
+       PINMUX_DATA(IODACK_MARK, PSA11_PSA10_FN1, PTE2_FN),
+       PINMUX_DATA(SCIF4_PTE_SCK_MARK, PSA11_PSA10_FN2, PTE2_FN),
+       PINMUX_DATA(IODREQ_MARK, PSA11_PSA10_FN1, PTE1_FN),
+       PINMUX_DATA(SCIF4_PTE_RXD_MARK, PSA11_PSA10_FN2, PTE1_FN),
+       PINMUX_DATA(IDEIORDY_MARK, PSA11_PSA10_FN1, PTE0_FN),
+       PINMUX_DATA(SCIF4_PTE_TXD_MARK, PSA11_PSA10_FN2, PTE0_FN),
+
+       /* PTF FN */
+       PINMUX_DATA(IDEINT_MARK, PTF7_FN),
+       PINMUX_DATA(IDEIOWR_MARK, PSA5_PSA4_FN1, PTF6_FN),
+       PINMUX_DATA(MSIOF0_PTF_SS2_MARK, PSA5_PSA4_FN2, PTF6_FN),
+       PINMUX_DATA(MSIOF0_PTF_RSYNC_MARK, PSA5_PSA4_FN3, PTF6_FN),
+       PINMUX_DATA(IDEIORD_MARK, PSA5_PSA4_FN1, PTF5_FN),
+       PINMUX_DATA(MSIOF0_PTF_SS1_MARK, PSA5_PSA4_FN2, PTF5_FN),
+       PINMUX_DATA(MSIOF0_PTF_RSCK_MARK, PSA5_PSA4_FN3, PTF5_FN),
+       PINMUX_DATA(IDECS1_MARK, PSA11_PSA10_FN1, PTF4_FN),
+       PINMUX_DATA(MSIOF0_PTF_TSYNC_MARK, PSA11_PSA10_FN2, PTF4_FN),
+       PINMUX_DATA(IDECS0_MARK, PSA11_PSA10_FN1, PTF3_FN),
+       PINMUX_DATA(MSIOF0_PTF_TSCK_MARK, PSA11_PSA10_FN2, PTF3_FN),
+       PINMUX_DATA(IDEA2_MARK, PSA11_PSA10_FN1, PTF2_FN),
+       PINMUX_DATA(MSIOF0_PTF_RXD_MARK, PSA11_PSA10_FN2, PTF2_FN),
+       PINMUX_DATA(IDEA1_MARK, PSA11_PSA10_FN1, PTF1_FN),
+       PINMUX_DATA(MSIOF0_PTF_TXD_MARK, PSA11_PSA10_FN2, PTF1_FN),
+       PINMUX_DATA(IDEA0_MARK, PSA11_PSA10_FN1, PTF0_FN),
+       PINMUX_DATA(MSIOF0_PTF_MCK_MARK, PSA11_PSA10_FN2, PTF0_FN),
+
+       /* PTG FN */
+       PINMUX_DATA(AUDCK_MARK, PTG5_FN),
+       PINMUX_DATA(AUDSYNC_MARK, PTG4_FN),
+       PINMUX_DATA(AUDATA3_MARK, PSA3_PSA2_FN1, PTG3_FN),
+       PINMUX_DATA(TPUTO3_MARK, PSA3_PSA2_FN2, PTG3_FN),
+       PINMUX_DATA(AUDATA2_MARK, PSA3_PSA2_FN1, PTG2_FN),
+       PINMUX_DATA(TPUTO2_MARK, PSA3_PSA2_FN2, PTG2_FN),
+       PINMUX_DATA(AUDATA1_MARK, PSA3_PSA2_FN1, PTG1_FN),
+       PINMUX_DATA(TPUTO1_MARK, PSA3_PSA2_FN2, PTG1_FN),
+       PINMUX_DATA(AUDATA0_MARK, PSA3_PSA2_FN1, PTG0_FN),
+       PINMUX_DATA(TPUTO0_MARK, PSA3_PSA2_FN2, PTG0_FN),
+
+       /* PTG FN */
+       PINMUX_DATA(LCDVCPWC_MARK, PTH7_FN),
+       PINMUX_DATA(LCDRD_MARK, PSB15_PSB14_FN1, PTH6_FN),
+       PINMUX_DATA(DV_CLKI_MARK, PSB15_PSB14_FN2, PTH6_FN),
+       PINMUX_DATA(LCDVSYN_MARK, PSB15_PSB14_FN1, PTH5_FN),
+       PINMUX_DATA(DV_CLK_MARK, PSB15_PSB14_FN2, PTH5_FN),
+       PINMUX_DATA(LCDDISP_MARK, PSB13_PSB12_LCDC_RGB, PTH4_FN),
+       PINMUX_DATA(LCDRS_MARK, PSB13_PSB12_LCDC_SYS, PTH4_FN),
+       PINMUX_DATA(LCDHSYN_MARK, PSB13_PSB12_LCDC_RGB, PTH3_FN),
+       PINMUX_DATA(LCDCS_MARK, PSB13_PSB12_LCDC_SYS, PTH3_FN),
+       PINMUX_DATA(LCDDON_MARK, PTH2_FN),
+       PINMUX_DATA(LCDDCK_MARK, PSB13_PSB12_LCDC_RGB, PTH1_FN),
+       PINMUX_DATA(LCDWR_MARK, PSB13_PSB12_LCDC_SYS, PTH1_FN),
+       PINMUX_DATA(LCDVEPWC_MARK, PTH0_FN),
+
+       /* PTJ FN */
+       PINMUX_DATA(STATUS0_MARK, PTJ7_FN),
+       PINMUX_DATA(PDSTATUS_MARK, PTJ5_FN),
+       PINMUX_DATA(A25_MARK, PTJ3_FN),
+       PINMUX_DATA(A24_MARK, PTJ2_FN),
+       PINMUX_DATA(A23_MARK, PTJ1_FN),
+       PINMUX_DATA(A22_MARK, PTJ0_FN),
+
+       /* PTK FN */
+       PINMUX_DATA(SIUAFCK_MARK, PTK7_FN),
+       PINMUX_DATA(SIUAILR_MARK, PSB9_PSB8_FN1, PTK6_FN),
+       PINMUX_DATA(MSIOF1_SS2_MARK, PSB9_PSB8_FN2, PTK6_FN),
+       PINMUX_DATA(MSIOF1_RSYNC_MARK, PSB9_PSB8_FN3, PTK6_FN),
+       PINMUX_DATA(SIUAIBT_MARK, PSB9_PSB8_FN1, PTK5_FN),
+       PINMUX_DATA(MSIOF1_SS1_MARK, PSB9_PSB8_FN2, PTK5_FN),
+       PINMUX_DATA(MSIOF1_RSCK_MARK, PSB9_PSB8_FN3, PTK5_FN),
+       PINMUX_DATA(SIUAISLD_MARK, PSB7_PSB6_FN1, PTK4_FN),
+       PINMUX_DATA(MSIOF1_RXD_MARK, PSB7_PSB6_FN2, PTK4_FN),
+       PINMUX_DATA(SIUAOLR_MARK, PSB7_PSB6_FN1, PTK3_FN),
+       PINMUX_DATA(MSIOF1_TSYNC_MARK, PSB7_PSB6_FN2, PTK3_FN),
+       PINMUX_DATA(SIUAOBT_MARK, PSB7_PSB6_FN1, PTK2_FN),
+       PINMUX_DATA(MSIOF1_TSCK_MARK, PSB7_PSB6_FN2, PTK2_FN),
+       PINMUX_DATA(SIUAOSLD_MARK, PSB7_PSB6_FN1, PTK1_FN),
+       PINMUX_DATA(MSIOF1_RXD_MARK, PSB7_PSB6_FN2, PTK1_FN),
+       PINMUX_DATA(SIUAMCK_MARK, PSB7_PSB6_FN1, PTK0_FN),
+       PINMUX_DATA(MSIOF1_MCK_MARK, PSB7_PSB6_FN2, PTK0_FN),
+
+       /* PTL FN */
+       PINMUX_DATA(LCDD15_MARK, PSB5_PSB4_FN1, PTL7_FN),
+       PINMUX_DATA(DV_D15_MARK, PSB5_PSB4_FN2, PTL7_FN),
+       PINMUX_DATA(LCDD14_MARK, PSB5_PSB4_FN1, PTL6_FN),
+       PINMUX_DATA(DV_D14_MARK, PSB5_PSB4_FN2, PTL6_FN),
+       PINMUX_DATA(LCDD13_MARK, PSB5_PSB4_FN1, PTL5_FN),
+       PINMUX_DATA(DV_D13_MARK, PSB5_PSB4_FN2, PTL5_FN),
+       PINMUX_DATA(LCDD12_MARK, PSB5_PSB4_FN1, PTL4_FN),
+       PINMUX_DATA(DV_D12_MARK, PSB5_PSB4_FN2, PTL4_FN),
+       PINMUX_DATA(LCDD11_MARK, PSB5_PSB4_FN1, PTL3_FN),
+       PINMUX_DATA(DV_D11_MARK, PSB5_PSB4_FN2, PTL3_FN),
+       PINMUX_DATA(LCDD10_MARK, PSB5_PSB4_FN1, PTL2_FN),
+       PINMUX_DATA(DV_D10_MARK, PSB5_PSB4_FN2, PTL2_FN),
+       PINMUX_DATA(LCDD9_MARK, PSB5_PSB4_FN1, PTL1_FN),
+       PINMUX_DATA(DV_D9_MARK, PSB5_PSB4_FN2, PTL1_FN),
+       PINMUX_DATA(LCDD8_MARK, PSB5_PSB4_FN1, PTL0_FN),
+       PINMUX_DATA(DV_D8_MARK, PSB5_PSB4_FN2, PTL0_FN),
+
+       /* PTM FN */
+       PINMUX_DATA(LCDD7_MARK, PSB5_PSB4_FN1, PTM7_FN),
+       PINMUX_DATA(DV_D7_MARK, PSB5_PSB4_FN2, PTM7_FN),
+       PINMUX_DATA(LCDD6_MARK, PSB5_PSB4_FN1, PTM6_FN),
+       PINMUX_DATA(DV_D6_MARK, PSB5_PSB4_FN2, PTM6_FN),
+       PINMUX_DATA(LCDD5_MARK, PSB5_PSB4_FN1, PTM5_FN),
+       PINMUX_DATA(DV_D5_MARK, PSB5_PSB4_FN2, PTM5_FN),
+       PINMUX_DATA(LCDD4_MARK, PSB5_PSB4_FN1, PTM4_FN),
+       PINMUX_DATA(DV_D4_MARK, PSB5_PSB4_FN2, PTM4_FN),
+       PINMUX_DATA(LCDD3_MARK, PSB5_PSB4_FN1, PTM3_FN),
+       PINMUX_DATA(DV_D3_MARK, PSB5_PSB4_FN2, PTM3_FN),
+       PINMUX_DATA(LCDD2_MARK, PSB5_PSB4_FN1, PTM2_FN),
+       PINMUX_DATA(DV_D2_MARK, PSB5_PSB4_FN2, PTM2_FN),
+       PINMUX_DATA(LCDD1_MARK, PSB5_PSB4_FN1, PTM1_FN),
+       PINMUX_DATA(DV_D1_MARK, PSB5_PSB4_FN2, PTM1_FN),
+       PINMUX_DATA(LCDD0_MARK, PSB5_PSB4_FN1, PTM0_FN),
+       PINMUX_DATA(DV_D0_MARK, PSB5_PSB4_FN2, PTM0_FN),
+
+       /* PTN FN */
+       PINMUX_DATA(LCDD23_MARK, PSB3_PSB2_FN1, PTN7_FN),
+       PINMUX_DATA(SCIF5_PTN_SCK_MARK, PSB3_PSB2_FN2, PTN7_FN),
+       PINMUX_DATA(LCDD22_MARK, PSB3_PSB2_FN1, PTN6_FN),
+       PINMUX_DATA(SCIF5_PTN_RXD_MARK, PSB3_PSB2_FN2, PTN6_FN),
+       PINMUX_DATA(LCDD21_MARK, PSB3_PSB2_FN1, PTN5_FN),
+       PINMUX_DATA(SCIF5_PTN_TXD_MARK, PSB3_PSB2_FN2, PTN5_FN),
+       PINMUX_DATA(LCDD20_MARK, PSB3_PSB2_FN1, PTN4_FN),
+       PINMUX_DATA(SCIF4_PTN_SCK_MARK, PSB3_PSB2_FN2, PTN4_FN),
+       PINMUX_DATA(LCDD19_MARK, PSB3_PSB2_FN1, PTN3_FN),
+       PINMUX_DATA(SCIF4_PTN_RXD_MARK, PSB3_PSB2_FN2, PTN3_FN),
+       PINMUX_DATA(LCDD18_MARK, PSB3_PSB2_FN1, PTN2_FN),
+       PINMUX_DATA(SCIF4_PTN_TXD_MARK, PSB3_PSB2_FN2, PTN2_FN),
+       PINMUX_DATA(LCDD17_MARK, PSB5_PSB4_FN1, PTN1_FN),
+       PINMUX_DATA(DV_VSYNC_MARK, PSB5_PSB4_FN2, PTN1_FN),
+       PINMUX_DATA(LCDD16_MARK, PSB5_PSB4_FN1, PTN0_FN),
+       PINMUX_DATA(DV_HSYNC_MARK, PSB5_PSB4_FN2, PTN0_FN),
+
+       /* PTQ FN */
+       PINMUX_DATA(AN3_MARK, PTQ3_FN),
+       PINMUX_DATA(AN2_MARK, PTQ2_FN),
+       PINMUX_DATA(AN1_MARK, PTQ1_FN),
+       PINMUX_DATA(AN0_MARK, PTQ0_FN),
+
+       /* PTR FN */
+       PINMUX_DATA(CS6B_CE1B_MARK, PTR7_FN),
+       PINMUX_DATA(CS6A_CE2B_MARK, PTR6_FN),
+       PINMUX_DATA(CS5B_CE1A_MARK, PTR5_FN),
+       PINMUX_DATA(CS5A_CE2A_MARK, PTR4_FN),
+       PINMUX_DATA(IOIS16_MARK, PSA13_PSA12_FN1, PTR3_FN),
+       PINMUX_DATA(LCDLCLK_PTR_MARK, PSA13_PSA12_FN2, PTR3_FN),
+       PINMUX_DATA(WAIT_MARK, PTR2_FN),
+       PINMUX_DATA(WE3_ICIOWR_MARK, PTR1_FN),
+       PINMUX_DATA(WE2_ICIORD_MARK, PTR0_FN),
+
+       /* PTS FN */
+       PINMUX_DATA(SCIF1_PTS_SCK_MARK, PSC15_PSC14_FN1, PTS7_FN),
+       PINMUX_DATA(SDHI0CD_PTS_MARK, PSC15_PSC14_FN2, PTS7_FN),
+       PINMUX_DATA(SCIF1_PTS_RXD_MARK, PSC15_PSC14_FN1, PTS6_FN),
+       PINMUX_DATA(SDHI0WP_PTS_MARK, PSC15_PSC14_FN2, PTS6_FN),
+       PINMUX_DATA(SCIF1_PTS_TXD_MARK, PSC15_PSC14_FN1, PTS5_FN),
+       PINMUX_DATA(SDHI0D3_PTS_MARK, PSC15_PSC14_FN2, PTS5_FN),
+       PINMUX_DATA(SCIF3_PTS_CTS_MARK, PSC15_PSC14_FN1, PTS4_FN),
+       PINMUX_DATA(SDHI0D2_PTS_MARK, PSC15_PSC14_FN2, PTS4_FN),
+       PINMUX_DATA(SCIF3_PTS_RTS_MARK, PSC15_PSC14_FN1, PTS3_FN),
+       PINMUX_DATA(SDHI0D1_PTS_MARK, PSC15_PSC14_FN2, PTS3_FN),
+       PINMUX_DATA(SCIF3_PTS_SCK_MARK, PSC15_PSC14_FN1, PTS2_FN),
+       PINMUX_DATA(SDHI0D0_PTS_MARK, PSC15_PSC14_FN2, PTS2_FN),
+       PINMUX_DATA(SCIF3_PTS_RXD_MARK, PSC15_PSC14_FN1, PTS1_FN),
+       PINMUX_DATA(SDHI0CMD_PTS_MARK, PSC15_PSC14_FN2, PTS1_FN),
+       PINMUX_DATA(SCIF3_PTS_TXD_MARK, PSC15_PSC14_FN1, PTS0_FN),
+       PINMUX_DATA(SDHI0CLK_PTS_MARK, PSC15_PSC14_FN2, PTS0_FN),
+
+       /* PTT FN */
+       PINMUX_DATA(SCIF0_PTT_SCK_MARK, PSC13_PSC12_FN1, PTT5_FN),
+       PINMUX_DATA(MSIOF0_PTT_TSCK_MARK, PSC13_PSC12_FN2, PTT5_FN),
+       PINMUX_DATA(SCIF0_PTT_RXD_MARK, PSC13_PSC12_FN1, PTT4_FN),
+       PINMUX_DATA(MSIOF0_PTT_RXD_MARK, PSC13_PSC12_FN2, PTT4_FN),
+       PINMUX_DATA(SCIF0_PTT_TXD_MARK, PSC13_PSC12_FN1, PTT3_FN),
+       PINMUX_DATA(MSIOF0_PTT_TXD_MARK, PSC13_PSC12_FN2, PTT3_FN),
+       PINMUX_DATA(SCIF2_PTT_SCK_MARK, PSC11_PSC10_FN1, PTT2_FN),
+       PINMUX_DATA(MSIOF0_PTT_TSYNC_MARK, PSC11_PSC10_FN2, PTT2_FN),
+       PINMUX_DATA(SCIF2_PTT_RXD_MARK, PSC11_PSC10_FN1, PTT1_FN),
+       PINMUX_DATA(MSIOF0_PTT_SS1_MARK, PSC11_PSC10_FN2, PTT1_FN),
+       PINMUX_DATA(MSIOF0_PTT_RSCK_MARK, PSC11_PSC10_FN3, PTT1_FN),
+       PINMUX_DATA(SCIF2_PTT_TXD_MARK, PSC11_PSC10_FN1, PTT0_FN),
+       PINMUX_DATA(MSIOF0_PTT_SS2_MARK, PSC11_PSC10_FN2, PTT0_FN),
+       PINMUX_DATA(MSIOF0_PTT_RSYNC_MARK, PSC11_PSC10_FN3, PTT0_FN),
+
+       /* PTU FN */
+       PINMUX_DATA(FCDE_MARK, PSC9_PSC8_FN1, PTU5_FN),
+       PINMUX_DATA(SCIF0_PTU_SCK_MARK, PSC9_PSC8_FN2, PTU5_FN),
+       PINMUX_DATA(FSC_MARK, PSC9_PSC8_FN1, PTU4_FN),
+       PINMUX_DATA(SCIF0_PTU_RXD_MARK, PSC9_PSC8_FN2, PTU4_FN),
+       PINMUX_DATA(FWE_MARK, PSC9_PSC8_FN1, PTU3_FN),
+       PINMUX_DATA(SCIF0_PTU_TXD_MARK, PSC9_PSC8_FN2, PTU3_FN),
+       PINMUX_DATA(FOE_MARK, PSC7_PSC6_FN1, PTU2_FN),
+       PINMUX_DATA(SCIF2_PTU_SCK_MARK, PSC7_PSC6_FN2, PTU2_FN),
+       PINMUX_DATA(VIO_VD2_MARK, PSC7_PSC6_FN3, PTU2_FN),
+       PINMUX_DATA(FRB_MARK, PSC7_PSC6_FN1, PTU1_FN),
+       PINMUX_DATA(SCIF2_PTU_RXD_MARK, PSC7_PSC6_FN2, PTU1_FN),
+       PINMUX_DATA(VIO_CLK2_MARK, PSC7_PSC6_FN3, PTU1_FN),
+       PINMUX_DATA(FCE_MARK, PSC7_PSC6_FN1, PTU0_FN),
+       PINMUX_DATA(SCIF2_PTU_TXD_MARK, PSC7_PSC6_FN2, PTU0_FN),
+       PINMUX_DATA(VIO_HD2_MARK, PSC7_PSC6_FN3, PTU0_FN),
+
+       /* PTV FN */
+       PINMUX_DATA(NAF7_MARK, PSC7_PSC6_FN1, PTV7_FN),
+       PINMUX_DATA(SCIF1_PTV_SCK_MARK, PSC7_PSC6_FN2, PTV7_FN),
+       PINMUX_DATA(VIO_D15_MARK, PSC7_PSC6_FN3, PTV7_FN),
+       PINMUX_DATA(NAF6_MARK, PSC7_PSC6_FN1, PTV6_FN),
+       PINMUX_DATA(SCIF1_PTV_RXD_MARK, PSC7_PSC6_FN2, PTV6_FN),
+       PINMUX_DATA(VIO_D14_MARK, PSC7_PSC6_FN3, PTV6_FN),
+       PINMUX_DATA(NAF5_MARK, PSC7_PSC6_FN1, PTV5_FN),
+       PINMUX_DATA(SCIF1_PTV_TXD_MARK, PSC7_PSC6_FN2, PTV5_FN),
+       PINMUX_DATA(VIO_D13_MARK, PSC7_PSC6_FN3, PTV5_FN),
+       PINMUX_DATA(NAF4_MARK, PSC7_PSC6_FN1, PTV4_FN),
+       PINMUX_DATA(SCIF3_PTV_CTS_MARK, PSC7_PSC6_FN2, PTV4_FN),
+       PINMUX_DATA(VIO_D12_MARK, PSC7_PSC6_FN3, PTV4_FN),
+       PINMUX_DATA(NAF3_MARK, PSC7_PSC6_FN1, PTV3_FN),
+       PINMUX_DATA(SCIF3_PTV_RTS_MARK, PSC7_PSC6_FN2, PTV3_FN),
+       PINMUX_DATA(VIO_D11_MARK, PSC7_PSC6_FN3, PTV3_FN),
+       PINMUX_DATA(NAF2_MARK, PSC7_PSC6_FN1, PTV2_FN),
+       PINMUX_DATA(SCIF3_PTV_SCK_MARK, PSC7_PSC6_FN2, PTV2_FN),
+       PINMUX_DATA(VIO_D10_MARK, PSC7_PSC6_FN3, PTV2_FN),
+       PINMUX_DATA(NAF1_MARK, PSC7_PSC6_FN1, PTV1_FN),
+       PINMUX_DATA(SCIF3_PTV_RXD_MARK, PSC7_PSC6_FN2, PTV1_FN),
+       PINMUX_DATA(VIO_D9_MARK, PSC7_PSC6_FN3, PTV1_FN),
+       PINMUX_DATA(NAF0_MARK, PSC7_PSC6_FN1, PTV0_FN),
+       PINMUX_DATA(SCIF3_PTV_TXD_MARK, PSC7_PSC6_FN2, PTV0_FN),
+       PINMUX_DATA(VIO_D8_MARK, PSC7_PSC6_FN3, PTV0_FN),
+
+       /* PTW FN */
+       PINMUX_DATA(IRQ7_MARK, PTW7_FN),
+       PINMUX_DATA(IRQ6_MARK, PTW6_FN),
+       PINMUX_DATA(IRQ5_MARK, PTW5_FN),
+       PINMUX_DATA(IRQ4_MARK, PSD15_PSD14_FN1, PTW4_FN),
+       PINMUX_DATA(LCDLCLK_PTW_MARK, PSD15_PSD14_FN2, PTW4_FN),
+       PINMUX_DATA(IRQ3_MARK, PSD13_PSD12_FN1, PTW3_FN),
+       PINMUX_DATA(ADTRG_MARK, PSD13_PSD12_FN2, PTW3_FN),
+       PINMUX_DATA(IRQ2_MARK, PSD11_PSD10_FN1, PTW2_FN),
+       PINMUX_DATA(BS_MARK, PSD11_PSD10_FN2, PTW2_FN),
+       PINMUX_DATA(VIO_CKO_MARK, PSD11_PSD10_FN3, PTW2_FN),
+       PINMUX_DATA(IRQ1_MARK, PSD9_PSD8_FN1, PTW1_FN),
+       PINMUX_DATA(SIUAISPD_MARK, PSD9_PSD8_FN2, PTW1_FN),
+       PINMUX_DATA(IRQ0_MARK, PSD7_PSD6_FN1, PTW0_FN),
+       PINMUX_DATA(SIUAOSPD_MARK, PSD7_PSD6_FN2, PTW0_FN),
+
+       /* PTX FN */
+       PINMUX_DATA(DACK1_MARK, PTX7_FN),
+       PINMUX_DATA(DREQ1_MARK, PSD3_PSD2_FN1, PTX6_FN),
+       PINMUX_DATA(MSIOF0_PTX_MCK_MARK, PSD3_PSD2_FN2, PTX6_FN),
+       PINMUX_DATA(DACK1_MARK, PTX5_FN),
+       PINMUX_DATA(IRDA_OUT_MARK, PSD5_PSD4_FN2, PTX5_FN),
+       PINMUX_DATA(DREQ1_MARK, PTX4_FN),
+       PINMUX_DATA(IRDA_IN_MARK, PSD5_PSD4_FN2, PTX4_FN),
+       PINMUX_DATA(TS0_SDAT_MARK, PTX3_FN),
+       PINMUX_DATA(TS0_SCK_MARK, PTX2_FN),
+       PINMUX_DATA(TS0_SDEN_MARK, PTX1_FN),
+       PINMUX_DATA(TS0_SPSYNC_MARK, PTX0_FN),
+
+       /* PTY FN */
+       PINMUX_DATA(VIO_D7_MARK, PTY7_FN),
+       PINMUX_DATA(VIO_D6_MARK, PTY6_FN),
+       PINMUX_DATA(VIO_D5_MARK, PTY5_FN),
+       PINMUX_DATA(VIO_D4_MARK, PTY4_FN),
+       PINMUX_DATA(VIO_D3_MARK, PTY3_FN),
+       PINMUX_DATA(VIO_D2_MARK, PTY2_FN),
+       PINMUX_DATA(VIO_D1_MARK, PTY1_FN),
+       PINMUX_DATA(VIO_D0_MARK, PTY0_FN),
+
+       /* PTZ FN */
+       PINMUX_DATA(SIUBOBT_MARK, PTZ7_FN),
+       PINMUX_DATA(SIUBOLR_MARK, PTZ6_FN),
+       PINMUX_DATA(SIUBOSLD_MARK, PTZ5_FN),
+       PINMUX_DATA(SIUBMCK_MARK, PTZ4_FN),
+       PINMUX_DATA(VIO_FLD_MARK, PSD1_PSD0_FN1, PTZ3_FN),
+       PINMUX_DATA(SIUBFCK_MARK, PSD1_PSD0_FN2, PTZ3_FN),
+       PINMUX_DATA(VIO_HD1_MARK, PSD1_PSD0_FN1, PTZ2_FN),
+       PINMUX_DATA(SIUBILR_MARK, PSD1_PSD0_FN2, PTZ2_FN),
+       PINMUX_DATA(VIO_VD1_MARK, PSD1_PSD0_FN1, PTZ1_FN),
+       PINMUX_DATA(SIUBIBT_MARK, PSD1_PSD0_FN2, PTZ1_FN),
+       PINMUX_DATA(VIO_CLK1_MARK, PSD1_PSD0_FN1, PTZ0_FN),
+       PINMUX_DATA(SIUBISLD_MARK, PSD1_PSD0_FN2, PTZ0_FN),
+};
+
+static struct pinmux_gpio pinmux_gpios[] = {
+       /* PTA */
+       PINMUX_GPIO(GPIO_PTA7, PTA7_DATA),
+       PINMUX_GPIO(GPIO_PTA6, PTA6_DATA),
+       PINMUX_GPIO(GPIO_PTA5, PTA5_DATA),
+       PINMUX_GPIO(GPIO_PTA4, PTA4_DATA),
+       PINMUX_GPIO(GPIO_PTA3, PTA3_DATA),
+       PINMUX_GPIO(GPIO_PTA2, PTA2_DATA),
+       PINMUX_GPIO(GPIO_PTA1, PTA1_DATA),
+       PINMUX_GPIO(GPIO_PTA0, PTA0_DATA),
+
+       /* PTB */
+       PINMUX_GPIO(GPIO_PTB7, PTB7_DATA),
+       PINMUX_GPIO(GPIO_PTB6, PTB6_DATA),
+       PINMUX_GPIO(GPIO_PTB5, PTB5_DATA),
+       PINMUX_GPIO(GPIO_PTB4, PTB4_DATA),
+       PINMUX_GPIO(GPIO_PTB3, PTB3_DATA),
+       PINMUX_GPIO(GPIO_PTB2, PTB2_DATA),
+       PINMUX_GPIO(GPIO_PTB1, PTB1_DATA),
+       PINMUX_GPIO(GPIO_PTB0, PTB0_DATA),
+
+       /* PTC */
+       PINMUX_GPIO(GPIO_PTC7, PTC7_DATA),
+       PINMUX_GPIO(GPIO_PTC6, PTC6_DATA),
+       PINMUX_GPIO(GPIO_PTC5, PTC5_DATA),
+       PINMUX_GPIO(GPIO_PTC4, PTC4_DATA),
+       PINMUX_GPIO(GPIO_PTC3, PTC3_DATA),
+       PINMUX_GPIO(GPIO_PTC2, PTC2_DATA),
+       PINMUX_GPIO(GPIO_PTC1, PTC1_DATA),
+       PINMUX_GPIO(GPIO_PTC0, PTC0_DATA),
+
+       /* PTD */
+       PINMUX_GPIO(GPIO_PTD7, PTD7_DATA),
+       PINMUX_GPIO(GPIO_PTD6, PTD6_DATA),
+       PINMUX_GPIO(GPIO_PTD5, PTD5_DATA),
+       PINMUX_GPIO(GPIO_PTD4, PTD4_DATA),
+       PINMUX_GPIO(GPIO_PTD3, PTD3_DATA),
+       PINMUX_GPIO(GPIO_PTD2, PTD2_DATA),
+       PINMUX_GPIO(GPIO_PTD1, PTD1_DATA),
+       PINMUX_GPIO(GPIO_PTD0, PTD0_DATA),
+
+       /* PTE */
+       PINMUX_GPIO(GPIO_PTE5, PTE5_DATA),
+       PINMUX_GPIO(GPIO_PTE4, PTE4_DATA),
+       PINMUX_GPIO(GPIO_PTE3, PTE3_DATA),
+       PINMUX_GPIO(GPIO_PTE2, PTE2_DATA),
+       PINMUX_GPIO(GPIO_PTE1, PTE1_DATA),
+       PINMUX_GPIO(GPIO_PTE0, PTE0_DATA),
+
+       /* PTF */
+       PINMUX_GPIO(GPIO_PTF7, PTF7_DATA),
+       PINMUX_GPIO(GPIO_PTF6, PTF6_DATA),
+       PINMUX_GPIO(GPIO_PTF5, PTF5_DATA),
+       PINMUX_GPIO(GPIO_PTF4, PTF4_DATA),
+       PINMUX_GPIO(GPIO_PTF3, PTF3_DATA),
+       PINMUX_GPIO(GPIO_PTF2, PTF2_DATA),
+       PINMUX_GPIO(GPIO_PTF1, PTF1_DATA),
+       PINMUX_GPIO(GPIO_PTF0, PTF0_DATA),
+
+       /* PTG */
+       PINMUX_GPIO(GPIO_PTG5, PTG5_DATA),
+       PINMUX_GPIO(GPIO_PTG4, PTG4_DATA),
+       PINMUX_GPIO(GPIO_PTG3, PTG3_DATA),
+       PINMUX_GPIO(GPIO_PTG2, PTG2_DATA),
+       PINMUX_GPIO(GPIO_PTG1, PTG1_DATA),
+       PINMUX_GPIO(GPIO_PTG0, PTG0_DATA),
+
+       /* PTH */
+       PINMUX_GPIO(GPIO_PTH7, PTH7_DATA),
+       PINMUX_GPIO(GPIO_PTH6, PTH6_DATA),
+       PINMUX_GPIO(GPIO_PTH5, PTH5_DATA),
+       PINMUX_GPIO(GPIO_PTH4, PTH4_DATA),
+       PINMUX_GPIO(GPIO_PTH3, PTH3_DATA),
+       PINMUX_GPIO(GPIO_PTH2, PTH2_DATA),
+       PINMUX_GPIO(GPIO_PTH1, PTH1_DATA),
+       PINMUX_GPIO(GPIO_PTH0, PTH0_DATA),
+
+       /* PTJ */
+       PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
+       PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
+       PINMUX_GPIO(GPIO_PTJ3, PTJ3_DATA),
+       PINMUX_GPIO(GPIO_PTJ2, PTJ2_DATA),
+       PINMUX_GPIO(GPIO_PTJ1, PTJ1_DATA),
+       PINMUX_GPIO(GPIO_PTJ0, PTJ0_DATA),
+
+       /* PTK */
+       PINMUX_GPIO(GPIO_PTK7, PTK7_DATA),
+       PINMUX_GPIO(GPIO_PTK6, PTK6_DATA),
+       PINMUX_GPIO(GPIO_PTK5, PTK5_DATA),
+       PINMUX_GPIO(GPIO_PTK4, PTK4_DATA),
+       PINMUX_GPIO(GPIO_PTK3, PTK3_DATA),
+       PINMUX_GPIO(GPIO_PTK2, PTK2_DATA),
+       PINMUX_GPIO(GPIO_PTK1, PTK1_DATA),
+       PINMUX_GPIO(GPIO_PTK0, PTK0_DATA),
+
+       /* PTL */
+       PINMUX_GPIO(GPIO_PTL7, PTL7_DATA),
+       PINMUX_GPIO(GPIO_PTL6, PTL6_DATA),
+       PINMUX_GPIO(GPIO_PTL5, PTL5_DATA),
+       PINMUX_GPIO(GPIO_PTL4, PTL4_DATA),
+       PINMUX_GPIO(GPIO_PTL3, PTL3_DATA),
+       PINMUX_GPIO(GPIO_PTL2, PTL2_DATA),
+       PINMUX_GPIO(GPIO_PTL1, PTL1_DATA),
+       PINMUX_GPIO(GPIO_PTL0, PTL0_DATA),
+
+       /* PTM */
+       PINMUX_GPIO(GPIO_PTM7, PTM7_DATA),
+       PINMUX_GPIO(GPIO_PTM6, PTM6_DATA),
+       PINMUX_GPIO(GPIO_PTM5, PTM5_DATA),
+       PINMUX_GPIO(GPIO_PTM4, PTM4_DATA),
+       PINMUX_GPIO(GPIO_PTM3, PTM3_DATA),
+       PINMUX_GPIO(GPIO_PTM2, PTM2_DATA),
+       PINMUX_GPIO(GPIO_PTM1, PTM1_DATA),
+       PINMUX_GPIO(GPIO_PTM0, PTM0_DATA),
+
+       /* PTN */
+       PINMUX_GPIO(GPIO_PTN7, PTN7_DATA),
+       PINMUX_GPIO(GPIO_PTN6, PTN6_DATA),
+       PINMUX_GPIO(GPIO_PTN5, PTN5_DATA),
+       PINMUX_GPIO(GPIO_PTN4, PTN4_DATA),
+       PINMUX_GPIO(GPIO_PTN3, PTN3_DATA),
+       PINMUX_GPIO(GPIO_PTN2, PTN2_DATA),
+       PINMUX_GPIO(GPIO_PTN1, PTN1_DATA),
+       PINMUX_GPIO(GPIO_PTN0, PTN0_DATA),
+
+       /* PTQ */
+       PINMUX_GPIO(GPIO_PTQ3, PTQ3_DATA),
+       PINMUX_GPIO(GPIO_PTQ2, PTQ2_DATA),
+       PINMUX_GPIO(GPIO_PTQ1, PTQ1_DATA),
+       PINMUX_GPIO(GPIO_PTQ0, PTQ0_DATA),
+
+       /* PTR */
+       PINMUX_GPIO(GPIO_PTR7, PTR7_DATA),
+       PINMUX_GPIO(GPIO_PTR6, PTR6_DATA),
+       PINMUX_GPIO(GPIO_PTR5, PTR5_DATA),
+       PINMUX_GPIO(GPIO_PTR4, PTR4_DATA),
+       PINMUX_GPIO(GPIO_PTR3, PTR3_DATA),
+       PINMUX_GPIO(GPIO_PTR2, PTR2_DATA),
+       PINMUX_GPIO(GPIO_PTR1, PTR1_DATA),
+       PINMUX_GPIO(GPIO_PTR0, PTR0_DATA),
+
+       /* PTS */
+       PINMUX_GPIO(GPIO_PTS7, PTS7_DATA),
+       PINMUX_GPIO(GPIO_PTS6, PTS6_DATA),
+       PINMUX_GPIO(GPIO_PTS5, PTS5_DATA),
+       PINMUX_GPIO(GPIO_PTS4, PTS4_DATA),
+       PINMUX_GPIO(GPIO_PTS3, PTS3_DATA),
+       PINMUX_GPIO(GPIO_PTS2, PTS2_DATA),
+       PINMUX_GPIO(GPIO_PTS1, PTS1_DATA),
+       PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
+
+       /* PTT */
+       PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
+       PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
+       PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
+       PINMUX_GPIO(GPIO_PTT2, PTT2_DATA),
+       PINMUX_GPIO(GPIO_PTT1, PTT1_DATA),
+       PINMUX_GPIO(GPIO_PTT0, PTT0_DATA),
+
+       /* PTU */
+       PINMUX_GPIO(GPIO_PTU5, PTU5_DATA),
+       PINMUX_GPIO(GPIO_PTU4, PTU4_DATA),
+       PINMUX_GPIO(GPIO_PTU3, PTU3_DATA),
+       PINMUX_GPIO(GPIO_PTU2, PTU2_DATA),
+       PINMUX_GPIO(GPIO_PTU1, PTU1_DATA),
+       PINMUX_GPIO(GPIO_PTU0, PTU0_DATA),
+
+       /* PTV */
+       PINMUX_GPIO(GPIO_PTV7, PTV7_DATA),
+       PINMUX_GPIO(GPIO_PTV6, PTV6_DATA),
+       PINMUX_GPIO(GPIO_PTV5, PTV5_DATA),
+       PINMUX_GPIO(GPIO_PTV4, PTV4_DATA),
+       PINMUX_GPIO(GPIO_PTV3, PTV3_DATA),
+       PINMUX_GPIO(GPIO_PTV2, PTV2_DATA),
+       PINMUX_GPIO(GPIO_PTV1, PTV1_DATA),
+       PINMUX_GPIO(GPIO_PTV0, PTV0_DATA),
+
+       /* PTW */
+       PINMUX_GPIO(GPIO_PTW7, PTW7_DATA),
+       PINMUX_GPIO(GPIO_PTW6, PTW6_DATA),
+       PINMUX_GPIO(GPIO_PTW5, PTW5_DATA),
+       PINMUX_GPIO(GPIO_PTW4, PTW4_DATA),
+       PINMUX_GPIO(GPIO_PTW3, PTW3_DATA),
+       PINMUX_GPIO(GPIO_PTW2, PTW2_DATA),
+       PINMUX_GPIO(GPIO_PTW1, PTW1_DATA),
+       PINMUX_GPIO(GPIO_PTW0, PTW0_DATA),
+
+       /* PTX */
+       PINMUX_GPIO(GPIO_PTX7, PTX7_DATA),
+       PINMUX_GPIO(GPIO_PTX6, PTX6_DATA),
+       PINMUX_GPIO(GPIO_PTX5, PTX5_DATA),
+       PINMUX_GPIO(GPIO_PTX4, PTX4_DATA),
+       PINMUX_GPIO(GPIO_PTX3, PTX3_DATA),
+       PINMUX_GPIO(GPIO_PTX2, PTX2_DATA),
+       PINMUX_GPIO(GPIO_PTX1, PTX1_DATA),
+       PINMUX_GPIO(GPIO_PTX0, PTX0_DATA),
+
+       /* PTY */
+       PINMUX_GPIO(GPIO_PTY7, PTY7_DATA),
+       PINMUX_GPIO(GPIO_PTY6, PTY6_DATA),
+       PINMUX_GPIO(GPIO_PTY5, PTY5_DATA),
+       PINMUX_GPIO(GPIO_PTY4, PTY4_DATA),
+       PINMUX_GPIO(GPIO_PTY3, PTY3_DATA),
+       PINMUX_GPIO(GPIO_PTY2, PTY2_DATA),
+       PINMUX_GPIO(GPIO_PTY1, PTY1_DATA),
+       PINMUX_GPIO(GPIO_PTY0, PTY0_DATA),
+
+       /* PTZ */
+       PINMUX_GPIO(GPIO_PTZ7, PTZ7_DATA),
+       PINMUX_GPIO(GPIO_PTZ6, PTZ6_DATA),
+       PINMUX_GPIO(GPIO_PTZ5, PTZ5_DATA),
+       PINMUX_GPIO(GPIO_PTZ4, PTZ4_DATA),
+       PINMUX_GPIO(GPIO_PTZ3, PTZ3_DATA),
+       PINMUX_GPIO(GPIO_PTZ2, PTZ2_DATA),
+       PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
+       PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
+
+       /* SCIF0 */
+       PINMUX_GPIO(GPIO_FN_SCIF0_PTT_TXD, SCIF0_PTT_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_PTT_RXD, SCIF0_PTT_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_PTT_SCK, SCIF0_PTT_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_PTU_TXD, SCIF0_PTU_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_PTU_RXD, SCIF0_PTU_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF0_PTU_SCK, SCIF0_PTU_SCK_MARK),
+
+       /* SCIF1 */
+       PINMUX_GPIO(GPIO_FN_SCIF1_PTS_TXD, SCIF1_PTS_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_PTS_RXD, SCIF1_PTS_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_PTS_SCK, SCIF1_PTS_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_PTV_TXD, SCIF1_PTV_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_PTV_RXD, SCIF1_PTV_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF1_PTV_SCK, SCIF1_PTV_SCK_MARK),
+
+       /* SCIF2 */
+       PINMUX_GPIO(GPIO_FN_SCIF2_PTT_TXD, SCIF2_PTT_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_PTT_RXD, SCIF2_PTT_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_PTT_SCK, SCIF2_PTT_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_PTU_TXD, SCIF2_PTU_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_PTU_RXD, SCIF2_PTU_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF2_PTU_SCK, SCIF2_PTU_SCK_MARK),
+
+       /* SCIF3 */
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTS_TXD, SCIF3_PTS_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTS_RXD, SCIF3_PTS_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTS_SCK, SCIF3_PTS_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTS_RTS, SCIF3_PTS_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTS_CTS, SCIF3_PTS_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTV_TXD, SCIF3_PTV_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTV_RXD, SCIF3_PTV_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTV_SCK, SCIF3_PTV_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTV_RTS, SCIF3_PTV_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF3_PTV_CTS, SCIF3_PTV_CTS_MARK),
+
+       /* SCIF4 */
+       PINMUX_GPIO(GPIO_FN_SCIF4_PTE_TXD, SCIF4_PTE_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF4_PTE_RXD, SCIF4_PTE_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF4_PTE_SCK, SCIF4_PTE_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF4_PTN_TXD, SCIF4_PTN_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF4_PTN_RXD, SCIF4_PTN_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF4_PTN_SCK, SCIF4_PTN_SCK_MARK),
+
+       /* SCIF5 */
+       PINMUX_GPIO(GPIO_FN_SCIF5_PTE_TXD, SCIF5_PTE_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF5_PTE_RXD, SCIF5_PTE_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF5_PTE_SCK, SCIF5_PTE_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF5_PTN_TXD, SCIF5_PTN_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF5_PTN_RXD, SCIF5_PTN_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_SCIF5_PTN_SCK, SCIF5_PTN_SCK_MARK),
+
+       /* CEU */
+       PINMUX_GPIO(GPIO_FN_VIO_D15, VIO_D15_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D14, VIO_D14_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D13, VIO_D13_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D12, VIO_D12_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D11, VIO_D11_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D10, VIO_D10_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D9, VIO_D9_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D8, VIO_D8_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D7, VIO_D7_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D6, VIO_D6_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D5, VIO_D5_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D4, VIO_D4_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D3, VIO_D3_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D2, VIO_D2_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D1, VIO_D1_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_D0, VIO_D0_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_CLK1, VIO_CLK1_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_VD1, VIO_VD1_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_HD1, VIO_HD1_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_FLD, VIO_FLD_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_CKO, VIO_CKO_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_VD2, VIO_VD2_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_HD2, VIO_HD2_MARK),
+       PINMUX_GPIO(GPIO_FN_VIO_CLK2, VIO_CLK2_MARK),
+
+       /* LCDC */
+       PINMUX_GPIO(GPIO_FN_LCDD23, LCDD23_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD22, LCDD22_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD21, LCDD21_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD20, LCDD20_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD19, LCDD19_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD18, LCDD18_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD17, LCDD17_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD16, LCDD16_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD15, LCDD15_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD14, LCDD14_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD13, LCDD13_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD12, LCDD12_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD11, LCDD11_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD10, LCDD10_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD9, LCDD9_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD8, LCDD8_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD7, LCDD7_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD6, LCDD6_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD5, LCDD5_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD4, LCDD4_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD3, LCDD3_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD2, LCDD2_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD1, LCDD1_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDD0, LCDD0_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDLCLK_PTR, LCDLCLK_PTR_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDLCLK_PTW, LCDLCLK_PTW_MARK),
+       /* Main LCD */
+       PINMUX_GPIO(GPIO_FN_LCDDON, LCDDON_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVCPWC, LCDVCPWC_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVEPWC, LCDVEPWC_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDVSYN, LCDVSYN_MARK),
+       /* Main LCD - RGB Mode */
+       PINMUX_GPIO(GPIO_FN_LCDDCK, LCDDCK_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDHSYN, LCDHSYN_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDDISP, LCDDISP_MARK),
+       /* Main LCD - SYS Mode */
+       PINMUX_GPIO(GPIO_FN_LCDRS, LCDRS_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDCS, LCDCS_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDWR, LCDWR_MARK),
+       PINMUX_GPIO(GPIO_FN_LCDRD, LCDRD_MARK),
+
+       /* IRQ */
+       PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3, IRQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ4, IRQ4_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
+
+       /* AUD */
+       PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA3, AUDATA3_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA2, AUDATA2_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA1, AUDATA1_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDATA0, AUDATA0_MARK),
+
+       /* SDHI0 (PTD) */
+       PINMUX_GPIO(GPIO_FN_SDHI0CD_PTD, SDHI0CD_PTD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0WP_PTD, SDHI0WP_PTD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D3_PTD, SDHI0D3_PTD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D2_PTD, SDHI0D2_PTD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D1_PTD, SDHI0D1_PTD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D0_PTD, SDHI0D0_PTD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0CMD_PTD, SDHI0CMD_PTD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0CLK_PTD, SDHI0CLK_PTD_MARK),
+
+       /* SDHI0 (PTS) */
+       PINMUX_GPIO(GPIO_FN_SDHI0CD_PTS, SDHI0CD_PTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0WP_PTS, SDHI0WP_PTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D3_PTS, SDHI0D3_PTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D2_PTS, SDHI0D2_PTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D1_PTS, SDHI0D1_PTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0D0_PTS, SDHI0D0_PTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0CMD_PTS, SDHI0CMD_PTS_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI0CLK_PTS, SDHI0CLK_PTS_MARK),
+
+       /* SDHI1 */
+       PINMUX_GPIO(GPIO_FN_SDHI1CD, SDHI1CD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI1WP, SDHI1WP_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI1D3, SDHI1D3_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI1D2, SDHI1D2_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI1D1, SDHI1D1_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI1D0, SDHI1D0_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI1CMD, SDHI1CMD_MARK),
+       PINMUX_GPIO(GPIO_FN_SDHI1CLK, SDHI1CLK_MARK),
+
+       /* SIUA */
+       PINMUX_GPIO(GPIO_FN_SIUAFCK, SIUAFCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAILR, SIUAILR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAIBT, SIUAIBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAISLD, SIUAISLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAOLR, SIUAOLR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAOBT, SIUAOBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAOSLD, SIUAOSLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAMCK, SIUAMCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUAISPD, SIUAISPD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUOSPD, SIUAOSPD_MARK),
+
+       /* SIUB */
+       PINMUX_GPIO(GPIO_FN_SIUBFCK, SIUBFCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBILR, SIUBILR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBIBT, SIUBIBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBISLD, SIUBISLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBOLR, SIUBOLR_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBOBT, SIUBOBT_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBOSLD, SIUBOSLD_MARK),
+       PINMUX_GPIO(GPIO_FN_SIUBMCK, SIUBMCK_MARK),
+
+       /* IRDA */
+       PINMUX_GPIO(GPIO_FN_IRDA_IN, IRDA_IN_MARK),
+       PINMUX_GPIO(GPIO_FN_IRDA_OUT, IRDA_OUT_MARK),
+
+       /* VOU */
+       PINMUX_GPIO(GPIO_FN_DV_CLKI, DV_CLKI_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_CLK, DV_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_HSYNC, DV_HSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_VSYNC, DV_VSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D15, DV_D15_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D14, DV_D14_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D13, DV_D13_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D12, DV_D12_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D11, DV_D11_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D10, DV_D10_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D9, DV_D9_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D8, DV_D8_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D7, DV_D7_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D6, DV_D6_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D5, DV_D5_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D4, DV_D4_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D3, DV_D3_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D2, DV_D2_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D1, DV_D1_MARK),
+       PINMUX_GPIO(GPIO_FN_DV_D0, DV_D0_MARK),
+
+       /* KEYSC */
+       PINMUX_GPIO(GPIO_FN_KEYIN0, KEYIN0_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN1, KEYIN1_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN2, KEYIN2_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN3, KEYIN3_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYIN4, KEYIN4_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT0, KEYOUT0_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT1, KEYOUT1_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT2, KEYOUT2_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT3, KEYOUT3_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT4_IN6, KEYOUT4_IN6_MARK),
+       PINMUX_GPIO(GPIO_FN_KEYOUT5_IN5, KEYOUT5_IN5_MARK),
+
+       /* MSIOF0 (PTF) */
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_TXD, MSIOF0_PTF_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_RXD, MSIOF0_PTF_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_MCK, MSIOF0_PTF_MCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_TSYNC, MSIOF0_PTF_TSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_TSCK, MSIOF0_PTF_TSCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_RSYNC, MSIOF0_PTF_RSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_RSCK, MSIOF0_PTF_RSCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_SS1, MSIOF0_PTF_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTF_SS2, MSIOF0_PTF_SS2_MARK),
+
+       /* MSIOF0 (PTT+PTX) */
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_TXD, MSIOF0_PTT_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_RXD, MSIOF0_PTT_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTX_MCK, MSIOF0_PTX_MCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_TSYNC, MSIOF0_PTT_TSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_TSCK, MSIOF0_PTT_TSCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_RSYNC, MSIOF0_PTT_RSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_RSCK, MSIOF0_PTT_RSCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_SS1, MSIOF0_PTT_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF0_PTT_SS2, MSIOF0_PTT_SS2_MARK),
+
+       /* MSIOF1 */
+       PINMUX_GPIO(GPIO_FN_MSIOF1_TXD, MSIOF1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_RXD, MSIOF1_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_MCK, MSIOF1_MCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_TSYNC, MSIOF1_TSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_TSCK, MSIOF1_TSCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_RSYNC, MSIOF1_RSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_RSCK, MSIOF1_RSCK_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_SS1, MSIOF1_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_MSIOF1_SS2, MSIOF1_SS2_MARK),
+
+       /* TSIF */
+       PINMUX_GPIO(GPIO_FN_TS0_SDAT, TS0_SDAT_MARK),
+       PINMUX_GPIO(GPIO_FN_TS0_SCK, TS0_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_TS0_SDEN, TS0_SDEN_MARK),
+       PINMUX_GPIO(GPIO_FN_TS0_SPSYNC, TS0_SPSYNC_MARK),
+
+       /* FLCTL */
+       PINMUX_GPIO(GPIO_FN_FCE, FCE_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF7, NAF7_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF6, NAF6_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF5, NAF5_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF4, NAF4_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF3, NAF3_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF2, NAF2_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF1, NAF1_MARK),
+       PINMUX_GPIO(GPIO_FN_NAF0, NAF0_MARK),
+       PINMUX_GPIO(GPIO_FN_FCDE, FCDE_MARK),
+       PINMUX_GPIO(GPIO_FN_FOE, FOE_MARK),
+       PINMUX_GPIO(GPIO_FN_FSC, FSC_MARK),
+       PINMUX_GPIO(GPIO_FN_FWE, FWE_MARK),
+       PINMUX_GPIO(GPIO_FN_FRB, FRB_MARK),
+
+       /* DMAC */
+       PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+
+       /* ADC */
+       PINMUX_GPIO(GPIO_FN_AN3, AN3_MARK),
+       PINMUX_GPIO(GPIO_FN_AN2, AN2_MARK),
+       PINMUX_GPIO(GPIO_FN_AN1, AN1_MARK),
+       PINMUX_GPIO(GPIO_FN_AN0, AN0_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG, ADTRG_MARK),
+
+       /* CPG */
+       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
+       PINMUX_GPIO(GPIO_FN_PDSTATUS, PDSTATUS_MARK),
+
+       /* TPU */
+       PINMUX_GPIO(GPIO_FN_TPUTO0, TPUTO0_MARK),
+       PINMUX_GPIO(GPIO_FN_TPUTO1, TPUTO1_MARK),
+       PINMUX_GPIO(GPIO_FN_TPUTO2, TPUTO2_MARK),
+       PINMUX_GPIO(GPIO_FN_TPUTO3, TPUTO3_MARK),
+
+       /* BSC */
+       PINMUX_GPIO(GPIO_FN_D31, D31_MARK),
+       PINMUX_GPIO(GPIO_FN_D30, D30_MARK),
+       PINMUX_GPIO(GPIO_FN_D29, D29_MARK),
+       PINMUX_GPIO(GPIO_FN_D28, D28_MARK),
+       PINMUX_GPIO(GPIO_FN_D27, D27_MARK),
+       PINMUX_GPIO(GPIO_FN_D26, D26_MARK),
+       PINMUX_GPIO(GPIO_FN_D25, D25_MARK),
+       PINMUX_GPIO(GPIO_FN_D24, D24_MARK),
+       PINMUX_GPIO(GPIO_FN_D23, D23_MARK),
+       PINMUX_GPIO(GPIO_FN_D22, D22_MARK),
+       PINMUX_GPIO(GPIO_FN_D21, D21_MARK),
+       PINMUX_GPIO(GPIO_FN_D20, D20_MARK),
+       PINMUX_GPIO(GPIO_FN_D19, D19_MARK),
+       PINMUX_GPIO(GPIO_FN_D18, D18_MARK),
+       PINMUX_GPIO(GPIO_FN_D17, D17_MARK),
+       PINMUX_GPIO(GPIO_FN_D16, D16_MARK),
+       PINMUX_GPIO(GPIO_FN_IOIS16, IOIS16_MARK),
+       PINMUX_GPIO(GPIO_FN_WAIT, WAIT_MARK),
+       PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
+       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
+       PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
+       PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6B_CE1B, CS6B_CE1B_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6A_CE2B, CS6A_CE2B_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5B_CE1A, CS5B_CE1A_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5A_CE2A, CS5A_CE2A_MARK),
+       PINMUX_GPIO(GPIO_FN_WE3_ICIOWR, WE3_ICIOWR_MARK),
+       PINMUX_GPIO(GPIO_FN_WE2_ICIORD, WE2_ICIORD_MARK),
+
+       /* ATAPI */
+       PINMUX_GPIO(GPIO_FN_IDED15, IDED15_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED14, IDED14_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED13, IDED13_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED12, IDED12_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED11, IDED11_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED10, IDED10_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED9, IDED9_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED8, IDED8_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED7, IDED7_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED6, IDED6_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED5, IDED5_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED4, IDED4_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED3, IDED3_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED2, IDED2_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED1, IDED1_MARK),
+       PINMUX_GPIO(GPIO_FN_IDED0, IDED0_MARK),
+       PINMUX_GPIO(GPIO_FN_DIRECTION, DIRECTION_MARK),
+       PINMUX_GPIO(GPIO_FN_EXBUF_ENB, EXBUF_ENB_MARK),
+       PINMUX_GPIO(GPIO_FN_IDERST, IDERST_MARK),
+       PINMUX_GPIO(GPIO_FN_IODACK, IODACK_MARK),
+       PINMUX_GPIO(GPIO_FN_IODREQ, IODREQ_MARK),
+       PINMUX_GPIO(GPIO_FN_IDEIORDY, IDEIORDY_MARK),
+       PINMUX_GPIO(GPIO_FN_IDEINT, IDEINT_MARK),
+       PINMUX_GPIO(GPIO_FN_IDEIOWR, IDEIOWR_MARK),
+       PINMUX_GPIO(GPIO_FN_IDEIORD, IDEIORD_MARK),
+       PINMUX_GPIO(GPIO_FN_IDECS1, IDECS1_MARK),
+       PINMUX_GPIO(GPIO_FN_IDECS0, IDECS0_MARK),
+       PINMUX_GPIO(GPIO_FN_IDEA2, IDEA2_MARK),
+       PINMUX_GPIO(GPIO_FN_IDEA1, IDEA1_MARK),
+       PINMUX_GPIO(GPIO_FN_IDEA0, IDEA0_MARK),
+ };
+
+static struct pinmux_cfg_reg pinmux_config_regs[] = {
+       { PINMUX_CFG_REG("PACR", 0xa4050100, 16, 2) {
+               PTA7_FN, PTA7_OUT, 0, PTA7_IN,
+               PTA6_FN, PTA6_OUT, 0, PTA6_IN,
+               PTA5_FN, PTA5_OUT, 0, PTA5_IN,
+               PTA4_FN, PTA4_OUT, PTA4_IN_PU, PTA4_IN,
+               PTA3_FN, PTA3_OUT, PTA3_IN_PU, PTA3_IN,
+               PTA2_FN, PTA2_OUT, PTA2_IN_PU, PTA2_IN,
+               PTA1_FN, PTA1_OUT, PTA1_IN_PU, PTA1_IN,
+               PTA0_FN, PTA0_OUT, PTA0_IN_PU, PTA0_IN }
+       },
+       { PINMUX_CFG_REG("PBCR", 0xa4050102, 16, 2) {
+               PTB7_FN, PTB7_OUT, 0, PTB7_IN,
+               PTB6_FN, PTB6_OUT, 0, PTB6_IN,
+               PTB5_FN, PTB5_OUT, 0, PTB5_IN,
+               PTB4_FN, PTB4_OUT, 0, PTB4_IN,
+               PTB3_FN, PTB3_OUT, 0, PTB3_IN,
+               PTB2_FN, PTB2_OUT, PTB2_IN_PU, PTB2_IN,
+               PTB1_FN, PTB1_OUT, PTB1_IN_PU, PTB1_IN,
+               PTB0_FN, PTB0_OUT, 0, PTB0_IN }
+       },
+       { PINMUX_CFG_REG("PCCR", 0xa4050104, 16, 2) {
+               PTC7_FN, PTC7_OUT, 0, PTC7_IN,
+               PTC6_FN, PTC6_OUT, 0, PTC6_IN,
+               PTC5_FN, PTC5_OUT, 0, PTC5_IN,
+               PTC4_FN, PTC4_OUT, 0, PTC4_IN,
+               PTC3_FN, PTC3_OUT, 0, PTC3_IN,
+               PTC2_FN, PTC2_OUT, 0, PTC2_IN,
+               PTC1_FN, PTC1_OUT, 0, PTC1_IN,
+               PTC0_FN, PTC0_OUT, 0, PTC0_IN }
+       },
+       { PINMUX_CFG_REG("PDCR", 0xa4050106, 16, 2) {
+               PTD7_FN, PTD7_OUT, 0, PTD7_IN,
+               PTD6_FN, PTD6_OUT, 0, PTD6_IN,
+               PTD5_FN, PTD5_OUT, 0, PTD5_IN,
+               PTD4_FN, PTD4_OUT, 0, PTD4_IN,
+               PTD3_FN, PTD3_OUT, 0, PTD3_IN,
+               PTD2_FN, PTD2_OUT, 0, PTD2_IN,
+               PTD1_FN, PTD1_OUT, 0, PTD1_IN,
+               PTD0_FN, PTD0_OUT, 0, PTD0_IN }
+       },
+       { PINMUX_CFG_REG("PECR", 0xa4050108, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTE5_FN, PTE5_OUT, 0, PTE5_IN,
+               PTE4_FN, PTE4_OUT, 0, PTE4_IN,
+               PTE3_FN, PTE3_OUT, 0, PTE3_IN,
+               PTE2_FN, PTE2_OUT, 0, PTE2_IN,
+               PTE1_FN, PTE1_OUT, 0, PTE1_IN,
+               PTE0_FN, PTE0_OUT, 0, PTE0_IN }
+       },
+       { PINMUX_CFG_REG("PFCR", 0xa405010a, 16, 2) {
+               PTF7_FN, PTF7_OUT, 0, PTF7_IN,
+               PTF6_FN, PTF6_OUT, 0, PTF6_IN,
+               PTF5_FN, PTF5_OUT, 0, PTF5_IN,
+               PTF4_FN, PTF4_OUT, 0, PTF4_IN,
+               PTF3_FN, PTF3_OUT, 0, PTF3_IN,
+               PTF2_FN, PTF2_OUT, 0, PTF2_IN,
+               PTF1_FN, PTF1_OUT, 0, PTF1_IN,
+               PTF0_FN, PTF0_OUT, 0, PTF0_IN }
+       },
+       { PINMUX_CFG_REG("PGCR", 0xa405010c, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTG5_FN, PTG5_OUT, 0, 0,
+               PTG4_FN, PTG4_OUT, 0, 0,
+               PTG3_FN, PTG3_OUT, 0, 0,
+               PTG2_FN, PTG2_OUT, 0, 0,
+               PTG1_FN, PTG1_OUT, 0, 0,
+               PTG0_FN, PTG0_OUT, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PHCR", 0xa405010e, 16, 2) {
+               PTH7_FN, PTH7_OUT, 0, PTH7_IN,
+               PTH6_FN, PTH6_OUT, 0, PTH6_IN,
+               PTH5_FN, PTH5_OUT, 0, PTH5_IN,
+               PTH4_FN, PTH4_OUT, 0, PTH4_IN,
+               PTH3_FN, PTH3_OUT, 0, PTH3_IN,
+               PTH2_FN, PTH2_OUT, 0, PTH2_IN,
+               PTH1_FN, PTH1_OUT, 0, PTH1_IN,
+               PTH0_FN, PTH0_OUT, 0, PTH0_IN }
+       },
+       { PINMUX_CFG_REG("PJCR", 0xa4050110, 16, 2) {
+               PTJ7_FN, PTJ7_OUT, 0, 0,
+               0, 0, 0, 0,
+               PTJ5_FN, PTJ5_OUT, 0, 0,
+               0, 0, 0, 0,
+               PTJ3_FN, PTJ3_OUT, 0, PTJ3_IN,
+               PTJ2_FN, PTJ2_OUT, 0, PTJ2_IN,
+               PTJ1_FN, PTJ1_OUT, 0, PTJ1_IN,
+               PTJ0_FN, PTJ0_OUT, 0, PTJ0_IN }
+       },
+       { PINMUX_CFG_REG("PKCR", 0xa4050112, 16, 2) {
+               PTK7_FN, PTK7_OUT, 0, PTK7_IN,
+               PTK6_FN, PTK6_OUT, 0, PTK6_IN,
+               PTK5_FN, PTK5_OUT, 0, PTK5_IN,
+               PTK4_FN, PTK4_OUT, 0, PTK4_IN,
+               PTK3_FN, PTK3_OUT, 0, PTK3_IN,
+               PTK2_FN, PTK2_OUT, 0, PTK2_IN,
+               PTK1_FN, PTK1_OUT, 0, PTK1_IN,
+               PTK0_FN, PTK0_OUT, 0, PTK0_IN }
+       },
+       { PINMUX_CFG_REG("PLCR", 0xa4050114, 16, 2) {
+               PTL7_FN, PTL7_OUT, 0, PTL7_IN,
+               PTL6_FN, PTL6_OUT, 0, PTL6_IN,
+               PTL5_FN, PTL5_OUT, 0, PTL5_IN,
+               PTL4_FN, PTL4_OUT, 0, PTL4_IN,
+               PTL3_FN, PTL3_OUT, 0, PTL3_IN,
+               PTL2_FN, PTL2_OUT, 0, PTL2_IN,
+               PTL1_FN, PTL1_OUT, 0, PTL1_IN,
+               PTL0_FN, PTL0_OUT, 0, PTL0_IN }
+       },
+       { PINMUX_CFG_REG("PMCR", 0xa4050116, 16, 2) {
+               PTM7_FN, PTM7_OUT, 0, PTM7_IN,
+               PTM6_FN, PTM6_OUT, 0, PTM6_IN,
+               PTM5_FN, PTM5_OUT, 0, PTM5_IN,
+               PTM4_FN, PTM4_OUT, 0, PTM4_IN,
+               PTM3_FN, PTM3_OUT, 0, PTM3_IN,
+               PTM2_FN, PTM2_OUT, 0, PTM2_IN,
+               PTM1_FN, PTM1_OUT, 0, PTM1_IN,
+               PTM0_FN, PTM0_OUT, 0, PTM0_IN }
+       },
+       { PINMUX_CFG_REG("PNCR", 0xa4050118, 16, 2) {
+               PTN7_FN, PTN7_OUT, 0, PTN7_IN,
+               PTN6_FN, PTN6_OUT, 0, PTN6_IN,
+               PTN5_FN, PTN5_OUT, 0, PTN5_IN,
+               PTN4_FN, PTN4_OUT, 0, PTN4_IN,
+               PTN3_FN, PTN3_OUT, 0, PTN3_IN,
+               PTN2_FN, PTN2_OUT, 0, PTN2_IN,
+               PTN1_FN, PTN1_OUT, 0, PTN1_IN,
+               PTN0_FN, PTN0_OUT, 0, PTN0_IN }
+       },
+       { PINMUX_CFG_REG("PQCR", 0xa405011a, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTQ3_FN, 0, 0, PTQ3_IN,
+               PTQ2_FN, 0, 0, PTQ2_IN,
+               PTQ1_FN, 0, 0, PTQ1_IN,
+               PTQ0_FN, 0, 0, PTQ0_IN }
+       },
+       { PINMUX_CFG_REG("PRCR", 0xa405011c, 16, 2) {
+               PTR7_FN, PTR7_OUT, 0, PTR7_IN,
+               PTR6_FN, PTR6_OUT, 0, PTR6_IN,
+               PTR5_FN, PTR5_OUT, 0, PTR5_IN,
+               PTR4_FN, PTR4_OUT, 0, PTR4_IN,
+               PTR3_FN, 0, 0, PTR3_IN,
+               PTR2_FN, 0, PTR2_IN_PU, PTR2_IN,
+               PTR1_FN, PTR1_OUT, 0, PTR1_IN,
+               PTR0_FN, PTR0_OUT, 0, PTR0_IN }
+       },
+       { PINMUX_CFG_REG("PSCR", 0xa405011e, 16, 2) {
+               PTS7_FN, PTS7_OUT, 0, PTS7_IN,
+               PTS6_FN, PTS6_OUT, 0, PTS6_IN,
+               PTS5_FN, PTS5_OUT, 0, PTS5_IN,
+               PTS4_FN, PTS4_OUT, 0, PTS4_IN,
+               PTS3_FN, PTS3_OUT, 0, PTS3_IN,
+               PTS2_FN, PTS2_OUT, 0, PTS2_IN,
+               PTS1_FN, PTS1_OUT, 0, PTS1_IN,
+               PTS0_FN, PTS0_OUT, 0, PTS0_IN }
+       },
+       { PINMUX_CFG_REG("PTCR", 0xa4050140, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTT5_FN, PTT5_OUT, 0, PTT5_IN,
+               PTT4_FN, PTT4_OUT, 0, PTT4_IN,
+               PTT3_FN, PTT3_OUT, 0, PTT3_IN,
+               PTT2_FN, PTT2_OUT, 0, PTT2_IN,
+               PTT1_FN, PTT1_OUT, 0, PTT1_IN,
+               PTT0_FN, PTT0_OUT, 0, PTT0_IN }
+       },
+       { PINMUX_CFG_REG("PUCR", 0xa4050142, 16, 2) {
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PTU5_FN, PTU5_OUT, 0, PTU5_IN,
+               PTU4_FN, PTU4_OUT, 0, PTU4_IN,
+               PTU3_FN, PTU3_OUT, 0, PTU3_IN,
+               PTU2_FN, PTU2_OUT, 0, PTU2_IN,
+               PTU1_FN, PTU1_OUT, 0, PTU1_IN,
+               PTU0_FN, PTU0_OUT, 0, PTU0_IN }
+       },
+       { PINMUX_CFG_REG("PVCR", 0xa4050144, 16, 2) {
+               PTV7_FN, PTV7_OUT, 0, PTV7_IN,
+               PTV6_FN, PTV6_OUT, 0, PTV6_IN,
+               PTV5_FN, PTV5_OUT, 0, PTV5_IN,
+               PTV4_FN, PTV4_OUT, 0, PTV4_IN,
+               PTV3_FN, PTV3_OUT, 0, PTV3_IN,
+               PTV2_FN, PTV2_OUT, 0, PTV2_IN,
+               PTV1_FN, PTV1_OUT, 0, PTV1_IN,
+               PTV0_FN, PTV0_OUT, 0, PTV0_IN }
+       },
+       { PINMUX_CFG_REG("PWCR", 0xa4050146, 16, 2) {
+               PTW7_FN, PTW7_OUT, 0, PTW7_IN,
+               PTW6_FN, PTW6_OUT, 0, PTW6_IN,
+               PTW5_FN, PTW5_OUT, 0, PTW5_IN,
+               PTW4_FN, PTW4_OUT, 0, PTW4_IN,
+               PTW3_FN, PTW3_OUT, 0, PTW3_IN,
+               PTW2_FN, PTW2_OUT, 0, PTW2_IN,
+               PTW1_FN, PTW1_OUT, 0, PTW1_IN,
+               PTW0_FN, PTW0_OUT, 0, PTW0_IN }
+       },
+       { PINMUX_CFG_REG("PXCR", 0xa4050148, 16, 2) {
+               PTX7_FN, PTX7_OUT, 0, PTX7_IN,
+               PTX6_FN, PTX6_OUT, 0, PTX6_IN,
+               PTX5_FN, PTX5_OUT, 0, PTX5_IN,
+               PTX4_FN, PTX4_OUT, 0, PTX4_IN,
+               PTX3_FN, PTX3_OUT, 0, PTX3_IN,
+               PTX2_FN, PTX2_OUT, 0, PTX2_IN,
+               PTX1_FN, PTX1_OUT, 0, PTX1_IN,
+               PTX0_FN, PTX0_OUT, 0, PTX0_IN }
+       },
+       { PINMUX_CFG_REG("PYCR", 0xa405014a, 16, 2) {
+               PTY7_FN, PTY7_OUT, 0, PTY7_IN,
+               PTY6_FN, PTY6_OUT, 0, PTY6_IN,
+               PTY5_FN, PTY5_OUT, 0, PTY5_IN,
+               PTY4_FN, PTY4_OUT, 0, PTY4_IN,
+               PTY3_FN, PTY3_OUT, 0, PTY3_IN,
+               PTY2_FN, PTY2_OUT, 0, PTY2_IN,
+               PTY1_FN, PTY1_OUT, 0, PTY1_IN,
+               PTY0_FN, PTY0_OUT, 0, PTY0_IN }
+       },
+       { PINMUX_CFG_REG("PZCR", 0xa405014c, 16, 2) {
+               PTZ7_FN, PTZ7_OUT, 0, PTZ7_IN,
+               PTZ6_FN, PTZ6_OUT, 0, PTZ6_IN,
+               PTZ5_FN, PTZ5_OUT, 0, PTZ5_IN,
+               PTZ4_FN, PTZ4_OUT, 0, PTZ4_IN,
+               PTZ3_FN, PTZ3_OUT, 0, PTZ3_IN,
+               PTZ2_FN, PTZ2_OUT, 0, PTZ2_IN,
+               PTZ1_FN, PTZ1_OUT, 0, PTZ1_IN,
+               PTZ0_FN, PTZ0_OUT, 0, PTZ0_IN }
+       },
+       { PINMUX_CFG_REG("PSELA", 0xa405014e, 16, 2) {
+               PSA15_PSA14_FN1, PSA15_PSA14_FN2, 0, 0,
+               PSA13_PSA12_FN1, PSA13_PSA12_FN2, 0, 0,
+               PSA11_PSA10_FN1, PSA11_PSA10_FN2, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PSA5_PSA4_FN1, PSA5_PSA4_FN2, PSA5_PSA4_FN3, 0,
+               PSA3_PSA2_FN1, PSA3_PSA2_FN2, 0, 0,
+               0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PSELB", 0xa4050150, 16, 2) {
+               PSB15_PSB14_FN1, PSB15_PSB14_FN2, 0, 0,
+               PSB13_PSB12_LCDC_RGB, PSB13_PSB12_LCDC_SYS, 0, 0,
+               0, 0, 0, 0,
+               PSB9_PSB8_FN1, PSB9_PSB8_FN2, PSB9_PSB8_FN3, 0,
+               PSB7_PSB6_FN1, PSB7_PSB6_FN2, 0, 0,
+               PSB5_PSB4_FN1, PSB5_PSB4_FN2, 0, 0,
+               PSB3_PSB2_FN1, PSB3_PSB2_FN2, 0, 0,
+               0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PSELC", 0xa4050152, 16, 2) {
+               PSC15_PSC14_FN1, PSC15_PSC14_FN2, 0, 0,
+               PSC13_PSC12_FN1, PSC13_PSC12_FN2, 0, 0,
+               PSC11_PSC10_FN1, PSC11_PSC10_FN2, PSC11_PSC10_FN3, 0,
+               PSC9_PSC8_FN1, PSC9_PSC8_FN2, 0, 0,
+               PSC7_PSC6_FN1, PSC7_PSC6_FN2, PSC7_PSC6_FN3, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               0, 0, 0, 0 }
+       },
+       { PINMUX_CFG_REG("PSELD", 0xa4050154, 16, 2) {
+               PSD15_PSD14_FN1, PSD15_PSD14_FN2, 0, 0,
+               PSD13_PSD12_FN1, PSD13_PSD12_FN2, 0, 0,
+               PSD11_PSD10_FN1, PSD11_PSD10_FN2, PSD11_PSD10_FN3, 0,
+               PSD9_PSD8_FN1, PSD9_PSD8_FN2, 0, 0,
+               PSD7_PSD6_FN1, PSD7_PSD6_FN2, 0, 0,
+               PSD5_PSD4_FN1, PSD5_PSD4_FN2, 0, 0,
+               PSD3_PSD2_FN1, PSD3_PSD2_FN2, 0, 0,
+               PSD1_PSD0_FN1, PSD1_PSD0_FN2, 0, 0 }
+       },
+       {}
+};
+
+static struct pinmux_data_reg pinmux_data_regs[] = {
+       { PINMUX_DATA_REG("PADR", 0xa4050120, 8) {
+               PTA7_DATA, PTA6_DATA, PTA5_DATA, PTA4_DATA,
+               PTA3_DATA, PTA2_DATA, PTA1_DATA, PTA0_DATA }
+       },
+       { PINMUX_DATA_REG("PBDR", 0xa4050122, 8) {
+               PTB7_DATA, PTB6_DATA, PTB5_DATA, PTB4_DATA,
+               PTB3_DATA, PTB2_DATA, PTB1_DATA, PTB0_DATA }
+       },
+       { PINMUX_DATA_REG("PCDR", 0xa4050124, 8) {
+               PTC7_DATA, PTC6_DATA, PTC5_DATA, PTC4_DATA,
+               PTC3_DATA, PTC2_DATA, PTC1_DATA, PTC0_DATA }
+       },
+       { PINMUX_DATA_REG("PDDR", 0xa4050126, 8) {
+               PTD7_DATA, PTD6_DATA, PTD5_DATA, PTD4_DATA,
+               PTD3_DATA, PTD2_DATA, PTD1_DATA, PTD0_DATA }
+       },
+       { PINMUX_DATA_REG("PEDR", 0xa4050128, 8) {
+               0, 0, PTE5_DATA, PTE4_DATA,
+               PTE3_DATA, PTE2_DATA, PTE1_DATA, PTE0_DATA }
+       },
+       { PINMUX_DATA_REG("PFDR", 0xa405012a, 8) {
+               PTF7_DATA, PTF6_DATA, PTF5_DATA, PTF4_DATA,
+               PTF3_DATA, PTF2_DATA, PTF1_DATA, PTF0_DATA }
+       },
+       { PINMUX_DATA_REG("PGDR", 0xa405012c, 8) {
+               0, 0, PTG5_DATA, PTG4_DATA,
+               PTG3_DATA, PTG2_DATA, PTG1_DATA, PTG0_DATA }
+       },
+       { PINMUX_DATA_REG("PHDR", 0xa405012e, 8) {
+               PTH7_DATA, PTH6_DATA, PTH5_DATA, PTH4_DATA,
+               PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA }
+       },
+       { PINMUX_DATA_REG("PJDR", 0xa4050130, 8) {
+               PTJ7_DATA, 0, PTJ5_DATA, 0,
+               PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA }
+       },
+       { PINMUX_DATA_REG("PKDR", 0xa4050132, 8) {
+               PTK7_DATA, PTK6_DATA, PTK5_DATA, PTK4_DATA,
+               PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
+       },
+       { PINMUX_DATA_REG("PLDR", 0xa4050134, 8) {
+               PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+               PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA }
+       },
+       { PINMUX_DATA_REG("PMDR", 0xa4050136, 8) {
+               PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+               PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
+       },
+       { PINMUX_DATA_REG("PNDR", 0xa4050138, 8) {
+               PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+               PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA }
+       },
+       { PINMUX_DATA_REG("PQDR", 0xa405013a, 8) {
+               0, 0, 0, 0,
+               PTQ3_DATA, PTQ2_DATA, PTQ1_DATA, PTQ0_DATA }
+       },
+       { PINMUX_DATA_REG("PRDR", 0xa405013c, 8) {
+               PTR7_DATA, PTR6_DATA, PTR5_DATA, PTR4_DATA,
+               PTR3_DATA, PTR2_DATA, PTR1_DATA, PTR0_DATA }
+       },
+       { PINMUX_DATA_REG("PSDR", 0xa405013e, 8) {
+               PTS7_DATA, PTS6_DATA, PTS5_DATA, PTS4_DATA,
+               PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
+       },
+       { PINMUX_DATA_REG("PTDR", 0xa4050160, 8) {
+               0, 0, PTT5_DATA, PTT4_DATA,
+               PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
+       },
+       { PINMUX_DATA_REG("PUDR", 0xa4050162, 8) {
+               0, 0, PTU5_DATA, PTU4_DATA,
+               PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA }
+       },
+       { PINMUX_DATA_REG("PVDR", 0xa4050164, 8) {
+               PTV7_DATA, PTV6_DATA, PTV5_DATA, PTV4_DATA,
+               PTV3_DATA, PTV2_DATA, PTV1_DATA, PTV0_DATA }
+       },
+       { PINMUX_DATA_REG("PWDR", 0xa4050166, 8) {
+               PTW7_DATA, PTW6_DATA, PTW5_DATA, PTW4_DATA,
+               PTW3_DATA, PTW2_DATA, PTW1_DATA, PTW0_DATA }
+       },
+       { PINMUX_DATA_REG("PXDR", 0xa4050168, 8) {
+               PTX7_DATA, PTX6_DATA, PTX5_DATA, PTX4_DATA,
+               PTX3_DATA, PTX2_DATA, PTX1_DATA, PTX0_DATA }
+       },
+       { PINMUX_DATA_REG("PYDR", 0xa405016a, 8) {
+               PTY7_DATA, PTY6_DATA, PTY5_DATA, PTY4_DATA,
+               PTY3_DATA, PTY2_DATA, PTY1_DATA, PTY0_DATA }
+       },
+       { PINMUX_DATA_REG("PZDR", 0xa405016c, 8) {
+               PTZ7_DATA, PTZ6_DATA, PTZ5_DATA, PTZ4_DATA,
+               PTZ3_DATA, PTZ2_DATA, PTZ1_DATA, PTZ0_DATA }
+       },
+       { },
+};
+
+static struct pinmux_info sh7723_pinmux_info = {
+       .name = "sh7723_pfc",
+       .reserved_id = PINMUX_RESERVED,
+       .data = { PINMUX_DATA_BEGIN, PINMUX_DATA_END },
+       .input = { PINMUX_INPUT_BEGIN, PINMUX_INPUT_END },
+       .input_pu = { PINMUX_INPUT_PULLUP_BEGIN, PINMUX_INPUT_PULLUP_END },
+       .output = { PINMUX_OUTPUT_BEGIN, PINMUX_OUTPUT_END },
+       .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
+       .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
+
+       .first_gpio = GPIO_PTA7,
+       .last_gpio = GPIO_FN_IDEA0,
+
+       .gpios = pinmux_gpios,
+       .cfg_regs = pinmux_config_regs,
+       .data_regs = pinmux_data_regs,
+
+       .gpio_data = pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(pinmux_data),
+};
+
+static int __init plat_pinmux_setup(void)
+{
+       return register_pinmux(&sh7723_pinmux_info);
+}
+
+arch_initcall(plat_pinmux_setup);
index e5e06845fa4328f6d5af7def93a4b117530eff03..b8869aa20decb6f281407ab7aef1c136f486757c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SH-X3 SMP
  *
- *  Copyright (C) 2007  Paul Mundt
+ *  Copyright (C) 2007 - 2008  Paul Mundt
  *  Copyright (C) 2007  Magnus Damm
  *
  * This file is subject to the terms and conditions of the GNU General Public
 #include <linux/interrupt.h>
 #include <linux/io.h>
 
+static irqreturn_t ipi_interrupt_handler(int irq, void *arg)
+{
+       unsigned int message = (unsigned int)(long)arg;
+       unsigned int cpu = hard_smp_processor_id();
+       unsigned int offs = 4 * cpu;
+       unsigned int x;
+
+       x = ctrl_inl(0xfe410070 + offs); /* C0INITICI..CnINTICI */
+       x &= (1 << (message << 2));
+       ctrl_outl(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */
+
+       smp_message_recv(message);
+
+       return IRQ_HANDLED;
+}
+
 void __init plat_smp_setup(void)
 {
        unsigned int cpu = 0;
@@ -40,6 +56,13 @@ void __init plat_smp_setup(void)
 
 void __init plat_prepare_cpus(unsigned int max_cpus)
 {
+       int i;
+
+       BUILD_BUG_ON(SMP_MSG_NR >= 8);
+
+       for (i = 0; i < SMP_MSG_NR; i++)
+               request_irq(104 + i, ipi_interrupt_handler, IRQF_DISABLED,
+                           "IPI", (void *)(long)i);
 }
 
 #define STBCR_REG(phys_id) (0xfe400004 | (phys_id << 12))
@@ -59,7 +82,7 @@ void plat_start_cpu(unsigned int cpu, unsigned long entry_point)
                ctrl_outl(STBCR_MSTP, STBCR_REG(cpu));
 
        while (!(ctrl_inl(STBCR_REG(cpu)) & STBCR_MSTP))
-               ;
+               cpu_relax();
 
        /* Start up secondary processor by sending a reset */
        ctrl_outl(STBCR_AP_VAL, STBCR_REG(cpu));
@@ -75,46 +98,6 @@ void plat_send_ipi(unsigned int cpu, unsigned int message)
        unsigned long addr = 0xfe410070 + (cpu * 4);
 
        BUG_ON(cpu >= 4);
-       BUG_ON(message >= SMP_MSG_NR);
 
        ctrl_outl(1 << (message << 2), addr); /* C0INTICI..CnINTICI */
 }
-
-struct ipi_data {
-       void (*handler)(void *);
-       void *arg;
-       unsigned int message;
-};
-
-static irqreturn_t ipi_interrupt_handler(int irq, void *arg)
-{
-       struct ipi_data *id = arg;
-       unsigned int cpu = hard_smp_processor_id();
-       unsigned int offs = 4 * cpu;
-       unsigned int x;
-
-       x = ctrl_inl(0xfe410070 + offs); /* C0INITICI..CnINTICI */
-       x &= (1 << (id->message << 2));
-       ctrl_outl(x, 0xfe410080 + offs); /* C0INTICICLR..CnINTICICLR */
-
-       id->handler(id->arg);
-
-       return IRQ_HANDLED;
-}
-
-static struct ipi_data ipi_handlers[SMP_MSG_NR];
-
-int plat_register_ipi_handler(unsigned int message,
-                             void (*handler)(void *), void *arg)
-{
-       struct ipi_data *id = &ipi_handlers[message];
-
-       BUG_ON(SMP_MSG_NR >= 8);
-       BUG_ON(message >= SMP_MSG_NR);
-
-       id->handler = handler;
-       id->arg = arg;
-       id->message = message;
-
-       return request_irq(104 + message, ipi_interrupt_handler, 0, "IPI", id);
-}
index 8646363e9dedd2f3090781c6108c500a45791bf8..ce4602ea23a81dbf1e49a4a55e5c2bdc766d535c 100644 (file)
@@ -5,3 +5,8 @@ obj-y := entry.o probe.o switchto.o
 
 obj-$(CONFIG_SH_FPU)           += fpu.o
 obj-$(CONFIG_KALLSYMS)         += unwind.o
+
+# Primary on-chip clocks (common)
+clock-$(CONFIG_CPU_SH5)                := clock-sh5.o
+
+obj-y                  += $(clock-y)
diff --git a/arch/sh/kernel/cpu/sh5/clock-sh5.c b/arch/sh/kernel/cpu/sh5/clock-sh5.c
new file mode 100644 (file)
index 0000000..52c4924
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * arch/sh/kernel/cpu/sh5/clock-sh5.c
+ *
+ * SH-5 support for the clock framework
+ *
+ *  Copyright (C) 2008  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <asm/clock.h>
+#include <asm/io.h>
+
+static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 };
+
+/* Clock, Power and Reset Controller */
+#define        CPRC_BLOCK_OFF  0x01010000
+#define CPRC_BASE      (PHYS_PERIPHERAL_BLOCK + CPRC_BLOCK_OFF)
+
+static unsigned long cprc_base;
+
+static void master_clk_init(struct clk *clk)
+{
+       int idx = (ctrl_inl(cprc_base + 0x00) >> 6) & 0x0007;
+       clk->rate *= ifc_table[idx];
+}
+
+static struct clk_ops sh5_master_clk_ops = {
+       .init           = master_clk_init,
+};
+
+static void module_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inw(cprc_base) >> 12) & 0x0007;
+       clk->rate = clk->parent->rate / ifc_table[idx];
+}
+
+static struct clk_ops sh5_module_clk_ops = {
+       .recalc         = module_clk_recalc,
+};
+
+static void bus_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inw(cprc_base) >> 3) & 0x0007;
+       clk->rate = clk->parent->rate / ifc_table[idx];
+}
+
+static struct clk_ops sh5_bus_clk_ops = {
+       .recalc         = bus_clk_recalc,
+};
+
+static void cpu_clk_recalc(struct clk *clk)
+{
+       int idx = (ctrl_inw(cprc_base) & 0x0007);
+       clk->rate = clk->parent->rate / ifc_table[idx];
+}
+
+static struct clk_ops sh5_cpu_clk_ops = {
+       .recalc         = cpu_clk_recalc,
+};
+
+static struct clk_ops *sh5_clk_ops[] = {
+       &sh5_master_clk_ops,
+       &sh5_module_clk_ops,
+       &sh5_bus_clk_ops,
+       &sh5_cpu_clk_ops,
+};
+
+void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
+{
+       cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC");
+       BUG_ON(!cprc_base);
+
+       if (idx < ARRAY_SIZE(sh5_clk_ops))
+               *ops = sh5_clk_ops[idx];
+}
index 4a2ecbe27d8e9257c068edad01124fbd48e04c8b..95d216255565aa119640c96e0d496125546486ee 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/io.h>
 #include <asm/uaccess.h>
 
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
diff --git a/arch/sh/kernel/dump_task.c b/arch/sh/kernel/dump_task.c
deleted file mode 100644 (file)
index 1db7ce0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#include <linux/elfcore.h>
-#include <linux/sched.h>
-#include <asm/fpu.h>
-
-/*
- * Capture the user space registers if the task is not running (in user space)
- */
-int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
-{
-       struct pt_regs ptregs;
-
-       ptregs = *task_pt_regs(tsk);
-       elf_core_copy_regs(regs, &ptregs);
-
-       return 1;
-}
-
-int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpu)
-{
-       int fpvalid = 0;
-
-#if defined(CONFIG_SH_FPU)
-       fpvalid = !!tsk_used_math(tsk);
-       if (fpvalid) {
-               unlazy_fpu(tsk, task_pt_regs(tsk));
-               memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
-       }
-#endif
-
-       return fpvalid;
-}
-
index efbb4268875e3a2b1fc43de0789b08b834cf2b3e..1a5cf9dd82dee327031d8461cbbd184c43c85758 100644 (file)
@@ -371,3 +371,47 @@ syscall_exit:
 #endif
 7:     .long   do_syscall_trace_enter
 8:     .long   do_syscall_trace_leave
+
+#ifdef CONFIG_FTRACE
+       .align 2
+       .globl  _mcount
+       .type   _mcount,@function
+       .globl  mcount
+       .type   mcount,@function
+_mcount:
+mcount:
+       mov.l   r4, @-r15
+       mov.l   r5, @-r15
+       mov.l   r6, @-r15
+       mov.l   r7, @-r15
+       sts.l   pr, @-r15
+
+       mov.l   @(20,r15),r4
+       sts     pr, r5
+
+       mov.l   1f, r6
+       mov.l   ftrace_stub, r7 
+       cmp/eq  r6, r7
+       bt      skip_trace
+
+       mov.l   @r6, r6
+       jsr     @r6
+        nop
+
+skip_trace:
+
+       lds.l   @r15+, pr
+       mov.l   @r15+, r7
+       mov.l   @r15+, r6
+       mov.l   @r15+, r5
+       rts
+        mov.l  @r15+, r4
+
+       .align 2
+1:     .long   ftrace_trace_function
+
+       .globl  ftrace_stub
+ftrace_stub:
+       rts
+        nop
+#endif /* CONFIG_FTRACE */
diff --git a/arch/sh/kernel/gpio.c b/arch/sh/kernel/gpio.c
new file mode 100644 (file)
index 0000000..bb8b812
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ * Pinmuxed GPIO support for SuperH.
+ *
+ * Copyright (C) 2008 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+
+static struct pinmux_info *registered_gpio;
+
+static struct pinmux_info *gpio_controller(unsigned gpio)
+{
+       if (!registered_gpio)
+               return NULL;
+
+       if (gpio < registered_gpio->first_gpio)
+               return NULL;
+
+       if (gpio > registered_gpio->last_gpio)
+               return NULL;
+
+       return registered_gpio;
+}
+
+static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
+{
+       if (enum_id < r->begin)
+               return 0;
+
+       if (enum_id > r->end)
+               return 0;
+
+       return 1;
+}
+
+static int read_write_reg(unsigned long reg, unsigned long reg_width,
+                         unsigned long field_width, unsigned long in_pos,
+                         unsigned long value, int do_write)
+{
+       unsigned long data, mask, pos;
+
+       data = 0;
+       mask = (1 << field_width) - 1;
+       pos = reg_width - ((in_pos + 1) * field_width);
+
+#ifdef DEBUG
+       pr_info("%s, addr = %lx, value = %ld, pos = %ld, "
+               "r_width = %ld, f_width = %ld\n",
+               do_write ? "write" : "read", reg, value, pos,
+               reg_width, field_width);
+#endif
+
+       switch (reg_width) {
+       case 8:
+               data = ctrl_inb(reg);
+               break;
+       case 16:
+               data = ctrl_inw(reg);
+               break;
+       case 32:
+               data = ctrl_inl(reg);
+               break;
+       }
+
+       if (!do_write)
+               return (data >> pos) & mask;
+
+       data &= ~(mask << pos);
+       data |= value << pos;
+
+       switch (reg_width) {
+       case 8:
+               ctrl_outb(data, reg);
+               break;
+       case 16:
+               ctrl_outw(data, reg);
+               break;
+       case 32:
+               ctrl_outl(data, reg);
+               break;
+       }
+       return 0;
+}
+
+static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
+                       struct pinmux_data_reg **drp, int *bitp)
+{
+       pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
+       struct pinmux_data_reg *data_reg;
+       int k, n;
+
+       if (!enum_in_range(enum_id, &gpioc->data))
+               return -1;
+
+       k = 0;
+       while (1) {
+               data_reg = gpioc->data_regs + k;
+
+               if (!data_reg->reg_width)
+                       break;
+
+               for (n = 0; n < data_reg->reg_width; n++) {
+                       if (data_reg->enum_ids[n] == enum_id) {
+                               *drp = data_reg;
+                               *bitp = n;
+                               return 0;
+
+                       }
+               }
+               k++;
+       }
+
+       return -1;
+}
+
+static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
+                         struct pinmux_cfg_reg **crp, int *indexp,
+                         unsigned long **cntp)
+{
+       struct pinmux_cfg_reg *config_reg;
+       unsigned long r_width, f_width;
+       int k, n;
+
+       k = 0;
+       while (1) {
+               config_reg = gpioc->cfg_regs + k;
+
+               r_width = config_reg->reg_width;
+               f_width = config_reg->field_width;
+
+               if (!r_width)
+                       break;
+               for (n = 0; n < (r_width / f_width) * 1 << f_width; n++) {
+                       if (config_reg->enum_ids[n] == enum_id) {
+                               *crp = config_reg;
+                               *indexp = n;
+                               *cntp = &config_reg->cnt[n / (1 << f_width)];
+                               return 0;
+                       }
+               }
+               k++;
+       }
+
+       return -1;
+}
+
+static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
+                           int pos, pinmux_enum_t *enum_idp)
+{
+       pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
+       pinmux_enum_t *data = gpioc->gpio_data;
+       int k;
+
+       if (!enum_in_range(enum_id, &gpioc->data)) {
+               if (!enum_in_range(enum_id, &gpioc->mark)) {
+                       pr_err("non data/mark enum_id for gpio %d\n", gpio);
+                       return -1;
+               }
+       }
+
+       if (pos) {
+               *enum_idp = data[pos + 1];
+               return pos + 1;
+       }
+
+       for (k = 0; k < gpioc->gpio_data_size; k++) {
+               if (data[k] == enum_id) {
+                       *enum_idp = data[k + 1];
+                       return k + 1;
+               }
+       }
+
+       pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio);
+       return -1;
+}
+
+static int write_config_reg(struct pinmux_info *gpioc,
+                           struct pinmux_cfg_reg *crp,
+                           int index)
+{
+       unsigned long ncomb, pos, value;
+
+       ncomb = 1 << crp->field_width;
+       pos = index / ncomb;
+       value = index % ncomb;
+
+       return read_write_reg(crp->reg, crp->reg_width,
+                             crp->field_width, pos, value, 1);
+}
+
+static int check_config_reg(struct pinmux_info *gpioc,
+                           struct pinmux_cfg_reg *crp,
+                           int index)
+{
+       unsigned long ncomb, pos, value;
+
+       ncomb = 1 << crp->field_width;
+       pos = index / ncomb;
+       value = index % ncomb;
+
+       if (read_write_reg(crp->reg, crp->reg_width,
+                          crp->field_width, pos, 0, 0) == value)
+               return 0;
+
+       return -1;
+}
+
+enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
+
+int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
+                      int pinmux_type, int cfg_mode)
+{
+       struct pinmux_cfg_reg *cr = NULL;
+       pinmux_enum_t enum_id;
+       struct pinmux_range *range;
+       int in_range, pos, index;
+       unsigned long *cntp;
+
+       switch (pinmux_type) {
+
+       case PINMUX_TYPE_FUNCTION:
+               range = NULL;
+               break;
+
+       case PINMUX_TYPE_OUTPUT:
+               range = &gpioc->output;
+               break;
+
+       case PINMUX_TYPE_INPUT:
+               range = &gpioc->input;
+               break;
+
+       case PINMUX_TYPE_INPUT_PULLUP:
+               range = &gpioc->input_pu;
+               break;
+
+       case PINMUX_TYPE_INPUT_PULLDOWN:
+               range = &gpioc->input_pd;
+               break;
+
+       default:
+               goto out_err;
+       }
+
+       pos = 0;
+       enum_id = 0;
+       index = 0;
+       while (1) {
+               pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
+               if (pos <= 0)
+                       goto out_err;
+
+               if (!enum_id)
+                       break;
+
+               in_range = enum_in_range(enum_id, &gpioc->function);
+               if (!in_range && range)
+                       in_range = enum_in_range(enum_id, range);
+
+               if (!in_range)
+                       continue;
+
+               if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0)
+                       goto out_err;
+
+               switch (cfg_mode) {
+               case GPIO_CFG_DRYRUN:
+                       if (!*cntp || !check_config_reg(gpioc, cr, index))
+                               continue;
+                       break;
+
+               case GPIO_CFG_REQ:
+                       if (write_config_reg(gpioc, cr, index) != 0)
+                               goto out_err;
+                       *cntp = *cntp + 1;
+                       break;
+
+               case GPIO_CFG_FREE:
+                       *cntp = *cntp - 1;
+                       break;
+               }
+       }
+
+       return 0;
+ out_err:
+       return -1;
+}
+
+static DEFINE_SPINLOCK(gpio_lock);
+
+int __gpio_request(unsigned gpio)
+{
+       struct pinmux_info *gpioc = gpio_controller(gpio);
+       struct pinmux_data_reg *dummy;
+       unsigned long flags;
+       int i, ret, pinmux_type;
+
+       ret = -EINVAL;
+
+       if (!gpioc)
+               goto err_out;
+
+       spin_lock_irqsave(&gpio_lock, flags);
+
+       if ((gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
+               goto err_unlock;
+
+       /* setup pin function here if no data is associated with pin */
+
+       if (get_data_reg(gpioc, gpio, &dummy, &i) != 0)
+               pinmux_type = PINMUX_TYPE_FUNCTION;
+       else
+               pinmux_type = PINMUX_TYPE_GPIO;
+
+       if (pinmux_type == PINMUX_TYPE_FUNCTION) {
+               if (pinmux_config_gpio(gpioc, gpio,
+                                      pinmux_type,
+                                      GPIO_CFG_DRYRUN) != 0)
+                       goto err_unlock;
+
+               if (pinmux_config_gpio(gpioc, gpio,
+                                      pinmux_type,
+                                      GPIO_CFG_REQ) != 0)
+                       BUG();
+       }
+
+       gpioc->gpios[gpio].flags = pinmux_type;
+
+       ret = 0;
+ err_unlock:
+       spin_unlock_irqrestore(&gpio_lock, flags);
+ err_out:
+       return ret;
+}
+EXPORT_SYMBOL(__gpio_request);
+
+void gpio_free(unsigned gpio)
+{
+       struct pinmux_info *gpioc = gpio_controller(gpio);
+       unsigned long flags;
+       int pinmux_type;
+
+       if (!gpioc)
+               return;
+
+       spin_lock_irqsave(&gpio_lock, flags);
+
+       pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
+       pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
+       gpioc->gpios[gpio].flags = PINMUX_TYPE_NONE;
+
+       spin_unlock_irqrestore(&gpio_lock, flags);
+}
+EXPORT_SYMBOL(gpio_free);
+
+static int pinmux_direction(struct pinmux_info *gpioc,
+                           unsigned gpio, int new_pinmux_type)
+{
+       int ret, pinmux_type;
+
+       ret = -EINVAL;
+       pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
+
+       switch (pinmux_type) {
+       case PINMUX_TYPE_GPIO:
+               break;
+       case PINMUX_TYPE_OUTPUT:
+       case PINMUX_TYPE_INPUT:
+       case PINMUX_TYPE_INPUT_PULLUP:
+       case PINMUX_TYPE_INPUT_PULLDOWN:
+               pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
+               break;
+       default:
+               goto err_out;
+       }
+
+       if (pinmux_config_gpio(gpioc, gpio,
+                              new_pinmux_type,
+                              GPIO_CFG_DRYRUN) != 0)
+               goto err_out;
+
+       if (pinmux_config_gpio(gpioc, gpio,
+                              new_pinmux_type,
+                              GPIO_CFG_REQ) != 0)
+               BUG();
+
+       gpioc->gpios[gpio].flags = new_pinmux_type;
+
+       ret = 0;
+ err_out:
+       return ret;
+}
+
+int gpio_direction_input(unsigned gpio)
+{
+       struct pinmux_info *gpioc = gpio_controller(gpio);
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (!gpioc)
+               goto err_out;
+
+       spin_lock_irqsave(&gpio_lock, flags);
+       ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_INPUT);
+       spin_unlock_irqrestore(&gpio_lock, flags);
+ err_out:
+       return ret;
+}
+EXPORT_SYMBOL(gpio_direction_input);
+
+static int __gpio_get_set_value(struct pinmux_info *gpioc,
+                               unsigned gpio, int value,
+                               int do_write)
+{
+       struct pinmux_data_reg *dr = NULL;
+       int bit = 0;
+
+       if (get_data_reg(gpioc, gpio, &dr, &bit) != 0)
+               BUG();
+       else
+               value = read_write_reg(dr->reg, dr->reg_width,
+                                      1, bit, value, do_write);
+
+       return value;
+}
+
+int gpio_direction_output(unsigned gpio, int value)
+{
+       struct pinmux_info *gpioc = gpio_controller(gpio);
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (!gpioc)
+               goto err_out;
+
+       spin_lock_irqsave(&gpio_lock, flags);
+       __gpio_get_set_value(gpioc, gpio, value, 1);
+       ret = pinmux_direction(gpioc, gpio, PINMUX_TYPE_OUTPUT);
+       spin_unlock_irqrestore(&gpio_lock, flags);
+ err_out:
+       return ret;
+}
+EXPORT_SYMBOL(gpio_direction_output);
+
+int gpio_get_value(unsigned gpio)
+{
+       struct pinmux_info *gpioc = gpio_controller(gpio);
+       unsigned long flags;
+       int value = 0;
+
+       if (!gpioc)
+               BUG();
+       else {
+               spin_lock_irqsave(&gpio_lock, flags);
+               value = __gpio_get_set_value(gpioc, gpio, 0, 0);
+               spin_unlock_irqrestore(&gpio_lock, flags);
+       }
+
+       return value;
+}
+EXPORT_SYMBOL(gpio_get_value);
+
+void gpio_set_value(unsigned gpio, int value)
+{
+       struct pinmux_info *gpioc = gpio_controller(gpio);
+       unsigned long flags;
+
+       if (!gpioc)
+               BUG();
+       else {
+               spin_lock_irqsave(&gpio_lock, flags);
+               __gpio_get_set_value(gpioc, gpio, value, 1);
+               spin_unlock_irqrestore(&gpio_lock, flags);
+       }
+}
+EXPORT_SYMBOL(gpio_set_value);
+
+int register_pinmux(struct pinmux_info *pip)
+{
+       registered_gpio = pip;
+       pr_info("pinmux: %s handling gpio %d -> %d\n",
+               pip->name, pip->first_gpio, pip->last_gpio);
+
+       return 0;
+}
index 2b8991229900cbaf96a1f595ebb0fc91a484d00d..29cf4588fc050a996d2e62f95aa4f3ada2ad9733 100644 (file)
  * Copy data from IO memory space to "real" memory space.
  * This needs to be optimized.
  */
-void memcpy_fromio(void *to, volatile void __iomem *from, unsigned long count)
+void memcpy_fromio(void *to, const volatile void __iomem *from, unsigned long count)
 {
-       char *p = to;
+       unsigned char *p = to;
         while (count) {
                 count--;
-                *p = readb((void __iomem *)from);
+                *p = readb(from);
                 p++;
                 from++;
         }
@@ -37,10 +37,10 @@ EXPORT_SYMBOL(memcpy_fromio);
  */
 void memcpy_toio(volatile void __iomem *to, const void *from, unsigned long count)
 {
-       const char *p = from;
+       const unsigned char *p = from;
         while (count) {
                 count--;
-                writeb(*p, (void __iomem *)to);
+                writeb(*p, to);
                 p++;
                 to++;
         }
@@ -55,7 +55,7 @@ void memset_io(volatile void __iomem *dst, int c, unsigned long count)
 {
         while (count) {
                 count--;
-                writeb(c, (void __iomem *)dst);
+                writeb(c, dst);
                 dst++;
         }
 }
index db769449f5a733daf74bcff1f86ed50a3f1f0d1d..5a7f554d9ca15c64cfb135b81d921ac3b4bd2b3f 100644 (file)
 /* SH3 has a PCMCIA bug that needs a dummy read from area 6 for a
  * workaround. */
 /* I'm not sure SH7709 has this kind of bug */
-#define dummy_read()   ctrl_inb(0xba000000)
+#define dummy_read()   __raw_readb(0xba000000)
 #else
 #define dummy_read()
 #endif
 
 unsigned long generic_io_base;
 
-static inline void delay(void)
-{
-       ctrl_inw(0xa0000000);
-}
-
 u8 generic_inb(unsigned long port)
 {
-       return ctrl_inb((unsigned long __force)__ioport_map(port, 1));
+       return __raw_readb(__ioport_map(port, 1));
 }
 
 u16 generic_inw(unsigned long port)
 {
-       return ctrl_inw((unsigned long __force)__ioport_map(port, 2));
+       return __raw_readw(__ioport_map(port, 2));
 }
 
 u32 generic_inl(unsigned long port)
 {
-       return ctrl_inl((unsigned long __force)__ioport_map(port, 4));
+       return __raw_readl(__ioport_map(port, 4));
 }
 
 u8 generic_inb_p(unsigned long port)
 {
        unsigned long v = generic_inb(port);
 
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -58,7 +53,7 @@ u16 generic_inw_p(unsigned long port)
 {
        unsigned long v = generic_inw(port);
 
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -66,7 +61,7 @@ u32 generic_inl_p(unsigned long port)
 {
        unsigned long v = generic_inl(port);
 
-       delay();
+       ctrl_delay();
        return v;
 }
 
@@ -81,7 +76,7 @@ void generic_insb(unsigned long port, void *dst, unsigned long count)
        volatile u8 *port_addr;
        u8 *buf = dst;
 
-       port_addr = (volatile u8 *)__ioport_map(port, 1);
+       port_addr = (volatile u8 __force *)__ioport_map(port, 1);
        while (count--)
                *buf++ = *port_addr;
 }
@@ -91,7 +86,7 @@ void generic_insw(unsigned long port, void *dst, unsigned long count)
        volatile u16 *port_addr;
        u16 *buf = dst;
 
-       port_addr = (volatile u16 *)__ioport_map(port, 2);
+       port_addr = (volatile u16 __force *)__ioport_map(port, 2);
        while (count--)
                *buf++ = *port_addr;
 
@@ -103,7 +98,7 @@ void generic_insl(unsigned long port, void *dst, unsigned long count)
        volatile u32 *port_addr;
        u32 *buf = dst;
 
-       port_addr = (volatile u32 *)__ioport_map(port, 4);
+       port_addr = (volatile u32 __force *)__ioport_map(port, 4);
        while (count--)
                *buf++ = *port_addr;
 
@@ -112,35 +107,35 @@ void generic_insl(unsigned long port, void *dst, unsigned long count)
 
 void generic_outb(u8 b, unsigned long port)
 {
-       ctrl_outb(b, (unsigned long __force)__ioport_map(port, 1));
+       __raw_writeb(b, __ioport_map(port, 1));
 }
 
 void generic_outw(u16 b, unsigned long port)
 {
-       ctrl_outw(b, (unsigned long __force)__ioport_map(port, 2));
+       __raw_writew(b, __ioport_map(port, 2));
 }
 
 void generic_outl(u32 b, unsigned long port)
 {
-       ctrl_outl(b, (unsigned long __force)__ioport_map(port, 4));
+       __raw_writel(b, __ioport_map(port, 4));
 }
 
 void generic_outb_p(u8 b, unsigned long port)
 {
        generic_outb(b, port);
-       delay();
+       ctrl_delay();
 }
 
 void generic_outw_p(u16 b, unsigned long port)
 {
        generic_outw(b, port);
-       delay();
+       ctrl_delay();
 }
 
 void generic_outl_p(u32 b, unsigned long port)
 {
        generic_outl(b, port);
-       delay();
+       ctrl_delay();
 }
 
 /*
@@ -184,36 +179,6 @@ void generic_outsl(unsigned long port, const void *src, unsigned long count)
        dummy_read();
 }
 
-u8 generic_readb(void __iomem *addr)
-{
-       return ctrl_inb((unsigned long __force)addr);
-}
-
-u16 generic_readw(void __iomem *addr)
-{
-       return ctrl_inw((unsigned long __force)addr);
-}
-
-u32 generic_readl(void __iomem *addr)
-{
-       return ctrl_inl((unsigned long __force)addr);
-}
-
-void generic_writeb(u8 b, void __iomem *addr)
-{
-       ctrl_outb(b, (unsigned long __force)addr);
-}
-
-void generic_writew(u16 b, void __iomem *addr)
-{
-       ctrl_outw(b, (unsigned long __force)addr);
-}
-
-void generic_writel(u32 b, void __iomem *addr)
-{
-       ctrl_outl(b, (unsigned long __force)addr);
-}
-
 void __iomem *generic_ioport_map(unsigned long addr, unsigned int size)
 {
        return (void __iomem *)(addr + generic_io_base);
diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c
new file mode 100644 (file)
index 0000000..c96850b
--- /dev/null
@@ -0,0 +1,584 @@
+/*
+ * Kernel probes (kprobes) for SuperH
+ *
+ * Copyright (C) 2007 Chris Smith <chris.smith@st.com>
+ * Copyright (C) 2006 Lineo Solutions, Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#include <linux/kprobes.h>
+#include <linux/module.h>
+#include <linux/ptrace.h>
+#include <linux/preempt.h>
+#include <linux/kdebug.h>
+#include <asm/cacheflush.h>
+#include <asm/uaccess.h>
+
+DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
+DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+
+static struct kprobe saved_current_opcode;
+static struct kprobe saved_next_opcode;
+static struct kprobe saved_next_opcode2;
+
+#define OPCODE_JMP(x)  (((x) & 0xF0FF) == 0x402b)
+#define OPCODE_JSR(x)  (((x) & 0xF0FF) == 0x400b)
+#define OPCODE_BRA(x)  (((x) & 0xF000) == 0xa000)
+#define OPCODE_BRAF(x) (((x) & 0xF0FF) == 0x0023)
+#define OPCODE_BSR(x)  (((x) & 0xF000) == 0xb000)
+#define OPCODE_BSRF(x) (((x) & 0xF0FF) == 0x0003)
+
+#define OPCODE_BF_S(x) (((x) & 0xFF00) == 0x8f00)
+#define OPCODE_BT_S(x) (((x) & 0xFF00) == 0x8d00)
+
+#define OPCODE_BF(x)   (((x) & 0xFF00) == 0x8b00)
+#define OPCODE_BT(x)   (((x) & 0xFF00) == 0x8900)
+
+#define OPCODE_RTS(x)  (((x) & 0x000F) == 0x000b)
+#define OPCODE_RTE(x)  (((x) & 0xFFFF) == 0x002b)
+
+int __kprobes arch_prepare_kprobe(struct kprobe *p)
+{
+       kprobe_opcode_t opcode = *(kprobe_opcode_t *) (p->addr);
+
+       if (OPCODE_RTE(opcode))
+               return -EFAULT; /* Bad breakpoint */
+
+       p->opcode = opcode;
+
+       return 0;
+}
+
+void __kprobes arch_copy_kprobe(struct kprobe *p)
+{
+       memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
+       p->opcode = *p->addr;
+}
+
+void __kprobes arch_arm_kprobe(struct kprobe *p)
+{
+       *p->addr = BREAKPOINT_INSTRUCTION;
+       flush_icache_range((unsigned long)p->addr,
+                          (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+void __kprobes arch_disarm_kprobe(struct kprobe *p)
+{
+       *p->addr = p->opcode;
+       flush_icache_range((unsigned long)p->addr,
+                          (unsigned long)p->addr + sizeof(kprobe_opcode_t));
+}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+       if (*p->addr == BREAKPOINT_INSTRUCTION)
+               return 1;
+
+       return 0;
+}
+
+/**
+ * If an illegal slot instruction exception occurs for an address
+ * containing a kprobe, remove the probe.
+ *
+ * Returns 0 if the exception was handled successfully, 1 otherwise.
+ */
+int __kprobes kprobe_handle_illslot(unsigned long pc)
+{
+       struct kprobe *p = get_kprobe((kprobe_opcode_t *) pc + 1);
+
+       if (p != NULL) {
+               printk("Warning: removing kprobe from delay slot: 0x%.8x\n",
+                      (unsigned int)pc + 2);
+               unregister_kprobe(p);
+               return 0;
+       }
+
+       return 1;
+}
+
+void __kprobes arch_remove_kprobe(struct kprobe *p)
+{
+       if (saved_next_opcode.addr != 0x0) {
+               arch_disarm_kprobe(p);
+               arch_disarm_kprobe(&saved_next_opcode);
+               saved_next_opcode.addr = 0x0;
+               saved_next_opcode.opcode = 0x0;
+
+               if (saved_next_opcode2.addr != 0x0) {
+                       arch_disarm_kprobe(&saved_next_opcode2);
+                       saved_next_opcode2.addr = 0x0;
+                       saved_next_opcode2.opcode = 0x0;
+               }
+       }
+}
+
+static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+       kcb->prev_kprobe.kp = kprobe_running();
+       kcb->prev_kprobe.status = kcb->kprobe_status;
+}
+
+static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
+{
+       __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
+       kcb->kprobe_status = kcb->prev_kprobe.status;
+}
+
+static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
+                                        struct kprobe_ctlblk *kcb)
+{
+       __get_cpu_var(current_kprobe) = p;
+}
+
+/*
+ * Singlestep is implemented by disabling the current kprobe and setting one
+ * on the next instruction, following branches. Two probes are set if the
+ * branch is conditional.
+ */
+static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
+{
+       kprobe_opcode_t *addr = NULL;
+       saved_current_opcode.addr = (kprobe_opcode_t *) (regs->pc);
+       addr = saved_current_opcode.addr;
+
+       if (p != NULL) {
+               arch_disarm_kprobe(p);
+
+               if (OPCODE_JSR(p->opcode) || OPCODE_JMP(p->opcode)) {
+                       unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
+                       saved_next_opcode.addr =
+                           (kprobe_opcode_t *) regs->regs[reg_nr];
+               } else if (OPCODE_BRA(p->opcode) || OPCODE_BSR(p->opcode)) {
+                       unsigned long disp = (p->opcode & 0x0FFF);
+                       saved_next_opcode.addr =
+                           (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
+
+               } else if (OPCODE_BRAF(p->opcode) || OPCODE_BSRF(p->opcode)) {
+                       unsigned int reg_nr = ((p->opcode >> 8) & 0x000F);
+                       saved_next_opcode.addr =
+                           (kprobe_opcode_t *) (regs->pc + 4 +
+                                                regs->regs[reg_nr]);
+
+               } else if (OPCODE_RTS(p->opcode)) {
+                       saved_next_opcode.addr = (kprobe_opcode_t *) regs->pr;
+
+               } else if (OPCODE_BF(p->opcode) || OPCODE_BT(p->opcode)) {
+                       unsigned long disp = (p->opcode & 0x00FF);
+                       /* case 1 */
+                       saved_next_opcode.addr = p->addr + 1;
+                       /* case 2 */
+                       saved_next_opcode2.addr =
+                           (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
+                       saved_next_opcode2.opcode = *(saved_next_opcode2.addr);
+                       arch_arm_kprobe(&saved_next_opcode2);
+
+               } else if (OPCODE_BF_S(p->opcode) || OPCODE_BT_S(p->opcode)) {
+                       unsigned long disp = (p->opcode & 0x00FF);
+                       /* case 1 */
+                       saved_next_opcode.addr = p->addr + 2;
+                       /* case 2 */
+                       saved_next_opcode2.addr =
+                           (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
+                       saved_next_opcode2.opcode = *(saved_next_opcode2.addr);
+                       arch_arm_kprobe(&saved_next_opcode2);
+
+               } else {
+                       saved_next_opcode.addr = p->addr + 1;
+               }
+
+               saved_next_opcode.opcode = *(saved_next_opcode.addr);
+               arch_arm_kprobe(&saved_next_opcode);
+       }
+}
+
+/* Called with kretprobe_lock held */
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+                                     struct pt_regs *regs)
+{
+       ri->ret_addr = (kprobe_opcode_t *) regs->pr;
+
+       /* Replace the return addr with trampoline addr */
+       regs->pr = (unsigned long)kretprobe_trampoline;
+}
+
+static int __kprobes kprobe_handler(struct pt_regs *regs)
+{
+       struct kprobe *p;
+       int ret = 0;
+       kprobe_opcode_t *addr = NULL;
+       struct kprobe_ctlblk *kcb;
+
+       /*
+        * We don't want to be preempted for the entire
+        * duration of kprobe processing
+        */
+       preempt_disable();
+       kcb = get_kprobe_ctlblk();
+
+       addr = (kprobe_opcode_t *) (regs->pc);
+
+       /* Check we're not actually recursing */
+       if (kprobe_running()) {
+               p = get_kprobe(addr);
+               if (p) {
+                       if (kcb->kprobe_status == KPROBE_HIT_SS &&
+                           *p->ainsn.insn == BREAKPOINT_INSTRUCTION) {
+                               goto no_kprobe;
+                       }
+                       /* We have reentered the kprobe_handler(), since
+                        * another probe was hit while within the handler.
+                        * We here save the original kprobes variables and
+                        * just single step on the instruction of the new probe
+                        * without calling any user handlers.
+                        */
+                       save_previous_kprobe(kcb);
+                       set_current_kprobe(p, regs, kcb);
+                       kprobes_inc_nmissed_count(p);
+                       prepare_singlestep(p, regs);
+                       kcb->kprobe_status = KPROBE_REENTER;
+                       return 1;
+               } else {
+                       p = __get_cpu_var(current_kprobe);
+                       if (p->break_handler && p->break_handler(p, regs)) {
+                               goto ss_probe;
+                       }
+               }
+               goto no_kprobe;
+       }
+
+       p = get_kprobe(addr);
+       if (!p) {
+               /* Not one of ours: let kernel handle it */
+               if (*(kprobe_opcode_t *)addr != BREAKPOINT_INSTRUCTION) {
+                       /*
+                        * The breakpoint instruction was removed right
+                        * after we hit it. Another cpu has removed
+                        * either a probepoint or a debugger breakpoint
+                        * at this address. In either case, no further
+                        * handling of this interrupt is appropriate.
+                        */
+                       ret = 1;
+               }
+
+               goto no_kprobe;
+       }
+
+       set_current_kprobe(p, regs, kcb);
+       kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+       if (p->pre_handler && p->pre_handler(p, regs))
+               /* handler has already set things up, so skip ss setup */
+               return 1;
+
+ss_probe:
+       prepare_singlestep(p, regs);
+       kcb->kprobe_status = KPROBE_HIT_SS;
+       return 1;
+
+no_kprobe:
+       preempt_enable_no_resched();
+       return ret;
+}
+
+/*
+ * For function-return probes, init_kprobes() establishes a probepoint
+ * here. When a retprobed function returns, this probe is hit and
+ * trampoline_probe_handler() runs, calling the kretprobe's handler.
+ */
+static void __used kretprobe_trampoline_holder(void)
+{
+       asm volatile (".globl kretprobe_trampoline\n"
+                     "kretprobe_trampoline:\n\t"
+                     "nop\n");
+}
+
+/*
+ * Called when we hit the probe point at kretprobe_trampoline
+ */
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct kretprobe_instance *ri = NULL;
+       struct hlist_head *head, empty_rp;
+       struct hlist_node *node, *tmp;
+       unsigned long flags, orig_ret_address = 0;
+       unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
+
+       INIT_HLIST_HEAD(&empty_rp);
+       kretprobe_hash_lock(current, &head, &flags);
+
+       /*
+        * It is possible to have multiple instances associated with a given
+        * task either because an multiple functions in the call path
+        * have a return probe installed on them, and/or more then one return
+        * return probe was registered for a target function.
+        *
+        * We can handle this because:
+        *     - instances are always inserted at the head of the list
+        *     - when multiple return probes are registered for the same
+        *       function, the first instance's ret_addr will point to the
+        *       real return address, and all the rest will point to
+        *       kretprobe_trampoline
+        */
+       hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+               if (ri->task != current)
+                       /* another task is sharing our hash bucket */
+                       continue;
+
+               if (ri->rp && ri->rp->handler) {
+                       __get_cpu_var(current_kprobe) = &ri->rp->kp;
+                       ri->rp->handler(ri, regs);
+                       __get_cpu_var(current_kprobe) = NULL;
+               }
+
+               orig_ret_address = (unsigned long)ri->ret_addr;
+               recycle_rp_inst(ri, &empty_rp);
+
+               if (orig_ret_address != trampoline_address)
+                       /*
+                        * This is the real return address. Any other
+                        * instances associated with this task are for
+                        * other calls deeper on the call stack
+                        */
+                       break;
+       }
+
+       kretprobe_assert(ri, orig_ret_address, trampoline_address);
+
+       regs->pc = orig_ret_address;
+       kretprobe_hash_unlock(current, &flags);
+
+       preempt_enable_no_resched();
+
+       hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
+               hlist_del(&ri->hlist);
+               kfree(ri);
+       }
+
+       return orig_ret_address;
+}
+
+static int __kprobes post_kprobe_handler(struct pt_regs *regs)
+{
+       struct kprobe *cur = kprobe_running();
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       kprobe_opcode_t *addr = NULL;
+       struct kprobe *p = NULL;
+
+       if (!cur)
+               return 0;
+
+       if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
+               kcb->kprobe_status = KPROBE_HIT_SSDONE;
+               cur->post_handler(cur, regs, 0);
+       }
+
+       if (saved_next_opcode.addr != 0x0) {
+               arch_disarm_kprobe(&saved_next_opcode);
+               saved_next_opcode.addr = 0x0;
+               saved_next_opcode.opcode = 0x0;
+
+               addr = saved_current_opcode.addr;
+               saved_current_opcode.addr = 0x0;
+
+               p = get_kprobe(addr);
+               arch_arm_kprobe(p);
+
+               if (saved_next_opcode2.addr != 0x0) {
+                       arch_disarm_kprobe(&saved_next_opcode2);
+                       saved_next_opcode2.addr = 0x0;
+                       saved_next_opcode2.opcode = 0x0;
+               }
+       }
+
+       /* Restore back the original saved kprobes variables and continue. */
+       if (kcb->kprobe_status == KPROBE_REENTER) {
+               restore_previous_kprobe(kcb);
+               goto out;
+       }
+
+       reset_current_kprobe();
+
+out:
+       preempt_enable_no_resched();
+
+       return 1;
+}
+
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+       struct kprobe *cur = kprobe_running();
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       const struct exception_table_entry *entry;
+
+       switch (kcb->kprobe_status) {
+       case KPROBE_HIT_SS:
+       case KPROBE_REENTER:
+               /*
+                * We are here because the instruction being single
+                * stepped caused a page fault. We reset the current
+                * kprobe, point the pc back to the probe address
+                * and allow the page fault handler to continue as a
+                * normal page fault.
+                */
+               regs->pc = (unsigned long)cur->addr;
+               if (kcb->kprobe_status == KPROBE_REENTER)
+                       restore_previous_kprobe(kcb);
+               else
+                       reset_current_kprobe();
+               preempt_enable_no_resched();
+               break;
+       case KPROBE_HIT_ACTIVE:
+       case KPROBE_HIT_SSDONE:
+               /*
+                * We increment the nmissed count for accounting,
+                * we can also use npre/npostfault count for accounting
+                * these specific fault cases.
+                */
+               kprobes_inc_nmissed_count(cur);
+
+               /*
+                * We come here because instructions in the pre/post
+                * handler caused the page_fault, this could happen
+                * if handler tries to access user space by
+                * copy_from_user(), get_user() etc. Let the
+                * user-specified handler try to fix it first.
+                */
+               if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
+                       return 1;
+
+               /*
+                * In case the user-specified fault handler returned
+                * zero, try to fix up.
+                */
+               if ((entry = search_exception_tables(regs->pc)) != NULL) {
+                       regs->pc = entry->fixup;
+                       return 1;
+               }
+
+               /*
+                * fixup_exception() could not handle it,
+                * Let do_page_fault() fix it.
+                */
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+/*
+ * Wrapper routine to for handling exceptions.
+ */
+int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
+                                      unsigned long val, void *data)
+{
+       struct kprobe *p = NULL;
+       struct die_args *args = (struct die_args *)data;
+       int ret = NOTIFY_DONE;
+       kprobe_opcode_t *addr = NULL;
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+       addr = (kprobe_opcode_t *) (args->regs->pc);
+       if (val == DIE_TRAP) {
+               if (!kprobe_running()) {
+                       if (kprobe_handler(args->regs)) {
+                               ret = NOTIFY_STOP;
+                       } else {
+                               /* Not a kprobe trap */
+                               ret = NOTIFY_DONE;
+                       }
+               } else {
+                       p = get_kprobe(addr);
+                       if ((kcb->kprobe_status == KPROBE_HIT_SS) ||
+                           (kcb->kprobe_status == KPROBE_REENTER)) {
+                               if (post_kprobe_handler(args->regs))
+                                       ret = NOTIFY_STOP;
+                       } else {
+                               if (kprobe_handler(args->regs)) {
+                                       ret = NOTIFY_STOP;
+                               } else {
+                                       p = __get_cpu_var(current_kprobe);
+                                       if (p->break_handler &&
+                                           p->break_handler(p, args->regs))
+                                               ret = NOTIFY_STOP;
+                               }
+                       }
+               }
+       }
+
+       return ret;
+}
+
+int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct jprobe *jp = container_of(p, struct jprobe, kp);
+       unsigned long addr;
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+
+       kcb->jprobe_saved_regs = *regs;
+       kcb->jprobe_saved_r15 = regs->regs[15];
+       addr = kcb->jprobe_saved_r15;
+
+       /*
+        * TBD: As Linus pointed out, gcc assumes that the callee
+        * owns the argument space and could overwrite it, e.g.
+        * tailcall optimization. So, to be absolutely safe
+        * we also save and restore enough stack bytes to cover
+        * the argument area.
+        */
+       memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr,
+              MIN_STACK_SIZE(addr));
+
+       regs->pc = (unsigned long)(jp->entry);
+
+       return 1;
+}
+
+void __kprobes jprobe_return(void)
+{
+       asm volatile ("trapa #0x3a\n\t" "jprobe_return_end:\n\t" "nop\n\t");
+}
+
+int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+       struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+       unsigned long stack_addr = kcb->jprobe_saved_r15;
+       u8 *addr = (u8 *)regs->pc;
+
+       if ((addr >= (u8 *)jprobe_return) &&
+           (addr <= (u8 *)jprobe_return_end)) {
+               *regs = kcb->jprobe_saved_regs;
+
+               memcpy((kprobe_opcode_t *)stack_addr, kcb->jprobes_stack,
+                      MIN_STACK_SIZE(stack_addr));
+
+               kcb->kprobe_status = KPROBE_HIT_SS;
+               preempt_enable_no_resched();
+               return 1;
+       }
+
+       return 0;
+}
+
+static struct kprobe trampoline_p = {
+       .addr = (kprobe_opcode_t *)&kretprobe_trampoline,
+       .pre_handler = trampoline_probe_handler
+};
+
+int __init arch_init_kprobes(void)
+{
+       saved_next_opcode.addr = 0x0;
+       saved_next_opcode.opcode = 0x0;
+
+       saved_current_opcode.addr = 0x0;
+       saved_current_opcode.opcode = 0x0;
+
+       saved_next_opcode2.addr = 0x0;
+       saved_next_opcode2.opcode = 0x0;
+
+       return register_kprobe(&trampoline_p);
+}
index 129b2cfd18a84db251d5791e17bb7c4360f869ae..c1ea41e5812a5897a5abfc8e8bb94fba925e414d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/string.h>
 #include <asm/machvec.h>
 #include <asm/sections.h>
+#include <asm/setup.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 
@@ -125,9 +126,6 @@ void __init sh_mv_setup(void)
        mv_set(insb);   mv_set(insw);   mv_set(insl);
        mv_set(outsb);  mv_set(outsw);  mv_set(outsl);
 
-       mv_set(readb);  mv_set(readw);  mv_set(readl);
-       mv_set(writeb); mv_set(writew); mv_set(writel);
-
        mv_set(ioport_map);
        mv_set(ioport_unmap);
        mv_set(irq_demux);
index 3326a45749d9ee2c0af9c9c35b4934cc57c487d9..b965f0282c7dab650ec30fa1b02d532ed6674be5 100644 (file)
@@ -7,7 +7,11 @@
  *
  *  SuperH version:  Copyright (C) 1999, 2000  Niibe Yutaka & Kaz Kojima
  *                  Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC
- *                  Copyright (C) 2002 - 2007  Paul Mundt
+ *                  Copyright (C) 2002 - 2008  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/module.h>
 #include <linux/mm.h>
@@ -26,6 +30,7 @@
 #include <asm/system.h>
 #include <asm/ubc.h>
 #include <asm/fpu.h>
+#include <asm/syscalls.h>
 
 static int hlt_counter;
 int ubc_usercnt = 0;
@@ -111,15 +116,21 @@ void show_regs(struct pt_regs * regs)
 {
        printk("\n");
        printk("Pid : %d, Comm: %20s\n", task_pid_nr(current), current->comm);
+       printk("CPU : %d    %s  (%s %.*s)\n",
+              smp_processor_id(), print_tainted(), init_utsname()->release,
+              (int)strcspn(init_utsname()->version, " "),
+              init_utsname()->version);
+
        print_symbol("PC is at %s\n", instruction_pointer(regs));
+       print_symbol("PR is at %s\n", regs->pr);
+
        printk("PC  : %08lx SP  : %08lx SR  : %08lx ",
               regs->pc, regs->regs[15], regs->sr);
 #ifdef CONFIG_MMU
-       printk("TEA : %08x    ", ctrl_inl(MMU_TEA));
+       printk("TEA : %08x\n", ctrl_inl(MMU_TEA));
 #else
-       printk("                  ");
+       printk("\n");
 #endif
-       printk("%s\n", print_tainted());
 
        printk("R0  : %08lx R1  : %08lx R2  : %08lx R3  : %08lx\n",
               regs->regs[0],regs->regs[1],
@@ -162,6 +173,7 @@ __asm__(".align 5\n"
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
        struct pt_regs regs;
+       int pid;
 
        memset(&regs, 0, sizeof(regs));
        regs.regs[4] = (unsigned long)arg;
@@ -171,8 +183,12 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        regs.sr = (1 << 30);
 
        /* Ok, create the new process.. */
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
-                      &regs, 0, NULL, NULL);
+       pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
+                     &regs, 0, NULL, NULL);
+
+       trace_mark(kernel_arch_kthread_create, "pid %d fn %p", pid, fn);
+
+       return pid;
 }
 
 /*
@@ -210,10 +226,10 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
        struct task_struct *tsk = current;
 
        fpvalid = !!tsk_used_math(tsk);
-       if (fpvalid) {
-               unlazy_fpu(tsk, regs);
-               memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu));
-       }
+       if (fpvalid)
+               fpvalid = !fpregs_get(tsk, NULL, 0,
+                                     sizeof(struct user_fpu_struct),
+                                     fpu, NULL);
 #endif
 
        return fpvalid;
index b9dbd2d3b4a5845624829c547ed613c8fe259b51..b7aa09235b51a65202119a5afaa324549d172b35 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/proc_fs.h>
 #include <linux/io.h>
+#include <asm/syscalls.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
@@ -395,6 +396,7 @@ ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *))
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
        struct pt_regs regs;
+       int pid;
 
        memset(&regs, 0, sizeof(regs));
        regs.regs[2] = (unsigned long)arg;
@@ -403,8 +405,13 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
        regs.pc = (unsigned long)kernel_thread_helper;
        regs.sr = (1 << 30);
 
-       return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
-                      &regs, 0, NULL, NULL);
+       /* Ok, create the new process.. */
+       pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,
+                     &regs, 0, NULL, NULL);
+
+       trace_mark(kernel_arch_kthread_create, "pid %d fn %p", pid, fn);
+
+       return pid;
 }
 
 /*
index 035cb300d3dcf245b894e86ac39931cbdeee696f..29ca09d24ef855b54c5e6bd431a01fd83e96cd0b 100644 (file)
@@ -1,12 +1,14 @@
 /*
- * linux/arch/sh/kernel/ptrace.c
+ * SuperH process tracing
  *
- * Original x86 implementation:
- *     By Ross Biro 1/23/92
- *     edited by Linus Torvalds
+ * Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
+ * Copyright (C) 2002 - 2008  Paul Mundt
  *
- * SuperH version:   Copyright (C) 1999, 2000  Kaz Kojima & Niibe Yutaka
- * Audit support: Yuichi Nakamura <ynakam@hitachisoft.jp>
+ * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/audit.h>
 #include <linux/seccomp.h>
 #include <linux/tracehook.h>
+#include <linux/elf.h>
+#include <linux/regset.h>
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
-
-/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- */
+#include <asm/syscalls.h>
+#include <asm/fpu.h>
 
 /*
  * This routine will get a word off of the process kernel stack.
@@ -61,16 +62,12 @@ static inline int put_stack_long(struct task_struct *task, int offset,
 
 void user_enable_single_step(struct task_struct *child)
 {
-       struct pt_regs *regs = task_pt_regs(child);
-       long pc;
-
-       pc = get_stack_long(child, (long)&regs->pc);
-
        /* Next scheduling will set up UBC */
        if (child->thread.ubc_pc == 0)
                ubc_usercnt += 1;
 
-       child->thread.ubc_pc = pc;
+       child->thread.ubc_pc = get_stack_long(child,
+                               offsetof(struct pt_regs, pc));
 
        set_tsk_thread_flag(child, TIF_SINGLESTEP);
 }
@@ -102,9 +99,213 @@ void ptrace_disable(struct task_struct *child)
        user_disable_single_step(child);
 }
 
+static int genregs_get(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      void *kbuf, void __user *ubuf)
+{
+       const struct pt_regs *regs = task_pt_regs(target);
+       int ret;
+
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                 regs->regs,
+                                 0, 16 * sizeof(unsigned long));
+       if (!ret)
+               /* PC, PR, SR, GBR, MACH, MACL, TRA */
+               ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                         &regs->pc,
+                                         offsetof(struct pt_regs, pc),
+                                         sizeof(struct pt_regs));
+       if (!ret)
+               ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+                                              sizeof(struct pt_regs), -1);
+
+       return ret;
+}
+
+static int genregs_set(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      const void *kbuf, const void __user *ubuf)
+{
+       struct pt_regs *regs = task_pt_regs(target);
+       int ret;
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                regs->regs,
+                                0, 16 * sizeof(unsigned long));
+       if (!ret && count > 0)
+               ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                        &regs->pc,
+                                        offsetof(struct pt_regs, pc),
+                                        sizeof(struct pt_regs));
+       if (!ret)
+               ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                               sizeof(struct pt_regs), -1);
+
+       return ret;
+}
+
+#ifdef CONFIG_SH_FPU
+int fpregs_get(struct task_struct *target,
+              const struct user_regset *regset,
+              unsigned int pos, unsigned int count,
+              void *kbuf, void __user *ubuf)
+{
+       int ret;
+
+       ret = init_fpu(target);
+       if (ret)
+               return ret;
+
+       if ((boot_cpu_data.flags & CPU_HAS_FPU))
+               return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                          &target->thread.fpu.hard, 0, -1);
+
+       return user_regset_copyout(&pos, &count, &kbuf, &ubuf,
+                                  &target->thread.fpu.soft, 0, -1);
+}
+
+static int fpregs_set(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      const void *kbuf, const void __user *ubuf)
+{
+       int ret;
+
+       ret = init_fpu(target);
+       if (ret)
+               return ret;
+
+       set_stopped_child_used_math(target);
+
+       if ((boot_cpu_data.flags & CPU_HAS_FPU))
+               return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                         &target->thread.fpu.hard, 0, -1);
+
+       return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+                                 &target->thread.fpu.soft, 0, -1);
+}
+
+static int fpregs_active(struct task_struct *target,
+                        const struct user_regset *regset)
+{
+       return tsk_used_math(target) ? regset->n : 0;
+}
+#endif
+
+#ifdef CONFIG_SH_DSP
+static int dspregs_get(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      void *kbuf, void __user *ubuf)
+{
+       const struct pt_dspregs *regs = task_pt_dspregs(target);
+       int ret;
+
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, regs,
+                                 0, sizeof(struct pt_dspregs));
+       if (!ret)
+               ret = user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
+                                              sizeof(struct pt_dspregs), -1);
+
+       return ret;
+}
+
+static int dspregs_set(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      const void *kbuf, const void __user *ubuf)
+{
+       struct pt_dspregs *regs = task_pt_dspregs(target);
+       int ret;
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs,
+                                0, sizeof(struct pt_dspregs));
+       if (!ret)
+               ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+                                               sizeof(struct pt_dspregs), -1);
+
+       return ret;
+}
+
+static int dspregs_active(struct task_struct *target,
+                         const struct user_regset *regset)
+{
+       struct pt_regs *regs = task_pt_regs(target);
+
+       return regs->sr & SR_DSP ? regset->n : 0;
+}
+#endif
+
+/*
+ * These are our native regset flavours.
+ */
+enum sh_regset {
+       REGSET_GENERAL,
+#ifdef CONFIG_SH_FPU
+       REGSET_FPU,
+#endif
+#ifdef CONFIG_SH_DSP
+       REGSET_DSP,
+#endif
+};
+
+static const struct user_regset sh_regsets[] = {
+       /*
+        * Format is:
+        *      R0 --> R15
+        *      PC, PR, SR, GBR, MACH, MACL, TRA
+        */
+       [REGSET_GENERAL] = {
+               .core_note_type = NT_PRSTATUS,
+               .n              = ELF_NGREG,
+               .size           = sizeof(long),
+               .align          = sizeof(long),
+               .get            = genregs_get,
+               .set            = genregs_set,
+       },
+
+#ifdef CONFIG_SH_FPU
+       [REGSET_FPU] = {
+               .core_note_type = NT_PRFPREG,
+               .n              = sizeof(struct user_fpu_struct) / sizeof(long),
+               .size           = sizeof(long),
+               .align          = sizeof(long),
+               .get            = fpregs_get,
+               .set            = fpregs_set,
+               .active         = fpregs_active,
+       },
+#endif
+
+#ifdef CONFIG_SH_DSP
+       [REGSET_DSP] = {
+               .n              = sizeof(struct pt_dspregs) / sizeof(long),
+               .size           = sizeof(long),
+               .align          = sizeof(long),
+               .get            = dspregs_get,
+               .set            = dspregs_set,
+               .active         = dspregs_active,
+       },
+#endif
+};
+
+static const struct user_regset_view user_sh_native_view = {
+       .name           = "sh",
+       .e_machine      = EM_SH,
+       .regsets        = sh_regsets,
+       .n              = ARRAY_SIZE(sh_regsets),
+};
+
+const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+{
+       return &user_sh_native_view;
+}
+
 long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 {
        struct user * dummy = NULL;
+       unsigned long __user *datap = (unsigned long __user *)data;
        int ret;
 
        switch (request) {
@@ -133,7 +334,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        tmp = !!tsk_used_math(child);
                else
                        tmp = 0;
-               ret = put_user(tmp, (unsigned long __user *)data);
+               ret = put_user(tmp, datap);
                break;
        }
 
@@ -157,34 +358,39 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                }
                break;
 
+       case PTRACE_GETREGS:
+               return copy_regset_to_user(child, &user_sh_native_view,
+                                          REGSET_GENERAL,
+                                          0, sizeof(struct pt_regs),
+                                          (void __user *)data);
+       case PTRACE_SETREGS:
+               return copy_regset_from_user(child, &user_sh_native_view,
+                                            REGSET_GENERAL,
+                                            0, sizeof(struct pt_regs),
+                                            (const void __user *)data);
+#ifdef CONFIG_SH_FPU
+       case PTRACE_GETFPREGS:
+               return copy_regset_to_user(child, &user_sh_native_view,
+                                          REGSET_FPU,
+                                          0, sizeof(struct user_fpu_struct),
+                                          (void __user *)data);
+       case PTRACE_SETFPREGS:
+               return copy_regset_from_user(child, &user_sh_native_view,
+                                            REGSET_FPU,
+                                            0, sizeof(struct user_fpu_struct),
+                                            (const void __user *)data);
+#endif
 #ifdef CONFIG_SH_DSP
-       case PTRACE_GETDSPREGS: {
-               unsigned long dp;
-
-               ret = -EIO;
-               dp = ((unsigned long) child) + THREAD_SIZE -
-                        sizeof(struct pt_dspregs);
-               if (*((int *) (dp - 4)) == SR_FD) {
-                       copy_to_user((void *)addr, (void *) dp,
-                               sizeof(struct pt_dspregs));
-                       ret = 0;
-               }
-               break;
-       }
-
-       case PTRACE_SETDSPREGS: {
-               unsigned long dp;
-
-               ret = -EIO;
-               dp = ((unsigned long) child) + THREAD_SIZE -
-                        sizeof(struct pt_dspregs);
-               if (*((int *) (dp - 4)) == SR_FD) {
-                       copy_from_user((void *) dp, (void *)addr,
-                               sizeof(struct pt_dspregs));
-                       ret = 0;
-               }
-               break;
-       }
+       case PTRACE_GETDSPREGS:
+               return copy_regset_to_user(child, &user_sh_native_view,
+                                          REGSET_DSP,
+                                          0, sizeof(struct pt_dspregs),
+                                          (void __user *)data);
+       case PTRACE_SETDSPREGS:
+               return copy_regset_from_user(child, &user_sh_native_view,
+                                            REGSET_DSP,
+                                            0, sizeof(struct pt_dspregs),
+                                            (const void __user *)data);
 #endif
 #ifdef CONFIG_BINFMT_ELF_FDPIC
        case PTRACE_GETFDPIC: {
@@ -202,7 +408,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                }
 
                ret = 0;
-               if (put_user(tmp, (unsigned long *) data)) {
+               if (put_user(tmp, datap)) {
                        ret = -EFAULT;
                        break;
                }
index 9c6424892bd37fcca32ae16e02e8691198c6c788..e15b099c1f069f8856e43caa7db2187ab129cb7e 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/mmu_context.h>
+#include <asm/syscalls.h>
 #include <asm/fpu.h>
 
 /* This mask defines the bits of the SR which the user is not allowed to
index de832056bf1b28ae1196633d0bf23633144f8f26..e7152cc6930e38bd4b3dc7bd36cd37ae1caf1cb4 100644 (file)
@@ -26,6 +26,9 @@
 #include <linux/err.h>
 #include <linux/debugfs.h>
 #include <linux/crash_dump.h>
+#include <linux/mmzone.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/page.h>
@@ -144,6 +147,7 @@ static void __init reserve_crashkernel(void)
 {
        unsigned long long free_mem;
        unsigned long long crash_size, crash_base;
+       void *vp;
        int ret;
 
        free_mem = ((unsigned long long)max_low_pfn - min_low_pfn) << PAGE_SHIFT;
@@ -152,12 +156,14 @@ static void __init reserve_crashkernel(void)
                        &crash_size, &crash_base);
        if (ret == 0 && crash_size) {
                if (crash_base <= 0) {
-                       printk(KERN_INFO "crashkernel reservation failed - "
-                                       "you have to specify a base address\n");
-                       return;
-               }
-
-               if (reserve_bootmem(crash_base, crash_size,
+                       vp = alloc_bootmem_nopanic(crash_size); 
+                       if (!vp) {
+                               printk(KERN_INFO "crashkernel allocation "
+                                      "failed\n");
+                               return;
+                       }
+                       crash_base = __pa(vp);
+               } else if (reserve_bootmem(crash_base, crash_size,
                                        BOOTMEM_EXCLUSIVE) < 0) {
                        printk(KERN_INFO "crashkernel reservation failed - "
                                        "memory is in use\n");
@@ -179,6 +185,24 @@ static inline void __init reserve_crashkernel(void)
 {}
 #endif
 
+#ifndef CONFIG_GENERIC_CALIBRATE_DELAY
+void __cpuinit calibrate_delay(void)
+{
+       struct clk *clk = clk_get(NULL, "cpu_clk");
+
+       if (IS_ERR(clk))
+               panic("Need a sane CPU clock definition!");
+
+       loops_per_jiffy = (clk_get_rate(clk) >> 1) / HZ;
+
+       printk(KERN_INFO "Calibrating delay loop (skipped)... "
+                        "%lu.%02lu BogoMIPS PRESET (lpj=%lu)\n",
+                        loops_per_jiffy/(500000/HZ),
+                        (loops_per_jiffy/(5000/HZ)) % 100,
+                        loops_per_jiffy);
+}
+#endif
+
 void __init __add_active_range(unsigned int nid, unsigned long start_pfn,
                                                unsigned long end_pfn)
 {
@@ -232,15 +256,17 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
         * case of us accidentally initializing the bootmem allocator with
         * an invalid RAM area.
         */
-       reserve_bootmem(__MEMORY_START+PAGE_SIZE,
-               (PFN_PHYS(free_pfn)+bootmap_size+PAGE_SIZE-1)-__MEMORY_START,
-               BOOTMEM_DEFAULT);
+       reserve_bootmem(__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET,
+                       (PFN_PHYS(free_pfn) + bootmap_size + PAGE_SIZE - 1) -
+                       (__MEMORY_START + CONFIG_ZERO_PAGE_OFFSET),
+                       BOOTMEM_DEFAULT);
 
        /*
         * reserve physical page 0 - it's a special BIOS page on many boxes,
         * enabling clean reboots, SMP operation, laptop functions.
         */
-       reserve_bootmem(__MEMORY_START, PAGE_SIZE, BOOTMEM_DEFAULT);
+       reserve_bootmem(__MEMORY_START, CONFIG_ZERO_PAGE_OFFSET,
+                       BOOTMEM_DEFAULT);
 
        sparse_memory_present_with_active_regions(0);
 
@@ -248,17 +274,18 @@ void __init setup_bootmem_allocator(unsigned long free_pfn)
        ROOT_DEV = Root_RAM0;
 
        if (LOADER_TYPE && INITRD_START) {
-               if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
-                       reserve_bootmem(INITRD_START + __MEMORY_START,
-                                       INITRD_SIZE, BOOTMEM_DEFAULT);
-                       initrd_start = INITRD_START + PAGE_OFFSET +
-                                       __MEMORY_START;
+               unsigned long initrd_start_phys = INITRD_START + __MEMORY_START;
+
+               if (initrd_start_phys + INITRD_SIZE <= PFN_PHYS(max_low_pfn)) {
+                       reserve_bootmem(initrd_start_phys, INITRD_SIZE,
+                                       BOOTMEM_DEFAULT);
+                       initrd_start = (unsigned long)__va(initrd_start_phys);
                        initrd_end = initrd_start + INITRD_SIZE;
                } else {
                        printk("initrd extends beyond end of memory "
-                           "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-                                   INITRD_START + INITRD_SIZE,
-                                   max_low_pfn << PAGE_SHIFT);
+                              "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                              initrd_start_phys + INITRD_SIZE,
+                              (unsigned long)PFN_PHYS(max_low_pfn));
                        initrd_start = 0;
                }
        }
@@ -530,6 +557,8 @@ struct dentry *sh_debugfs_root;
 static int __init sh_debugfs_init(void)
 {
        sh_debugfs_root = debugfs_create_dir("sh", NULL);
+       if (!sh_debugfs_root)
+               return -ENOMEM;
        if (IS_ERR(sh_debugfs_root))
                return PTR_ERR(sh_debugfs_root);
 
index 6e1b1c2716584a8bc79ab206098465029a700eea..d917b7b4042bcb81ce8c2a1219e099b95a3feea1 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/delay.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
+#include <asm/ftrace.h>
 
 extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
 extern struct hw_interrupt_type no_irq_type;
@@ -133,6 +134,9 @@ EXPORT_SYMBOL(__flush_purge_region);
 EXPORT_SYMBOL(clear_user_page);
 #endif
 
+#ifdef CONFIG_FTRACE
+EXPORT_SYMBOL(mcount);
+#endif
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
 #ifdef CONFIG_IPV6
index 51689d29ad45d331aa7c42b9ca4c301afafabdb6..69d09c0b3498e672057fc92f7a5d740be853ef6b 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
+#include <asm/syscalls.h>
 #include <asm/fpu.h>
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -215,6 +216,9 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
        sigset_t set;
        int r0;
 
+        /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
 
@@ -247,9 +251,11 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15];
        sigset_t set;
-       stack_t st;
        int r0;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
 
@@ -265,11 +271,9 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
                goto badframe;
 
-       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+       if (do_sigaltstack(&frame->uc.uc_stack, NULL,
+                          regs->regs[15]) == -EFAULT)
                goto badframe;
-       /* It is more difficult to avoid calling this function than to
-          call it and ignore errors.  */
-       do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame);
 
        return r0;
 
@@ -429,7 +433,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->uc.uc_flags);
-       err |= __put_user(0, &frame->uc.uc_link);
+       err |= __put_user(NULL, &frame->uc.uc_link);
        err |= __put_user((void *)current->sas_ss_sp,
                          &frame->uc.uc_stack.ss_sp);
        err |= __put_user(sas_ss_flags(regs->regs[15]),
@@ -492,37 +496,43 @@ give_sigsegv:
        return -EFAULT;
 }
 
+static inline void
+handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
+                      struct sigaction *sa)
+{
+       /* If we're not from a syscall, bail out */
+       if (regs->tra < 0)
+               return;
+
+       /* check for system call restart.. */
+       switch (regs->regs[0]) {
+               case -ERESTART_RESTARTBLOCK:
+               case -ERESTARTNOHAND:
+               no_system_call_restart:
+                       regs->regs[0] = -EINTR;
+                       regs->sr |= 1;
+                       break;
+
+               case -ERESTARTSYS:
+                       if (!(sa->sa_flags & SA_RESTART))
+                               goto no_system_call_restart;
+               /* fallthrough */
+               case -ERESTARTNOINTR:
+                       regs->regs[0] = save_r0;
+                       regs->pc -= instruction_size(ctrl_inw(regs->pc - 4));
+                       break;
+       }
+}
+
 /*
  * OK, we're invoking a handler
  */
-
 static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
              sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
 {
        int ret;
 
-       /* Are we from a system call? */
-       if (regs->tra >= 0) {
-               /* If so, check system call restarting.. */
-               switch (regs->regs[0]) {
-                       case -ERESTART_RESTARTBLOCK:
-                       case -ERESTARTNOHAND:
-                       no_system_call_restart:
-                               regs->regs[0] = -EINTR;
-                               break;
-
-                       case -ERESTARTSYS:
-                               if (!(ka->sa.sa_flags & SA_RESTART))
-                                       goto no_system_call_restart;
-                       /* fallthrough */
-                       case -ERESTARTNOINTR:
-                               regs->regs[0] = save_r0;
-                               regs->pc -= instruction_size(
-                                               ctrl_inw(regs->pc - 4));
-                               break;
-               }
-       }
 
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
@@ -580,6 +590,9 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
+               if (regs->sr & 1)
+                       handle_syscall_restart(save_r0, regs, &ka.sa);
+
                /* Whee!  Actually deliver the signal.  */
                if (handle_signal(signr, &ka, &info, oldset,
                                  regs, save_r0) == 0) {
index 1d62dfef77f1df57d4c2b555e0a7d64a16052f8d..ce3e851dffcbca6906f85ebbbfca80421469d461 100644 (file)
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
+static void
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+               sigset_t *oldset, struct pt_regs * regs);
+
 /*
  * Note that 'init' is a special process: it doesn't get signals it doesn't
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
@@ -371,6 +375,9 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
        sigset_t set;
        long long ret;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
 
@@ -408,6 +415,9 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
        stack_t __user st;
        long long ret;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
 
@@ -535,7 +545,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
                 * On SH5 all edited pointers are subject to NEFF
                 */
                DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                               (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
        } else {
                /*
                 * Different approach on SH5.
@@ -550,10 +560,10 @@ static void setup_frame(int sig, struct k_sigaction *ka,
                 */
                DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
                DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                               (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
 
                if (__copy_to_user(frame->retcode,
-                       (unsigned long long)sa_default_restorer & (~1), 16) != 0)
+                       (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
                        goto give_sigsegv;
 
                /* Cohere the trampoline with the I-cache. */
@@ -566,7 +576,7 @@ static void setup_frame(int sig, struct k_sigaction *ka,
         */
        regs->regs[REG_SP] = (unsigned long) frame;
        regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
-                        (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
+                (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
        regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
 
         /* FIXME:
@@ -652,7 +662,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                 * On SH5 all edited pointers are subject to NEFF
                 */
                DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                               (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
        } else {
                /*
                 * Different approach on SH5.
@@ -668,10 +678,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
                DEREF_REG_PR = (unsigned long) frame->retcode | 0x01;
                DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
-                               (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
+                       (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
 
                if (__copy_to_user(frame->retcode,
-                       (unsigned long long)sa_default_rt_restorer & (~1), 16) != 0)
+                       (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
                        goto give_sigsegv;
 
                flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
@@ -683,7 +693,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
         */
        regs->regs[REG_SP] = (unsigned long) frame;
        regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
-                        (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
+                (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
        regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
        regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
        regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
index 001778f9adaf83eee6cb3766866809516d346bc0..508dfb023628d980233110f462802dd27f8c93d2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SMP support for the SuperH processors.
  *
- * Copyright (C) 2002 - 2007 Paul Mundt
+ * Copyright (C) 2002 - 2008 Paul Mundt
  * Copyright (C) 2006 - 2007 Akio Idehara
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -86,9 +86,12 @@ asmlinkage void __cpuinit start_secondary(void)
 
        local_irq_enable();
 
+       cpu = smp_processor_id();
+
+       /* Enable local timers */
+       local_timer_setup(cpu);
        calibrate_delay();
 
-       cpu = smp_processor_id();
        smp_store_cpu_info(cpu);
 
        cpu_set(cpu, cpu_online_map);
@@ -186,6 +189,42 @@ void arch_send_call_function_single_ipi(int cpu)
        plat_send_ipi(cpu, SMP_MSG_FUNCTION_SINGLE);
 }
 
+void smp_timer_broadcast(cpumask_t mask)
+{
+       int cpu;
+
+       for_each_cpu_mask(cpu, mask)
+               plat_send_ipi(cpu, SMP_MSG_TIMER);
+}
+
+static void ipi_timer(void)
+{
+       irq_enter();
+       local_timer_interrupt();
+       irq_exit();
+}
+
+void smp_message_recv(unsigned int msg)
+{
+       switch (msg) {
+       case SMP_MSG_FUNCTION:
+               generic_smp_call_function_interrupt();
+               break;
+       case SMP_MSG_RESCHEDULE:
+               break;
+       case SMP_MSG_FUNCTION_SINGLE:
+               generic_smp_call_function_single_interrupt();
+               break;
+       case SMP_MSG_TIMER:
+               ipi_timer();
+               break;
+       default:
+               printk(KERN_WARNING "SMP %d: %s(): unknown IPI %d\n",
+                      smp_processor_id(), __func__, msg);
+               break;
+       }
+}
+
 /* Not really SMP stuff ... */
 int setup_profiling_timer(unsigned int multiplier)
 {
index 54d1f61aa00778c22cb55552e5fc18197e12d3b8..1a2a5eb76e41cd419182b358d24127758838a997 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Stack trace management functions
  *
- *  Copyright (C) 2006  Paul Mundt
+ *  Copyright (C) 2006 - 2008  Paul Mundt
  *
  * 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
@@ -36,3 +36,24 @@ void save_stack_trace(struct stack_trace *trace)
        }
 }
 EXPORT_SYMBOL_GPL(save_stack_trace);
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+       unsigned long *sp = (unsigned long *)tsk->thread.sp;
+
+       while (!kstack_end(sp)) {
+               unsigned long addr = *sp++;
+
+               if (__kernel_text_address(addr)) {
+                       if (in_sched_functions(addr))
+                               break;
+                       if (trace->skip > 0)
+                               trace->skip--;
+                       else
+                               trace->entries[trace->nr_entries++] = addr;
+                       if (trace->nr_entries >= trace->max_entries)
+                               break;
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
index 9061b86d73fadefef5b20d7834a6c25299fcc289..38f098c9c72de2e2fd6eb47cbe4b3c874420aa72 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/fs.h>
 #include <linux/ipc.h>
 #include <asm/cacheflush.h>
+#include <asm/syscalls.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 
@@ -170,6 +171,8 @@ asmlinkage int sys_ipc(uint call, int first, int second,
        version = call >> 16; /* hack for backward compatibility */
        call &= 0xffff;
 
+       trace_mark(kernel_arch_ipc_call, "call %u first %d", call, first);
+
        if (call <= SEMTIMEDOP)
                switch (call) {
                case SEMOP:
@@ -186,7 +189,7 @@ asmlinkage int sys_ipc(uint call, int first, int second,
                        union semun fourth;
                        if (!ptr)
                                return -EINVAL;
-                       if (get_user(fourth.__pad, (void * __user *) ptr))
+                       if (get_user(fourth.__pad, (void __user * __user *) ptr))
                                return -EFAULT;
                        return sys_semctl (first, second, third, fourth);
                        }
@@ -261,13 +264,13 @@ asmlinkage int sys_ipc(uint call, int first, int second,
        return -EINVAL;
 }
 
-asmlinkage int sys_uname(struct old_utsname name)
+asmlinkage int sys_uname(struct old_utsname __user *name)
 {
        int err;
        if (!name)
                return -EFAULT;
        down_read(&uts_sem);
-       err = copy_to_user(name, utsname(), sizeof (*name));
+       err = copy_to_user(name, utsname(), sizeof(*name));
        up_read(&uts_sem);
        return err?-EFAULT:0;
 }
index f0aa5c398656ca5b7fc1e4d0812b41951c57a79b..dbba1e1833d43703362aee63cbba2f2c8bfb08f2 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/cacheflush.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
+#include <asm/syscalls.h>
 
 /*
  * sys_pipe() is the normal C calling standard for creating
@@ -37,13 +38,13 @@ asmlinkage int sys_pipe(unsigned long r4, unsigned long r5,
        return error;
 }
 
-asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char buf,
+asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char __user *buf,
                             size_t count, long dummy, loff_t pos)
 {
        return sys_pread64(fd, buf, count, pos);
 }
 
-asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char buf,
+asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char __user *buf,
                              size_t count, long dummy, loff_t pos)
 {
        return sys_pwrite64(fd, buf, count, pos);
index 0758b5ee818079b3fd2f3948da6dfe7af5825d0b..23ca711c27d2af9e6e15106a17bcdb8e92bea47c 100644 (file)
@@ -1,9 +1,9 @@
 /*
- *  arch/sh/kernel/time.c
+ *  arch/sh/kernel/time_32.c
  *
  *  Copyright (C) 1999  Tetsuya Okada & Niibe Yutaka
  *  Copyright (C) 2000  Philipp Rumpf <prumpf@tux.org>
- *  Copyright (C) 2002 - 2007  Paul Mundt
+ *  Copyright (C) 2002 - 2008  Paul Mundt
  *  Copyright (C) 2002  M. R. Brown  <mrbrown@linux-sh.org>
  *
  *  Some code taken from i386 version.
@@ -16,6 +16,8 @@
 #include <linux/timex.h>
 #include <linux/sched.h>
 #include <linux/clockchips.h>
+#include <linux/mc146818rtc.h> /* for rtc_lock */
+#include <linux/smp.h>
 #include <asm/clock.h>
 #include <asm/rtc.h>
 #include <asm/timer.h>
@@ -253,6 +255,10 @@ void __init time_init(void)
        set_normalized_timespec(&wall_to_monotonic,
                                -xtime.tv_sec, -xtime.tv_nsec);
 
+#ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
+       local_timer_setup(smp_processor_id());
+#endif
+
        /*
         * Find the timer to use as the system timer, it will be
         * initialized for us.
@@ -260,6 +266,7 @@ void __init time_init(void)
        sys_timer = get_sys_timer();
        printk(KERN_INFO "Using %s for system timer\n", sys_timer->name);
 
+
        if (sys_timer->ops->read)
                clocksource_sh.read = sys_timer->ops->read;
 
index 791edabf7d834fe8d52410b508f50bc18f9fe981..bbb2af1004d9eb2639598c1eef87b8954e147ef8 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/delay.h>
+#include <asm/clock.h>
 
 #define TMU_TOCR_INIT  0x00
 #define TMU0_TCR_INIT  0x0020
 #define RTC_RCR1_CIE   0x10    /* Carry Interrupt Enable */
 #define RTC_RCR1       (rtc_base + 0x38)
 
-/* Clock, Power and Reset Controller */
-#define        CPRC_BLOCK_OFF  0x01010000
-#define CPRC_BASE      PHYS_PERIPHERAL_BLOCK + CPRC_BLOCK_OFF
-
-#define FRQCR          (cprc_base+0x0)
-#define WTCSR          (cprc_base+0x0018)
-#define STBCR          (cprc_base+0x0030)
-
 /* Time Management Unit */
 #define        TMU_BLOCK_OFF   0x01020000
 #define TMU_BASE       PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF
@@ -293,103 +286,17 @@ static irqreturn_t timer_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-
-static __init unsigned int get_cpu_hz(void)
-{
-       unsigned int count;
-       unsigned long __dummy;
-       unsigned long ctc_val_init, ctc_val;
-
-       /*
-       ** Regardless the toolchain, force the compiler to use the
-       ** arbitrary register r3 as a clock tick counter.
-       ** NOTE: r3 must be in accordance with sh64_rtc_interrupt()
-       */
-       register unsigned long long  __rtc_irq_flag __asm__ ("r3");
-
-       local_irq_enable();
-       do {} while (ctrl_inb(rtc_base) != 0);
-       ctrl_outb(RTC_RCR1_CIE, RTC_RCR1); /* Enable carry interrupt */
-
-       /*
-        * r3 is arbitrary. CDC does not support "=z".
-        */
-       ctc_val_init = 0xffffffff;
-       ctc_val = ctc_val_init;
-
-       asm volatile("gettr     tr0, %1\n\t"
-                    "putcon    %0, " __CTC "\n\t"
-                    "and       %2, r63, %2\n\t"
-                    "pta       $+4, tr0\n\t"
-                    "beq/l     %2, r63, tr0\n\t"
-                    "ptabs     %1, tr0\n\t"
-                    "getcon    " __CTC ", %0\n\t"
-               : "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag)
-               : "0" (0));
-       local_irq_disable();
-       /*
-        * SH-3:
-        * CPU clock = 4 stages * loop
-        * tst    rm,rm      if id ex
-        * bt/s   1b            if id ex
-        * add    #1,rd            if id ex
-         *                            (if) pipe line stole
-        * tst    rm,rm                  if id ex
-         * ....
-        *
-        *
-        * SH-4:
-        * CPU clock = 6 stages * loop
-        * I don't know why.
-         * ....
-        *
-        * SH-5:
-        * Use CTC register to count.  This approach returns the right value
-        * even if the I-cache is disabled (e.g. whilst debugging.)
-        *
-        */
-
-       count = ctc_val_init - ctc_val; /* CTC counts down */
-
-       /*
-        * This really is count by the number of clock cycles
-         * by the ratio between a complete R64CNT
-         * wrap-around (128) and CUI interrupt being raised (64).
-        */
-       return count*2;
-}
-
-static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id)
-{
-       struct pt_regs *regs = get_irq_regs();
-
-       ctrl_outb(0, RTC_RCR1); /* Disable Carry Interrupts */
-       regs->regs[3] = 1;      /* Using r3 */
-
-       return IRQ_HANDLED;
-}
-
 static struct irqaction irq0  = {
        .handler = timer_interrupt,
        .flags = IRQF_DISABLED,
        .mask = CPU_MASK_NONE,
        .name = "timer",
 };
-static struct irqaction irq1  = {
-       .handler = sh64_rtc_interrupt,
-       .flags = IRQF_DISABLED,
-       .mask = CPU_MASK_NONE,
-       .name = "rtc",
-};
 
 void __init time_init(void)
 {
-       unsigned int cpu_clock, master_clock, bus_clock, module_clock;
        unsigned long interval;
-       unsigned long frqcr, ifc, pfc;
-       static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 };
-#define bfc_table ifc_table    /* Same */
-#define pfc_table ifc_table    /* Same */
+       struct clk *clk;
 
        tmu_base = onchip_remap(TMU_BASE, 1024, "TMU");
        if (!tmu_base) {
@@ -401,50 +308,19 @@ void __init time_init(void)
                panic("Unable to remap RTC\n");
        }
 
-       cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC");
-       if (!cprc_base) {
-               panic("Unable to remap CPRC\n");
-       }
+       clk = clk_get(NULL, "cpu_clk");
+       scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) /
+                       (unsigned long long)(clk_get_rate(clk) / HZ));
 
        rtc_sh_get_time(&xtime);
 
        setup_irq(TIMER_IRQ, &irq0);
-       setup_irq(RTC_IRQ, &irq1);
-
-       /* Check how fast it is.. */
-       cpu_clock = get_cpu_hz();
-
-       /* Note careful order of operations to maintain reasonable precision and avoid overflow. */
-       scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) / (unsigned long long)(cpu_clock / HZ));
-
-       free_irq(RTC_IRQ, NULL);
-
-       printk("CPU clock: %d.%02dMHz\n",
-              (cpu_clock / 1000000), (cpu_clock % 1000000)/10000);
-       {
-               unsigned short bfc;
-               frqcr = ctrl_inl(FRQCR);
-               ifc  = ifc_table[(frqcr>> 6) & 0x0007];
-               bfc  = bfc_table[(frqcr>> 3) & 0x0007];
-               pfc  = pfc_table[(frqcr>> 12) & 0x0007];
-               master_clock = cpu_clock * ifc;
-               bus_clock = master_clock/bfc;
-       }
 
-       printk("Bus clock: %d.%02dMHz\n",
-              (bus_clock/1000000), (bus_clock % 1000000)/10000);
-       module_clock = master_clock/pfc;
-       printk("Module clock: %d.%02dMHz\n",
-              (module_clock/1000000), (module_clock % 1000000)/10000);
-       interval = (module_clock/(HZ*4));
+       clk = clk_get(NULL, "module_clk");
+       interval = (clk_get_rate(clk)/(HZ*4));
 
        printk("Interval = %ld\n", interval);
 
-       current_cpu_data.cpu_clock    = cpu_clock;
-       current_cpu_data.master_clock = master_clock;
-       current_cpu_data.bus_clock    = bus_clock;
-       current_cpu_data.module_clock = module_clock;
-
        /* Start TMU0 */
        ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
        ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
@@ -454,36 +330,6 @@ void __init time_init(void)
        ctrl_outb(TMU_TSTR_INIT, TMU_TSTR);
 }
 
-void enter_deep_standby(void)
-{
-       /* Disable watchdog timer */
-       ctrl_outl(0xa5000000, WTCSR);
-       /* Configure deep standby on sleep */
-       ctrl_outl(0x03, STBCR);
-
-#ifdef CONFIG_SH_ALPHANUMERIC
-       {
-               extern void mach_alphanum(int position, unsigned char value);
-               extern void mach_alphanum_brightness(int setting);
-               char halted[] = "Halted. ";
-               int i;
-               mach_alphanum_brightness(6); /* dimmest setting above off */
-               for (i=0; i<8; i++) {
-                       mach_alphanum(i, halted[i]);
-               }
-               asm __volatile__ ("synco");
-       }
-#endif
-
-       asm __volatile__ ("sleep");
-       asm __volatile__ ("synci");
-       asm __volatile__ ("nop");
-       asm __volatile__ ("nop");
-       asm __volatile__ ("nop");
-       asm __volatile__ ("nop");
-       panic("Unexpected wakeup!\n");
-}
-
 static struct resource rtc_resources[] = {
        [0] = {
                /* RTC base, filled in by rtc_init */
index bcf244ff6a128a90698257804490f9d6c3d4be97..0b7f8577193ffb2a10d268309b12f607f3a0ad7f 100644 (file)
@@ -8,3 +8,4 @@ obj-$(CONFIG_SH_TMU)            += timer-tmu.o
 obj-$(CONFIG_SH_MTU2)          += timer-mtu2.o
 obj-$(CONFIG_SH_CMT)           += timer-cmt.o
 
+obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += timer-broadcast.o
diff --git a/arch/sh/kernel/timers/timer-broadcast.c b/arch/sh/kernel/timers/timer-broadcast.c
new file mode 100644 (file)
index 0000000..c231763
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Dummy local timer
+ *
+ * Copyright (C) 2008  Paul Mundt
+ *
+ * cloned from:
+ *
+ *  linux/arch/arm/mach-realview/localtimer.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/smp.h>
+#include <linux/jiffies.h>
+#include <linux/percpu.h>
+#include <linux/clockchips.h>
+#include <linux/irq.h>
+
+static DEFINE_PER_CPU(struct clock_event_device, local_clockevent);
+
+/*
+ * Used on SMP for either the local timer or SMP_MSG_TIMER
+ */
+void local_timer_interrupt(void)
+{
+       struct clock_event_device *clk = &__get_cpu_var(local_clockevent);
+
+       clk->event_handler(clk);
+}
+
+static void dummy_timer_set_mode(enum clock_event_mode mode,
+                                struct clock_event_device *clk)
+{
+}
+
+void __cpuinit local_timer_setup(unsigned int cpu)
+{
+       struct clock_event_device *clk = &per_cpu(local_clockevent, cpu);
+
+       clk->name               = "dummy_timer";
+       clk->features           = CLOCK_EVT_FEAT_DUMMY;
+       clk->rating             = 200;
+       clk->mult               = 1;
+       clk->set_mode           = dummy_timer_set_mode;
+       clk->broadcast          = smp_timer_broadcast;
+       clk->cpumask            = cpumask_of_cpu(cpu);
+
+       clockevents_register_device(clk);
+}
index d20c8c3758817981549ac4fce5e47d7dafc2ffa7..c127293271e1f4072140e334697346bb0ab24779 100644 (file)
@@ -174,7 +174,7 @@ static int cmt_timer_init(void)
        return 0;
 }
 
-struct sys_timer_ops cmt_timer_ops = {
+static struct sys_timer_ops cmt_timer_ops = {
        .init           = cmt_timer_init,
        .start          = cmt_timer_start,
        .stop           = cmt_timer_stop,
index 1ca9ad49b54145c89b001d24371b40876751ba49..aaaf90d06b85f89237e776125c27fd43e6eb8064 100644 (file)
 #define TMU_TOCR_INIT  0x00
 #define TMU_TCR_INIT   0x0020
 
-static int tmu_timer_start(void)
+#define TMU0           (0)
+#define TMU1           (1)
+
+static inline void _tmu_start(int tmu_num)
 {
-       ctrl_outb(ctrl_inb(TMU_012_TSTR) | 0x3, TMU_012_TSTR);
-       return 0;
+       ctrl_outb(ctrl_inb(TMU_012_TSTR) | (0x1<<tmu_num), TMU_012_TSTR);
 }
 
-static void tmu0_timer_set_interval(unsigned long interval, unsigned int reload)
+static inline void _tmu_set_irq(int tmu_num, int enabled)
 {
-       ctrl_outl(interval, TMU0_TCNT);
+       register unsigned long tmu_tcr = TMU0_TCR + (0xc*tmu_num);
+       ctrl_outw( (enabled ? ctrl_inw(tmu_tcr) | (1<<5) : ctrl_inw(tmu_tcr) & ~(1<<5)), tmu_tcr);
+}
 
-       /*
-        * TCNT reloads from TCOR on underflow, clear it if we don't
-        * intend to auto-reload
-        */
-       if (reload)
-               ctrl_outl(interval, TMU0_TCOR);
-       else
-               ctrl_outl(0, TMU0_TCOR);
+static inline void _tmu_stop(int tmu_num)
+{
+       ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~(0x1<<tmu_num), TMU_012_TSTR);
+}
+
+static inline void _tmu_clear_status(int tmu_num)
+{
+       register unsigned long tmu_tcr = TMU0_TCR + (0xc*tmu_num);
+       /* Clear UNF bit */
+       ctrl_outw(ctrl_inw(tmu_tcr) & ~0x100, tmu_tcr);
+}
 
-       tmu_timer_start();
+static inline unsigned long _tmu_read(int tmu_num)
+{
+        return ctrl_inl(TMU0_TCNT+0xC*tmu_num);
+}
+
+static int tmu_timer_start(void)
+{
+       _tmu_start(TMU0);
+       _tmu_start(TMU1);
+       _tmu_set_irq(TMU0,1);
+       return 0;
 }
 
 static int tmu_timer_stop(void)
 {
-       ctrl_outb(ctrl_inb(TMU_012_TSTR) & ~0x3, TMU_012_TSTR);
+       _tmu_stop(TMU0);
+       _tmu_stop(TMU1);
+       _tmu_clear_status(TMU0);
        return 0;
 }
 
+/*
+ * also when the module_clk is scaled the TMU1
+ * will show the same frequency
+ */
+static int tmus_are_scaled;
+
 static cycle_t tmu_timer_read(void)
 {
-       return ~ctrl_inl(TMU1_TCNT);
+       return ((cycle_t)(~_tmu_read(TMU1)))<<tmus_are_scaled;
+}
+
+
+static unsigned long tmu_latest_interval[3];
+static void tmu_timer_set_interval(int tmu_num, unsigned long interval, unsigned int reload)
+{
+       unsigned long tmu_tcnt = TMU0_TCNT + tmu_num*0xC;
+       unsigned long tmu_tcor = TMU0_TCOR + tmu_num*0xC;
+
+       _tmu_stop(tmu_num);
+
+       ctrl_outl(interval, tmu_tcnt);
+       tmu_latest_interval[tmu_num] = interval;
+
+       /*
+        * TCNT reloads from TCOR on underflow, clear it if we don't
+        * intend to auto-reload
+        */
+       ctrl_outl( reload ? interval : 0 , tmu_tcor);
+
+       _tmu_start(tmu_num);
 }
 
 static int tmu_set_next_event(unsigned long cycles,
                              struct clock_event_device *evt)
 {
-       tmu0_timer_set_interval(cycles, 1);
+       tmu_timer_set_interval(TMU0,cycles, evt->mode == CLOCK_EVT_MODE_PERIODIC);
+       _tmu_set_irq(TMU0,1);
        return 0;
 }
 
@@ -96,12 +143,8 @@ static struct clock_event_device tmu0_clockevent = {
 static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 {
        struct clock_event_device *evt = &tmu0_clockevent;
-       unsigned long timer_status;
-
-       /* Clear UNF bit */
-       timer_status = ctrl_inw(TMU0_TCR);
-       timer_status &= ~0x100;
-       ctrl_outw(timer_status, TMU0_TCR);
+       _tmu_clear_status(TMU0);
+       _tmu_set_irq(TMU0,tmu0_clockevent.mode != CLOCK_EVT_MODE_ONESHOT);
 
        evt->event_handler(evt);
 
@@ -109,56 +152,73 @@ static irqreturn_t tmu_timer_interrupt(int irq, void *dummy)
 }
 
 static struct irqaction tmu0_irq = {
-       .name           = "periodic timer",
+       .name           = "periodic/oneshot timer",
        .handler        = tmu_timer_interrupt,
        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .mask           = CPU_MASK_NONE,
 };
 
-static void tmu0_clk_init(struct clk *clk)
+static void __init tmu_clk_init(struct clk *clk)
 {
-       u8 divisor = TMU_TCR_INIT & 0x7;
-       ctrl_outw(TMU_TCR_INIT, TMU0_TCR);
-       clk->rate = clk->parent->rate / (4 << (divisor << 1));
+       u8 divisor  = TMU_TCR_INIT & 0x7;
+       int tmu_num = clk->name[3]-'0';
+       ctrl_outw(TMU_TCR_INIT, TMU0_TCR+(tmu_num*0xC));
+       clk->rate = clk_get_rate(clk->parent) / (4 << (divisor << 1));
 }
 
-static void tmu0_clk_recalc(struct clk *clk)
+static void tmu_clk_recalc(struct clk *clk)
 {
-       u8 divisor = ctrl_inw(TMU0_TCR) & 0x7;
-       clk->rate = clk->parent->rate / (4 << (divisor << 1));
-}
+       int tmu_num = clk->name[3]-'0';
+       unsigned long prev_rate = clk_get_rate(clk);
+       unsigned long flags;
+       u8 divisor = ctrl_inw(TMU0_TCR+tmu_num*0xC) & 0x7;
+       clk->rate  = clk_get_rate(clk->parent) / (4 << (divisor << 1));
 
-static struct clk_ops tmu0_clk_ops = {
-       .init           = tmu0_clk_init,
-       .recalc         = tmu0_clk_recalc,
-};
+       if(prev_rate==clk_get_rate(clk))
+               return;
 
-static struct clk tmu0_clk = {
-       .name           = "tmu0_clk",
-       .ops            = &tmu0_clk_ops,
-};
+       if(tmu_num)
+               return; /* No more work on TMU1 */
 
-static void tmu1_clk_init(struct clk *clk)
-{
-       u8 divisor = TMU_TCR_INIT & 0x7;
-       ctrl_outw(divisor, TMU1_TCR);
-       clk->rate = clk->parent->rate / (4 << (divisor << 1));
-}
+       local_irq_save(flags);
+       tmus_are_scaled = (prev_rate > clk->rate);
 
-static void tmu1_clk_recalc(struct clk *clk)
-{
-       u8 divisor = ctrl_inw(TMU1_TCR) & 0x7;
-       clk->rate = clk->parent->rate / (4 << (divisor << 1));
+       _tmu_stop(TMU0);
+
+       tmu0_clockevent.mult = div_sc(clk->rate, NSEC_PER_SEC,
+                               tmu0_clockevent.shift);
+       tmu0_clockevent.max_delta_ns =
+                       clockevent_delta2ns(-1, &tmu0_clockevent);
+       tmu0_clockevent.min_delta_ns =
+                       clockevent_delta2ns(1, &tmu0_clockevent);
+
+       if (tmus_are_scaled)
+               tmu_latest_interval[TMU0] >>= 1;
+       else
+               tmu_latest_interval[TMU0] <<= 1;
+
+       tmu_timer_set_interval(TMU0,
+               tmu_latest_interval[TMU0],
+               tmu0_clockevent.mode == CLOCK_EVT_MODE_PERIODIC);
+
+       _tmu_start(TMU0);
+
+       local_irq_restore(flags);
 }
 
-static struct clk_ops tmu1_clk_ops = {
-       .init           = tmu1_clk_init,
-       .recalc         = tmu1_clk_recalc,
+static struct clk_ops tmu_clk_ops = {
+       .init           = tmu_clk_init,
+       .recalc         = tmu_clk_recalc,
+};
+
+static struct clk tmu0_clk = {
+       .name           = "tmu0_clk",
+       .ops            = &tmu_clk_ops,
 };
 
 static struct clk tmu1_clk = {
        .name           = "tmu1_clk",
-       .ops            = &tmu1_clk_ops,
+       .ops            = &tmu_clk_ops,
 };
 
 static int tmu_timer_init(void)
@@ -189,11 +249,12 @@ static int tmu_timer_init(void)
        frequency = clk_get_rate(&tmu0_clk);
        interval = (frequency + HZ / 2) / HZ;
 
-       sh_hpt_frequency = clk_get_rate(&tmu1_clk);
-       ctrl_outl(~0, TMU1_TCNT);
-       ctrl_outl(~0, TMU1_TCOR);
+       tmu_timer_set_interval(TMU0,interval, 1);
+       tmu_timer_set_interval(TMU1,~0,1);
 
-       tmu0_timer_set_interval(interval, 1);
+       _tmu_start(TMU1);
+
+       sh_hpt_frequency = clk_get_rate(&tmu1_clk);
 
        tmu0_clockevent.mult = div_sc(frequency, NSEC_PER_SEC,
                                      tmu0_clockevent.shift);
index 511a9426cec58a348fb7fd45bdf4db11d654b31c..b359b08a8e33a9cb827145abe0c02c6ad66dc9d9 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/fpu.h>
+#include <asm/kprobes.h>
 
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
@@ -192,6 +193,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
        int ret, index, count;
        unsigned long *rm, *rn;
        unsigned char *src, *dst;
+       unsigned char __user *srcu, *dstu;
 
        index = (instruction>>8)&15;    /* 0x0F00 */
        rn = &regs->regs[index];
@@ -206,28 +208,28 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
        case 0: /* mov.[bwl] to/from memory via r0+rn */
                if (instruction & 8) {
                        /* from memory */
-                       src = (unsigned char*) *rm;
-                       src += regs->regs[0];
-                       dst = (unsigned char*) rn;
-                       *(unsigned long*)dst = 0;
+                       srcu = (unsigned char __user *)*rm;
+                       srcu += regs->regs[0];
+                       dst = (unsigned char *)rn;
+                       *(unsigned long *)dst = 0;
 
 #if !defined(__LITTLE_ENDIAN__)
                        dst += 4-count;
 #endif
-                       if (ma->from(dst, src, count))
+                       if (ma->from(dst, srcu, count))
                                goto fetch_fault;
 
                        sign_extend(count, dst);
                } else {
                        /* to memory */
-                       src = (unsigned char*) rm;
+                       src = (unsigned char *)rm;
 #if !defined(__LITTLE_ENDIAN__)
                        src += 4-count;
 #endif
-                       dst = (unsigned char*) *rn;
-                       dst += regs->regs[0];
+                       dstu = (unsigned char __user *)*rn;
+                       dstu += regs->regs[0];
 
-                       if (ma->to(dst, src, count))
+                       if (ma->to(dstu, src, count))
                                goto fetch_fault;
                }
                ret = 0;
@@ -235,10 +237,10 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
 
        case 1: /* mov.l Rm,@(disp,Rn) */
                src = (unsigned char*) rm;
-               dst = (unsigned char*) *rn;
-               dst += (instruction&0x000F)<<2;
+               dstu = (unsigned char __user *)*rn;
+               dstu += (instruction&0x000F)<<2;
 
-               if (ma->to(dst, src, 4))
+               if (ma->to(dstu, src, 4))
                        goto fetch_fault;
                ret = 0;
                break;
@@ -247,28 +249,28 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
                if (instruction & 4)
                        *rn -= count;
                src = (unsigned char*) rm;
-               dst = (unsigned char*) *rn;
+               dstu = (unsigned char __user *)*rn;
 #if !defined(__LITTLE_ENDIAN__)
                src += 4-count;
 #endif
-               if (ma->to(dst, src, count))
+               if (ma->to(dstu, src, count))
                        goto fetch_fault;
                ret = 0;
                break;
 
        case 5: /* mov.l @(disp,Rm),Rn */
-               src = (unsigned char*) *rm;
-               src += (instruction&0x000F)<<2;
-               dst = (unsigned char*) rn;
-               *(unsigned long*)dst = 0;
+               srcu = (unsigned char __user *)*rm;
+               srcu += (instruction & 0x000F) << 2;
+               dst = (unsigned char *)rn;
+               *(unsigned long *)dst = 0;
 
-               if (ma->from(dst, src, 4))
+               if (ma->from(dst, srcu, 4))
                        goto fetch_fault;
                ret = 0;
                break;
 
        case 6: /* mov.[bwl] from memory, possibly with post-increment */
-               src = (unsigned char*) *rm;
+               srcu = (unsigned char __user *)*rm;
                if (instruction & 4)
                        *rm += count;
                dst = (unsigned char*) rn;
@@ -277,7 +279,7 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
 #if !defined(__LITTLE_ENDIAN__)
                dst += 4-count;
 #endif
-               if (ma->from(dst, src, count))
+               if (ma->from(dst, srcu, count))
                        goto fetch_fault;
                sign_extend(count, dst);
                ret = 0;
@@ -286,28 +288,28 @@ static int handle_unaligned_ins(opcode_t instruction, struct pt_regs *regs,
        case 8:
                switch ((instruction&0xFF00)>>8) {
                case 0x81: /* mov.w R0,@(disp,Rn) */
-                       src = (unsigned char*) &regs->regs[0];
+                       src = (unsigned char *) &regs->regs[0];
 #if !defined(__LITTLE_ENDIAN__)
                        src += 2;
 #endif
-                       dst = (unsigned char*) *rm; /* called Rn in the spec */
-                       dst += (instruction&0x000F)<<1;
+                       dstu = (unsigned char __user *)*rm; /* called Rn in the spec */
+                       dstu += (instruction & 0x000F) << 1;
 
-                       if (ma->to(dst, src, 2))
+                       if (ma->to(dstu, src, 2))
                                goto fetch_fault;
                        ret = 0;
                        break;
 
                case 0x85: /* mov.w @(disp,Rm),R0 */
-                       src = (unsigned char*) *rm;
-                       src += (instruction&0x000F)<<1;
-                       dst = (unsigned char*) &regs->regs[0];
-                       *(unsigned long*)dst = 0;
+                       srcu = (unsigned char __user *)*rm;
+                       srcu += (instruction & 0x000F) << 1;
+                       dst = (unsigned char *) &regs->regs[0];
+                       *(unsigned long *)dst = 0;
 
 #if !defined(__LITTLE_ENDIAN__)
                        dst += 2;
 #endif
-                       if (ma->from(dst, src, 2))
+                       if (ma->from(dst, srcu, 2))
                                goto fetch_fault;
                        sign_extend(2, dst);
                        ret = 0;
@@ -333,7 +335,8 @@ static inline int handle_delayslot(struct pt_regs *regs,
                                   struct mem_access *ma)
 {
        opcode_t instruction;
-       void *addr = (void *)(regs->pc + instruction_size(old_instruction));
+       void __user *addr = (void __user *)(regs->pc +
+               instruction_size(old_instruction));
 
        if (copy_from_user(&instruction, addr, sizeof(instruction))) {
                /* the instruction-fetch faulted */
@@ -511,14 +514,6 @@ int handle_unaligned_access(opcode_t instruction, struct pt_regs *regs,
        return ret;
 }
 
-#ifdef CONFIG_CPU_HAS_SR_RB
-#define lookup_exception_vector(x)     \
-       __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x)))
-#else
-#define lookup_exception_vector(x)     \
-       __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x)))
-#endif
-
 /*
  * Handle various address error exceptions:
  *  - instruction address error:
@@ -542,7 +537,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,
 
        /* Intentional ifdef */
 #ifdef CONFIG_CPU_HAS_SR_RB
-       lookup_exception_vector(error_code);
+       error_code = lookup_exception_vector();
 #endif
 
        oldfs = get_fs();
@@ -559,7 +554,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,
                }
 
                set_fs(USER_DS);
-               if (copy_from_user(&instruction, (void *)(regs->pc),
+               if (copy_from_user(&instruction, (void __user *)(regs->pc),
                                   sizeof(instruction))) {
                        /* Argh. Fault on the instruction itself.
                           This should never happen non-SMP
@@ -589,7 +584,7 @@ uspace_segv:
                        die("unaligned program counter", regs, error_code);
 
                set_fs(KERNEL_DS);
-               if (copy_from_user(&instruction, (void *)(regs->pc),
+               if (copy_from_user(&instruction, (void __user *)(regs->pc),
                                   sizeof(instruction))) {
                        /* Argh. Fault on the instruction itself.
                           This should never happen non-SMP
@@ -683,7 +678,7 @@ asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5,
        }
 #endif
 
-       lookup_exception_vector(error_code);
+       error_code = lookup_exception_vector();
 
        local_irq_enable();
        CHK_REMOTE_DEBUG(regs);
@@ -739,11 +734,13 @@ asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
                                struct pt_regs __regs)
 {
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
-       unsigned long error_code;
+       unsigned long inst;
        struct task_struct *tsk = current;
-#ifdef CONFIG_SH_FPU_EMU
-       unsigned short inst = 0;
 
+       if (kprobe_handle_illslot(regs->pc) == 0)
+               return;
+
+#ifdef CONFIG_SH_FPU_EMU
        get_user(inst, (unsigned short *)regs->pc + 1);
        if (!do_fpu_inst(inst, regs)) {
                get_user(inst, (unsigned short *)regs->pc);
@@ -754,12 +751,12 @@ asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5,
        /* not a FPU inst. */
 #endif
 
-       lookup_exception_vector(error_code);
+       inst = lookup_exception_vector();
 
        local_irq_enable();
        CHK_REMOTE_DEBUG(regs);
        force_sig(SIGILL, tsk);
-       die_if_no_fixup("illegal slot instruction", regs, error_code);
+       die_if_no_fixup("illegal slot instruction", regs, inst);
 }
 
 asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
@@ -769,7 +766,7 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5,
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        long ex;
 
-       lookup_exception_vector(ex);
+       ex = lookup_exception_vector();
        die_if_kernel("exception", regs, ex);
 }
 
index 4bef3b5d964a1aecdec64923883f1424227a7d54..60e76aa8b53eceb6aaac7edf548c4c3a857d5827 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include <linux/types.h>
+#include <asm/div64.h>
 
 extern uint64_t __xdiv64_32(u64 n, u32 d);
 
index 4f54ec43516f297296605d57ba20dbca65345f44..88dfe6e396bc44a67e557534e8bcb86b94b43e63 100644 (file)
 #include <linux/module.h>
 #include <linux/io.h>
 
-void __raw_readsl(unsigned long addr, void *datap, int len)
+void __raw_readsl(const void __iomem *addr, void *datap, int len)
 {
        u32 *data;
 
        for (data = datap; (len != 0) && (((u32)data & 0x1f) != 0); len--)
-               *data++ = ctrl_inl(addr);
+               *data++ = __raw_readl(addr);
 
        if (likely(len >= (0x20 >> 2))) {
                int tmp2, tmp3, tmp4, tmp5, tmp6;
@@ -59,11 +59,11 @@ void __raw_readsl(unsigned long addr, void *datap, int len)
        }
 
        for (; len != 0; len--)
-               *data++ = ctrl_inl(addr);
+               *data++ = __raw_readl(addr);
 }
 EXPORT_SYMBOL(__raw_readsl);
 
-void __raw_writesl(unsigned long addr, const void *data, int len)
+void __raw_writesl(void __iomem *addr, const void *data, int len)
 {
        if (likely(len != 0)) {
                int tmp1;
index 8a03926ea84f21076c96b2775b49e4d27c7b0caf..555ec9714b9e042c6e5f6247515d5e0343021e83 100644 (file)
@@ -132,7 +132,11 @@ config ARCH_SELECT_MEMORY_MODEL
 
 config ARCH_ENABLE_MEMORY_HOTPLUG
        def_bool y
-       depends on SPARSEMEM
+       depends on SPARSEMEM && MMU
+
+config ARCH_ENABLE_MEMORY_HOTREMOVE
+       def_bool y
+       depends on SPARSEMEM && MMU
 
 config ARCH_MEMORY_PROBE
        def_bool y
index 0e189ccd4a77a7ce7462f9eb863409d419a71150..5ba067b2659109caf9d013e79d59e91c4f5278eb 100644 (file)
@@ -130,12 +130,18 @@ static int __init cache_debugfs_init(void)
        dcache_dentry = debugfs_create_file("dcache", S_IRUSR, sh_debugfs_root,
                                            (unsigned int *)CACHE_TYPE_DCACHE,
                                            &cache_debugfs_fops);
+       if (!dcache_dentry)
+               return -ENOMEM;
        if (IS_ERR(dcache_dentry))
                return PTR_ERR(dcache_dentry);
 
        icache_dentry = debugfs_create_file("icache", S_IRUSR, sh_debugfs_root,
                                            (unsigned int *)CACHE_TYPE_ICACHE,
                                            &cache_debugfs_fops);
+       if (!icache_dentry) {
+               debugfs_remove(dcache_dentry);
+               return -ENOMEM;
+       }
        if (IS_ERR(icache_dentry)) {
                debugfs_remove(dcache_dentry);
                return PTR_ERR(icache_dentry);
index 1fdc8d90254a177bbb4a345456712378a17fdb2c..5cfe08dbb59ed0997c4451459577423b8713e817 100644 (file)
@@ -261,7 +261,7 @@ void flush_dcache_page(struct page *page)
 }
 
 /* TODO: Selective icache invalidation through IC address array.. */
-static inline void __uses_jump_to_uncached flush_icache_all(void)
+static void __uses_jump_to_uncached flush_icache_all(void)
 {
        unsigned long flags, ccr;
 
index 64b8f7f96f9aed038e87be11ee374d5b0797f239..9f8ea3ada4dbe845d6ff5dde86267471022e8afc 100644 (file)
 #include <asm/addrspace.h>
 #include <asm/io.h>
 
-struct dma_coherent_mem {
-       void            *virt_base;
-       u32             device_base;
-       int             size;
-       int             flags;
-       unsigned long   *bitmap;
-};
-
 void *dma_alloc_coherent(struct device *dev, size_t size,
                           dma_addr_t *dma_handle, gfp_t gfp)
 {
@@ -44,7 +36,7 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
         */
        dma_cache_sync(dev, ret, size, DMA_BIDIRECTIONAL);
 
-       ret_nocache = ioremap_nocache(virt_to_phys(ret), size);
+       ret_nocache = (void __force *)ioremap_nocache(virt_to_phys(ret), size);
        if (!ret_nocache) {
                free_pages((unsigned long)ret, order);
                return NULL;
@@ -58,12 +50,10 @@ EXPORT_SYMBOL(dma_alloc_coherent);
 void dma_free_coherent(struct device *dev, size_t size,
                         void *vaddr, dma_addr_t dma_handle)
 {
-       struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
        int order = get_order(size);
 
        if (!dma_release_from_coherent(dev, order, vaddr)) {
                WARN_ON(irqs_disabled());       /* for portability */
-               BUG_ON(mem && mem->flags & DMA_MEMORY_EXCLUSIVE);
                free_pages((unsigned long)phys_to_virt(dma_handle), order);
                iounmap(vaddr);
        }
index 0c776fdfbddae6800480dc0a3dc7be54103509b3..898d477e47c171e6930832d950d85f0a3bd9a617 100644 (file)
@@ -2,7 +2,7 @@
  * Page fault handler for SH with an MMU.
  *
  *  Copyright (C) 1999  Niibe Yutaka
- *  Copyright (C) 2003 - 2007  Paul Mundt
+ *  Copyright (C) 2003 - 2008  Paul Mundt
  *
  *  Based on linux/arch/i386/mm/fault.c:
  *   Copyright (C) 1995  Linus Torvalds
@@ -15,6 +15,7 @@
 #include <linux/mm.h>
 #include <linux/hardirq.h>
 #include <linux/kprobes.h>
+#include <linux/marker.h>
 #include <asm/io_trapped.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
@@ -37,10 +38,10 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
        int fault;
        siginfo_t info;
 
-#ifdef CONFIG_SH_KGDB
-       if (kgdb_nofault && kgdb_bus_err_hook)
-               kgdb_bus_err_hook();
-#endif
+       /*
+        * We don't bother with any notifier callbacks here, as they are
+        * all handled through the __do_page_fault() fast-path.
+        */
 
        tsk = current;
        si_code = SEGV_MAPERR;
@@ -61,7 +62,6 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
                pgd = get_TTB() + offset;
                pgd_k = swapper_pg_dir + offset;
 
-               /* This will never happen with the folded page table. */
                if (!pgd_present(*pgd)) {
                        if (!pgd_present(*pgd_k))
                                goto bad_area_nosemaphore;
@@ -71,9 +71,13 @@ asmlinkage void __kprobes do_page_fault(struct pt_regs *regs,
 
                pud = pud_offset(pgd, address);
                pud_k = pud_offset(pgd_k, address);
-               if (pud_present(*pud) || !pud_present(*pud_k))
-                       goto bad_area_nosemaphore;
-               set_pud(pud, *pud_k);
+
+               if (!pud_present(*pud)) {
+                       if (!pud_present(*pud_k))
+                               goto bad_area_nosemaphore;
+                       set_pud(pud, *pud_k);
+                       return;
+               }
 
                pmd = pmd_offset(pud, address);
                pmd_k = pmd_offset(pud_k, address);
@@ -242,6 +246,25 @@ do_sigbus:
                goto no_context;
 }
 
+static inline int notify_page_fault(struct pt_regs *regs, int trap)
+{
+       int ret = 0;
+
+       trace_mark(kernel_arch_trap_entry, "trap_id %d ip #p%ld",
+                  trap >> 5, instruction_pointer(regs));
+
+#ifdef CONFIG_KPROBES
+       if (!user_mode(regs)) {
+               preempt_disable();
+               if (kprobe_running() && kprobe_fault_handler(regs, trap))
+                       ret = 1;
+               preempt_enable();
+       }
+#endif
+
+       return ret;
+}
+
 #ifdef CONFIG_SH_STORE_QUEUES
 /*
  * This is a special case for the SH-4 store queues, as pages for this
@@ -265,12 +288,18 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
        pmd_t *pmd;
        pte_t *pte;
        pte_t entry;
+       int ret = 0;
+
+       if (notify_page_fault(regs, lookup_exception_vector()))
+               goto out;
 
 #ifdef CONFIG_SH_KGDB
        if (kgdb_nofault && kgdb_bus_err_hook)
                kgdb_bus_err_hook();
 #endif
 
+       ret = 1;
+
        /*
         * We don't take page faults for P1, P2, and parts of P4, these
         * are always mapped, whether it be due to legacy behaviour in
@@ -280,24 +309,23 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
                pgd = pgd_offset_k(address);
        } else {
                if (unlikely(address >= TASK_SIZE || !current->mm))
-                       return 1;
+                       goto out;
 
                pgd = pgd_offset(current->mm, address);
        }
 
        pud = pud_offset(pgd, address);
        if (pud_none_or_clear_bad(pud))
-               return 1;
+               goto out;
        pmd = pmd_offset(pud, address);
        if (pmd_none_or_clear_bad(pmd))
-               return 1;
-
+               goto out;
        pte = pte_offset_kernel(pmd, address);
        entry = *pte;
        if (unlikely(pte_none(entry) || pte_not_present(entry)))
-               return 1;
+               goto out;
        if (unlikely(writeaccess && !pte_write(entry)))
-               return 1;
+               goto out;
 
        if (writeaccess)
                entry = pte_mkdirty(entry);
@@ -314,5 +342,8 @@ asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs,
        set_pte(pte, entry);
        update_mmu_cache(NULL, address, entry);
 
-       return 0;
+       ret = 0;
+out:
+       trace_mark(kernel_arch_trap_exit, MARK_NOARGS);
+       return ret;
 }
index b75a7acd62fb7818f8fec20cc72aa7794d0ff159..2a53943924b2c99479e3c748a31acf9db45494d1 100644 (file)
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 pgd_t swapper_pg_dir[PTRS_PER_PGD];
-unsigned long cached_to_uncached = 0;
+
+#ifdef CONFIG_SUPERH32
+/*
+ * Handle trivial transitions between cached and uncached
+ * segments, making use of the 1:1 mapping relationship in
+ * 512MB lowmem.
+ *
+ * This is the offset of the uncached section from its cached alias.
+ * Default value only valid in 29 bit mode, in 32bit mode will be
+ * overridden in pmb_init.
+ */
+unsigned long cached_to_uncached = P2SEG - P1SEG;
+#endif
 
 #ifdef CONFIG_MMU
 static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
@@ -58,9 +70,7 @@ static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
        }
 
        set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
-
-       if (cached_to_uncached)
-               flush_tlb_one(get_asid(), addr);
+       flush_tlb_one(get_asid(), addr);
 }
 
 /*
@@ -113,7 +123,6 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
                if (!pmd_present(*pmd)) {
                        pte_t *pte_table;
                        pte_table = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE);
-                       memset(pte_table, 0, PAGE_SIZE);
                        pmd_populate_kernel(&init_mm, pmd, pte_table);
                }
 
@@ -165,15 +174,6 @@ void __init paging_init(void)
 #ifdef CONFIG_SUPERH32
        /* Set up the uncached fixmap */
        set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start));
-
-#ifdef CONFIG_29BIT
-       /*
-        * Handle trivial transitions between cached and uncached
-        * segments, making use of the 1:1 mapping relationship in
-        * 512MB lowmem.
-        */
-       cached_to_uncached = P2SEG - P1SEG;
-#endif
 #endif
 }
 
@@ -265,6 +265,35 @@ void free_initrd_mem(unsigned long start, unsigned long end)
 }
 #endif
 
+#if THREAD_SHIFT < PAGE_SHIFT
+static struct kmem_cache *thread_info_cache;
+
+struct thread_info *alloc_thread_info(struct task_struct *tsk)
+{
+       struct thread_info *ti;
+
+       ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
+       if (unlikely(ti == NULL))
+               return NULL;
+#ifdef CONFIG_DEBUG_STACK_USAGE
+       memset(ti, 0, THREAD_SIZE);
+#endif
+       return ti;
+}
+
+void free_thread_info(struct thread_info *ti)
+{
+       kmem_cache_free(thread_info_cache, ti);
+}
+
+void thread_info_cache_init(void)
+{
+       thread_info_cache = kmem_cache_create("thread_info", THREAD_SIZE,
+                                             THREAD_SIZE, 0, NULL);
+       BUG_ON(thread_info_cache == NULL);
+}
+#endif /* THREAD_SHIFT < PAGE_SHIFT */
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 int arch_add_memory(int nid, u64 start, u64 size)
 {
@@ -292,4 +321,21 @@ int memory_add_physaddr_to_nid(u64 addr)
 }
 EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
 #endif
+
+#ifdef CONFIG_MEMORY_HOTREMOVE
+int remove_memory(u64 start, u64 size)
+{
+       unsigned long start_pfn = start >> PAGE_SHIFT;
+       unsigned long end_pfn = start_pfn + (size >> PAGE_SHIFT);
+       int ret;
+
+       ret = offline_pages(start_pfn, end_pfn, 120 * HZ);
+       if (unlikely(ret))
+               printk("%s: Failed, offline_pages() == %d\n", __func__, ret);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(remove_memory);
 #endif
+
+#endif /* CONFIG_MEMORY_HOTPLUG */
index 677dd57f0877dfa0cb0ca6de0025558b2df176de..91ed4e695ff7cd0e9624583c777eab2215411b69 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <asm/page.h>
+#include <asm/uaccess.h>
 
 void copy_page(void *to, void *from)
 {
index cef727669c8759dde6ce20ceb9ecc138d71a28bb..84241676265e61455f4e9579f7cf41810601f1e9 100644 (file)
@@ -394,6 +394,8 @@ static int __init pmb_debugfs_init(void)
 
        dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
                                     sh_debugfs_root, NULL, &pmb_debugfs_fops);
+       if (!dentry)
+               return -ENOMEM;
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
 
index 15111bc7ddd62719d6fd9fe25e9bd6dcacaa659e..71c742b5aee313b4badeaa62ac8610086fad2522 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 /*
  * Nothing too terribly exciting here ..
index 0a11cc08f0a593d0bf134bade882b0de0e6f2449..d4fb11f7e2ee131def513e5fb2515c2b2da2fad3 100644 (file)
@@ -30,6 +30,7 @@ HP6XX                 SH_HP6XX
 DREAMCAST              SH_DREAMCAST
 SNAPGEAR               SH_SECUREEDGE5410
 EDOSK7705              SH_EDOSK7705
+EDOSK7760              SH_EDOSK7760
 SH4202_MICRODEV                SH_SH4202_MICRODEV
 SH03                   SH_SH03
 LANDISK                        SH_LANDISK
index 97671dac12a649765e3b8fda6d22317963872749..e594559c8dbaa7658f56f079354e8ed25468fdcf 100644 (file)
@@ -37,6 +37,8 @@ config HZ
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 menu "General machine setup"
 
 config SMP
index 29899fd5b1b228236d3f495c35e16ed511b57cb4..80fe547c3f45c5048c981ce2401e40243879e13f 100644 (file)
@@ -135,6 +135,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 #define TIF_POLLING_NRFLAG     9       /* true if poll_idle() is polling
                                         * TIF_NEED_RESCHED */
 #define TIF_MEMDIE             10
+#define TIF_FREEZE             11      /* is freezing for suspend */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
@@ -148,6 +149,7 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 #define _TIF_DO_NOTIFY_RESUME_MASK     (_TIF_NOTIFY_RESUME | \
                                         _TIF_SIGPENDING | \
                                         _TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 #endif /* __KERNEL__ */
 
index c0a737d7292c4462456f0b0e27ff6aae149142a6..639ac805448ab500497270013b9176510849062a 100644 (file)
@@ -237,6 +237,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define TIF_ABI_PENDING                12
 #define TIF_MEMDIE             13
 #define TIF_POLLING_NRFLAG     14
+#define TIF_FREEZE             15      /* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
@@ -249,6 +250,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 #define _TIF_USER_WORK_MASK    ((0xff << TI_FLAG_WSAVED_SHIFT) | \
                                 _TIF_DO_NOTIFY_RESUME_MASK | \
index 5446e2a499b13d36e3e50a529e85cd0e91ad5de4..035b15af90d8a668583001ef9610ab761d7b9478 100644 (file)
@@ -96,6 +96,7 @@ config GENERIC_HARDIRQS_NO__DO_IRQ
        def_bool y
 
 source "init/Kconfig"
+source "kernel/Kconfig.freezer"
 
 menu "Processor type and features"
 
index 6976812cfb184553bb93778bba38b2f3c01f922c..393bccfe1785108579dc6c18bab682f2e7984110 100644 (file)
@@ -229,6 +229,8 @@ endmenu
 
 source "init/Kconfig"
 
+source "kernel/Kconfig.freezer"
+
 source "drivers/block/Kconfig"
 
 source "arch/um/Kconfig.char"
index fd0c25ad6af3ecdbd03be96d1a9ee142ec8560e2..129647375a6ccfb7f61910f0c8543ed9053f7480 100644 (file)
@@ -179,7 +179,8 @@ static int copy_sc_from_user(struct pt_regs *regs,
        if (have_fpx_regs) {
                struct user_fxsr_struct fpx;
 
-               err = copy_from_user(&fpx, &sc.fpstate->_fxsr_env[0],
+               err = copy_from_user(&fpx,
+                       &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
                                     sizeof(struct user_fxsr_struct));
                if (err)
                        return 1;
index bd3c2c53873ecb4cd0b944e31996b746884d6cf0..49349ba77d80b81141deb6065510e54fc74eb077 100644 (file)
@@ -193,6 +193,7 @@ config X86_TRAMPOLINE
 config KTIME_SCALAR
        def_bool X86_32
 source "init/Kconfig"
+source "kernel/Kconfig.freezer"
 
 menu "Processor type and features"
 
index 72d0c56c1b48eff12779b557a75f3aee376c5571..f7cdb3b457aadc7f0f8951323dc507827211be75 100644 (file)
@@ -13,6 +13,9 @@
 
 static void *kdump_buf_page;
 
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
index e90a60ef10c2b641f524844e4902969cdd8235b4..045b36cada655370382231cb186d45d5d8820d95 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
+/* Stores the physical address of elf header of crash image. */
+unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
+
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
index 0a23b5795b25a87c38b117e4bfc168dfc565c2d5..dd6f2b71561bfbdc245e78cae8cfac30d44d425e 100644 (file)
@@ -52,7 +52,7 @@ int mach_set_rtc_mmss(unsigned long nowtime)
 
        cmos_minutes = CMOS_READ(RTC_MINUTES);
        if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               BCD_TO_BIN(cmos_minutes);
+               cmos_minutes = bcd2bin(cmos_minutes);
 
        /*
         * since we're only adjusting minutes and seconds,
@@ -69,8 +69,8 @@ int mach_set_rtc_mmss(unsigned long nowtime)
 
        if (abs(real_minutes - cmos_minutes) < 30) {
                if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-                       BIN_TO_BCD(real_seconds);
-                       BIN_TO_BCD(real_minutes);
+                       real_seconds = bin2bcd(real_seconds);
+                       real_minutes = bin2bcd(real_minutes);
                }
                CMOS_WRITE(real_seconds,RTC_SECONDS);
                CMOS_WRITE(real_minutes,RTC_MINUTES);
@@ -124,16 +124,16 @@ unsigned long mach_get_cmos_time(void)
        WARN_ON_ONCE(RTC_ALWAYS_BCD && (status & RTC_DM_BINARY));
 
        if (RTC_ALWAYS_BCD || !(status & RTC_DM_BINARY)) {
-               BCD_TO_BIN(sec);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(hour);
-               BCD_TO_BIN(day);
-               BCD_TO_BIN(mon);
-               BCD_TO_BIN(year);
+               sec = bcd2bin(sec);
+               min = bcd2bin(min);
+               hour = bcd2bin(hour);
+               day = bcd2bin(day);
+               mon = bcd2bin(mon);
+               year = bcd2bin(year);
        }
 
        if (century) {
-               BCD_TO_BIN(century);
+               century = bcd2bin(century);
                year += century * 100;
                printk(KERN_INFO "Extended CMOS year: %d\n", century * 100);
        } else
index 2255782e8d4b94664ff8c3c053af26aa114d0e6c..b2c97874ec0f95f7cfbea51b7b7695a2939c1b01 100644 (file)
@@ -561,7 +561,13 @@ static void __init reserve_standard_io_resources(void)
 
 }
 
-#ifdef CONFIG_PROC_VMCORE
+/*
+ * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
+ * is_kdump_kernel() to determine if we are booting after a panic. Hence
+ * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
+ */
+
+#ifdef CONFIG_CRASH_DUMP
 /* elfcorehdr= specifies the location of elf core header
  * stored by the crashed kernel. This option will be passed
  * by kexec loader to the capture kernel.
index a9ec89c3fbca32c3fda0e65d8da8846c8f96ed2a..407d8784f669603fd48667c8d2ee22bb8e870f35 100644 (file)
@@ -792,6 +792,8 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
        /* Must avoid aliasing mappings in the highmem code */
        kmap_flush_unused();
 
+       vm_unmap_aliases();
+
        cpa.vaddr = addr;
        cpa.numpages = numpages;
        cpa.mask_set = mask_set;
index 0013a729b41ddc93045510068da9bcbbadf76433..b61534c7a4c4d5894812c5bb97a89f29a0f72338 100644 (file)
@@ -871,6 +871,7 @@ static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned l
                        /* make sure there are no stray mappings of
                           this page */
                        kmap_flush_unused();
+                       vm_unmap_aliases();
        }
 }
 
index ae173f6edd8ba044f5cc5372193ea7ce0af2e299..d4d52f5a1cf7bae392801e19367030ebe58ccf79 100644 (file)
@@ -846,6 +846,7 @@ static void __xen_pgd_pin(struct mm_struct *mm, pgd_t *pgd)
                /* re-enable interrupts for kmap_flush_unused */
                xen_mc_issue(0);
                kmap_flush_unused();
+               vm_unmap_aliases();
                xen_mc_batch();
        }
 
index 02e417d3d8e95815713b1420146b069112da6b99..a213260b51e5b4d8d3d64d7aebc85d2b2f21eb74 100644 (file)
@@ -55,6 +55,7 @@ config HZ
        default 100
 
 source "init/Kconfig"
+source "kernel/Kconfig.freezer"
 
 menu "Processor type and features"
 
index b1c723f9f58d1fce3861730870b58550fe13f6a2..70f7f60929ca552f87dfa819dd93296abd3cea60 100644 (file)
@@ -431,7 +431,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
 }
 
 static struct device_attribute alarm_attr = {
-       .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
+       .attr = {.name = "alarm", .mode = 0644},
        .show = acpi_battery_alarm_show,
        .store = acpi_battery_alarm_store,
 };
index 10a36512647ca6107a76c5982a5f3acaa140b571..7b011e7e29fe00b35ab1616d4c7a232c32ec8d2b 100644 (file)
@@ -463,7 +463,7 @@ static ssize_t acpi_battery_alarm_store(struct device *dev,
 }
 
 static struct device_attribute alarm_attr = {
-       .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE},
+       .attr = {.name = "alarm", .mode = 0644},
        .show = acpi_battery_alarm_show,
        .store = acpi_battery_alarm_store,
 };
index bf5b04de02d1c6e48123454656ab3f36e72bf8b7..631ee2ee2ca0028193ab5d52dee2acc0d15579f2 100644 (file)
@@ -120,13 +120,13 @@ static int acpi_system_alarm_seq_show(struct seq_file *seq, void *offset)
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(sec);
-               BCD_TO_BIN(min);
-               BCD_TO_BIN(hr);
-               BCD_TO_BIN(day);
-               BCD_TO_BIN(mo);
-               BCD_TO_BIN(yr);
-               BCD_TO_BIN(cent);
+               sec = bcd2bin(sec);
+               min = bcd2bin(min);
+               hr = bcd2bin(hr);
+               day = bcd2bin(day);
+               mo = bcd2bin(mo);
+               yr = bcd2bin(yr);
+               cent = bcd2bin(cent);
        }
 
        /* we're trusting the FADT (see above) */
@@ -204,7 +204,7 @@ static u32 cmos_bcd_read(int offset, int rtc_control)
 {
        u32 val = CMOS_READ(offset);
        if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               BCD_TO_BIN(val);
+               val = bcd2bin(val);
        return val;
 }
 
@@ -212,7 +212,7 @@ static u32 cmos_bcd_read(int offset, int rtc_control)
 static void cmos_bcd_write(u32 val, int offset, int rtc_control)
 {
        if (!(rtc_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               BIN_TO_BCD(val);
+               val = bin2bcd(val);
        CMOS_WRITE(val, offset);
 }
 
index 91dec448b3edcd5055112a892f1c368433bc6281..24e80fd927e238a6e8ea60ebafe2d4ae57f5f2c1 100644 (file)
@@ -115,7 +115,6 @@ static void acpi_table_attr_init(struct acpi_table_attr *table_attr,
        table_attr->attr.read = acpi_table_show;
        table_attr->attr.attr.name = table_attr->name;
        table_attr->attr.attr.mode = 0444;
-       table_attr->attr.attr.owner = THIS_MODULE;
 
        return;
 }
index af0d175c025dcd168c5a6de866351fd0b1f83d5a..5260e9e0df48a3f9b52221f179e72fac01b45f6a 100644 (file)
@@ -21,6 +21,8 @@
 #include <linux/memory_hotplug.h>
 #include <linux/mm.h>
 #include <linux/mutex.h>
+#include <linux/stat.h>
+
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 
@@ -325,7 +327,7 @@ memory_probe_store(struct class *class, const char *buf, size_t count)
 
        return count;
 }
-static CLASS_ATTR(probe, 0700, NULL, memory_probe_store);
+static CLASS_ATTR(probe, S_IWUSR, NULL, memory_probe_store);
 
 static int memory_probe_init(void)
 {
index 5116b78c632586884a19ab8b8329b798bc5cce14..f5207090885a8fc80f28b670b95a6fa13ca87418 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/nodemask.h>
 #include <linux/cpu.h>
 #include <linux/device.h>
+#include <linux/swap.h>
 
 static struct sysdev_class node_class = {
        .name = "node",
@@ -61,34 +62,52 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
        si_meminfo_node(&i, nid);
 
        n = sprintf(buf, "\n"
-                      "Node %d MemTotal:     %8lu kB\n"
-                      "Node %d MemFree:      %8lu kB\n"
-                      "Node %d MemUsed:      %8lu kB\n"
-                      "Node %d Active:       %8lu kB\n"
-                      "Node %d Inactive:     %8lu kB\n"
+                      "Node %d MemTotal:       %8lu kB\n"
+                      "Node %d MemFree:        %8lu kB\n"
+                      "Node %d MemUsed:        %8lu kB\n"
+                      "Node %d Active:         %8lu kB\n"
+                      "Node %d Inactive:       %8lu kB\n"
+                      "Node %d Active(anon):   %8lu kB\n"
+                      "Node %d Inactive(anon): %8lu kB\n"
+                      "Node %d Active(file):   %8lu kB\n"
+                      "Node %d Inactive(file): %8lu kB\n"
+#ifdef CONFIG_UNEVICTABLE_LRU
+                      "Node %d Unevictable:    %8lu kB\n"
+                      "Node %d Mlocked:        %8lu kB\n"
+#endif
 #ifdef CONFIG_HIGHMEM
-                      "Node %d HighTotal:    %8lu kB\n"
-                      "Node %d HighFree:     %8lu kB\n"
-                      "Node %d LowTotal:     %8lu kB\n"
-                      "Node %d LowFree:      %8lu kB\n"
+                      "Node %d HighTotal:      %8lu kB\n"
+                      "Node %d HighFree:       %8lu kB\n"
+                      "Node %d LowTotal:       %8lu kB\n"
+                      "Node %d LowFree:        %8lu kB\n"
 #endif
-                      "Node %d Dirty:        %8lu kB\n"
-                      "Node %d Writeback:    %8lu kB\n"
-                      "Node %d FilePages:    %8lu kB\n"
-                      "Node %d Mapped:       %8lu kB\n"
-                      "Node %d AnonPages:    %8lu kB\n"
-                      "Node %d PageTables:   %8lu kB\n"
-                      "Node %d NFS_Unstable: %8lu kB\n"
-                      "Node %d Bounce:       %8lu kB\n"
-                      "Node %d WritebackTmp: %8lu kB\n"
-                      "Node %d Slab:         %8lu kB\n"
-                      "Node %d SReclaimable: %8lu kB\n"
-                      "Node %d SUnreclaim:   %8lu kB\n",
+                      "Node %d Dirty:          %8lu kB\n"
+                      "Node %d Writeback:      %8lu kB\n"
+                      "Node %d FilePages:      %8lu kB\n"
+                      "Node %d Mapped:         %8lu kB\n"
+                      "Node %d AnonPages:      %8lu kB\n"
+                      "Node %d PageTables:     %8lu kB\n"
+                      "Node %d NFS_Unstable:   %8lu kB\n"
+                      "Node %d Bounce:         %8lu kB\n"
+                      "Node %d WritebackTmp:   %8lu kB\n"
+                      "Node %d Slab:           %8lu kB\n"
+                      "Node %d SReclaimable:   %8lu kB\n"
+                      "Node %d SUnreclaim:     %8lu kB\n",
                       nid, K(i.totalram),
                       nid, K(i.freeram),
                       nid, K(i.totalram - i.freeram),
-                      nid, K(node_page_state(nid, NR_ACTIVE)),
-                      nid, K(node_page_state(nid, NR_INACTIVE)),
+                      nid, K(node_page_state(nid, NR_ACTIVE_ANON) +
+                               node_page_state(nid, NR_ACTIVE_FILE)),
+                      nid, K(node_page_state(nid, NR_INACTIVE_ANON) +
+                               node_page_state(nid, NR_INACTIVE_FILE)),
+                      nid, K(node_page_state(nid, NR_ACTIVE_ANON)),
+                      nid, K(node_page_state(nid, NR_INACTIVE_ANON)),
+                      nid, K(node_page_state(nid, NR_ACTIVE_FILE)),
+                      nid, K(node_page_state(nid, NR_INACTIVE_FILE)),
+#ifdef CONFIG_UNEVICTABLE_LRU
+                      nid, K(node_page_state(nid, NR_UNEVICTABLE)),
+                      nid, K(node_page_state(nid, NR_MLOCK)),
+#endif
 #ifdef CONFIG_HIGHMEM
                       nid, K(i.totalhigh),
                       nid, K(i.freehigh),
@@ -173,6 +192,8 @@ 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);
+
+               scan_unevictable_register_node(node);
        }
        return error;
 }
@@ -192,6 +213,8 @@ void unregister_node(struct node *node)
        sysdev_remove_file(&node->sysdev, &attr_numastat);
        sysdev_remove_file(&node->sysdev, &attr_distance);
 
+       scan_unevictable_unregister_node(node);
+
        sysdev_unregister(&node->sysdev);
 }
 
index b82654e883a759f10d46dd67f311eab59a35fec6..d876ad861237d9367abdf3df8ef9606274d0ebfb 100644 (file)
@@ -90,7 +90,7 @@ static DEVICE_ATTR(state, S_IRUGO, aoedisk_show_state, NULL);
 static DEVICE_ATTR(mac, S_IRUGO, aoedisk_show_mac, NULL);
 static DEVICE_ATTR(netif, S_IRUGO, aoedisk_show_netif, NULL);
 static struct device_attribute dev_attr_firmware_version = {
-       .attr = { .name = "firmware-version", .mode = S_IRUGO, .owner = THIS_MODULE },
+       .attr = { .name = "firmware-version", .mode = S_IRUGO },
        .show = aoedisk_show_fwver,
 };
 
index 7b3351260d564015c203d9a2342b94d063eaaccb..9034ca585afd710d6425d53f7b6357c13357a6af 100644 (file)
@@ -391,7 +391,7 @@ static ssize_t pid_show(struct device *dev,
 }
 
 static struct device_attribute pid_attr = {
-       .attr = { .name = "pid", .mode = S_IRUGO, .owner = THIS_MODULE },
+       .attr = { .name = "pid", .mode = S_IRUGO},
        .show = pid_show,
 };
 
index 5329d482b582bd06fff9d4acf66b044683de05e5..0a826d7be10ee21b85ef5178d3830aac0ef46e9a 100644 (file)
@@ -210,8 +210,8 @@ static int ds1286_ioctl(struct inode *inode, struct file *file,
                if (sec != 0)
                        return -EINVAL;
 
-               min = BIN2BCD(min);
-               min = BIN2BCD(hrs);
+               min = bin2bcd(min);
+               min = bin2bcd(hrs);
 
                spin_lock(&ds1286_lock);
                rtc_write(hrs, RTC_HOURS_ALARM);
@@ -353,7 +353,7 @@ static int ds1286_proc_output(char *buf)
 
        ds1286_get_time(&tm);
        hundredth = rtc_read(RTC_HUNDREDTH_SECOND);
-       BCD_TO_BIN(hundredth);
+       hundredth = bcd2bin(hundredth);
 
        p += sprintf(p,
                     "rtc_time\t: %02d:%02d:%02d.%02d\n"
@@ -477,12 +477,12 @@ static void ds1286_get_time(struct rtc_time *rtc_tm)
        rtc_write(save_control, RTC_CMD);
        spin_unlock_irqrestore(&ds1286_lock, flags);
 
-       BCD_TO_BIN(rtc_tm->tm_sec);
-       BCD_TO_BIN(rtc_tm->tm_min);
-       BCD_TO_BIN(rtc_tm->tm_hour);
-       BCD_TO_BIN(rtc_tm->tm_mday);
-       BCD_TO_BIN(rtc_tm->tm_mon);
-       BCD_TO_BIN(rtc_tm->tm_year);
+       rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+       rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+       rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+       rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+       rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+       rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
 
        /*
         * Account for differences between how the RTC uses the values
@@ -531,12 +531,12 @@ static int ds1286_set_time(struct rtc_time *rtc_tm)
        if (yrs >= 100)
                yrs -= 100;
 
-       BIN_TO_BCD(sec);
-       BIN_TO_BCD(min);
-       BIN_TO_BCD(hrs);
-       BIN_TO_BCD(day);
-       BIN_TO_BCD(mon);
-       BIN_TO_BCD(yrs);
+       sec = bin2bcd(sec);
+       min = bin2bcd(min);
+       hrs = bin2bcd(hrs);
+       day = bin2bcd(day);
+       mon = bin2bcd(mon);
+       yrs = bin2bcd(yrs);
 
        spin_lock_irqsave(&ds1286_lock, flags);
        save_control = rtc_read(RTC_CMD);
@@ -572,8 +572,8 @@ static void ds1286_get_alm_time(struct rtc_time *alm_tm)
        cmd = rtc_read(RTC_CMD);
        spin_unlock_irqrestore(&ds1286_lock, flags);
 
-       BCD_TO_BIN(alm_tm->tm_min);
-       BCD_TO_BIN(alm_tm->tm_hour);
+       alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
+       alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
        alm_tm->tm_sec = 0;
 }
 
index c5e67a623951bbc89f05cb7f9b5ade1530866fc1..170693c93c73d275fceb2c310c41df8a323c9297 100644 (file)
@@ -131,12 +131,12 @@ get_rtc_time(struct rtc_time *rtc_tm)
 
        local_irq_restore(flags);
 
-       BCD_TO_BIN(rtc_tm->tm_sec);
-       BCD_TO_BIN(rtc_tm->tm_min);
-       BCD_TO_BIN(rtc_tm->tm_hour);
-       BCD_TO_BIN(rtc_tm->tm_mday);
-       BCD_TO_BIN(rtc_tm->tm_mon);
-       BCD_TO_BIN(rtc_tm->tm_year);
+       rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+       rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+       rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+       rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+       rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+       rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
 
        /*
         * Account for differences between how the RTC uses the values
@@ -211,12 +211,12 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        else
                                yrs -= 1900;    /* RTC (70, 71, ... 99) */
 
-                       BIN_TO_BCD(sec);
-                       BIN_TO_BCD(min);
-                       BIN_TO_BCD(hrs);
-                       BIN_TO_BCD(day);
-                       BIN_TO_BCD(mon);
-                       BIN_TO_BCD(yrs);
+                       sec = bin2bcd(sec);
+                       min = bin2bcd(min);
+                       hrs = bin2bcd(hrs);
+                       day = bin2bcd(day);
+                       mon = bin2bcd(mon);
+                       yrs = bin2bcd(yrs);
 
                        lock_kernel();
                        local_irq_save(flags);
index ec9d0443d92c7a3f77b67832d064111119dfdead..2abd881b4cbcc07a8b16c087b9b474d2c6e58100 100644 (file)
@@ -130,12 +130,12 @@ static long rtc_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                if (yrs >= 100)
                        yrs -= 100;
 
-               sec = BIN2BCD(sec);
-               min = BIN2BCD(min);
-               hrs = BIN2BCD(hrs);
-               day = BIN2BCD(day);
-               mon = BIN2BCD(mon);
-               yrs = BIN2BCD(yrs);
+               sec = bin2bcd(sec);
+               min = bin2bcd(min);
+               hrs = bin2bcd(hrs);
+               day = bin2bcd(day);
+               mon = bin2bcd(mon);
+               yrs = bin2bcd(yrs);
 
                spin_lock_irq(&rtc_lock);
                rtc->control |= M48T35_RTC_SET;
@@ -311,12 +311,12 @@ static void get_rtc_time(struct rtc_time *rtc_tm)
        rtc->control &= ~M48T35_RTC_READ;
        spin_unlock_irq(&rtc_lock);
 
-       rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec);
-       rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min);
-       rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour);
-       rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday);
-       rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon);
-       rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year);
+       rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+       rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+       rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+       rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+       rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+       rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
 
        /*
         * Account for differences between how the RTC uses the values
index b930de50407aaac9536c9a74adb8b740ce3bae67..3f7da8cf3a80aa0b95b2d98875c3a742f50cd8d1 100644 (file)
@@ -41,7 +41,8 @@ static u8 pc8736x_gpio_shadow[4];
 #define SIO_BASE2       0x4E   /* alt command-reg to check */
 
 #define SIO_SID                0x20    /* SuperI/O ID Register */
-#define SIO_SID_VALUE  0xe9    /* Expected value in SuperI/O ID Register */
+#define SIO_SID_PC87365        0xe5    /* Expected value in ID Register for PC87365 */
+#define SIO_SID_PC87366        0xe9    /* Expected value in ID Register for PC87366 */
 
 #define SIO_CF1                0x21    /* chip config, bit0 is chip enable */
 
@@ -91,13 +92,17 @@ static inline int superio_inb(int addr)
 
 static int pc8736x_superio_present(void)
 {
+       int id;
+
        /* try the 2 possible values, read a hardware reg to verify */
        superio_cmd = SIO_BASE1;
-       if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+       id = superio_inb(SIO_SID);
+       if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
                return superio_cmd;
 
        superio_cmd = SIO_BASE2;
-       if (superio_inb(SIO_SID) == SIO_SID_VALUE)
+       id = superio_inb(SIO_SID);
+       if (id == SIO_SID_PC87365 || id == SIO_SID_PC87366)
                return superio_cmd;
 
        return 0;
index 17683de95717e2a2b5eb763fa345ce418fed6181..32dc89720d5896a6f6efebcfdfa8e8999999d85f 100644 (file)
@@ -518,17 +518,17 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
                if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
                                                        RTC_ALWAYS_BCD) {
                        if (sec < 60)
-                               BIN_TO_BCD(sec);
+                               sec = bin2bcd(sec);
                        else
                                sec = 0xff;
 
                        if (min < 60)
-                               BIN_TO_BCD(min);
+                               min = bin2bcd(min);
                        else
                                min = 0xff;
 
                        if (hrs < 24)
-                               BIN_TO_BCD(hrs);
+                               hrs = bin2bcd(hrs);
                        else
                                hrs = 0xff;
                }
@@ -614,12 +614,12 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
 
                if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
                    || RTC_ALWAYS_BCD) {
-                       BIN_TO_BCD(sec);
-                       BIN_TO_BCD(min);
-                       BIN_TO_BCD(hrs);
-                       BIN_TO_BCD(day);
-                       BIN_TO_BCD(mon);
-                       BIN_TO_BCD(yrs);
+                       sec = bin2bcd(sec);
+                       min = bin2bcd(min);
+                       hrs = bin2bcd(hrs);
+                       day = bin2bcd(day);
+                       mon = bin2bcd(mon);
+                       yrs = bin2bcd(yrs);
                }
 
                save_control = CMOS_READ(RTC_CONTROL);
@@ -1099,7 +1099,7 @@ no_irq:
        spin_unlock_irq(&rtc_lock);
 
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-               BCD_TO_BIN(year);       /* This should never happen... */
+               year = bcd2bin(year);       /* This should never happen... */
 
        if (year < 20) {
                epoch = 2000;
@@ -1352,13 +1352,13 @@ static void rtc_get_rtc_time(struct rtc_time *rtc_tm)
        spin_unlock_irqrestore(&rtc_lock, flags);
 
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(rtc_tm->tm_sec);
-               BCD_TO_BIN(rtc_tm->tm_min);
-               BCD_TO_BIN(rtc_tm->tm_hour);
-               BCD_TO_BIN(rtc_tm->tm_mday);
-               BCD_TO_BIN(rtc_tm->tm_mon);
-               BCD_TO_BIN(rtc_tm->tm_year);
-               BCD_TO_BIN(rtc_tm->tm_wday);
+               rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+               rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+               rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+               rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+               rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+               rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
+               rtc_tm->tm_wday = bcd2bin(rtc_tm->tm_wday);
        }
 
 #ifdef CONFIG_MACH_DECSTATION
@@ -1392,9 +1392,9 @@ static void get_rtc_alm_time(struct rtc_time *alm_tm)
        spin_unlock_irq(&rtc_lock);
 
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-               BCD_TO_BIN(alm_tm->tm_sec);
-               BCD_TO_BIN(alm_tm->tm_min);
-               BCD_TO_BIN(alm_tm->tm_hour);
+               alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
+               alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
+               alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
        }
 }
 
index 5b8d7a1aa3e64853c21eb524339123a81bd31f3b..ba4e86281fbf29dde6dc9b121da6228628f22d33 100644 (file)
@@ -2504,7 +2504,7 @@ static void __devexit sx_remove_card(struct sx_board *board,
                del_timer(&board->timer);
                if (pdev) {
 #ifdef CONFIG_PCI
-                       pci_iounmap(pdev, board->base2);
+                       iounmap(board->base2);
                        pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
 #endif
                } else {
@@ -2677,7 +2677,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,
        }
        board->hw_base = pci_resource_start(pdev, reg);
        board->base2 =
-       board->base = pci_iomap(pdev, reg, WINDOW_LEN(board));
+       board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
        if (!board->base) {
                dev_err(&pdev->dev, "ioremap failed\n");
                goto err_reg;
@@ -2703,7 +2703,7 @@ static int __devinit sx_pci_probe(struct pci_dev *pdev,
 
        return 0;
 err_unmap:
-       pci_iounmap(pdev, board->base2);
+       iounmap(board->base2);
 err_reg:
        pci_release_region(pdev, reg);
 err_flag:
index dce4cc0e695338210391a11311507ef1b8d49f76..d0c0d64ed366ce9e961c7dbbfca03a9764e29321 100644 (file)
@@ -168,7 +168,7 @@ static void sysrq_handle_show_timers(int key, struct tty_struct *tty)
 static struct sysrq_key_op sysrq_show_timers_op = {
        .handler        = sysrq_handle_show_timers,
        .help_msg       = "show-all-timers(Q)",
-       .action_msg     = "Show Pending Timers",
+       .action_msg     = "Show pending hrtimers (no others)",
 };
 
 static void sysrq_handle_mountro(int key, struct tty_struct *tty)
index e70d13defde4bcc30724187ff6443f553730eeb7..9c47dc48c9fd4526ac8e8972fb80c6b21ba2cae8 100644 (file)
@@ -1157,7 +1157,7 @@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
  * Once all references to platform device are down to 0,
  * release all allocated structures.
  */
-static void tpm_dev_release(struct device *dev)
+void tpm_dev_release(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
index 0e024fe2d8c486ce8ab0bddca34b91e8b9f53165..887072f5dc8b8b703db223751a4bd47b6631e5f8 100644 (file)
@@ -142,7 +142,7 @@ static void __devinit cell_edac_init_csrows(struct mem_ctl_info *mci)
                csrow->nr_pages = (r.end - r.start + 1) >> PAGE_SHIFT;
                csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
                csrow->mtype = MEM_XDR;
-               csrow->edac_mode = EDAC_FLAG_EC | EDAC_FLAG_SECDED;
+               csrow->edac_mode = EDAC_SECDED;
                dev_dbg(mci->dev,
                        "Initialized on node %d, chanmask=0x%x,"
                        " first_page=0x%lx, nr_pages=0x%x\n",
index deb154aa47c412be66f4ee68281f053cf7a4c241..4353414a0b770c368b938760e8630f50bd065346 100644 (file)
@@ -732,7 +732,6 @@ static int __init ibft_create_attribute(struct ibft_kobject *kobj_data,
 
        attr->attr.name = name;
        attr->attr.mode = S_IRUSR;
-       attr->attr.owner = THIS_MODULE;
 
        attr->hdr = hdr;
        attr->show = show;
index 9112830107a53d4c208b5a8cbf1934026549bac1..22edc4273ef68cd46eceabe2ec249cca93faf0a5 100644 (file)
@@ -248,7 +248,7 @@ static ssize_t gpio_value_show(struct device *dev,
        if (!test_bit(FLAG_EXPORT, &desc->flags))
                status = -EIO;
        else
-               status = sprintf(buf, "%d\n", gpio_get_value_cansleep(gpio));
+               status = sprintf(buf, "%d\n", !!gpio_get_value_cansleep(gpio));
 
        mutex_unlock(&sysfs_lock);
        return status;
@@ -1105,7 +1105,7 @@ int gpio_get_value_cansleep(unsigned gpio)
 
        might_sleep_if(extra_checks);
        chip = gpio_to_chip(gpio);
-       return chip->get(chip, gpio - chip->base);
+       return chip->get ? chip->get(chip, gpio - chip->base) : 0;
 }
 EXPORT_SYMBOL_GPL(gpio_get_value_cansleep);
 
index b06b8e090a278e9164c8603d7fa1d311be17317e..bc011da79e148249e24a1439e3c4cb55fcd1c7b0 100644 (file)
@@ -49,6 +49,9 @@
 
 #define APPLESMC_MAX_DATA_LENGTH 32
 
+#define APPLESMC_MIN_WAIT      0x0040
+#define APPLESMC_MAX_WAIT      0x8000
+
 #define APPLESMC_STATUS_MASK   0x0f
 #define APPLESMC_READ_CMD      0x10
 #define APPLESMC_WRITE_CMD     0x11
@@ -57,8 +60,8 @@
 
 #define KEY_COUNT_KEY          "#KEY" /* r-o ui32 */
 
-#define LIGHT_SENSOR_LEFT_KEY  "ALV0" /* r-o {alv (6 bytes) */
-#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
+#define LIGHT_SENSOR_LEFT_KEY  "ALV0" /* r-o {alv (6-10 bytes) */
+#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */
 #define BACKLIGHT_KEY          "LKSB" /* w-o {lkb (2 bytes) */
 
 #define CLAMSHELL_KEY          "MSLD" /* r-o ui8 (unused) */
@@ -104,6 +107,15 @@ static const char* temperature_sensors_sets[][36] = {
 /* Set 6: Macbook3 set */
        { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
          "Th0S", "Th1H", NULL },
+/* Set 7: Macbook Air */
+       { "TB0T", "TB1S", "TB1T", "TB2S", "TB2T", "TC0D", "TC0P", "TCFP",
+         "TTF0", "TW0P", "Th0H", "Tp0P", "TpFP", "Ts0P", "Ts0S", NULL },
+/* Set 8: Macbook Pro 4,1 (Penryn) */
+       { "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", "Th0H",
+         "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
+/* Set 9: Macbook Pro 3,1 (Santa Rosa) */
+       { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P",
+         "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL },
 };
 
 /* List of keys used to read/write fan speeds */
@@ -163,25 +175,25 @@ static unsigned int key_at_index;
 static struct workqueue_struct *applesmc_led_wq;
 
 /*
- * __wait_status - Wait up to 2ms for the status port to get a certain value
+ * __wait_status - Wait up to 32ms for the status port to get a certain value
  * (masked with 0x0f), returning zero if the value is obtained.  Callers must
  * hold applesmc_lock.
  */
 static int __wait_status(u8 val)
 {
-       unsigned int i;
+       int us;
 
        val = val & APPLESMC_STATUS_MASK;
 
-       for (i = 0; i < 200; i++) {
+       for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
+               udelay(us);
                if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
                        if (debug)
                                printk(KERN_DEBUG
-                                               "Waited %d us for status %x\n",
-                                               i*10, val);
+                                       "Waited %d us for status %x\n",
+                                       2 * us - APPLESMC_MIN_WAIT, val);
                        return 0;
                }
-               udelay(10);
        }
 
        printk(KERN_WARNING "applesmc: wait status failed: %x != %x\n",
@@ -190,6 +202,25 @@ static int __wait_status(u8 val)
        return -EIO;
 }
 
+/*
+ * special treatment of command port - on newer macbooks, it seems necessary
+ * to resend the command byte before polling the status again. Callers must
+ * hold applesmc_lock.
+ */
+static int send_command(u8 cmd)
+{
+       int us;
+       for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) {
+               outb(cmd, APPLESMC_CMD_PORT);
+               udelay(us);
+               if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
+                       return 0;
+       }
+       printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
+               cmd, inb(APPLESMC_CMD_PORT));
+       return -EIO;
+}
+
 /*
  * applesmc_read_key - reads len bytes from a given key, and put them in buffer.
  * Returns zero on success or a negative error on failure. Callers must
@@ -205,8 +236,7 @@ static int applesmc_read_key(const char* key, u8* buffer, u8 len)
                return -EINVAL;
        }
 
-       outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT);
-       if (__wait_status(0x0c))
+       if (send_command(APPLESMC_READ_CMD))
                return -EIO;
 
        for (i = 0; i < 4; i++) {
@@ -249,8 +279,7 @@ static int applesmc_write_key(const char* key, u8* buffer, u8 len)
                return -EINVAL;
        }
 
-       outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT);
-       if (__wait_status(0x0c))
+       if (send_command(APPLESMC_WRITE_CMD))
                return -EIO;
 
        for (i = 0; i < 4; i++) {
@@ -284,8 +313,7 @@ static int applesmc_get_key_at_index(int index, char* key)
        readkey[2] = index >> 8;
        readkey[3] = index;
 
-       outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT);
-       if (__wait_status(0x0c))
+       if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD))
                return -EIO;
 
        for (i = 0; i < 4; i++) {
@@ -315,8 +343,7 @@ static int applesmc_get_key_type(char* key, char* type)
 {
        int i;
 
-       outb(APPLESMC_GET_KEY_TYPE_CMD, APPLESMC_CMD_PORT);
-       if (__wait_status(0x0c))
+       if (send_command(APPLESMC_GET_KEY_TYPE_CMD))
                return -EIO;
 
        for (i = 0; i < 4; i++) {
@@ -325,7 +352,7 @@ static int applesmc_get_key_type(char* key, char* type)
                        return -EIO;
        }
 
-       outb(5, APPLESMC_DATA_PORT);
+       outb(6, APPLESMC_DATA_PORT);
 
        for (i = 0; i < 6; i++) {
                if (__wait_status(0x05))
@@ -527,17 +554,27 @@ out:
 static ssize_t applesmc_light_show(struct device *dev,
                                struct device_attribute *attr, char *sysfsbuf)
 {
+       static int data_length;
        int ret;
        u8 left = 0, right = 0;
-       u8 buffer[6];
+       u8 buffer[10], query[6];
 
        mutex_lock(&applesmc_lock);
 
-       ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, 6);
+       if (!data_length) {
+               ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query);
+               if (ret)
+                       goto out;
+               data_length = clamp_val(query[0], 0, 10);
+               printk(KERN_INFO "applesmc: light sensor data length set to "
+                       "%d\n", data_length);
+       }
+
+       ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
        left = buffer[2];
        if (ret)
                goto out;
-       ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, 6);
+       ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
        right = buffer[2];
 
 out:
@@ -1233,39 +1270,57 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = {
        { .accelerometer = 0, .light = 0, .temperature_set = 5 },
 /* MacBook3: accelerometer and temperature set 6 */
        { .accelerometer = 1, .light = 0, .temperature_set = 6 },
+/* MacBook Air: accelerometer, backlight and temperature set 7 */
+       { .accelerometer = 1, .light = 1, .temperature_set = 7 },
+/* MacBook Pro 4: accelerometer, backlight and temperature set 8 */
+       { .accelerometer = 1, .light = 1, .temperature_set = 8 },
+/* MacBook Pro 3: accelerometer, backlight and temperature set 9 */
+       { .accelerometer = 1, .light = 1, .temperature_set = 9 },
 };
 
 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
  * So we need to put "Apple MacBook Pro" before "Apple MacBook". */
 static __initdata struct dmi_system_id applesmc_whitelist[] = {
+       { applesmc_dmi_match, "Apple MacBook Air", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") },
+               &applesmc_dmi_data[7]},
+       { applesmc_dmi_match, "Apple MacBook Pro 4", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") },
+               &applesmc_dmi_data[8]},
+       { applesmc_dmi_match, "Apple MacBook Pro 3", {
+         DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro3") },
+               &applesmc_dmi_data[9]},
        { applesmc_dmi_match, "Apple MacBook Pro", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
-               (void*)&applesmc_dmi_data[0]},
+               &applesmc_dmi_data[0]},
        { applesmc_dmi_match, "Apple MacBook (v2)", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") },
-               (void*)&applesmc_dmi_data[1]},
+               &applesmc_dmi_data[1]},
        { applesmc_dmi_match, "Apple MacBook (v3)", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
-               (void*)&applesmc_dmi_data[6]},
+               &applesmc_dmi_data[6]},
        { applesmc_dmi_match, "Apple MacBook", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
-               (void*)&applesmc_dmi_data[2]},
+               &applesmc_dmi_data[2]},
        { applesmc_dmi_match, "Apple Macmini", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"Macmini") },
-               (void*)&applesmc_dmi_data[3]},
+               &applesmc_dmi_data[3]},
        { applesmc_dmi_match, "Apple MacPro2", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
-               (void*)&applesmc_dmi_data[4]},
+               &applesmc_dmi_data[4]},
        { applesmc_dmi_match, "Apple iMac", {
          DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
          DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
-               (void*)&applesmc_dmi_data[5]},
+               &applesmc_dmi_data[5]},
        { .ident = NULL }
 };
 
index 9b462bb13fa33b3b9cc67d66e884628a7e2043ba..5fbfa34c110e36e455e632363eaff7228f4b0aaf 100644 (file)
@@ -75,7 +75,8 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID");
 #define FSCM   0x09    /* Logical device: fans */
 #define VLM    0x0d    /* Logical device: voltages */
 #define TMS    0x0e    /* Logical device: temperatures */
-static const u8 logdev[3] = { FSCM, VLM, TMS };
+#define LDNI_MAX 3
+static const u8 logdev[LDNI_MAX] = { FSCM, VLM, TMS };
 
 #define LD_FAN         0
 #define LD_IN          1
@@ -489,11 +490,66 @@ static struct sensor_device_attribute in_max[] = {
        SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
 };
 
+/* (temp & vin) channel status register alarm bits (pdf sec.11.5.12) */
+#define CHAN_ALM_MIN   0x02    /* min limit crossed */
+#define CHAN_ALM_MAX   0x04    /* max limit exceeded */
+#define TEMP_ALM_CRIT  0x08    /* temp crit exceeded (temp only) */
+
+/* show_in_min/max_alarm() reads data from the per-channel status
+   register (sec 11.5.12), not the vin event status registers (sec
+   11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms) */
+
+static ssize_t show_in_min_alarm(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
+}
+static ssize_t show_in_max_alarm(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX));
+}
+
+static struct sensor_device_attribute in_min_alarm[] = {
+       SENSOR_ATTR(in0_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 0),
+       SENSOR_ATTR(in1_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 1),
+       SENSOR_ATTR(in2_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 2),
+       SENSOR_ATTR(in3_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 3),
+       SENSOR_ATTR(in4_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 4),
+       SENSOR_ATTR(in5_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 5),
+       SENSOR_ATTR(in6_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 6),
+       SENSOR_ATTR(in7_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 7),
+       SENSOR_ATTR(in8_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 8),
+       SENSOR_ATTR(in9_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 9),
+       SENSOR_ATTR(in10_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 10),
+};
+static struct sensor_device_attribute in_max_alarm[] = {
+       SENSOR_ATTR(in0_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 0),
+       SENSOR_ATTR(in1_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 1),
+       SENSOR_ATTR(in2_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 2),
+       SENSOR_ATTR(in3_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 3),
+       SENSOR_ATTR(in4_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 4),
+       SENSOR_ATTR(in5_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 5),
+       SENSOR_ATTR(in6_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 6),
+       SENSOR_ATTR(in7_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 7),
+       SENSOR_ATTR(in8_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 8),
+       SENSOR_ATTR(in9_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 9),
+       SENSOR_ATTR(in10_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 10),
+};
+
 #define VIN_UNIT_ATTRS(X) \
        &in_input[X].dev_attr.attr,     \
        &in_status[X].dev_attr.attr,    \
        &in_min[X].dev_attr.attr,       \
-       &in_max[X].dev_attr.attr
+       &in_max[X].dev_attr.attr,       \
+       &in_min_alarm[X].dev_attr.attr, \
+       &in_max_alarm[X].dev_attr.attr
 
 static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -658,12 +714,68 @@ static struct sensor_device_attribute therm_crit[] = {
                    show_therm_crit, set_therm_crit, 2+11),
 };
 
+/* show_therm_min/max_alarm() reads data from the per-channel voltage
+   status register (sec 11.5.12) */
+
+static ssize_t show_therm_min_alarm(struct device *dev,
+                               struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN));
+}
+static ssize_t show_therm_max_alarm(struct device *dev,
+                               struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX));
+}
+static ssize_t show_therm_crit_alarm(struct device *dev,
+                               struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->in_status[nr] & TEMP_ALM_CRIT));
+}
+
+static struct sensor_device_attribute therm_min_alarm[] = {
+       SENSOR_ATTR(temp4_min_alarm, S_IRUGO,
+                   show_therm_min_alarm, NULL, 0+11),
+       SENSOR_ATTR(temp5_min_alarm, S_IRUGO,
+                   show_therm_min_alarm, NULL, 1+11),
+       SENSOR_ATTR(temp6_min_alarm, S_IRUGO,
+                   show_therm_min_alarm, NULL, 2+11),
+};
+static struct sensor_device_attribute therm_max_alarm[] = {
+       SENSOR_ATTR(temp4_max_alarm, S_IRUGO,
+                   show_therm_max_alarm, NULL, 0+11),
+       SENSOR_ATTR(temp5_max_alarm, S_IRUGO,
+                   show_therm_max_alarm, NULL, 1+11),
+       SENSOR_ATTR(temp6_max_alarm, S_IRUGO,
+                   show_therm_max_alarm, NULL, 2+11),
+};
+static struct sensor_device_attribute therm_crit_alarm[] = {
+       SENSOR_ATTR(temp4_crit_alarm, S_IRUGO,
+                   show_therm_crit_alarm, NULL, 0+11),
+       SENSOR_ATTR(temp5_crit_alarm, S_IRUGO,
+                   show_therm_crit_alarm, NULL, 1+11),
+       SENSOR_ATTR(temp6_crit_alarm, S_IRUGO,
+                   show_therm_crit_alarm, NULL, 2+11),
+};
+
 #define THERM_UNIT_ATTRS(X) \
        &therm_input[X].dev_attr.attr,  \
        &therm_status[X].dev_attr.attr, \
        &therm_min[X].dev_attr.attr,    \
        &therm_max[X].dev_attr.attr,    \
-       &therm_crit[X].dev_attr.attr
+       &therm_crit[X].dev_attr.attr,   \
+       &therm_min_alarm[X].dev_attr.attr, \
+       &therm_max_alarm[X].dev_attr.attr, \
+       &therm_crit_alarm[X].dev_attr.attr
 
 static struct attribute * pc8736x_therm_attr_array[] = {
        THERM_UNIT_ATTRS(0),
@@ -790,12 +902,76 @@ static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *att
 }
 static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
 
+/* show_temp_min/max_alarm() reads data from the per-channel status
+   register (sec 12.3.7), not the temp event status registers (sec
+   12.3.2) that show_temp_alarm() reads (via data->temp_alarms) */
+
+static ssize_t show_temp_min_alarm(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN));
+}
+static ssize_t show_temp_max_alarm(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX));
+}
+static ssize_t show_temp_crit_alarm(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_ALM_CRIT));
+}
+
+static struct sensor_device_attribute temp_min_alarm[] = {
+       SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 0),
+       SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1),
+       SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2),
+};
+static struct sensor_device_attribute temp_max_alarm[] = {
+       SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0),
+       SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1),
+       SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2),
+};
+static struct sensor_device_attribute temp_crit_alarm[] = {
+       SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0),
+       SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1),
+       SENSOR_ATTR(temp3_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 2),
+};
+
+#define TEMP_FAULT     0x40    /* open diode */
+static ssize_t show_temp_fault(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
+{
+       struct pc87360_data *data = pc87360_update_device(dev);
+       unsigned nr = to_sensor_dev_attr(devattr)->index;
+
+       return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_FAULT));
+}
+static struct sensor_device_attribute temp_fault[] = {
+       SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0),
+       SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1),
+       SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2),
+};
+
 #define TEMP_UNIT_ATTRS(X) \
        &temp_input[X].dev_attr.attr,   \
        &temp_status[X].dev_attr.attr,  \
        &temp_min[X].dev_attr.attr,     \
        &temp_max[X].dev_attr.attr,     \
-       &temp_crit[X].dev_attr.attr
+       &temp_crit[X].dev_attr.attr,    \
+       &temp_min_alarm[X].dev_attr.attr, \
+       &temp_max_alarm[X].dev_attr.attr, \
+       &temp_crit_alarm[X].dev_attr.attr, \
+       &temp_fault[X].dev_attr.attr
 
 static struct attribute * pc8736x_temp_attr_array[] = {
        TEMP_UNIT_ATTRS(0),
@@ -809,8 +985,8 @@ static const struct attribute_group pc8736x_temp_group = {
        .attrs = pc8736x_temp_attr_array,
 };
 
-static ssize_t show_name(struct device *dev, struct device_attribute
-                        *devattr, char *buf)
+static ssize_t show_name(struct device *dev,
+                       struct device_attribute *devattr, char *buf)
 {
        struct pc87360_data *data = dev_get_drvdata(dev);
        return sprintf(buf, "%s\n", data->name);
@@ -955,7 +1131,7 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
        mutex_init(&data->update_lock);
        platform_set_drvdata(pdev, data);
 
-       for (i = 0; i < 3; i++) {
+       for (i = 0; i < LDNI_MAX; i++) {
                if (((data->address[i] = extra_isa[i]))
                 && !request_region(extra_isa[i], PC87360_EXTENT,
                                    pc87360_driver.driver.name)) {
@@ -1031,7 +1207,15 @@ static int __devinit pc87360_probe(struct platform_device *pdev)
                            || (err = device_create_file(dev,
                                        &temp_crit[i].dev_attr))
                            || (err = device_create_file(dev,
-                                       &temp_status[i].dev_attr)))
+                                       &temp_status[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_min_alarm[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_max_alarm[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_crit_alarm[i].dev_attr))
+                           || (err = device_create_file(dev,
+                                       &temp_fault[i].dev_attr)))
                                goto ERROR3;
                }
                if ((err = device_create_file(dev, &dev_attr_alarms_temp)))
@@ -1131,6 +1315,16 @@ static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
        mutex_unlock(&(data->lock));
 }
 
+/* (temp & vin) channel conversion status register flags (pdf sec.11.5.12) */
+#define CHAN_CNVRTD    0x80    /* new data ready */
+#define CHAN_ENA       0x01    /* enabled channel (temp or vin) */
+#define CHAN_ALM_ENA   0x10    /* propagate to alarms-reg ?? (chk val!) */
+#define CHAN_READY     (CHAN_ENA|CHAN_CNVRTD) /* sample ready mask */
+
+#define TEMP_OTS_OE    0x20    /* OTS Output Enable */
+#define VIN_RW1C_MASK  (CHAN_READY|CHAN_ALM_MAX|CHAN_ALM_MIN)   /* 0x87 */
+#define TEMP_RW1C_MASK (VIN_RW1C_MASK|TEMP_ALM_CRIT|TEMP_FAULT) /* 0xCF */
+
 static void pc87360_init_device(struct platform_device *pdev,
                                int use_thermistors)
 {
@@ -1152,11 +1346,12 @@ static void pc87360_init_device(struct platform_device *pdev,
 
        nr = data->innr < 11 ? data->innr : 11;
        for (i = 0; i < nr; i++) {
+               reg = pc87360_read_value(data, LD_IN, i,
+                                        PC87365_REG_IN_STATUS);
+               dev_dbg(&pdev->dev, "bios in%d status:0x%02x\n", i, reg);
                if (init >= init_in[i]) {
                        /* Forcibly enable voltage channel */
-                       reg = pc87360_read_value(data, LD_IN, i,
-                                                PC87365_REG_IN_STATUS);
-                       if (!(reg & 0x01)) {
+                       if (!(reg & CHAN_ENA)) {
                                dev_dbg(&pdev->dev, "Forcibly "
                                        "enabling in%d\n", i);
                                pc87360_write_value(data, LD_IN, i,
@@ -1168,19 +1363,24 @@ static void pc87360_init_device(struct platform_device *pdev,
 
        /* We can't blindly trust the Super-I/O space configuration bit,
           most BIOS won't set it properly */
+       dev_dbg(&pdev->dev, "bios thermistors:%d\n", use_thermistors);
        for (i = 11; i < data->innr; i++) {
                reg = pc87360_read_value(data, LD_IN, i,
                                         PC87365_REG_TEMP_STATUS);
-               use_thermistors = use_thermistors || (reg & 0x01);
+               use_thermistors = use_thermistors || (reg & CHAN_ENA);
+               /* thermistors are temp[4-6], measured on vin[11-14] */
+               dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i-7, reg);
        }
+       dev_dbg(&pdev->dev, "using thermistors:%d\n", use_thermistors);
 
        i = use_thermistors ? 2 : 0;
        for (; i < data->tempnr; i++) {
+               reg = pc87360_read_value(data, LD_TEMP, i,
+                                        PC87365_REG_TEMP_STATUS);
+               dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i+1, reg);
                if (init >= init_temp[i]) {
                        /* Forcibly enable temperature channel */
-                       reg = pc87360_read_value(data, LD_TEMP, i,
-                                                PC87365_REG_TEMP_STATUS);
-                       if (!(reg & 0x01)) {
+                       if (!(reg & CHAN_ENA)) {
                                dev_dbg(&pdev->dev, "Forcibly "
                                        "enabling temp%d\n", i+1);
                                pc87360_write_value(data, LD_TEMP, i,
@@ -1197,7 +1397,7 @@ static void pc87360_init_device(struct platform_device *pdev,
                                   diodes */
                                reg = pc87360_read_value(data, LD_TEMP,
                                      (i-11)/2, PC87365_REG_TEMP_STATUS);
-                               if (reg & 0x01) {
+                               if (reg & CHAN_ENA) {
                                        dev_dbg(&pdev->dev, "Skipping "
                                                "temp%d, pin already in use "
                                                "by temp%d\n", i-7, (i-11)/2);
@@ -1207,7 +1407,7 @@ static void pc87360_init_device(struct platform_device *pdev,
                                /* Forcibly enable thermistor channel */
                                reg = pc87360_read_value(data, LD_IN, i,
                                                         PC87365_REG_IN_STATUS);
-                               if (!(reg & 0x01)) {
+                               if (!(reg & CHAN_ENA)) {
                                        dev_dbg(&pdev->dev, "Forcibly "
                                                "enabling temp%d\n", i-7);
                                        pc87360_write_value(data, LD_IN, i,
@@ -1221,7 +1421,8 @@ static void pc87360_init_device(struct platform_device *pdev,
        if (data->innr) {
                reg = pc87360_read_value(data, LD_IN, NO_BANK,
                                         PC87365_REG_IN_CONFIG);
-               if (reg & 0x01) {
+               dev_dbg(&pdev->dev, "bios vin-cfg:0x%02x\n", reg);
+               if (reg & CHAN_ENA) {
                        dev_dbg(&pdev->dev, "Forcibly "
                                "enabling monitoring (VLM)\n");
                        pc87360_write_value(data, LD_IN, NO_BANK,
@@ -1233,7 +1434,8 @@ static void pc87360_init_device(struct platform_device *pdev,
        if (data->tempnr) {
                reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
                                         PC87365_REG_TEMP_CONFIG);
-               if (reg & 0x01) {
+               dev_dbg(&pdev->dev, "bios temp-cfg:0x%02x\n", reg);
+               if (reg & CHAN_ENA) {
                        dev_dbg(&pdev->dev, "Forcibly enabling "
                                "monitoring (TMS)\n");
                        pc87360_write_value(data, LD_TEMP, NO_BANK,
@@ -1336,11 +1538,11 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
                        pc87360_write_value(data, LD_IN, i,
                                            PC87365_REG_IN_STATUS,
                                            data->in_status[i]);
-                       if ((data->in_status[i] & 0x81) == 0x81) {
+                       if ((data->in_status[i] & CHAN_READY) == CHAN_READY) {
                                data->in[i] = pc87360_read_value(data, LD_IN,
                                              i, PC87365_REG_IN);
                        }
-                       if (data->in_status[i] & 0x01) {
+                       if (data->in_status[i] & CHAN_ENA) {
                                data->in_min[i] = pc87360_read_value(data,
                                                  LD_IN, i,
                                                  PC87365_REG_IN_MIN);
@@ -1373,12 +1575,12 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
                        pc87360_write_value(data, LD_TEMP, i,
                                            PC87365_REG_TEMP_STATUS,
                                            data->temp_status[i]);
-                       if ((data->temp_status[i] & 0x81) == 0x81) {
+                       if ((data->temp_status[i] & CHAN_READY) == CHAN_READY) {
                                data->temp[i] = pc87360_read_value(data,
                                                LD_TEMP, i,
                                                PC87365_REG_TEMP);
                        }
-                       if (data->temp_status[i] & 0x01) {
+                       if (data->temp_status[i] & CHAN_ENA) {
                                data->temp_min[i] = pc87360_read_value(data,
                                                    LD_TEMP, i,
                                                    PC87365_REG_TEMP_MIN);
index 2a4acb2695693b9b3108a6317301efbeef6e1416..d4775528abc69b2d4c4d580d712e48862ef7d1d7 100644 (file)
@@ -460,7 +460,6 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
         */
        at24->bin.attr.name = "eeprom";
        at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
-       at24->bin.attr.owner = THIS_MODULE;
        at24->bin.read = at24_bin_read;
        at24->bin.size = chip.byte_len;
 
index 23be4d42cb02c48da998864f3d13da047e75092b..f3ee4a1abb7714fa2dca513043dce44947d8b962 100644 (file)
@@ -190,7 +190,6 @@ static struct bin_attribute ds1682_eeprom_attr = {
        .attr = {
                .name = "eeprom",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = DS1682_EEPROM_SIZE,
        .read = ds1682_eeprom_read,
index 176126d3a01d3054318347cff48dfce8dc2805a1..4b364bae6b3ebc30f6774c167360a205c71ce303 100644 (file)
@@ -832,52 +832,52 @@ static irqreturn_t menelaus_irq(int irq, void *_menelaus)
 
 static void menelaus_to_time(char *regs, struct rtc_time *t)
 {
-       t->tm_sec = BCD2BIN(regs[0]);
-       t->tm_min = BCD2BIN(regs[1]);
+       t->tm_sec = bcd2bin(regs[0]);
+       t->tm_min = bcd2bin(regs[1]);
        if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
-               t->tm_hour = BCD2BIN(regs[2] & 0x1f) - 1;
+               t->tm_hour = bcd2bin(regs[2] & 0x1f) - 1;
                if (regs[2] & RTC_HR_PM)
                        t->tm_hour += 12;
        } else
-               t->tm_hour = BCD2BIN(regs[2] & 0x3f);
-       t->tm_mday = BCD2BIN(regs[3]);
-       t->tm_mon = BCD2BIN(regs[4]) - 1;
-       t->tm_year = BCD2BIN(regs[5]) + 100;
+               t->tm_hour = bcd2bin(regs[2] & 0x3f);
+       t->tm_mday = bcd2bin(regs[3]);
+       t->tm_mon = bcd2bin(regs[4]) - 1;
+       t->tm_year = bcd2bin(regs[5]) + 100;
 }
 
 static int time_to_menelaus(struct rtc_time *t, int regnum)
 {
        int     hour, status;
 
-       status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_sec));
+       status = menelaus_write_reg(regnum++, bin2bcd(t->tm_sec));
        if (status < 0)
                goto fail;
 
-       status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_min));
+       status = menelaus_write_reg(regnum++, bin2bcd(t->tm_min));
        if (status < 0)
                goto fail;
 
        if (the_menelaus->rtc_control & RTC_CTRL_MODE12) {
                hour = t->tm_hour + 1;
                if (hour > 12)
-                       hour = RTC_HR_PM | BIN2BCD(hour - 12);
+                       hour = RTC_HR_PM | bin2bcd(hour - 12);
                else
-                       hour = BIN2BCD(hour);
+                       hour = bin2bcd(hour);
        } else
-               hour = BIN2BCD(t->tm_hour);
+               hour = bin2bcd(t->tm_hour);
        status = menelaus_write_reg(regnum++, hour);
        if (status < 0)
                goto fail;
 
-       status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mday));
+       status = menelaus_write_reg(regnum++, bin2bcd(t->tm_mday));
        if (status < 0)
                goto fail;
 
-       status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_mon + 1));
+       status = menelaus_write_reg(regnum++, bin2bcd(t->tm_mon + 1));
        if (status < 0)
                goto fail;
 
-       status = menelaus_write_reg(regnum++, BIN2BCD(t->tm_year - 100));
+       status = menelaus_write_reg(regnum++, bin2bcd(t->tm_year - 100));
        if (status < 0)
                goto fail;
 
@@ -914,7 +914,7 @@ static int menelaus_read_time(struct device *dev, struct rtc_time *t)
        }
 
        menelaus_to_time(regs, t);
-       t->tm_wday = BCD2BIN(regs[6]);
+       t->tm_wday = bcd2bin(regs[6]);
 
        return 0;
 }
@@ -927,7 +927,7 @@ static int menelaus_set_time(struct device *dev, struct rtc_time *t)
        status = time_to_menelaus(t, MENELAUS_RTC_SEC);
        if (status < 0)
                return status;
-       status = menelaus_write_reg(MENELAUS_RTC_WKDAY, BIN2BCD(t->tm_wday));
+       status = menelaus_write_reg(MENELAUS_RTC_WKDAY, bin2bcd(t->tm_wday));
        if (status < 0) {
                dev_err(&the_menelaus->client->dev, "rtc write reg %02x "
                                "err %d\n", MENELAUS_RTC_WKDAY, status);
index a78d35aecee3de339520308358d6ca565d69cdd1..f1e82a92e61ec09fb879a9b00ec41b5e35b192f4 100644 (file)
@@ -122,7 +122,7 @@ struct cm_counter_attribute {
 
 #define CM_COUNTER_ATTR(_name, _index) \
 struct cm_counter_attribute cm_##_name##_counter_attr = { \
-       .attr = { .name = __stringify(_name), .mode = 0444, .owner = THIS_MODULE }, \
+       .attr = { .name = __stringify(_name), .mode = 0444 }, \
        .index = _index \
 }
 
index c38d4e0f95c6a093e7bf009fcb662160b97a3a8e..a89700e7ace42138e10a6a47e085a4b90a6f9c15 100644 (file)
@@ -5,7 +5,7 @@
 #include <asm/io.h>
 #include <asm/delay.h>
 #include <asm/adc.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
 
 #define MODNAME "hp680_ts_input"
 
index 844d5979c9045bfa6126eb8b4828706ac9f68655..e8fb1baf8a5072e3d3454b3366e32d1c2c015140 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/leds.h>
 #include <asm/hd64461.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
 
 static void hp6xxled_green_set(struct led_classdev *led_cdev,
                               enum led_brightness value)
index c7c770c2898825c8a06c65400b880ea817c90cdc..aa1ff524256e1397012bcde72919d94113df6f18 100644 (file)
@@ -36,7 +36,6 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 #include <linux/poll.h>
-#include <linux/byteorder/swabb.h>
 #include <linux/smp_lock.h>
 
 #include <linux/kernel.h>
@@ -52,6 +51,7 @@
 #include <linux/i2c.h>
 #include <linux/kthread.h>
 #include <asm/unaligned.h>
+#include <asm/byteorder.h>
 
 #include <asm/system.h>
 
index fa8be0731a3f70ee3d6ca40a6301af86d7930a86..a4b1708fafe74eb070fe8d4b3f3c61b440f16358 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/pagemap.h>
 #include <linux/workqueue.h>
 #include <linux/mutex.h>
+#include <asm/byteorder.h>
 
 #include <linux/dvb/video.h>
 #include <linux/dvb/audio.h>
index bc29436e8a3cd4c3acc93a3c62df8b884d88d478..3733b2afec5f5f92b6c30f4f1c32cbce2cfd327a 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
+#include <asm/byteorder.h>
 
 #include <linux/dvb/video.h>
 #include <linux/dvb/audio.h>
index 6e291bf8237adaa0d7c5ea84f8ffda8e9ee440e3..5263913e0c69e8935add96731944373ee968f01d 100644 (file)
@@ -1044,7 +1044,6 @@ static int mspro_block_read_attributes(struct memstick_dev *card)
 
                s_attr->dev_attr.attr.name = s_attr->name;
                s_attr->dev_attr.attr.mode = S_IRUGO;
-               s_attr->dev_attr.attr.owner = THIS_MODULE;
                s_attr->dev_attr.show = mspro_block_attr_show(s_attr->id);
 
                if (!rc)
index 5dabfb69ee537f25a1bc93814c0e894ebf3ba494..4b7c24c519c34cba280c13bf4667e23051bca741 100644 (file)
@@ -82,6 +82,7 @@ static struct key_entry hp_wmi_keymap[] = {
        {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
        {KE_KEY, 0x20e6, KEY_PROG1},
        {KE_KEY, 0x2142, KEY_MEDIA},
+       {KE_KEY, 0x213b, KEY_INFO},
        {KE_KEY, 0x231b, KEY_HELP},
        {KE_END, 0}
 };
index 14f11f8b9e5fd556fcd71dbe4d6178634c851bcc..a90d50c2c3e5535343e859c5df1c40c3be7e464a 100644 (file)
@@ -172,6 +172,11 @@ config MTD_CHAR
          memory chips, and also use ioctl() to obtain information about
          the device, or to erase parts of it.
 
+config HAVE_MTD_OTP
+       bool
+       help
+         Enable access to OTP regions using MTD_CHAR.
+
 config MTD_BLKDEVS
        tristate "Common interface to block layer for MTD 'translation layers'"
        depends on BLOCK
index 479d32b57a1eb54b20b731855274bd9d343a62ae..9408099eec48e59b033900957f8ce0a02c76dbb6 100644 (file)
@@ -6,6 +6,7 @@ menu "RAM/ROM/Flash chip drivers"
 config MTD_CFI
        tristate "Detect flash chips by Common Flash Interface (CFI) probe"
        select MTD_GEN_PROBE
+       select MTD_CFI_UTIL
        help
          The Common Flash Interface specification was developed by Intel,
          AMD and other flash manufactures that provides a universal method
@@ -154,6 +155,7 @@ config MTD_CFI_I8
 config MTD_OTP
        bool "Protection Registers aka one-time programmable (OTP) bits"
        depends on MTD_CFI_ADV_OPTIONS
+       select HAVE_MTD_OTP
        default n
        help
          This enables support for reading, writing and locking so called
@@ -187,7 +189,7 @@ config MTD_CFI_INTELEXT
          StrataFlash and other parts.
 
 config MTD_CFI_AMDSTD
-       tristate "Support for AMD/Fujitsu flash chips"
+       tristate "Support for AMD/Fujitsu/Spansion flash chips"
        depends on MTD_GEN_PROBE
        select MTD_CFI_UTIL
        help
index 5f1b472137a024b96fcff3ea3f9bcd654c7389f8..c93a8be5d5f1f541e96c6e104d5d10f4997bf451 100644 (file)
@@ -478,6 +478,28 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
                else
                        cfi->chips[i].erase_time = 2000000;
 
+               if (cfi->cfiq->WordWriteTimeoutTyp &&
+                   cfi->cfiq->WordWriteTimeoutMax)
+                       cfi->chips[i].word_write_time_max =
+                               1<<(cfi->cfiq->WordWriteTimeoutTyp +
+                                   cfi->cfiq->WordWriteTimeoutMax);
+               else
+                       cfi->chips[i].word_write_time_max = 50000 * 8;
+
+               if (cfi->cfiq->BufWriteTimeoutTyp &&
+                   cfi->cfiq->BufWriteTimeoutMax)
+                       cfi->chips[i].buffer_write_time_max =
+                               1<<(cfi->cfiq->BufWriteTimeoutTyp +
+                                   cfi->cfiq->BufWriteTimeoutMax);
+
+               if (cfi->cfiq->BlockEraseTimeoutTyp &&
+                   cfi->cfiq->BlockEraseTimeoutMax)
+                       cfi->chips[i].erase_time_max =
+                               1000<<(cfi->cfiq->BlockEraseTimeoutTyp +
+                                      cfi->cfiq->BlockEraseTimeoutMax);
+               else
+                       cfi->chips[i].erase_time_max = 2000000 * 8;
+
                cfi->chips[i].ref_point_counter = 0;
                init_waitqueue_head(&(cfi->chips[i].wq));
        }
@@ -703,6 +725,10 @@ static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long
        struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
        unsigned long timeo = jiffies + HZ;
 
+       /* Prevent setting state FL_SYNCING for chip in suspended state. */
+       if (mode == FL_SYNCING && chip->oldstate != FL_READY)
+               goto sleep;
+
        switch (chip->state) {
 
        case FL_STATUS:
@@ -808,8 +834,9 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
        DECLARE_WAITQUEUE(wait, current);
 
  retry:
-       if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING
-                          || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) {
+       if (chip->priv &&
+           (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE
+           || mode == FL_SHUTDOWN) && chip->state != FL_SYNCING) {
                /*
                 * OK. We have possibility for contention on the write/erase
                 * operations which are global to the real chip and not per
@@ -859,6 +886,14 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr
                                return ret;
                        }
                        spin_lock(&shared->lock);
+
+                       /* We should not own chip if it is already
+                        * in FL_SYNCING state. Put contender and retry. */
+                       if (chip->state == FL_SYNCING) {
+                               put_chip(map, contender, contender->start);
+                               spin_unlock(contender->mutex);
+                               goto retry;
+                       }
                        spin_unlock(contender->mutex);
                }
 
@@ -1012,7 +1047,7 @@ static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
 
 static int __xipram xip_wait_for_operation(
                struct map_info *map, struct flchip *chip,
-               unsigned long adr, unsigned int chip_op_time )
+               unsigned long adr, unsigned int chip_op_time_max)
 {
        struct cfi_private *cfi = map->fldrv_priv;
        struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
@@ -1021,7 +1056,7 @@ static int __xipram xip_wait_for_operation(
        flstate_t oldstate, newstate;
 
                start = xip_currtime();
-       usec = chip_op_time * 8;
+       usec = chip_op_time_max;
        if (usec == 0)
                usec = 500000;
        done = 0;
@@ -1131,8 +1166,8 @@ static int __xipram xip_wait_for_operation(
 #define XIP_INVAL_CACHED_RANGE(map, from, size)  \
        INVALIDATE_CACHED_RANGE(map, from, size)
 
-#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
-       xip_wait_for_operation(map, chip, cmd_adr, usec)
+#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec, usec_max) \
+       xip_wait_for_operation(map, chip, cmd_adr, usec_max)
 
 #else
 
@@ -1144,7 +1179,7 @@ static int __xipram xip_wait_for_operation(
 static int inval_cache_and_wait_for_operation(
                struct map_info *map, struct flchip *chip,
                unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
-               unsigned int chip_op_time)
+               unsigned int chip_op_time, unsigned int chip_op_time_max)
 {
        struct cfi_private *cfi = map->fldrv_priv;
        map_word status, status_OK = CMD(0x80);
@@ -1156,8 +1191,7 @@ static int inval_cache_and_wait_for_operation(
                INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
        spin_lock(chip->mutex);
 
-       /* set our timeout to 8 times the expected delay */
-       timeo = chip_op_time * 8;
+       timeo = chip_op_time_max;
        if (!timeo)
                timeo = 500000;
        reset_timeo = timeo;
@@ -1217,8 +1251,8 @@ static int inval_cache_and_wait_for_operation(
 
 #endif
 
-#define WAIT_TIMEOUT(map, chip, adr, udelay) \
-       INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);
+#define WAIT_TIMEOUT(map, chip, adr, udelay, udelay_max) \
+       INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay, udelay_max);
 
 
 static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
@@ -1452,7 +1486,8 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip,
 
        ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
                                   adr, map_bankwidth(map),
-                                  chip->word_write_time);
+                                  chip->word_write_time,
+                                  chip->word_write_time_max);
        if (ret) {
                xip_enable(map, chip, adr);
                printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
@@ -1623,7 +1658,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 
        chip->state = FL_WRITING_TO_BUFFER;
        map_write(map, write_cmd, cmd_adr);
-       ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0);
+       ret = WAIT_TIMEOUT(map, chip, cmd_adr, 0, 0);
        if (ret) {
                /* Argh. Not ready for write to buffer */
                map_word Xstatus = map_read(map, cmd_adr);
@@ -1640,7 +1675,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 
        /* Figure out the number of words to write */
        word_gap = (-adr & (map_bankwidth(map)-1));
-       words = (len - word_gap + map_bankwidth(map) - 1) / map_bankwidth(map);
+       words = DIV_ROUND_UP(len - word_gap, map_bankwidth(map));
        if (!word_gap) {
                words--;
        } else {
@@ -1692,7 +1727,8 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip,
 
        ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
                                   initial_adr, initial_len,
-                                  chip->buffer_write_time);
+                                  chip->buffer_write_time,
+                                  chip->buffer_write_time_max);
        if (ret) {
                map_write(map, CMD(0x70), cmd_adr);
                chip->state = FL_STATUS;
@@ -1827,7 +1863,8 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip,
 
        ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
                                   adr, len,
-                                  chip->erase_time);
+                                  chip->erase_time,
+                                  chip->erase_time_max);
        if (ret) {
                map_write(map, CMD(0x70), adr);
                chip->state = FL_STATUS;
@@ -2006,7 +2043,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip
         */
        udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0;
 
-       ret = WAIT_TIMEOUT(map, chip, adr, udelay);
+       ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100);
        if (ret) {
                map_write(map, CMD(0x70), adr);
                chip->state = FL_STATUS;
index a972cc6be436367f797a90f5099aca14a7e8a7a9..3e6f5d8609e8e513b38e5110bc7719a3fce5c1d0 100644 (file)
@@ -13,6 +13,8 @@
  * XIP support hooks by Vitaly Wool (based on code for Intel flash
  * by Nicolas Pitre)
  *
+ * 25/09/2008 Christopher Moore: TopBottom fixup for many Macronix with CFI V1.0
+ *
  * Occasionally maintained by Thayne Harbaugh tharbaugh at lnxi dot com
  *
  * This code is GPL
@@ -43,6 +45,7 @@
 
 #define MANUFACTURER_AMD       0x0001
 #define MANUFACTURER_ATMEL     0x001F
+#define MANUFACTURER_MACRONIX  0x00C2
 #define MANUFACTURER_SST       0x00BF
 #define SST49LF004B            0x0060
 #define SST49LF040B            0x0050
@@ -144,12 +147,44 @@ static void fixup_amd_bootblock(struct mtd_info *mtd, void* param)
 
        if (((major << 8) | minor) < 0x3131) {
                /* CFI version 1.0 => don't trust bootloc */
+
+               DEBUG(MTD_DEBUG_LEVEL1,
+                       "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n",
+                       map->name, cfi->mfr, cfi->id);
+
+               /* AFAICS all 29LV400 with a bottom boot block have a device ID
+                * of 0x22BA in 16-bit mode and 0xBA in 8-bit mode.
+                * These were badly detected as they have the 0x80 bit set
+                * so treat them as a special case.
+                */
+               if (((cfi->id == 0xBA) || (cfi->id == 0x22BA)) &&
+
+                       /* Macronix added CFI to their 2nd generation
+                        * MX29LV400C B/T but AFAICS no other 29LV400 (AMD,
+                        * Fujitsu, Spansion, EON, ESI and older Macronix)
+                        * has CFI.
+                        *
+                        * Therefore also check the manufacturer.
+                        * This reduces the risk of false detection due to
+                        * the 8-bit device ID.
+                        */
+                       (cfi->mfr == MANUFACTURER_MACRONIX)) {
+                       DEBUG(MTD_DEBUG_LEVEL1,
+                               "%s: Macronix MX29LV400C with bottom boot block"
+                               " detected\n", map->name);
+                       extp->TopBottom = 2;    /* bottom boot */
+               } else
                if (cfi->id & 0x80) {
                        printk(KERN_WARNING "%s: JEDEC Device ID is 0x%02X. Assuming broken CFI table.\n", map->name, cfi->id);
                        extp->TopBottom = 3;    /* top boot */
                } else {
                        extp->TopBottom = 2;    /* bottom boot */
                }
+
+               DEBUG(MTD_DEBUG_LEVEL1,
+                       "%s: AMD CFI PRI V%c.%c has no boot block field;"
+                       " deduced %s from Device ID\n", map->name, major, minor,
+                       extp->TopBottom == 2 ? "bottom" : "top");
        }
 }
 #endif
@@ -178,10 +213,18 @@ static void fixup_convert_atmel_pri(struct mtd_info *mtd, void *param)
        if (atmel_pri.Features & 0x02)
                extp->EraseSuspend = 2;
 
-       if (atmel_pri.BottomBoot)
-               extp->TopBottom = 2;
-       else
-               extp->TopBottom = 3;
+       /* Some chips got it backwards... */
+       if (cfi->id == AT49BV6416) {
+               if (atmel_pri.BottomBoot)
+                       extp->TopBottom = 3;
+               else
+                       extp->TopBottom = 2;
+       } else {
+               if (atmel_pri.BottomBoot)
+                       extp->TopBottom = 2;
+               else
+                       extp->TopBottom = 3;
+       }
 
        /* burst write mode not supported */
        cfi->cfiq->BufWriteTimeoutTyp = 0;
@@ -243,6 +286,7 @@ static struct cfi_fixup cfi_fixup_table[] = {
        { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL },
 #ifdef AMD_BOOTLOC_BUG
        { CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock, NULL },
+       { MANUFACTURER_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock, NULL },
 #endif
        { CFI_MFR_AMD, 0x0050, fixup_use_secsi, NULL, },
        { CFI_MFR_AMD, 0x0053, fixup_use_secsi, NULL, },
index c418e92e1d92b79286f46a173bd1f93ff3591939..e63e6749429a29c282323ebc7c5d5949ef284616 100644 (file)
@@ -44,17 +44,14 @@ do { \
 
 #define xip_enable(base, map, cfi) \
 do { \
-       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
-       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
+       cfi_qry_mode_off(base, map, cfi);               \
        xip_allowed(base, map); \
 } while (0)
 
 #define xip_disable_qry(base, map, cfi) \
 do { \
        xip_disable(); \
-       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); \
-       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); \
-       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); \
+       cfi_qry_mode_on(base, map, cfi); \
 } while (0)
 
 #else
@@ -70,32 +67,6 @@ do { \
    in: interleave,type,mode
    ret: table index, <0 for error
  */
-static int __xipram qry_present(struct map_info *map, __u32 base,
-                               struct cfi_private *cfi)
-{
-       int osf = cfi->interleave * cfi->device_type;   // scale factor
-       map_word val[3];
-       map_word qry[3];
-
-       qry[0] = cfi_build_cmd('Q', map, cfi);
-       qry[1] = cfi_build_cmd('R', map, cfi);
-       qry[2] = cfi_build_cmd('Y', map, cfi);
-
-       val[0] = map_read(map, base + osf*0x10);
-       val[1] = map_read(map, base + osf*0x11);
-       val[2] = map_read(map, base + osf*0x12);
-
-       if (!map_word_equal(map, qry[0], val[0]))
-               return 0;
-
-       if (!map_word_equal(map, qry[1], val[1]))
-               return 0;
-
-       if (!map_word_equal(map, qry[2], val[2]))
-               return 0;
-
-       return 1;       // "QRY" found
-}
 
 static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
                                   unsigned long *chip_map, struct cfi_private *cfi)
@@ -116,11 +87,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
        }
 
        xip_disable();
-       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
-
-       if (!qry_present(map,base,cfi)) {
+       if (!cfi_qry_mode_on(base, map, cfi)) {
                xip_enable(base, map, cfi);
                return 0;
        }
@@ -141,14 +108,13 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
                start = i << cfi->chipshift;
                /* This chip should be in read mode if it's one
                   we've already touched. */
-               if (qry_present(map, start, cfi)) {
+               if (cfi_qry_present(map, start, cfi)) {
                        /* Eep. This chip also had the QRY marker.
                         * Is it an alias for the new one? */
-                       cfi_send_gen_cmd(0xF0, 0, start, map, cfi, cfi->device_type, NULL);
-                       cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
+                       cfi_qry_mode_off(start, map, cfi);
 
                        /* If the QRY marker goes away, it's an alias */
-                       if (!qry_present(map, start, cfi)) {
+                       if (!cfi_qry_present(map, start, cfi)) {
                                xip_allowed(base, map);
                                printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
                                       map->name, base, start);
@@ -158,10 +124,9 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
                         * unfortunate. Stick the new chip in read mode
                         * too and if it's the same, assume it's an alias. */
                        /* FIXME: Use other modes to do a proper check */
-                       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-                       cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL);
+                       cfi_qry_mode_off(base, map, cfi);
 
-                       if (qry_present(map, base, cfi)) {
+                       if (cfi_qry_present(map, base, cfi)) {
                                xip_allowed(base, map);
                                printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n",
                                       map->name, base, start);
@@ -176,8 +141,7 @@ static int __xipram cfi_probe_chip(struct map_info *map, __u32 base,
        cfi->numchips++;
 
        /* Put it back into Read Mode */
-       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_qry_mode_off(base, map, cfi);
        xip_allowed(base, map);
 
        printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n",
@@ -237,9 +201,7 @@ static int __xipram cfi_chip_setup(struct map_info *map,
                          cfi_read_query(map, base + 0xf * ofs_factor);
 
        /* Put it back into Read Mode */
-       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
-       /* ... even if it's an Intel chip */
-       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_qry_mode_off(base, map, cfi);
        xip_allowed(base, map);
 
        /* Do any necessary byteswapping */
index 0ee457018016083743ca772a38d77325aa6911ae..34d40e25d312952b3cd2186465e17eff5a55d101 100644 (file)
 #include <linux/mtd/cfi.h>
 #include <linux/mtd/compatmac.h>
 
+int __xipram cfi_qry_present(struct map_info *map, __u32 base,
+                            struct cfi_private *cfi)
+{
+       int osf = cfi->interleave * cfi->device_type;   /* scale factor */
+       map_word val[3];
+       map_word qry[3];
+
+       qry[0] = cfi_build_cmd('Q', map, cfi);
+       qry[1] = cfi_build_cmd('R', map, cfi);
+       qry[2] = cfi_build_cmd('Y', map, cfi);
+
+       val[0] = map_read(map, base + osf*0x10);
+       val[1] = map_read(map, base + osf*0x11);
+       val[2] = map_read(map, base + osf*0x12);
+
+       if (!map_word_equal(map, qry[0], val[0]))
+               return 0;
+
+       if (!map_word_equal(map, qry[1], val[1]))
+               return 0;
+
+       if (!map_word_equal(map, qry[2], val[2]))
+               return 0;
+
+       return 1;       /* "QRY" found */
+}
+EXPORT_SYMBOL_GPL(cfi_qry_present);
+
+int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
+                            struct cfi_private *cfi)
+{
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+       if (cfi_qry_present(map, base, cfi))
+               return 1;
+       /* QRY not found probably we deal with some odd CFI chips */
+       /* Some revisions of some old Intel chips? */
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+       if (cfi_qry_present(map, base, cfi))
+               return 1;
+       /* ST M29DW chips */
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
+       if (cfi_qry_present(map, base, cfi))
+               return 1;
+       /* QRY not found */
+       return 0;
+}
+EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
+
+void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
+                              struct cfi_private *cfi)
+{
+       cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
+}
+EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
+
 struct cfi_extquery *
 __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name)
 {
@@ -48,8 +108,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
 #endif
 
        /* Switch it into Query Mode */
-       cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
-
+       cfi_qry_mode_on(base, map, cfi);
        /* Read in the Extended Query Table */
        for (i=0; i<size; i++) {
                ((unsigned char *)extp)[i] =
@@ -57,8 +116,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n
        }
 
        /* Make sure it returns to read mode */
-       cfi_send_gen_cmd(0xf0, 0, base, map, cfi, cfi->device_type, NULL);
-       cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL);
+       cfi_qry_mode_off(base, map, cfi);
 
 #ifdef CONFIG_MTD_XIP
        (void) map_read(map, base);
index f061885b2812dc5d04bba96f488aa6fa18a9ae49..e2dc96441e05e0a6affa6c5fa2611fef0f545d9e 100644 (file)
@@ -111,7 +111,7 @@ static struct cfi_private *genprobe_ident_chips(struct map_info *map, struct chi
                max_chips = 1;
        }
 
-       mapsize = sizeof(long) * ( (max_chips + BITS_PER_LONG-1) / BITS_PER_LONG );
+       mapsize = sizeof(long) * DIV_ROUND_UP(max_chips, BITS_PER_LONG);
        chip_map = kzalloc(mapsize, GFP_KERNEL);
        if (!chip_map) {
                printk(KERN_WARNING "%s: kmalloc failed for CFI chip map\n", map->name);
index 71bc07f149b7910f964a5bc9b4c678a149cfbdf9..50a340388e742024945b6011490c760d0de4dcad 100644 (file)
@@ -7,6 +7,7 @@
  *
  * mtdparts=<mtddef>[;<mtddef]
  * <mtddef>  := <mtd-id>:<partdef>[,<partdef>]
+ *              where <mtd-id> is the name from the "cat /proc/mtd" command
  * <partdef> := <size>[@offset][<name>][ro][lk]
  * <mtd-id>  := unique name used in mapping driver/device (mtd->name)
  * <size>    := standard linux memsize OR "-" to denote all remaining space
index 9c613f06623cd4d1191eafb7e6d4adfb75736037..6fde0a2e3567d589fb4757a12eb49929b1c6c463 100644 (file)
@@ -59,6 +59,27 @@ config MTD_DATAFLASH
          Sometimes DataFlash chips are packaged inside MMC-format
          cards; at this writing, the MMC stack won't handle those.
 
+config MTD_DATAFLASH_WRITE_VERIFY
+       bool "Verify DataFlash page writes"
+       depends on MTD_DATAFLASH
+       help
+         This adds an extra check when data is written to the flash.
+         It may help if you are verifying chip setup (timings etc) on
+         your board.  There is a rare possibility that even though the
+         device thinks the write was successful, a bit could have been
+         flipped accidentally due to device wear or something else.
+
+config MTD_DATAFLASH_OTP
+       bool "DataFlash OTP support (Security Register)"
+       depends on MTD_DATAFLASH
+       select HAVE_MTD_OTP
+       help
+         Newer DataFlash chips (revisions C and D) support 128 bytes of
+         one-time-programmable (OTP) data.  The first half may be written
+         (once) with up to 64 bytes of data, such as a serial number or
+         other key product data.  The second half is programmed with a
+         unique-to-each-chip bit pattern at the factory.
+
 config MTD_M25P80
        tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
        depends on SPI_MASTER && EXPERIMENTAL
index b35c3333e210b61878493d3fd052e1228b38d6db..76a76751da3660ce63123844d97eca891d2cbab2 100644 (file)
@@ -39,6 +39,7 @@
 #define        OPCODE_PP               0x02    /* Page program (up to 256 bytes) */
 #define        OPCODE_BE_4K            0x20    /* Erase 4KiB block */
 #define        OPCODE_BE_32K           0x52    /* Erase 32KiB block */
+#define        OPCODE_BE               0xc7    /* Erase whole flash block */
 #define        OPCODE_SE               0xd8    /* Sector erase (usually 64KiB) */
 #define        OPCODE_RDID             0x9f    /* Read JEDEC ID */
 
@@ -161,6 +162,31 @@ static int wait_till_ready(struct m25p *flash)
        return 1;
 }
 
+/*
+ * Erase the whole flash memory
+ *
+ * Returns 0 if successful, non-zero otherwise.
+ */
+static int erase_block(struct m25p *flash)
+{
+       DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB\n",
+                       flash->spi->dev.bus_id, __func__,
+                       flash->mtd.size / 1024);
+
+       /* Wait until finished previous write command. */
+       if (wait_till_ready(flash))
+               return 1;
+
+       /* Send write enable, then erase commands. */
+       write_enable(flash);
+
+       /* Set up command buffer. */
+       flash->command[0] = OPCODE_BE;
+
+       spi_write(flash->spi, flash->command, 1);
+
+       return 0;
+}
 
 /*
  * Erase one sector of flash memory at offset ``offset'' which is any
@@ -229,15 +255,21 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
         */
 
        /* now erase those sectors */
-       while (len) {
-               if (erase_sector(flash, addr)) {
-                       instr->state = MTD_ERASE_FAILED;
-                       mutex_unlock(&flash->lock);
-                       return -EIO;
-               }
+       if (len == flash->mtd.size && erase_block(flash)) {
+               instr->state = MTD_ERASE_FAILED;
+               mutex_unlock(&flash->lock);
+               return -EIO;
+       } else {
+               while (len) {
+                       if (erase_sector(flash, addr)) {
+                               instr->state = MTD_ERASE_FAILED;
+                               mutex_unlock(&flash->lock);
+                               return -EIO;
+                       }
 
-               addr += mtd->erasesize;
-               len -= mtd->erasesize;
+                       addr += mtd->erasesize;
+                       len -= mtd->erasesize;
+               }
        }
 
        mutex_unlock(&flash->lock);
@@ -437,6 +469,7 @@ struct flash_info {
         * then a two byte device id.
         */
        u32             jedec_id;
+       u16             ext_id;
 
        /* The size listed here is what works with OPCODE_SE, which isn't
         * necessarily called a "sector" by the vendor.
@@ -456,72 +489,75 @@ struct flash_info {
 static struct flash_info __devinitdata m25p_data [] = {
 
        /* Atmel -- some are (confusingly) marketed as "DataFlash" */
-       { "at25fs010",  0x1f6601, 32 * 1024, 4, SECT_4K, },
-       { "at25fs040",  0x1f6604, 64 * 1024, 8, SECT_4K, },
+       { "at25fs010",  0x1f6601, 0, 32 * 1024, 4, SECT_4K, },
+       { "at25fs040",  0x1f6604, 0, 64 * 1024, 8, SECT_4K, },
 
-       { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, },
-       { "at25df641",  0x1f4800, 64 * 1024, 128, SECT_4K, },
+       { "at25df041a", 0x1f4401, 0, 64 * 1024, 8, SECT_4K, },
+       { "at25df641",  0x1f4800, 0, 64 * 1024, 128, SECT_4K, },
 
-       { "at26f004",   0x1f0400, 64 * 1024, 8, SECT_4K, },
-       { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, },
-       { "at26df161a", 0x1f4601, 64 * 1024, 32, SECT_4K, },
-       { "at26df321",  0x1f4701, 64 * 1024, 64, SECT_4K, },
+       { "at26f004",   0x1f0400, 0, 64 * 1024, 8, SECT_4K, },
+       { "at26df081a", 0x1f4501, 0, 64 * 1024, 16, SECT_4K, },
+       { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
+       { "at26df321",  0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
 
        /* Spansion -- single (large) sector size only, at least
         * for the chips listed here (without boot sectors).
         */
-       { "s25sl004a", 0x010212, 64 * 1024, 8, },
-       { "s25sl008a", 0x010213, 64 * 1024, 16, },
-       { "s25sl016a", 0x010214, 64 * 1024, 32, },
-       { "s25sl032a", 0x010215, 64 * 1024, 64, },
-       { "s25sl064a", 0x010216, 64 * 1024, 128, },
+       { "s25sl004a", 0x010212, 0, 64 * 1024, 8, },
+       { "s25sl008a", 0x010213, 0, 64 * 1024, 16, },
+       { "s25sl016a", 0x010214, 0, 64 * 1024, 32, },
+       { "s25sl032a", 0x010215, 0, 64 * 1024, 64, },
+       { "s25sl064a", 0x010216, 0, 64 * 1024, 128, },
+        { "s25sl12800", 0x012018, 0x0300, 256 * 1024, 64, },
+       { "s25sl12801", 0x012018, 0x0301, 64 * 1024, 256, },
 
        /* SST -- large erase sizes are "overlays", "sectors" are 4K */
-       { "sst25vf040b", 0xbf258d, 64 * 1024, 8, SECT_4K, },
-       { "sst25vf080b", 0xbf258e, 64 * 1024, 16, SECT_4K, },
-       { "sst25vf016b", 0xbf2541, 64 * 1024, 32, SECT_4K, },
-       { "sst25vf032b", 0xbf254a, 64 * 1024, 64, SECT_4K, },
+       { "sst25vf040b", 0xbf258d, 0, 64 * 1024, 8, SECT_4K, },
+       { "sst25vf080b", 0xbf258e, 0, 64 * 1024, 16, SECT_4K, },
+       { "sst25vf016b", 0xbf2541, 0, 64 * 1024, 32, SECT_4K, },
+       { "sst25vf032b", 0xbf254a, 0, 64 * 1024, 64, SECT_4K, },
 
        /* ST Microelectronics -- newer production may have feature updates */
-       { "m25p05",  0x202010,  32 * 1024, 2, },
-       { "m25p10",  0x202011,  32 * 1024, 4, },
-       { "m25p20",  0x202012,  64 * 1024, 4, },
-       { "m25p40",  0x202013,  64 * 1024, 8, },
-       { "m25p80",         0,  64 * 1024, 16, },
-       { "m25p16",  0x202015,  64 * 1024, 32, },
-       { "m25p32",  0x202016,  64 * 1024, 64, },
-       { "m25p64",  0x202017,  64 * 1024, 128, },
-       { "m25p128", 0x202018, 256 * 1024, 64, },
-
-       { "m45pe80", 0x204014,  64 * 1024, 16, },
-       { "m45pe16", 0x204015,  64 * 1024, 32, },
-
-       { "m25pe80", 0x208014,  64 * 1024, 16, },
-       { "m25pe16", 0x208015,  64 * 1024, 32, SECT_4K, },
+       { "m25p05",  0x202010,  0, 32 * 1024, 2, },
+       { "m25p10",  0x202011,  0, 32 * 1024, 4, },
+       { "m25p20",  0x202012,  0, 64 * 1024, 4, },
+       { "m25p40",  0x202013,  0, 64 * 1024, 8, },
+       { "m25p80",         0,  0, 64 * 1024, 16, },
+       { "m25p16",  0x202015,  0, 64 * 1024, 32, },
+       { "m25p32",  0x202016,  0, 64 * 1024, 64, },
+       { "m25p64",  0x202017,  0, 64 * 1024, 128, },
+       { "m25p128", 0x202018, 0, 256 * 1024, 64, },
+
+       { "m45pe80", 0x204014,  0, 64 * 1024, 16, },
+       { "m45pe16", 0x204015,  0, 64 * 1024, 32, },
+
+       { "m25pe80", 0x208014,  0, 64 * 1024, 16, },
+       { "m25pe16", 0x208015,  0, 64 * 1024, 32, SECT_4K, },
 
        /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
-       { "w25x10", 0xef3011, 64 * 1024, 2, SECT_4K, },
-       { "w25x20", 0xef3012, 64 * 1024, 4, SECT_4K, },
-       { "w25x40", 0xef3013, 64 * 1024, 8, SECT_4K, },
-       { "w25x80", 0xef3014, 64 * 1024, 16, SECT_4K, },
-       { "w25x16", 0xef3015, 64 * 1024, 32, SECT_4K, },
-       { "w25x32", 0xef3016, 64 * 1024, 64, SECT_4K, },
-       { "w25x64", 0xef3017, 64 * 1024, 128, SECT_4K, },
+       { "w25x10", 0xef3011, 0, 64 * 1024, 2, SECT_4K, },
+       { "w25x20", 0xef3012, 0, 64 * 1024, 4, SECT_4K, },
+       { "w25x40", 0xef3013, 0, 64 * 1024, 8, SECT_4K, },
+       { "w25x80", 0xef3014, 0, 64 * 1024, 16, SECT_4K, },
+       { "w25x16", 0xef3015, 0, 64 * 1024, 32, SECT_4K, },
+       { "w25x32", 0xef3016, 0, 64 * 1024, 64, SECT_4K, },
+       { "w25x64", 0xef3017, 0, 64 * 1024, 128, SECT_4K, },
 };
 
 static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
 {
        int                     tmp;
        u8                      code = OPCODE_RDID;
-       u8                      id[3];
+       u8                      id[5];
        u32                     jedec;
+       u16                     ext_jedec;
        struct flash_info       *info;
 
        /* JEDEC also defines an optional "extended device information"
         * string for after vendor-specific data, after the three bytes
         * we use here.  Supporting some chips might require using it.
         */
-       tmp = spi_write_then_read(spi, &code, 1, id, 3);
+       tmp = spi_write_then_read(spi, &code, 1, id, 5);
        if (tmp < 0) {
                DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
                        spi->dev.bus_id, tmp);
@@ -533,10 +569,14 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
        jedec = jedec << 8;
        jedec |= id[2];
 
+       ext_jedec = id[3] << 8 | id[4];
+
        for (tmp = 0, info = m25p_data;
                        tmp < ARRAY_SIZE(m25p_data);
                        tmp++, info++) {
                if (info->jedec_id == jedec)
+                       if (ext_jedec != 0 && info->ext_id != ext_jedec)
+                               continue;
                        return info;
        }
        dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
index 8bd0dea6885f4ad91288d8f5313f08cb636fe10e..6dd9aff8bb2d37181fb711c98f9d839f1fd52a15 100644 (file)
  * doesn't (yet) use these for any kind of i/o overlap or prefetching.
  *
  * Sometimes DataFlash is packaged in MMC-format cards, although the
- * MMC stack can't use SPI (yet), or distinguish between MMC and DataFlash
+ * MMC stack can't (yet?) distinguish between MMC and DataFlash
  * protocols during enumeration.
  */
 
-#define CONFIG_DATAFLASH_WRITE_VERIFY
-
 /* reads can bypass the buffers */
 #define OP_READ_CONTINUOUS     0xE8
 #define OP_READ_PAGE           0xD2
@@ -80,7 +78,8 @@
  */
 #define OP_READ_ID             0x9F
 #define OP_READ_SECURITY       0x77
-#define OP_WRITE_SECURITY      0x9A    /* OTP bits */
+#define OP_WRITE_SECURITY_REVC 0x9A
+#define OP_WRITE_SECURITY      0x9B    /* revision D */
 
 
 struct dataflash {
@@ -402,7 +401,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
                (void) dataflash_waitready(priv->spi);
 
 
-#ifdef CONFIG_DATAFLASH_WRITE_VERIFY
+#ifdef CONFIG_MTD_DATAFLASH_VERIFY_WRITE
 
                /* (3) Compare to Buffer1 */
                addr = pageaddr << priv->page_offset;
@@ -431,7 +430,7 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
                } else
                        status = 0;
 
-#endif /* CONFIG_DATAFLASH_WRITE_VERIFY */
+#endif /* CONFIG_MTD_DATAFLASH_VERIFY_WRITE */
 
                remaining = remaining - writelen;
                pageaddr++;
@@ -451,16 +450,192 @@ static int dataflash_write(struct mtd_info *mtd, loff_t to, size_t len,
 
 /* ......................................................................... */
 
+#ifdef CONFIG_MTD_DATAFLASH_OTP
+
+static int dataflash_get_otp_info(struct mtd_info *mtd,
+               struct otp_info *info, size_t len)
+{
+       /* Report both blocks as identical:  bytes 0..64, locked.
+        * Unless the user block changed from all-ones, we can't
+        * tell whether it's still writable; so we assume it isn't.
+        */
+       info->start = 0;
+       info->length = 64;
+       info->locked = 1;
+       return sizeof(*info);
+}
+
+static ssize_t otp_read(struct spi_device *spi, unsigned base,
+               uint8_t *buf, loff_t off, size_t len)
+{
+       struct spi_message      m;
+       size_t                  l;
+       uint8_t                 *scratch;
+       struct spi_transfer     t;
+       int                     status;
+
+       if (off > 64)
+               return -EINVAL;
+
+       if ((off + len) > 64)
+               len = 64 - off;
+       if (len == 0)
+               return len;
+
+       spi_message_init(&m);
+
+       l = 4 + base + off + len;
+       scratch = kzalloc(l, GFP_KERNEL);
+       if (!scratch)
+               return -ENOMEM;
+
+       /* OUT: OP_READ_SECURITY, 3 don't-care bytes, zeroes
+        * IN:  ignore 4 bytes, data bytes 0..N (max 127)
+        */
+       scratch[0] = OP_READ_SECURITY;
+
+       memset(&t, 0, sizeof t);
+       t.tx_buf = scratch;
+       t.rx_buf = scratch;
+       t.len = l;
+       spi_message_add_tail(&t, &m);
+
+       dataflash_waitready(spi);
+
+       status = spi_sync(spi, &m);
+       if (status >= 0) {
+               memcpy(buf, scratch + 4 + base + off, len);
+               status = len;
+       }
+
+       kfree(scratch);
+       return status;
+}
+
+static int dataflash_read_fact_otp(struct mtd_info *mtd,
+               loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+       struct dataflash        *priv = (struct dataflash *)mtd->priv;
+       int                     status;
+
+       /* 64 bytes, from 0..63 ... start at 64 on-chip */
+       mutex_lock(&priv->lock);
+       status = otp_read(priv->spi, 64, buf, from, len);
+       mutex_unlock(&priv->lock);
+
+       if (status < 0)
+               return status;
+       *retlen = status;
+       return 0;
+}
+
+static int dataflash_read_user_otp(struct mtd_info *mtd,
+               loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+       struct dataflash        *priv = (struct dataflash *)mtd->priv;
+       int                     status;
+
+       /* 64 bytes, from 0..63 ... start at 0 on-chip */
+       mutex_lock(&priv->lock);
+       status = otp_read(priv->spi, 0, buf, from, len);
+       mutex_unlock(&priv->lock);
+
+       if (status < 0)
+               return status;
+       *retlen = status;
+       return 0;
+}
+
+static int dataflash_write_user_otp(struct mtd_info *mtd,
+               loff_t from, size_t len, size_t *retlen, u_char *buf)
+{
+       struct spi_message      m;
+       const size_t            l = 4 + 64;
+       uint8_t                 *scratch;
+       struct spi_transfer     t;
+       struct dataflash        *priv = (struct dataflash *)mtd->priv;
+       int                     status;
+
+       if (len > 64)
+               return -EINVAL;
+
+       /* Strictly speaking, we *could* truncate the write ... but
+        * let's not do that for the only write that's ever possible.
+        */
+       if ((from + len) > 64)
+               return -EINVAL;
+
+       /* OUT: OP_WRITE_SECURITY, 3 zeroes, 64 data-or-zero bytes
+        * IN:  ignore all
+        */
+       scratch = kzalloc(l, GFP_KERNEL);
+       if (!scratch)
+               return -ENOMEM;
+       scratch[0] = OP_WRITE_SECURITY;
+       memcpy(scratch + 4 + from, buf, len);
+
+       spi_message_init(&m);
+
+       memset(&t, 0, sizeof t);
+       t.tx_buf = scratch;
+       t.len = l;
+       spi_message_add_tail(&t, &m);
+
+       /* Write the OTP bits, if they've not yet been written.
+        * This modifies SRAM buffer1.
+        */
+       mutex_lock(&priv->lock);
+       dataflash_waitready(priv->spi);
+       status = spi_sync(priv->spi, &m);
+       mutex_unlock(&priv->lock);
+
+       kfree(scratch);
+
+       if (status >= 0) {
+               status = 0;
+               *retlen = len;
+       }
+       return status;
+}
+
+static char *otp_setup(struct mtd_info *device, char revision)
+{
+       device->get_fact_prot_info = dataflash_get_otp_info;
+       device->read_fact_prot_reg = dataflash_read_fact_otp;
+       device->get_user_prot_info = dataflash_get_otp_info;
+       device->read_user_prot_reg = dataflash_read_user_otp;
+
+       /* rev c parts (at45db321c and at45db1281 only!) use a
+        * different write procedure; not (yet?) implemented.
+        */
+       if (revision > 'c')
+               device->write_user_prot_reg = dataflash_write_user_otp;
+
+       return ", OTP";
+}
+
+#else
+
+static char *otp_setup(struct mtd_info *device, char revision)
+{
+       return " (OTP)";
+}
+
+#endif
+
+/* ......................................................................... */
+
 /*
  * Register DataFlash device with MTD subsystem.
  */
 static int __devinit
-add_dataflash(struct spi_device *spi, char *name,
-               int nr_pages, int pagesize, int pageoffset)
+add_dataflash_otp(struct spi_device *spi, char *name,
+               int nr_pages, int pagesize, int pageoffset, char revision)
 {
        struct dataflash                *priv;
        struct mtd_info                 *device;
        struct flash_platform_data      *pdata = spi->dev.platform_data;
+       char                            *otp_tag = "";
 
        priv = kzalloc(sizeof *priv, GFP_KERNEL);
        if (!priv)
@@ -489,8 +664,12 @@ add_dataflash(struct spi_device *spi, char *name,
        device->write = dataflash_write;
        device->priv = priv;
 
-       dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes\n",
-                       name, DIV_ROUND_UP(device->size, 1024), pagesize);
+       if (revision >= 'c')
+               otp_tag = otp_setup(device, revision);
+
+       dev_info(&spi->dev, "%s (%d KBytes) pagesize %d bytes%s\n",
+                       name, DIV_ROUND_UP(device->size, 1024),
+                       pagesize, otp_tag);
        dev_set_drvdata(&spi->dev, priv);
 
        if (mtd_has_partitions()) {
@@ -519,6 +698,14 @@ add_dataflash(struct spi_device *spi, char *name,
        return add_mtd_device(device) == 1 ? -ENODEV : 0;
 }
 
+static inline int __devinit
+add_dataflash(struct spi_device *spi, char *name,
+               int nr_pages, int pagesize, int pageoffset)
+{
+       return add_dataflash_otp(spi, name, nr_pages, pagesize,
+                       pageoffset, 0);
+}
+
 struct flash_info {
        char            *name;
 
@@ -664,13 +851,16 @@ static int __devinit dataflash_probe(struct spi_device *spi)
         * Try to detect dataflash by JEDEC ID.
         * If it succeeds we know we have either a C or D part.
         * D will support power of 2 pagesize option.
+        * Both support the security register, though with different
+        * write procedures.
         */
        info = jedec_probe(spi);
        if (IS_ERR(info))
                return PTR_ERR(info);
        if (info != NULL)
-               return add_dataflash(spi, info->name, info->nr_pages,
-                                info->pagesize, info->pageoffset);
+               return add_dataflash_otp(spi, info->name, info->nr_pages,
+                               info->pagesize, info->pageoffset,
+                               (info->flags & SUP_POW2PS) ? 'd' : 'c');
 
        /*
         * Older chips support only legacy commands, identifing
index c4f9d3378b24c658f246d8777d47735050cfdffe..50ce13887f63b6b81d2525a5070fbfc511643b1c 100644 (file)
@@ -388,6 +388,10 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
                if (thisEUN == targetEUN)
                        break;
 
+               /* Unlink the last block from the chain. */
+               inftl->PUtable[prevEUN] = BLOCK_NIL;
+
+               /* Now try to erase it. */
                if (INFTL_formatblock(inftl, thisEUN) < 0) {
                        /*
                         * Could not erase : mark block as reserved.
@@ -396,7 +400,6 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
                } else {
                        /* Correctly erased : mark it as free */
                        inftl->PUtable[thisEUN] = BLOCK_FREE;
-                       inftl->PUtable[prevEUN] = BLOCK_NIL;
                        inftl->numfreeEUNs++;
                }
        }
index df8e00bba07b2726f71fbf02b6b1d27ff0cf396a..5ea1693621642b84fbcbe482202395d493b0a91b 100644 (file)
@@ -332,30 +332,6 @@ config MTD_CFI_FLAGADM
          Mapping for the Flaga digital module. If you don't have one, ignore
          this setting.
 
-config MTD_WALNUT
-       tristate "Flash device mapped on IBM 405GP Walnut"
-       depends on MTD_JEDECPROBE && WALNUT && !PPC_MERGE
-       help
-         This enables access routines for the flash chips on the IBM 405GP
-         Walnut board. If you have one of these boards and would like to
-         use the flash chips on it, say 'Y'.
-
-config MTD_EBONY
-       tristate "Flash devices mapped on IBM 440GP Ebony"
-       depends on MTD_JEDECPROBE && EBONY && !PPC_MERGE
-       help
-         This enables access routines for the flash chips on the IBM 440GP
-         Ebony board. If you have one of these boards and would like to
-         use the flash chips on it, say 'Y'.
-
-config MTD_OCOTEA
-       tristate "Flash devices mapped on IBM 440GX Ocotea"
-       depends on MTD_CFI && OCOTEA && !PPC_MERGE
-       help
-         This enables access routines for the flash chips on the IBM 440GX
-         Ocotea board. If you have one of these boards and would like to
-         use the flash chips on it, say 'Y'.
-
 config MTD_REDWOOD
        tristate "CFI Flash devices mapped on IBM Redwood"
        depends on MTD_CFI && ( REDWOOD_4 || REDWOOD_5 || REDWOOD_6 )
@@ -458,13 +434,6 @@ config MTD_CEIVA
          PhotoMax Digital Picture Frame.
          If you have such a device, say 'Y'.
 
-config MTD_NOR_TOTO
-       tristate "NOR Flash device on TOTO board"
-       depends on ARCH_OMAP && OMAP_TOTO
-       help
-         This enables access to the NOR flash on the Texas Instruments
-         TOTO board.
-
 config MTD_H720X
        tristate "Hynix evaluation board mappings"
        depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
@@ -522,7 +491,7 @@ config MTD_BFIN_ASYNC
 
 config MTD_UCLINUX
        tristate "Generic uClinux RAM/ROM filesystem support"
-       depends on MTD_PARTITIONS && !MMU
+       depends on MTD_PARTITIONS && MTD_RAM && !MMU
        help
          Map driver to support image based filesystems for uClinux.
 
index 6cda6df973e5d11c187533e48534ac5ff60c6038..6d9ba35caf11a26bbeb4caefec9eae1dddcd9940 100644 (file)
@@ -50,12 +50,8 @@ obj-$(CONFIG_MTD_REDWOOD)    += redwood.o
 obj-$(CONFIG_MTD_UCLINUX)      += uclinux.o
 obj-$(CONFIG_MTD_NETtel)       += nettel.o
 obj-$(CONFIG_MTD_SCB2_FLASH)   += scb2_flash.o
-obj-$(CONFIG_MTD_EBONY)                += ebony.o
-obj-$(CONFIG_MTD_OCOTEA)       += ocotea.o
-obj-$(CONFIG_MTD_WALNUT)        += walnut.o
 obj-$(CONFIG_MTD_H720X)                += h720x-flash.o
 obj-$(CONFIG_MTD_SBC8240)      += sbc8240.o
-obj-$(CONFIG_MTD_NOR_TOTO)     += omap-toto-flash.o
 obj-$(CONFIG_MTD_IXP4XX)       += ixp4xx.o
 obj-$(CONFIG_MTD_IXP2000)      += ixp2000.o
 obj-$(CONFIG_MTD_WRSBC8260)    += wr_sbc82xx_flash.o
diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c
deleted file mode 100644 (file)
index d92b7c7..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Mapping for Ebony user flash
- *
- * Matt Porter <mporter@kernel.crashing.org>
- *
- * Copyright 2002-2004 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/ibm44x.h>
-#include <platforms/4xx/ebony.h>
-
-static struct mtd_info *flash;
-
-static struct map_info ebony_small_map = {
-       .name =         "Ebony small flash",
-       .size =         EBONY_SMALL_FLASH_SIZE,
-       .bankwidth =    1,
-};
-
-static struct map_info ebony_large_map = {
-       .name =         "Ebony large flash",
-       .size =         EBONY_LARGE_FLASH_SIZE,
-       .bankwidth =    1,
-};
-
-static struct mtd_partition ebony_small_partitions[] = {
-       {
-               .name =   "OpenBIOS",
-               .offset = 0x0,
-               .size =   0x80000,
-       }
-};
-
-static struct mtd_partition ebony_large_partitions[] = {
-       {
-               .name =   "fs",
-               .offset = 0,
-               .size =   0x380000,
-       },
-       {
-               .name =   "firmware",
-               .offset = 0x380000,
-               .size =   0x80000,
-       }
-};
-
-int __init init_ebony(void)
-{
-       u8 fpga0_reg;
-       u8 __iomem *fpga0_adr;
-       unsigned long long small_flash_base, large_flash_base;
-
-       fpga0_adr = ioremap64(EBONY_FPGA_ADDR, 16);
-       if (!fpga0_adr)
-               return -ENOMEM;
-
-       fpga0_reg = readb(fpga0_adr);
-       iounmap(fpga0_adr);
-
-       if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
-                       !EBONY_FLASH_SEL(fpga0_reg))
-               small_flash_base = EBONY_SMALL_FLASH_HIGH2;
-       else if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
-                       EBONY_FLASH_SEL(fpga0_reg))
-               small_flash_base = EBONY_SMALL_FLASH_HIGH1;
-       else if (!EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
-                       !EBONY_FLASH_SEL(fpga0_reg))
-               small_flash_base = EBONY_SMALL_FLASH_LOW2;
-       else
-               small_flash_base = EBONY_SMALL_FLASH_LOW1;
-
-       if (EBONY_BOOT_SMALL_FLASH(fpga0_reg) &&
-                       !EBONY_ONBRD_FLASH_EN(fpga0_reg))
-               large_flash_base = EBONY_LARGE_FLASH_LOW;
-       else
-               large_flash_base = EBONY_LARGE_FLASH_HIGH;
-
-       ebony_small_map.phys = small_flash_base;
-       ebony_small_map.virt = ioremap64(small_flash_base,
-                                        ebony_small_map.size);
-
-       if (!ebony_small_map.virt) {
-               printk("Failed to ioremap flash\n");
-               return -EIO;
-       }
-
-       simple_map_init(&ebony_small_map);
-
-       flash = do_map_probe("jedec_probe", &ebony_small_map);
-       if (flash) {
-               flash->owner = THIS_MODULE;
-               add_mtd_partitions(flash, ebony_small_partitions,
-                                       ARRAY_SIZE(ebony_small_partitions));
-       } else {
-               printk("map probe failed for flash\n");
-               iounmap(ebony_small_map.virt);
-               return -ENXIO;
-       }
-
-       ebony_large_map.phys = large_flash_base;
-       ebony_large_map.virt = ioremap64(large_flash_base,
-                                        ebony_large_map.size);
-
-       if (!ebony_large_map.virt) {
-               printk("Failed to ioremap flash\n");
-               iounmap(ebony_small_map.virt);
-               return -EIO;
-       }
-
-       simple_map_init(&ebony_large_map);
-
-       flash = do_map_probe("jedec_probe", &ebony_large_map);
-       if (flash) {
-               flash->owner = THIS_MODULE;
-               add_mtd_partitions(flash, ebony_large_partitions,
-                                       ARRAY_SIZE(ebony_large_partitions));
-       } else {
-               printk("map probe failed for flash\n");
-               iounmap(ebony_small_map.virt);
-               iounmap(ebony_large_map.virt);
-               return -ENXIO;
-       }
-
-       return 0;
-}
-
-static void __exit cleanup_ebony(void)
-{
-       if (flash) {
-               del_mtd_partitions(flash);
-               map_destroy(flash);
-       }
-
-       if (ebony_small_map.virt) {
-               iounmap(ebony_small_map.virt);
-               ebony_small_map.virt = NULL;
-       }
-
-       if (ebony_large_map.virt) {
-               iounmap(ebony_large_map.virt);
-               ebony_large_map.virt = NULL;
-       }
-}
-
-module_init(init_ebony);
-module_exit(cleanup_ebony);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 440GP Ebony boards");
diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c
deleted file mode 100644 (file)
index 5522eac..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Mapping for Ocotea user flash
- *
- * Matt Porter <mporter@kernel.crashing.org>
- *
- * Copyright 2002-2004 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/ibm44x.h>
-#include <platforms/4xx/ocotea.h>
-
-static struct mtd_info *flash;
-
-static struct map_info ocotea_small_map = {
-       .name =         "Ocotea small flash",
-       .size =         OCOTEA_SMALL_FLASH_SIZE,
-       .buswidth =     1,
-};
-
-static struct map_info ocotea_large_map = {
-       .name =         "Ocotea large flash",
-       .size =         OCOTEA_LARGE_FLASH_SIZE,
-       .buswidth =     1,
-};
-
-static struct mtd_partition ocotea_small_partitions[] = {
-       {
-               .name =   "pibs",
-               .offset = 0x0,
-               .size =   0x100000,
-       }
-};
-
-static struct mtd_partition ocotea_large_partitions[] = {
-       {
-               .name =   "fs",
-               .offset = 0,
-               .size =   0x300000,
-       },
-       {
-               .name =   "firmware",
-               .offset = 0x300000,
-               .size =   0x100000,
-       }
-};
-
-int __init init_ocotea(void)
-{
-       u8 fpga0_reg;
-       u8 *fpga0_adr;
-       unsigned long long small_flash_base, large_flash_base;
-
-       fpga0_adr = ioremap64(OCOTEA_FPGA_ADDR, 16);
-       if (!fpga0_adr)
-               return -ENOMEM;
-
-       fpga0_reg = readb((unsigned long)fpga0_adr);
-       iounmap(fpga0_adr);
-
-       if (OCOTEA_BOOT_LARGE_FLASH(fpga0_reg)) {
-               small_flash_base = OCOTEA_SMALL_FLASH_HIGH;
-               large_flash_base = OCOTEA_LARGE_FLASH_LOW;
-       }
-       else {
-               small_flash_base = OCOTEA_SMALL_FLASH_LOW;
-               large_flash_base = OCOTEA_LARGE_FLASH_HIGH;
-       }
-
-       ocotea_small_map.phys = small_flash_base;
-       ocotea_small_map.virt = ioremap64(small_flash_base,
-                                        ocotea_small_map.size);
-
-       if (!ocotea_small_map.virt) {
-               printk("Failed to ioremap flash\n");
-               return -EIO;
-       }
-
-       simple_map_init(&ocotea_small_map);
-
-       flash = do_map_probe("map_rom", &ocotea_small_map);
-       if (flash) {
-               flash->owner = THIS_MODULE;
-               add_mtd_partitions(flash, ocotea_small_partitions,
-                                       ARRAY_SIZE(ocotea_small_partitions));
-       } else {
-               printk("map probe failed for flash\n");
-               iounmap(ocotea_small_map.virt);
-               return -ENXIO;
-       }
-
-       ocotea_large_map.phys = large_flash_base;
-       ocotea_large_map.virt = ioremap64(large_flash_base,
-                                        ocotea_large_map.size);
-
-       if (!ocotea_large_map.virt) {
-               printk("Failed to ioremap flash\n");
-               iounmap(ocotea_small_map.virt);
-               return -EIO;
-       }
-
-       simple_map_init(&ocotea_large_map);
-
-       flash = do_map_probe("cfi_probe", &ocotea_large_map);
-       if (flash) {
-               flash->owner = THIS_MODULE;
-               add_mtd_partitions(flash, ocotea_large_partitions,
-                                       ARRAY_SIZE(ocotea_large_partitions));
-       } else {
-               printk("map probe failed for flash\n");
-               iounmap(ocotea_small_map.virt);
-               iounmap(ocotea_large_map.virt);
-               return -ENXIO;
-       }
-
-       return 0;
-}
-
-static void __exit cleanup_ocotea(void)
-{
-       if (flash) {
-               del_mtd_partitions(flash);
-               map_destroy(flash);
-       }
-
-       if (ocotea_small_map.virt) {
-               iounmap((void *)ocotea_small_map.virt);
-               ocotea_small_map.virt = 0;
-       }
-
-       if (ocotea_large_map.virt) {
-               iounmap((void *)ocotea_large_map.virt);
-               ocotea_large_map.virt = 0;
-       }
-}
-
-module_init(init_ocotea);
-module_exit(cleanup_ocotea);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matt Porter <mporter@kernel.crashing.org>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 440GX Ocotea boards");
diff --git a/drivers/mtd/maps/omap-toto-flash.c b/drivers/mtd/maps/omap-toto-flash.c
deleted file mode 100644 (file)
index 0a60ebb..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * NOR Flash memory access on TI Toto board
- *
- * jzhang@ti.com (C) 2003 Texas Instruments.
- *
- *  (C) 2002 MontVista Software, Inc.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#include <asm/hardware.h>
-#include <asm/io.h>
-
-
-#ifndef CONFIG_ARCH_OMAP
-#error This is for OMAP architecture only
-#endif
-
-//these lines need be moved to a hardware header file
-#define OMAP_TOTO_FLASH_BASE 0xd8000000
-#define OMAP_TOTO_FLASH_SIZE 0x80000
-
-static struct map_info omap_toto_map_flash = {
-       .name =         "OMAP Toto flash",
-       .bankwidth =    2,
-       .virt =         (void __iomem *)OMAP_TOTO_FLASH_BASE,
-};
-
-
-static struct mtd_partition toto_flash_partitions[] = {
-       {
-               .name =         "BootLoader",
-               .size =         0x00040000,     /* hopefully u-boot will stay 128k + 128*/
-               .offset =       0,
-               .mask_flags =   MTD_WRITEABLE,  /* force read-only */
-       }, {
-               .name =         "ReservedSpace",
-               .size =         0x00030000,
-               .offset =       MTDPART_OFS_APPEND,
-               //mask_flags:   MTD_WRITEABLE,  /* force read-only */
-       }, {
-               .name =         "EnvArea",      /* bottom 64KiB for env vars */
-               .size =         MTDPART_SIZ_FULL,
-               .offset =       MTDPART_OFS_APPEND,
-       }
-};
-
-static struct mtd_partition *parsed_parts;
-
-static struct mtd_info *flash_mtd;
-
-static int __init init_flash (void)
-{
-
-       struct mtd_partition *parts;
-       int nb_parts = 0;
-       int parsed_nr_parts = 0;
-       const char *part_type;
-
-       /*
-        * Static partition definition selection
-        */
-       part_type = "static";
-
-       parts = toto_flash_partitions;
-       nb_parts = ARRAY_SIZE(toto_flash_partitions);
-       omap_toto_map_flash.size = OMAP_TOTO_FLASH_SIZE;
-       omap_toto_map_flash.phys = virt_to_phys(OMAP_TOTO_FLASH_BASE);
-
-       simple_map_init(&omap_toto_map_flash);
-       /*
-        * Now let's probe for the actual flash.  Do it here since
-        * specific machine settings might have been set above.
-        */
-       printk(KERN_NOTICE "OMAP toto flash: probing %d-bit flash bus\n",
-               omap_toto_map_flash.bankwidth*8);
-       flash_mtd = do_map_probe("jedec_probe", &omap_toto_map_flash);
-       if (!flash_mtd)
-               return -ENXIO;
-
-       if (parsed_nr_parts > 0) {
-               parts = parsed_parts;
-               nb_parts = parsed_nr_parts;
-       }
-
-       if (nb_parts == 0) {
-               printk(KERN_NOTICE "OMAP toto flash: no partition info available,"
-                       "registering whole flash at once\n");
-               if (add_mtd_device(flash_mtd)){
-            return -ENXIO;
-        }
-       } else {
-               printk(KERN_NOTICE "Using %s partition definition\n",
-                       part_type);
-               return add_mtd_partitions(flash_mtd, parts, nb_parts);
-       }
-       return 0;
-}
-
-int __init omap_toto_mtd_init(void)
-{
-       int status;
-
-       if (status = init_flash()) {
-               printk(KERN_ERR "OMAP Toto Flash: unable to init map for toto flash\n");
-       }
-    return status;
-}
-
-static void  __exit omap_toto_mtd_cleanup(void)
-{
-       if (flash_mtd) {
-               del_mtd_partitions(flash_mtd);
-               map_destroy(flash_mtd);
-               kfree(parsed_parts);
-       }
-}
-
-module_init(omap_toto_mtd_init);
-module_exit(omap_toto_mtd_cleanup);
-
-MODULE_AUTHOR("Jian Zhang");
-MODULE_DESCRIPTION("OMAP Toto board map driver");
-MODULE_LICENSE("GPL");
index 5c6a25c90380aa70ab2afb4b3f34860adf76d43f..48f4cf5cb9d1d8f18a31c9f80af75b703d933b21 100644 (file)
@@ -203,15 +203,8 @@ intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
                 * not enabled, should we be allocating a new resource for it
                 * or simply enabling it?
                 */
-               if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) &
-                                   IORESOURCE_ROM_ENABLE)) {
-                       u32 val;
-                       pci_resource_flags(dev, PCI_ROM_RESOURCE) |= IORESOURCE_ROM_ENABLE;
-                       pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
-                       val |= PCI_ROM_ADDRESS_ENABLE;
-                       pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
-                       printk("%s: enabling expansion ROM\n", pci_name(dev));
-               }
+               pci_enable_rom(dev);
+               printk("%s: enabling expansion ROM\n", pci_name(dev));
        }
 
        if (!len || !base)
@@ -232,18 +225,13 @@ intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
 static void
 intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
 {
-       u32 val;
-
        if (map->base)
                iounmap(map->base);
 
        /*
         * We need to undo the PCI BAR2/PCI ROM BAR address alteration.
         */
-       pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~IORESOURCE_ROM_ENABLE;
-       pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
-       val &= ~PCI_ROM_ADDRESS_ENABLE;
-       pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
+       pci_disable_rom(dev);
 }
 
 static unsigned long
index 49acd41718934f2a671d887c94e6603b596f32f7..5fcfec034a9466819f83fb5ae00670e1c7fa976a 100644 (file)
@@ -230,8 +230,7 @@ static int __devinit of_flash_probe(struct of_device *dev,
 
 #ifdef CONFIG_MTD_OF_PARTS
        if (err == 0) {
-               err = of_mtd_parse_partitions(&dev->dev, info->mtd,
-                                             dp, &info->parts);
+               err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
                if (err < 0)
                        return err;
        }
diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c
deleted file mode 100644 (file)
index e243476..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Mapping for Walnut flash
- * (used ebony.c as a "framework")
- *
- * Heikki Lindholm <holindho@infradead.org>
- *
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/ibm4xx.h>
-#include <platforms/4xx/walnut.h>
-
-/* these should be in platforms/4xx/walnut.h ? */
-#define WALNUT_FLASH_ONBD_N(x)         (x & 0x02)
-#define WALNUT_FLASH_SRAM_SEL(x)       (x & 0x01)
-#define WALNUT_FLASH_LOW               0xFFF00000
-#define WALNUT_FLASH_HIGH              0xFFF80000
-#define WALNUT_FLASH_SIZE              0x80000
-
-static struct mtd_info *flash;
-
-static struct map_info walnut_map = {
-       .name =         "Walnut flash",
-       .size =         WALNUT_FLASH_SIZE,
-       .bankwidth =    1,
-};
-
-/* Actually, OpenBIOS is the last 128 KiB of the flash - better
- * partitioning could be made */
-static struct mtd_partition walnut_partitions[] = {
-       {
-               .name =   "OpenBIOS",
-               .offset = 0x0,
-               .size =   WALNUT_FLASH_SIZE,
-               /*.mask_flags = MTD_WRITEABLE, */ /* force read-only */
-       }
-};
-
-int __init init_walnut(void)
-{
-       u8 fpga_brds1;
-       void *fpga_brds1_adr;
-       void *fpga_status_adr;
-       unsigned long flash_base;
-
-       /* this should already be mapped (platform/4xx/walnut.c) */
-       fpga_status_adr = ioremap(WALNUT_FPGA_BASE, 8);
-       if (!fpga_status_adr)
-               return -ENOMEM;
-
-       fpga_brds1_adr = fpga_status_adr+5;
-       fpga_brds1 = readb(fpga_brds1_adr);
-       /* iounmap(fpga_status_adr); */
-
-       if (WALNUT_FLASH_ONBD_N(fpga_brds1)) {
-               printk("The on-board flash is disabled (U79 sw 5)!");
-               iounmap(fpga_status_adr);
-               return -EIO;
-       }
-       if (WALNUT_FLASH_SRAM_SEL(fpga_brds1))
-               flash_base = WALNUT_FLASH_LOW;
-       else
-               flash_base = WALNUT_FLASH_HIGH;
-
-       walnut_map.phys = flash_base;
-       walnut_map.virt =
-               (void __iomem *)ioremap(flash_base, walnut_map.size);
-
-       if (!walnut_map.virt) {
-               printk("Failed to ioremap flash.\n");
-               iounmap(fpga_status_adr);
-               return -EIO;
-       }
-
-       simple_map_init(&walnut_map);
-
-       flash = do_map_probe("jedec_probe", &walnut_map);
-       if (flash) {
-               flash->owner = THIS_MODULE;
-               add_mtd_partitions(flash, walnut_partitions,
-                                       ARRAY_SIZE(walnut_partitions));
-       } else {
-               printk("map probe failed for flash\n");
-               iounmap(fpga_status_adr);
-               return -ENXIO;
-       }
-
-       iounmap(fpga_status_adr);
-       return 0;
-}
-
-static void __exit cleanup_walnut(void)
-{
-       if (flash) {
-               del_mtd_partitions(flash);
-               map_destroy(flash);
-       }
-
-       if (walnut_map.virt) {
-               iounmap((void *)walnut_map.virt);
-               walnut_map.virt = 0;
-       }
-}
-
-module_init(init_walnut);
-module_exit(cleanup_walnut);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Heikki Lindholm <holindho@infradead.org>");
-MODULE_DESCRIPTION("MTD map and partitions for IBM 405GP Walnut boards");
index 1c74762dec89c25f73c3d7ab7fa4fbdaf2e08688..963840e9b5bf3d25177baa281b3eb70769d69950 100644 (file)
@@ -348,7 +348,7 @@ static void mtdchar_erase_callback (struct erase_info *instr)
        wake_up((wait_queue_head_t *)instr->priv);
 }
 
-#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+#ifdef CONFIG_HAVE_MTD_OTP
 static int otp_select_filemode(struct mtd_file_info *mfi, int mode)
 {
        struct mtd_info *mtd = mfi->mtd;
@@ -665,7 +665,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
                break;
        }
 
-#if defined(CONFIG_MTD_OTP) || defined(CONFIG_MTD_ONENAND_OTP)
+#ifdef CONFIG_HAVE_MTD_OTP
        case OTPSELECT:
        {
                int mode;
index 2972a5edb73d507e60b9b633b5e85e14a9070074..789842d0e6f21352023729c4037327205dccc067 100644 (file)
@@ -444,7 +444,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
                        return -EINVAL;
        }
 
-       instr->fail_addr = 0xffffffff;
+       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 
        /* make a local copy of instr to avoid modifying the caller's struct */
        erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
@@ -493,7 +493,7 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
                        /* sanity check: should never happen since
                         * block alignment has been checked above */
                        BUG_ON(err == -EINVAL);
-                       if (erase->fail_addr != 0xffffffff)
+                       if (erase->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
                                instr->fail_addr = erase->fail_addr + offset;
                        break;
                }
index 5a680e1e61f14dbc2ba684482792f2f40aabbee9..aebb3b27edbd7554135b7e4899850eb19f929b28 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/interrupt.h>
 #include <linux/mtd/mtd.h>
 
+#define MTDOOPS_KERNMSG_MAGIC 0x5d005d00
 #define OOPS_PAGE_SIZE 4096
 
 static struct mtdoops_context {
@@ -99,7 +100,7 @@ static void mtdoops_inc_counter(struct mtdoops_context *cxt)
        int ret;
 
        cxt->nextpage++;
-       if (cxt->nextpage > cxt->oops_pages)
+       if (cxt->nextpage >= cxt->oops_pages)
                cxt->nextpage = 0;
        cxt->nextcount++;
        if (cxt->nextcount == 0xffffffff)
@@ -141,7 +142,7 @@ static void mtdoops_workfunc_erase(struct work_struct *work)
        mod = (cxt->nextpage * OOPS_PAGE_SIZE) % mtd->erasesize;
        if (mod != 0) {
                cxt->nextpage = cxt->nextpage + ((mtd->erasesize - mod) / OOPS_PAGE_SIZE);
-               if (cxt->nextpage > cxt->oops_pages)
+               if (cxt->nextpage >= cxt->oops_pages)
                        cxt->nextpage = 0;
        }
 
@@ -158,7 +159,7 @@ badblock:
                                cxt->nextpage * OOPS_PAGE_SIZE);
                i++;
                cxt->nextpage = cxt->nextpage + (mtd->erasesize / OOPS_PAGE_SIZE);
-               if (cxt->nextpage > cxt->oops_pages)
+               if (cxt->nextpage >= cxt->oops_pages)
                        cxt->nextpage = 0;
                if (i == (cxt->oops_pages / (mtd->erasesize / OOPS_PAGE_SIZE))) {
                        printk(KERN_ERR "mtdoops: All blocks bad!\n");
@@ -224,40 +225,40 @@ static void find_next_position(struct mtdoops_context *cxt)
 {
        struct mtd_info *mtd = cxt->mtd;
        int ret, page, maxpos = 0;
-       u32 count, maxcount = 0xffffffff;
+       u32 count[2], maxcount = 0xffffffff;
        size_t retlen;
 
        for (page = 0; page < cxt->oops_pages; page++) {
-               ret = mtd->read(mtd, page * OOPS_PAGE_SIZE, 4, &retlen, (u_char *) &count);
-               if ((retlen != 4) || ((ret < 0) && (ret != -EUCLEAN))) {
-                       printk(KERN_ERR "mtdoops: Read failure at %d (%td of 4 read)"
+               ret = mtd->read(mtd, page * OOPS_PAGE_SIZE, 8, &retlen, (u_char *) &count[0]);
+               if ((retlen != 8) || ((ret < 0) && (ret != -EUCLEAN))) {
+                       printk(KERN_ERR "mtdoops: Read failure at %d (%td of 8 read)"
                                ", err %d.\n", page * OOPS_PAGE_SIZE, retlen, ret);
                        continue;
                }
 
-               if (count == 0xffffffff)
+               if (count[1] != MTDOOPS_KERNMSG_MAGIC)
+                       continue;
+               if (count[0] == 0xffffffff)
                        continue;
                if (maxcount == 0xffffffff) {
-                       maxcount = count;
+                       maxcount = count[0];
                        maxpos = page;
-               } else if ((count < 0x40000000) && (maxcount > 0xc0000000)) {
-                       maxcount = count;
+               } else if ((count[0] < 0x40000000) && (maxcount > 0xc0000000)) {
+                       maxcount = count[0];
                        maxpos = page;
-               } else if ((count > maxcount) && (count < 0xc0000000)) {
-                       maxcount = count;
+               } else if ((count[0] > maxcount) && (count[0] < 0xc0000000)) {
+                       maxcount = count[0];
                        maxpos = page;
-               } else if ((count > maxcount) && (count > 0xc0000000)
+               } else if ((count[0] > maxcount) && (count[0] > 0xc0000000)
                                        && (maxcount > 0x80000000)) {
-                       maxcount = count;
+                       maxcount = count[0];
                        maxpos = page;
                }
        }
        if (maxcount == 0xffffffff) {
                cxt->nextpage = 0;
                cxt->nextcount = 1;
-               cxt->ready = 1;
-               printk(KERN_DEBUG "mtdoops: Ready %d, %d (first init)\n",
-                               cxt->nextpage, cxt->nextcount);
+               schedule_work(&cxt->work_erase);
                return;
        }
 
@@ -358,8 +359,9 @@ mtdoops_console_write(struct console *co, const char *s, unsigned int count)
 
        if (cxt->writecount == 0) {
                u32 *stamp = cxt->oops_buf;
-               *stamp = cxt->nextcount;
-               cxt->writecount = 4;
+               *stamp++ = cxt->nextcount;
+               *stamp = MTDOOPS_KERNMSG_MAGIC;
+               cxt->writecount = 8;
        }
 
        if ((count + cxt->writecount) > OOPS_PAGE_SIZE)
index 9a06dc93ee0d36a14428b618d810fb2ece02140d..3728913fa5fa553ebc358f0bd6792f8c74ec0699 100644 (file)
@@ -214,7 +214,7 @@ static int part_erase(struct mtd_info *mtd, struct erase_info *instr)
        instr->addr += part->offset;
        ret = part->master->erase(part->master, instr);
        if (ret) {
-               if (instr->fail_addr != 0xffffffff)
+               if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
                        instr->fail_addr -= part->offset;
                instr->addr -= part->offset;
        }
@@ -226,7 +226,7 @@ void mtd_erase_callback(struct erase_info *instr)
        if (instr->mtd->erase == part_erase) {
                struct mtd_part *part = PART(instr->mtd);
 
-               if (instr->fail_addr != 0xffffffff)
+               if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN)
                        instr->fail_addr -= part->offset;
                instr->addr -= part->offset;
        }
index 41f361c49b32b73344b62f0838eb35647328dceb..1c2e9450d663ca9e7c2c3fd8a8a5a8b98b26755c 100644 (file)
@@ -56,6 +56,12 @@ config MTD_NAND_H1900
        help
          This enables the driver for the iPAQ h1900 flash.
 
+config MTD_NAND_GPIO
+       tristate "GPIO NAND Flash driver"
+       depends on GENERIC_GPIO && ARM
+       help
+         This enables a GPIO based NAND flash driver.
+
 config MTD_NAND_SPIA
        tristate "NAND Flash device on SPIA board"
        depends on ARCH_P720T
@@ -68,12 +74,6 @@ config MTD_NAND_AMS_DELTA
        help
          Support for NAND flash on Amstrad E3 (Delta).
 
-config MTD_NAND_TOTO
-       tristate "NAND Flash device on TOTO board"
-       depends on ARCH_OMAP && BROKEN
-       help
-         Support for NAND flash on Texas Instruments Toto platform.
-
 config MTD_NAND_TS7250
        tristate "NAND Flash device on TS-7250 board"
        depends on MACH_TS72XX
@@ -163,13 +163,6 @@ config MTD_NAND_S3C2410_HWECC
          incorrect ECC generation, and if using these, the default of
          software ECC is preferable.
 
-config MTD_NAND_NDFC
-       tristate "NDFC NanD Flash Controller"
-       depends on 4xx && !PPC_MERGE
-       select MTD_NAND_ECC_SMC
-       help
-        NDFC Nand Flash Controllers are integrated in IBM/AMCC's 4xx SoCs
-
 config MTD_NAND_S3C2410_CLKSTOP
        bool "S3C2410 NAND IDLE clock stop"
        depends on MTD_NAND_S3C2410
@@ -340,6 +333,13 @@ config MTD_NAND_PXA3xx
          This enables the driver for the NAND flash device found on
          PXA3xx processors
 
+config MTD_NAND_PXA3xx_BUILTIN
+       bool "Use builtin definitions for some NAND chips (deprecated)"
+       depends on MTD_NAND_PXA3xx
+       help
+         This enables builtin definitions for some NAND chips. This
+         is deprecated in favor of platform specific data.
+
 config MTD_NAND_CM_X270
        tristate "Support for NAND Flash on CM-X270 modules"
        depends on MTD_NAND && MACH_ARMCORE
@@ -400,10 +400,24 @@ config MTD_NAND_FSL_ELBC
 
 config MTD_NAND_FSL_UPM
        tristate "Support for NAND on Freescale UPM"
-       depends on MTD_NAND && OF_GPIO && (PPC_83xx || PPC_85xx)
+       depends on MTD_NAND && (PPC_83xx || PPC_85xx)
        select FSL_LBC
        help
          Enables support for NAND Flash chips wired onto Freescale PowerPC
          processor localbus with User-Programmable Machine support.
 
+config MTD_NAND_MXC
+       tristate "MXC NAND support"
+       depends on ARCH_MX2
+       help
+         This enables the driver for the NAND flash controller on the
+         MXC processors.
+
+config MTD_NAND_SH_FLCTL
+       tristate "Support for NAND on Renesas SuperH FLCTL"
+       depends on MTD_NAND && SUPERH && CPU_SUBTYPE_SH7723
+       help
+         Several Renesas SuperH CPU has FLCTL. This option enables support
+         for NAND Flash using FLCTL. This driver support SH7723.
+
 endif # MTD_NAND
index b786c5da82da227fe388bf468c6dc370caee49ea..b661586afbfc38f5b2d616b4c5615207c9d5862e 100644 (file)
@@ -8,7 +8,6 @@ obj-$(CONFIG_MTD_NAND_IDS)              += nand_ids.o
 obj-$(CONFIG_MTD_NAND_CAFE)            += cafe_nand.o
 obj-$(CONFIG_MTD_NAND_SPIA)            += spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)       += ams-delta.o
-obj-$(CONFIG_MTD_NAND_TOTO)            += toto.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)                += autcpu12.o
 obj-$(CONFIG_MTD_NAND_EDB7312)         += edb7312.o
 obj-$(CONFIG_MTD_NAND_AU1550)          += au1550nd.o
@@ -24,6 +23,7 @@ obj-$(CONFIG_MTD_NAND_NANDSIM)                += nandsim.o
 obj-$(CONFIG_MTD_NAND_CS553X)          += cs553x_nand.o
 obj-$(CONFIG_MTD_NAND_NDFC)            += ndfc.o
 obj-$(CONFIG_MTD_NAND_ATMEL)           += atmel_nand.o
+obj-$(CONFIG_MTD_NAND_GPIO)            += gpio.o
 obj-$(CONFIG_MTD_NAND_CM_X270)         += cmx270_nand.o
 obj-$(CONFIG_MTD_NAND_BASLER_EXCITE)   += excite_nandflash.o
 obj-$(CONFIG_MTD_NAND_PXA3xx)          += pxa3xx_nand.o
@@ -34,5 +34,7 @@ obj-$(CONFIG_MTD_NAND_PASEMI)         += pasemi_nand.o
 obj-$(CONFIG_MTD_NAND_ORION)           += orion_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_ELBC)                += fsl_elbc_nand.o
 obj-$(CONFIG_MTD_NAND_FSL_UPM)         += fsl_upm.o
+obj-$(CONFIG_MTD_NAND_SH_FLCTL)                += sh_flctl.o
+obj-$(CONFIG_MTD_NAND_MXC)             += mxc_nand.o
 
 nand-objs := nand_base.o nand_bbt.o
index 3387e0d5076b06bad1af8506d73f673db99a1d2a..c98c1570a40b1ef5f3f3931ab4e0512be0341406 100644 (file)
@@ -173,48 +173,6 @@ static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
        __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
 }
 
-/*
- * write oob for small pages
- */
-static int atmel_nand_write_oob_512(struct mtd_info *mtd,
-               struct nand_chip *chip, int page)
-{
-       int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
-       int eccsize = chip->ecc.size, length = mtd->oobsize;
-       int len, pos, status = 0;
-       const uint8_t *bufpoi = chip->oob_poi;
-
-       pos = eccsize + chunk;
-
-       chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
-       len = min_t(int, length, chunk);
-       chip->write_buf(mtd, bufpoi, len);
-       bufpoi += len;
-       length -= len;
-       if (length > 0)
-               chip->write_buf(mtd, bufpoi, length);
-
-       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-       status = chip->waitfunc(mtd, chip);
-
-       return status & NAND_STATUS_FAIL ? -EIO : 0;
-
-}
-
-/*
- * read oob for small pages
- */
-static int atmel_nand_read_oob_512(struct mtd_info *mtd,
-               struct nand_chip *chip, int page, int sndcmd)
-{
-       if (sndcmd) {
-               chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
-               sndcmd = 0;
-       }
-       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-       return sndcmd;
-}
-
 /*
  * Calculate HW ECC
  *
@@ -235,14 +193,14 @@ static int atmel_nand_calculate(struct mtd_info *mtd,
        /* get the first 2 ECC bytes */
        ecc_value = ecc_readl(host->ecc, PR);
 
-       ecc_code[eccpos[0]] = ecc_value & 0xFF;
-       ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF;
+       ecc_code[0] = ecc_value & 0xFF;
+       ecc_code[1] = (ecc_value >> 8) & 0xFF;
 
        /* get the last 2 ECC bytes */
        ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY;
 
-       ecc_code[eccpos[2]] = ecc_value & 0xFF;
-       ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF;
+       ecc_code[2] = ecc_value & 0xFF;
+       ecc_code[3] = (ecc_value >> 8) & 0xFF;
 
        return 0;
 }
@@ -476,14 +434,12 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                        res = -EIO;
                        goto err_ecc_ioremap;
                }
-               nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME;
+               nand_chip->ecc.mode = NAND_ECC_HW;
                nand_chip->ecc.calculate = atmel_nand_calculate;
                nand_chip->ecc.correct = atmel_nand_correct;
                nand_chip->ecc.hwctl = atmel_nand_hwctl;
                nand_chip->ecc.read_page = atmel_nand_read_page;
                nand_chip->ecc.bytes = 4;
-               nand_chip->ecc.prepad = 0;
-               nand_chip->ecc.postpad = 0;
        }
 
        nand_chip->chip_delay = 20;             /* 20us command delay time */
@@ -514,7 +470,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                goto err_scan_ident;
        }
 
-       if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) {
+       if (nand_chip->ecc.mode == NAND_ECC_HW) {
                /* ECC is calculated for the whole page (1 step) */
                nand_chip->ecc.size = mtd->writesize;
 
@@ -522,8 +478,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                switch (mtd->writesize) {
                case 512:
                        nand_chip->ecc.layout = &atmel_oobinfo_small;
-                       nand_chip->ecc.read_oob = atmel_nand_read_oob_512;
-                       nand_chip->ecc.write_oob = atmel_nand_write_oob_512;
                        ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
                        break;
                case 1024:
index 3370a800fd3612fd43f6bb54d4cf8a36cbdf2f14..9f1b451005ca14f8ce73aaa3c64e087cf2e7e607 100644 (file)
@@ -289,8 +289,10 @@ static int __init cs553x_init(void)
        int i;
        uint64_t val;
 
+#ifdef CONFIG_MTD_PARTITIONS
        int mtd_parts_nb = 0;
        struct mtd_partition *mtd_parts = NULL;
+#endif
 
        /* If the CPU isn't a Geode GX or LX, abort */
        if (!is_geode())
index 98ad3cefcaf47d5678c81b9a4481ff4c6bec5b4e..4aa5bd6158daf8060c8dcb7f7e06dc9286c64203 100644 (file)
@@ -918,8 +918,7 @@ static int __devinit fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl,
 
 #ifdef CONFIG_MTD_OF_PARTS
        if (ret == 0) {
-               ret = of_mtd_parse_partitions(priv->dev, &priv->mtd,
-                                             node, &parts);
+               ret = of_mtd_parse_partitions(priv->dev, node, &parts);
                if (ret < 0)
                        goto err;
        }
index 1ebfd87f00b401de487f65836aac60e810bf5214..024e3fffd4bb49b6176af4701c07e344120a3fc2 100644 (file)
@@ -13,6 +13,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/delay.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
@@ -36,8 +37,6 @@ struct fsl_upm_nand {
        uint8_t upm_cmd_offset;
        void __iomem *io_base;
        int rnb_gpio;
-       const uint32_t *wait_pattern;
-       const uint32_t *wait_write;
        int chip_delay;
 };
 
@@ -61,10 +60,11 @@ static void fun_wait_rnb(struct fsl_upm_nand *fun)
        if (fun->rnb_gpio >= 0) {
                while (--cnt && !fun_chip_ready(&fun->mtd))
                        cpu_relax();
+               if (!cnt)
+                       dev_err(fun->dev, "tired waiting for RNB\n");
+       } else {
+               ndelay(100);
        }
-
-       if (!cnt)
-               dev_err(fun->dev, "tired waiting for RNB\n");
 }
 
 static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
@@ -89,8 +89,7 @@ static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 
        fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd);
 
-       if (fun->wait_pattern)
-               fun_wait_rnb(fun);
+       fun_wait_rnb(fun);
 }
 
 static uint8_t fun_read_byte(struct mtd_info *mtd)
@@ -116,14 +115,16 @@ static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 
        for (i = 0; i < len; i++) {
                out_8(fun->chip.IO_ADDR_W, buf[i]);
-               if (fun->wait_write)
-                       fun_wait_rnb(fun);
+               fun_wait_rnb(fun);
        }
 }
 
-static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
+static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
+                                  const struct device_node *upm_np,
+                                  const struct resource *io_res)
 {
        int ret;
+       struct device_node *flash_np;
 #ifdef CONFIG_MTD_PARTITIONS
        static const char *part_types[] = { "cmdlinepart", NULL, };
 #endif
@@ -143,18 +144,37 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun)
        fun->mtd.priv = &fun->chip;
        fun->mtd.owner = THIS_MODULE;
 
+       flash_np = of_get_next_child(upm_np, NULL);
+       if (!flash_np)
+               return -ENODEV;
+
+       fun->mtd.name = kasprintf(GFP_KERNEL, "%x.%s", io_res->start,
+                                 flash_np->name);
+       if (!fun->mtd.name) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
        ret = nand_scan(&fun->mtd, 1);
        if (ret)
-               return ret;
-
-       fun->mtd.name = fun->dev->bus_id;
+               goto err;
 
 #ifdef CONFIG_MTD_PARTITIONS
        ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
+
+#ifdef CONFIG_MTD_OF_PARTS
+       if (ret == 0)
+               ret = of_mtd_parse_partitions(fun->dev, &fun->mtd,
+                                             flash_np, &fun->parts);
+#endif
        if (ret > 0)
-               return add_mtd_partitions(&fun->mtd, fun->parts, ret);
+               ret = add_mtd_partitions(&fun->mtd, fun->parts, ret);
+       else
 #endif
-       return add_mtd_device(&fun->mtd);
+               ret = add_mtd_device(&fun->mtd);
+err:
+       of_node_put(flash_np);
+       return ret;
 }
 
 static int __devinit fun_probe(struct of_device *ofdev,
@@ -211,6 +231,12 @@ static int __devinit fun_probe(struct of_device *ofdev,
                goto err2;
        }
 
+       prop = of_get_property(ofdev->node, "chip-delay", NULL);
+       if (prop)
+               fun->chip_delay = *prop;
+       else
+               fun->chip_delay = 50;
+
        fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start,
                                          io_res.end - io_res.start + 1);
        if (!fun->io_base) {
@@ -220,17 +246,8 @@ static int __devinit fun_probe(struct of_device *ofdev,
 
        fun->dev = &ofdev->dev;
        fun->last_ctrl = NAND_CLE;
-       fun->wait_pattern = of_get_property(ofdev->node, "fsl,wait-pattern",
-                                           NULL);
-       fun->wait_write = of_get_property(ofdev->node, "fsl,wait-write", NULL);
-
-       prop = of_get_property(ofdev->node, "chip-delay", NULL);
-       if (prop)
-               fun->chip_delay = *prop;
-       else
-               fun->chip_delay = 50;
 
-       ret = fun_chip_init(fun);
+       ret = fun_chip_init(fun, ofdev->node, &io_res);
        if (ret)
                goto err2;
 
@@ -251,6 +268,7 @@ static int __devexit fun_remove(struct of_device *ofdev)
        struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev);
 
        nand_release(&fun->mtd);
+       kfree(fun->mtd.name);
 
        if (fun->rnb_gpio >= 0)
                gpio_free(fun->rnb_gpio);
diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c
new file mode 100644 (file)
index 0000000..8f902e7
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * drivers/mtd/nand/gpio.c
+ *
+ * Updated, and converted to generic GPIO based driver by Russell King.
+ *
+ * Written by Ben Dooks <ben@simtec.co.uk>
+ *   Based on 2.4 version by Mark Whittaker
+ *
+ * Â© 2004 Simtec Electronics
+ *
+ * Device driver for NAND connected via GPIO
+ *
+ * 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/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand-gpio.h>
+
+struct gpiomtd {
+       void __iomem            *io_sync;
+       struct mtd_info         mtd_info;
+       struct nand_chip        nand_chip;
+       struct gpio_nand_platdata plat;
+};
+
+#define gpio_nand_getpriv(x) container_of(x, struct gpiomtd, mtd_info)
+
+
+#ifdef CONFIG_ARM
+/* gpio_nand_dosync()
+ *
+ * Make sure the GPIO state changes occur in-order with writes to NAND
+ * memory region.
+ * Needed on PXA due to bus-reordering within the SoC itself (see section on
+ * I/O ordering in PXA manual (section 2.3, p35)
+ */
+static void gpio_nand_dosync(struct gpiomtd *gpiomtd)
+{
+       unsigned long tmp;
+
+       if (gpiomtd->io_sync) {
+               /*
+                * Linux memory barriers don't cater for what's required here.
+                * What's required is what's here - a read from a separate
+                * region with a dependency on that read.
+                */
+               tmp = readl(gpiomtd->io_sync);
+               asm volatile("mov %1, %0\n" : "=r" (tmp) : "r" (tmp));
+       }
+}
+#else
+static inline void gpio_nand_dosync(struct gpiomtd *gpiomtd) {}
+#endif
+
+static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
+{
+       struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
+
+       gpio_nand_dosync(gpiomtd);
+
+       if (ctrl & NAND_CTRL_CHANGE) {
+               gpio_set_value(gpiomtd->plat.gpio_nce, !(ctrl & NAND_NCE));
+               gpio_set_value(gpiomtd->plat.gpio_cle, !!(ctrl & NAND_CLE));
+               gpio_set_value(gpiomtd->plat.gpio_ale, !!(ctrl & NAND_ALE));
+               gpio_nand_dosync(gpiomtd);
+       }
+       if (cmd == NAND_CMD_NONE)
+               return;
+
+       writeb(cmd, gpiomtd->nand_chip.IO_ADDR_W);
+       gpio_nand_dosync(gpiomtd);
+}
+
+static void gpio_nand_writebuf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       writesb(this->IO_ADDR_W, buf, len);
+}
+
+static void gpio_nand_readbuf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       readsb(this->IO_ADDR_R, buf, len);
+}
+
+static int gpio_nand_verifybuf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+       unsigned char read, *p = (unsigned char *) buf;
+       int i, err = 0;
+
+       for (i = 0; i < len; i++) {
+               read = readb(this->IO_ADDR_R);
+               if (read != p[i]) {
+                       pr_debug("%s: err at %d (read %04x vs %04x)\n",
+                              __func__, i, read, p[i]);
+                       err = -EFAULT;
+               }
+       }
+       return err;
+}
+
+static void gpio_nand_writebuf16(struct mtd_info *mtd, const u_char *buf,
+                                int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       if (IS_ALIGNED((unsigned long)buf, 2)) {
+               writesw(this->IO_ADDR_W, buf, len>>1);
+       } else {
+               int i;
+               unsigned short *ptr = (unsigned short *)buf;
+
+               for (i = 0; i < len; i += 2, ptr++)
+                       writew(*ptr, this->IO_ADDR_W);
+       }
+}
+
+static void gpio_nand_readbuf16(struct mtd_info *mtd, u_char *buf, int len)
+{
+       struct nand_chip *this = mtd->priv;
+
+       if (IS_ALIGNED((unsigned long)buf, 2)) {
+               readsw(this->IO_ADDR_R, buf, len>>1);
+       } else {
+               int i;
+               unsigned short *ptr = (unsigned short *)buf;
+
+               for (i = 0; i < len; i += 2, ptr++)
+                       *ptr = readw(this->IO_ADDR_R);
+       }
+}
+
+static int gpio_nand_verifybuf16(struct mtd_info *mtd, const u_char *buf,
+                                int len)
+{
+       struct nand_chip *this = mtd->priv;
+       unsigned short read, *p = (unsigned short *) buf;
+       int i, err = 0;
+       len >>= 1;
+
+       for (i = 0; i < len; i++) {
+               read = readw(this->IO_ADDR_R);
+               if (read != p[i]) {
+                       pr_debug("%s: err at %d (read %04x vs %04x)\n",
+                              __func__, i, read, p[i]);
+                       err = -EFAULT;
+               }
+       }
+       return err;
+}
+
+
+static int gpio_nand_devready(struct mtd_info *mtd)
+{
+       struct gpiomtd *gpiomtd = gpio_nand_getpriv(mtd);
+       return gpio_get_value(gpiomtd->plat.gpio_rdy);
+}
+
+static int __devexit gpio_nand_remove(struct platform_device *dev)
+{
+       struct gpiomtd *gpiomtd = platform_get_drvdata(dev);
+       struct resource *res;
+
+       nand_release(&gpiomtd->mtd_info);
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 1);
+       iounmap(gpiomtd->io_sync);
+       if (res)
+               release_mem_region(res->start, res->end - res->start + 1);
+
+       res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       iounmap(gpiomtd->nand_chip.IO_ADDR_R);
+       release_mem_region(res->start, res->end - res->start + 1);
+
+       if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+               gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
+       gpio_set_value(gpiomtd->plat.gpio_nce, 1);
+
+       gpio_free(gpiomtd->plat.gpio_cle);
+       gpio_free(gpiomtd->plat.gpio_ale);
+       gpio_free(gpiomtd->plat.gpio_nce);
+       if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+               gpio_free(gpiomtd->plat.gpio_nwp);
+       gpio_free(gpiomtd->plat.gpio_rdy);
+
+       kfree(gpiomtd);
+
+       return 0;
+}
+
+static void __iomem *request_and_remap(struct resource *res, size_t size,
+                                       const char *name, int *err)
+{
+       void __iomem *ptr;
+
+       if (!request_mem_region(res->start, res->end - res->start + 1, name)) {
+               *err = -EBUSY;
+               return NULL;
+       }
+
+       ptr = ioremap(res->start, size);
+       if (!ptr) {
+               release_mem_region(res->start, res->end - res->start + 1);
+               *err = -ENOMEM;
+       }
+       return ptr;
+}
+
+static int __devinit gpio_nand_probe(struct platform_device *dev)
+{
+       struct gpiomtd *gpiomtd;
+       struct nand_chip *this;
+       struct resource *res0, *res1;
+       int ret;
+
+       if (!dev->dev.platform_data)
+               return -EINVAL;
+
+       res0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
+       if (!res0)
+               return -EINVAL;
+
+       gpiomtd = kzalloc(sizeof(*gpiomtd), GFP_KERNEL);
+       if (gpiomtd == NULL) {
+               dev_err(&dev->dev, "failed to create NAND MTD\n");
+               return -ENOMEM;
+       }
+
+       this = &gpiomtd->nand_chip;
+       this->IO_ADDR_R = request_and_remap(res0, 2, "NAND", &ret);
+       if (!this->IO_ADDR_R) {
+               dev_err(&dev->dev, "unable to map NAND\n");
+               goto err_map;
+       }
+
+       res1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
+       if (res1) {
+               gpiomtd->io_sync = request_and_remap(res1, 4, "NAND sync", &ret);
+               if (!gpiomtd->io_sync) {
+                       dev_err(&dev->dev, "unable to map sync NAND\n");
+                       goto err_sync;
+               }
+       }
+
+       memcpy(&gpiomtd->plat, dev->dev.platform_data, sizeof(gpiomtd->plat));
+
+       ret = gpio_request(gpiomtd->plat.gpio_nce, "NAND NCE");
+       if (ret)
+               goto err_nce;
+       gpio_direction_output(gpiomtd->plat.gpio_nce, 1);
+       if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) {
+               ret = gpio_request(gpiomtd->plat.gpio_nwp, "NAND NWP");
+               if (ret)
+                       goto err_nwp;
+               gpio_direction_output(gpiomtd->plat.gpio_nwp, 1);
+       }
+       ret = gpio_request(gpiomtd->plat.gpio_ale, "NAND ALE");
+       if (ret)
+               goto err_ale;
+       gpio_direction_output(gpiomtd->plat.gpio_ale, 0);
+       ret = gpio_request(gpiomtd->plat.gpio_cle, "NAND CLE");
+       if (ret)
+               goto err_cle;
+       gpio_direction_output(gpiomtd->plat.gpio_cle, 0);
+       ret = gpio_request(gpiomtd->plat.gpio_rdy, "NAND RDY");
+       if (ret)
+               goto err_rdy;
+       gpio_direction_input(gpiomtd->plat.gpio_rdy);
+
+
+       this->IO_ADDR_W  = this->IO_ADDR_R;
+       this->ecc.mode   = NAND_ECC_SOFT;
+       this->options    = gpiomtd->plat.options;
+       this->chip_delay = gpiomtd->plat.chip_delay;
+
+       /* install our routines */
+       this->cmd_ctrl   = gpio_nand_cmd_ctrl;
+       this->dev_ready  = gpio_nand_devready;
+
+       if (this->options & NAND_BUSWIDTH_16) {
+               this->read_buf   = gpio_nand_readbuf16;
+               this->write_buf  = gpio_nand_writebuf16;
+               this->verify_buf = gpio_nand_verifybuf16;
+       } else {
+               this->read_buf   = gpio_nand_readbuf;
+               this->write_buf  = gpio_nand_writebuf;
+               this->verify_buf = gpio_nand_verifybuf;
+       }
+
+       /* set the mtd private data for the nand driver */
+       gpiomtd->mtd_info.priv = this;
+       gpiomtd->mtd_info.owner = THIS_MODULE;
+
+       if (nand_scan(&gpiomtd->mtd_info, 1)) {
+               dev_err(&dev->dev, "no nand chips found?\n");
+               ret = -ENXIO;
+               goto err_wp;
+       }
+
+       if (gpiomtd->plat.adjust_parts)
+               gpiomtd->plat.adjust_parts(&gpiomtd->plat,
+                                          gpiomtd->mtd_info.size);
+
+       add_mtd_partitions(&gpiomtd->mtd_info, gpiomtd->plat.parts,
+                          gpiomtd->plat.num_parts);
+       platform_set_drvdata(dev, gpiomtd);
+
+       return 0;
+
+err_wp:
+       if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+               gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
+       gpio_free(gpiomtd->plat.gpio_rdy);
+err_rdy:
+       gpio_free(gpiomtd->plat.gpio_cle);
+err_cle:
+       gpio_free(gpiomtd->plat.gpio_ale);
+err_ale:
+       if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
+               gpio_free(gpiomtd->plat.gpio_nwp);
+err_nwp:
+       gpio_free(gpiomtd->plat.gpio_nce);
+err_nce:
+       iounmap(gpiomtd->io_sync);
+       if (res1)
+               release_mem_region(res1->start, res1->end - res1->start + 1);
+err_sync:
+       iounmap(gpiomtd->nand_chip.IO_ADDR_R);
+       release_mem_region(res0->start, res0->end - res0->start + 1);
+err_map:
+       kfree(gpiomtd);
+       return ret;
+}
+
+static struct platform_driver gpio_nand_driver = {
+       .probe          = gpio_nand_probe,
+       .remove         = gpio_nand_remove,
+       .driver         = {
+               .name   = "gpio-nand",
+       },
+};
+
+static int __init gpio_nand_init(void)
+{
+       printk(KERN_INFO "GPIO NAND driver, Â© 2004 Simtec Electronics\n");
+
+       return platform_driver_register(&gpio_nand_driver);
+}
+
+static void __exit gpio_nand_exit(void)
+{
+       platform_driver_unregister(&gpio_nand_driver);
+}
+
+module_init(gpio_nand_init);
+module_exit(gpio_nand_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
+MODULE_DESCRIPTION("GPIO NAND Driver");
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
new file mode 100644 (file)
index 0000000..21fd4f1
--- /dev/null
@@ -0,0 +1,1077 @@
+/*
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008 Sascha Hauer, kernel@pengutronix.de
+ *
+ * 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/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <asm/mach/flash.h>
+#include <mach/mxc_nand.h>
+
+#define DRIVER_NAME "mxc_nand"
+
+/* Addresses for NFC registers */
+#define NFC_BUF_SIZE           0xE00
+#define NFC_BUF_ADDR           0xE04
+#define NFC_FLASH_ADDR         0xE06
+#define NFC_FLASH_CMD          0xE08
+#define NFC_CONFIG             0xE0A
+#define NFC_ECC_STATUS_RESULT  0xE0C
+#define NFC_RSLTMAIN_AREA      0xE0E
+#define NFC_RSLTSPARE_AREA     0xE10
+#define NFC_WRPROT             0xE12
+#define NFC_UNLOCKSTART_BLKADDR        0xE14
+#define NFC_UNLOCKEND_BLKADDR  0xE16
+#define NFC_NF_WRPRST          0xE18
+#define NFC_CONFIG1            0xE1A
+#define NFC_CONFIG2            0xE1C
+
+/* Addresses for NFC RAM BUFFER Main area 0 */
+#define MAIN_AREA0             0x000
+#define MAIN_AREA1             0x200
+#define MAIN_AREA2             0x400
+#define MAIN_AREA3             0x600
+
+/* Addresses for NFC SPARE BUFFER Spare area 0 */
+#define SPARE_AREA0            0x800
+#define SPARE_AREA1            0x810
+#define SPARE_AREA2            0x820
+#define SPARE_AREA3            0x830
+
+/* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Command operation */
+#define NFC_CMD            0x1
+
+/* Set INT to 0, FADD to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Address operation */
+#define NFC_ADDR           0x2
+
+/* Set INT to 0, FDI to 1, rest to 0 in NFC_CONFIG2 Register
+ * for Input operation */
+#define NFC_INPUT          0x4
+
+/* Set INT to 0, FDO to 001, rest to 0 in NFC_CONFIG2 Register
+ * for Data Output operation */
+#define NFC_OUTPUT         0x8
+
+/* Set INT to 0, FD0 to 010, rest to 0 in NFC_CONFIG2 Register
+ * for Read ID operation */
+#define NFC_ID             0x10
+
+/* Set INT to 0, FDO to 100, rest to 0 in NFC_CONFIG2 Register
+ * for Read Status operation */
+#define NFC_STATUS         0x20
+
+/* Set INT to 1, rest to 0 in NFC_CONFIG2 Register for Read
+ * Status operation */
+#define NFC_INT            0x8000
+
+#define NFC_SP_EN           (1 << 2)
+#define NFC_ECC_EN          (1 << 3)
+#define NFC_INT_MSK         (1 << 4)
+#define NFC_BIG             (1 << 5)
+#define NFC_RST             (1 << 6)
+#define NFC_CE              (1 << 7)
+#define NFC_ONE_CYCLE       (1 << 8)
+
+struct mxc_nand_host {
+       struct mtd_info         mtd;
+       struct nand_chip        nand;
+       struct mtd_partition    *parts;
+       struct device           *dev;
+
+       void __iomem            *regs;
+       int                     spare_only;
+       int                     status_request;
+       int                     pagesize_2k;
+       uint16_t                col_addr;
+       struct clk              *clk;
+       int                     clk_act;
+       int                     irq;
+
+       wait_queue_head_t       irq_waitq;
+};
+
+/* Define delays in microsec for NAND device operations */
+#define TROP_US_DELAY   2000
+/* Macros to get byte and bit positions of ECC */
+#define COLPOS(x)  ((x) >> 3)
+#define BITPOS(x) ((x) & 0xf)
+
+/* Define single bit Error positions in Main & Spare area */
+#define MAIN_SINGLEBIT_ERROR 0x4
+#define SPARE_SINGLEBIT_ERROR 0x1
+
+/* OOB placement block for use with hardware ecc generation */
+static struct nand_ecclayout nand_hw_eccoob_8 = {
+       .eccbytes = 5,
+       .eccpos = {6, 7, 8, 9, 10},
+       .oobfree = {{0, 5}, {11, 5}, }
+};
+
+static struct nand_ecclayout nand_hw_eccoob_16 = {
+       .eccbytes = 5,
+       .eccpos = {6, 7, 8, 9, 10},
+       .oobfree = {{0, 6}, {12, 4}, }
+};
+
+#ifdef CONFIG_MTD_PARTITIONS
+static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
+#endif
+
+static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
+{
+       struct mxc_nand_host *host = dev_id;
+
+       uint16_t tmp;
+
+       tmp = readw(host->regs + NFC_CONFIG1);
+       tmp |= NFC_INT_MSK; /* Disable interrupt */
+       writew(tmp, host->regs + NFC_CONFIG1);
+
+       wake_up(&host->irq_waitq);
+
+       return IRQ_HANDLED;
+}
+
+/* This function polls the NANDFC to wait for the basic operation to
+ * complete by checking the INT bit of config2 register.
+ */
+static void wait_op_done(struct mxc_nand_host *host, int max_retries,
+                               uint16_t param, int useirq)
+{
+       uint32_t tmp;
+
+       if (useirq) {
+               if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
+
+                       tmp = readw(host->regs + NFC_CONFIG1);
+                       tmp  &= ~NFC_INT_MSK;   /* Enable interrupt */
+                       writew(tmp, host->regs + NFC_CONFIG1);
+
+                       wait_event(host->irq_waitq,
+                               readw(host->regs + NFC_CONFIG2) & NFC_INT);
+
+                       tmp = readw(host->regs + NFC_CONFIG2);
+                       tmp  &= ~NFC_INT;
+                       writew(tmp, host->regs + NFC_CONFIG2);
+               }
+       } else {
+               while (max_retries-- > 0) {
+                       if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
+                               tmp = readw(host->regs + NFC_CONFIG2);
+                               tmp  &= ~NFC_INT;
+                               writew(tmp, host->regs + NFC_CONFIG2);
+                               break;
+                       }
+                       udelay(1);
+               }
+               if (max_retries <= 0)
+                       DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
+                             __func__, param);
+       }
+}
+
+/* This function issues the specified command to the NAND device and
+ * waits for completion. */
+static void send_cmd(struct mxc_nand_host *host, uint16_t cmd, int useirq)
+{
+       DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
+
+       writew(cmd, host->regs + NFC_FLASH_CMD);
+       writew(NFC_CMD, host->regs + NFC_CONFIG2);
+
+       /* Wait for operation to complete */
+       wait_op_done(host, TROP_US_DELAY, cmd, useirq);
+}
+
+/* This function sends an address (or partial address) to the
+ * NAND device. The address is used to select the source/destination for
+ * a NAND command. */
+static void send_addr(struct mxc_nand_host *host, uint16_t addr, int islast)
+{
+       DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
+
+       writew(addr, host->regs + NFC_FLASH_ADDR);
+       writew(NFC_ADDR, host->regs + NFC_CONFIG2);
+
+       /* Wait for operation to complete */
+       wait_op_done(host, TROP_US_DELAY, addr, islast);
+}
+
+/* This function requests the NANDFC to initate the transfer
+ * of data currently in the NANDFC RAM buffer to the NAND device. */
+static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
+                       int spare_only)
+{
+       DEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+
+       /* NANDFC buffer 0 is used for page read/write */
+       writew(buf_id, host->regs + NFC_BUF_ADDR);
+
+       /* Configure spare or page+spare access */
+       if (!host->pagesize_2k) {
+               uint16_t config1 = readw(host->regs + NFC_CONFIG1);
+               if (spare_only)
+                       config1 |= NFC_SP_EN;
+               else
+                       config1 &= ~(NFC_SP_EN);
+               writew(config1, host->regs + NFC_CONFIG1);
+       }
+
+       writew(NFC_INPUT, host->regs + NFC_CONFIG2);
+
+       /* Wait for operation to complete */
+       wait_op_done(host, TROP_US_DELAY, spare_only, true);
+}
+
+/* Requests NANDFC to initated the transfer of data from the
+ * NAND device into in the NANDFC ram buffer. */
+static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
+               int spare_only)
+{
+       DEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
+
+       /* NANDFC buffer 0 is used for page read/write */
+       writew(buf_id, host->regs + NFC_BUF_ADDR);
+
+       /* Configure spare or page+spare access */
+       if (!host->pagesize_2k) {
+               uint32_t config1 = readw(host->regs + NFC_CONFIG1);
+               if (spare_only)
+                       config1 |= NFC_SP_EN;
+               else
+                       config1 &= ~NFC_SP_EN;
+               writew(config1, host->regs + NFC_CONFIG1);
+       }
+
+       writew(NFC_OUTPUT, host->regs + NFC_CONFIG2);
+
+       /* Wait for operation to complete */
+       wait_op_done(host, TROP_US_DELAY, spare_only, true);
+}
+
+/* Request the NANDFC to perform a read of the NAND device ID. */
+static void send_read_id(struct mxc_nand_host *host)
+{
+       struct nand_chip *this = &host->nand;
+       uint16_t tmp;
+
+       /* NANDFC buffer 0 is used for device ID output */
+       writew(0x0, host->regs + NFC_BUF_ADDR);
+
+       /* Read ID into main buffer */
+       tmp = readw(host->regs + NFC_CONFIG1);
+       tmp &= ~NFC_SP_EN;
+       writew(tmp, host->regs + NFC_CONFIG1);
+
+       writew(NFC_ID, host->regs + NFC_CONFIG2);
+
+       /* Wait for operation to complete */
+       wait_op_done(host, TROP_US_DELAY, 0, true);
+
+       if (this->options & NAND_BUSWIDTH_16) {
+               void __iomem *main_buf = host->regs + MAIN_AREA0;
+               /* compress the ID info */
+               writeb(readb(main_buf + 2), main_buf + 1);
+               writeb(readb(main_buf + 4), main_buf + 2);
+               writeb(readb(main_buf + 6), main_buf + 3);
+               writeb(readb(main_buf + 8), main_buf + 4);
+               writeb(readb(main_buf + 10), main_buf + 5);
+       }
+}
+
+/* This function requests the NANDFC to perform a read of the
+ * NAND device status and returns the current status. */
+static uint16_t get_dev_status(struct mxc_nand_host *host)
+{
+       void __iomem *main_buf = host->regs + MAIN_AREA1;
+       uint32_t store;
+       uint16_t ret, tmp;
+       /* Issue status request to NAND device */
+
+       /* store the main area1 first word, later do recovery */
+       store = readl(main_buf);
+       /* NANDFC buffer 1 is used for device status to prevent
+        * corruption of read/write buffer on status requests. */
+       writew(1, host->regs + NFC_BUF_ADDR);
+
+       /* Read status into main buffer */
+       tmp = readw(host->regs + NFC_CONFIG1);
+       tmp &= ~NFC_SP_EN;
+       writew(tmp, host->regs + NFC_CONFIG1);
+
+       writew(NFC_STATUS, host->regs + NFC_CONFIG2);
+
+       /* Wait for operation to complete */
+       wait_op_done(host, TROP_US_DELAY, 0, true);
+
+       /* Status is placed in first word of main buffer */
+       /* get status, then recovery area 1 data */
+       ret = readw(main_buf);
+       writel(store, main_buf);
+
+       return ret;
+}
+
+/* This functions is used by upper layer to checks if device is ready */
+static int mxc_nand_dev_ready(struct mtd_info *mtd)
+{
+       /*
+        * NFC handles R/B internally. Therefore, this function
+        * always returns status as ready.
+        */
+       return 1;
+}
+
+static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
+{
+       /*
+        * If HW ECC is enabled, we turn it on during init. There is
+        * no need to enable again here.
+        */
+}
+
+static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
+                                u_char *read_ecc, u_char *calc_ecc)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct mxc_nand_host *host = nand_chip->priv;
+
+       /*
+        * 1-Bit errors are automatically corrected in HW.  No need for
+        * additional correction.  2-Bit errors cannot be corrected by
+        * HW ECC, so we need to return failure
+        */
+       uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
+
+       if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+               DEBUG(MTD_DEBUG_LEVEL0,
+                     "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+               return -1;
+       }
+
+       return 0;
+}
+
+static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+                                 u_char *ecc_code)
+{
+       return 0;
+}
+
+static u_char mxc_nand_read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct mxc_nand_host *host = nand_chip->priv;
+       uint8_t ret = 0;
+       uint16_t col, rd_word;
+       uint16_t __iomem *main_buf = host->regs + MAIN_AREA0;
+       uint16_t __iomem *spare_buf = host->regs + SPARE_AREA0;
+
+       /* Check for status request */
+       if (host->status_request)
+               return get_dev_status(host) & 0xFF;
+
+       /* Get column for 16-bit access */
+       col = host->col_addr >> 1;
+
+       /* If we are accessing the spare region */
+       if (host->spare_only)
+               rd_word = readw(&spare_buf[col]);
+       else
+               rd_word = readw(&main_buf[col]);
+
+       /* Pick upper/lower byte of word from RAM buffer */
+       if (host->col_addr & 0x1)
+               ret = (rd_word >> 8) & 0xFF;
+       else
+               ret = rd_word & 0xFF;
+
+       /* Update saved column address */
+       host->col_addr++;
+
+       return ret;
+}
+
+static uint16_t mxc_nand_read_word(struct mtd_info *mtd)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct mxc_nand_host *host = nand_chip->priv;
+       uint16_t col, rd_word, ret;
+       uint16_t __iomem *p;
+
+       DEBUG(MTD_DEBUG_LEVEL3,
+             "mxc_nand_read_word(col = %d)\n", host->col_addr);
+
+       col = host->col_addr;
+       /* Adjust saved column address */
+       if (col < mtd->writesize && host->spare_only)
+               col += mtd->writesize;
+
+       if (col < mtd->writesize)
+               p = (host->regs + MAIN_AREA0) + (col >> 1);
+       else
+               p = (host->regs + SPARE_AREA0) + ((col - mtd->writesize) >> 1);
+
+       if (col & 1) {
+               rd_word = readw(p);
+               ret = (rd_word >> 8) & 0xff;
+               rd_word = readw(&p[1]);
+               ret |= (rd_word << 8) & 0xff00;
+
+       } else
+               ret = readw(p);
+
+       /* Update saved column address */
+       host->col_addr = col + 2;
+
+       return ret;
+}
+
+/* Write data of length len to buffer buf. The data to be
+ * written on NAND Flash is first copied to RAMbuffer. After the Data Input
+ * Operation by the NFC, the data is written to NAND Flash */
+static void mxc_nand_write_buf(struct mtd_info *mtd,
+                               const u_char *buf, int len)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct mxc_nand_host *host = nand_chip->priv;
+       int n, col, i = 0;
+
+       DEBUG(MTD_DEBUG_LEVEL3,
+             "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
+             len);
+
+       col = host->col_addr;
+
+       /* Adjust saved column address */
+       if (col < mtd->writesize && host->spare_only)
+               col += mtd->writesize;
+
+       n = mtd->writesize + mtd->oobsize - col;
+       n = min(len, n);
+
+       DEBUG(MTD_DEBUG_LEVEL3,
+             "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+
+       while (n) {
+               void __iomem *p;
+
+               if (col < mtd->writesize)
+                       p = host->regs + MAIN_AREA0 + (col & ~3);
+               else
+                       p = host->regs + SPARE_AREA0 -
+                                               mtd->writesize + (col & ~3);
+
+               DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+                     __LINE__, p);
+
+               if (((col | (int)&buf[i]) & 3) || n < 16) {
+                       uint32_t data = 0;
+
+                       if (col & 3 || n < 4)
+                               data = readl(p);
+
+                       switch (col & 3) {
+                       case 0:
+                               if (n) {
+                                       data = (data & 0xffffff00) |
+                                           (buf[i++] << 0);
+                                       n--;
+                                       col++;
+                               }
+                       case 1:
+                               if (n) {
+                                       data = (data & 0xffff00ff) |
+                                           (buf[i++] << 8);
+                                       n--;
+                                       col++;
+                               }
+                       case 2:
+                               if (n) {
+                                       data = (data & 0xff00ffff) |
+                                           (buf[i++] << 16);
+                                       n--;
+                                       col++;
+                               }
+                       case 3:
+                               if (n) {
+                                       data = (data & 0x00ffffff) |
+                                           (buf[i++] << 24);
+                                       n--;
+                                       col++;
+                               }
+                       }
+
+                       writel(data, p);
+               } else {
+                       int m = mtd->writesize - col;
+
+                       if (col >= mtd->writesize)
+                               m += mtd->oobsize;
+
+                       m = min(n, m) & ~3;
+
+                       DEBUG(MTD_DEBUG_LEVEL3,
+                             "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
+                             __func__,  __LINE__, n, m, i, col);
+
+                       memcpy(p, &buf[i], m);
+                       col += m;
+                       i += m;
+                       n -= m;
+               }
+       }
+       /* Update saved column address */
+       host->col_addr = col;
+}
+
+/* Read the data buffer from the NAND Flash. To read the data from NAND
+ * Flash first the data output cycle is initiated by the NFC, which copies
+ * the data to RAMbuffer. This data of length len is then copied to buffer buf.
+ */
+static void mxc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct mxc_nand_host *host = nand_chip->priv;
+       int n, col, i = 0;
+
+       DEBUG(MTD_DEBUG_LEVEL3,
+             "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
+
+       col = host->col_addr;
+
+       /* Adjust saved column address */
+       if (col < mtd->writesize && host->spare_only)
+               col += mtd->writesize;
+
+       n = mtd->writesize + mtd->oobsize - col;
+       n = min(len, n);
+
+       while (n) {
+               void __iomem *p;
+
+               if (col < mtd->writesize)
+                       p = host->regs + MAIN_AREA0 + (col & ~3);
+               else
+                       p = host->regs + SPARE_AREA0 -
+                                       mtd->writesize + (col & ~3);
+
+               if (((col | (int)&buf[i]) & 3) || n < 16) {
+                       uint32_t data;
+
+                       data = readl(p);
+                       switch (col & 3) {
+                       case 0:
+                               if (n) {
+                                       buf[i++] = (uint8_t) (data);
+                                       n--;
+                                       col++;
+                               }
+                       case 1:
+                               if (n) {
+                                       buf[i++] = (uint8_t) (data >> 8);
+                                       n--;
+                                       col++;
+                               }
+                       case 2:
+                               if (n) {
+                                       buf[i++] = (uint8_t) (data >> 16);
+                                       n--;
+                                       col++;
+                               }
+                       case 3:
+                               if (n) {
+                                       buf[i++] = (uint8_t) (data >> 24);
+                                       n--;
+                                       col++;
+                               }
+                       }
+               } else {
+                       int m = mtd->writesize - col;
+
+                       if (col >= mtd->writesize)
+                               m += mtd->oobsize;
+
+                       m = min(n, m) & ~3;
+                       memcpy(&buf[i], p, m);
+                       col += m;
+                       i += m;
+                       n -= m;
+               }
+       }
+       /* Update saved column address */
+       host->col_addr = col;
+
+}
+
+/* Used by the upper layer to verify the data in NAND Flash
+ * with the data in the buf. */
+static int mxc_nand_verify_buf(struct mtd_info *mtd,
+                               const u_char *buf, int len)
+{
+       return -EFAULT;
+}
+
+/* This function is used by upper layer for select and
+ * deselect of the NAND chip */
+static void mxc_nand_select_chip(struct mtd_info *mtd, int chip)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct mxc_nand_host *host = nand_chip->priv;
+
+#ifdef CONFIG_MTD_NAND_MXC_FORCE_CE
+       if (chip > 0) {
+               DEBUG(MTD_DEBUG_LEVEL0,
+                     "ERROR:  Illegal chip select (chip = %d)\n", chip);
+               return;
+       }
+
+       if (chip == -1) {
+               writew(readw(host->regs + NFC_CONFIG1) & ~NFC_CE,
+                               host->regs + NFC_CONFIG1);
+               return;
+       }
+
+       writew(readw(host->regs + NFC_CONFIG1) | NFC_CE,
+                       host->regs + NFC_CONFIG1);
+#endif
+
+       switch (chip) {
+       case -1:
+               /* Disable the NFC clock */
+               if (host->clk_act) {
+                       clk_disable(host->clk);
+                       host->clk_act = 0;
+               }
+               break;
+       case 0:
+               /* Enable the NFC clock */
+               if (!host->clk_act) {
+                       clk_enable(host->clk);
+                       host->clk_act = 1;
+               }
+               break;
+
+       default:
+               break;
+       }
+}
+
+/* Used by the upper layer to write command to NAND Flash for
+ * different operations to be carried out on NAND Flash */
+static void mxc_nand_command(struct mtd_info *mtd, unsigned command,
+                               int column, int page_addr)
+{
+       struct nand_chip *nand_chip = mtd->priv;
+       struct mxc_nand_host *host = nand_chip->priv;
+       int useirq = true;
+
+       DEBUG(MTD_DEBUG_LEVEL3,
+             "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+             command, column, page_addr);
+
+       /* Reset command state information */
+       host->status_request = false;
+
+       /* Command pre-processing step */
+       switch (command) {
+
+       case NAND_CMD_STATUS:
+               host->col_addr = 0;
+               host->status_request = true;
+               break;
+
+       case NAND_CMD_READ0:
+               host->col_addr = column;
+               host->spare_only = false;
+               useirq = false;
+               break;
+
+       case NAND_CMD_READOOB:
+               host->col_addr = column;
+               host->spare_only = true;
+               useirq = false;
+               if (host->pagesize_2k)
+                       command = NAND_CMD_READ0; /* only READ0 is valid */
+               break;
+
+       case NAND_CMD_SEQIN:
+               if (column >= mtd->writesize) {
+                       /*
+                        * FIXME: before send SEQIN command for write OOB,
+                        * We must read one page out.
+                        * For K9F1GXX has no READ1 command to set current HW
+                        * pointer to spare area, we must write the whole page
+                        * including OOB together.
+                        */
+                       if (host->pagesize_2k)
+                               /* call ourself to read a page */
+                               mxc_nand_command(mtd, NAND_CMD_READ0, 0,
+                                               page_addr);
+
+                       host->col_addr = column - mtd->writesize;
+                       host->spare_only = true;
+
+                       /* Set program pointer to spare region */
+                       if (!host->pagesize_2k)
+                               send_cmd(host, NAND_CMD_READOOB, false);
+               } else {
+                       host->spare_only = false;
+                       host->col_addr = column;
+
+                       /* Set program pointer to page start */
+                       if (!host->pagesize_2k)
+                               send_cmd(host, NAND_CMD_READ0, false);
+               }
+               useirq = false;
+               break;
+
+       case NAND_CMD_PAGEPROG:
+               send_prog_page(host, 0, host->spare_only);
+
+               if (host->pagesize_2k) {
+                       /* data in 4 areas datas */
+                       send_prog_page(host, 1, host->spare_only);
+                       send_prog_page(host, 2, host->spare_only);
+                       send_prog_page(host, 3, host->spare_only);
+               }
+
+               break;
+
+       case NAND_CMD_ERASE1:
+               useirq = false;
+               break;
+       }
+
+       /* Write out the command to the device. */
+       send_cmd(host, command, useirq);
+
+       /* Write out column address, if necessary */
+       if (column != -1) {
+               /*
+                * MXC NANDFC can only perform full page+spare or
+                * spare-only read/write.  When the upper layers
+                * layers perform a read/write buf operation,
+                * we will used the saved column adress to index into
+                * the full page.
+                */
+               send_addr(host, 0, page_addr == -1);
+               if (host->pagesize_2k)
+                       /* another col addr cycle for 2k page */
+                       send_addr(host, 0, false);
+       }
+
+       /* Write out page address, if necessary */
+       if (page_addr != -1) {
+               /* paddr_0 - p_addr_7 */
+               send_addr(host, (page_addr & 0xff), false);
+
+               if (host->pagesize_2k) {
+                       send_addr(host, (page_addr >> 8) & 0xFF, false);
+                       if (mtd->size >= 0x40000000)
+                               send_addr(host, (page_addr >> 16) & 0xff, true);
+               } else {
+                       /* One more address cycle for higher density devices */
+                       if (mtd->size >= 0x4000000) {
+                               /* paddr_8 - paddr_15 */
+                               send_addr(host, (page_addr >> 8) & 0xff, false);
+                               send_addr(host, (page_addr >> 16) & 0xff, true);
+                       } else
+                               /* paddr_8 - paddr_15 */
+                               send_addr(host, (page_addr >> 8) & 0xff, true);
+               }
+       }
+
+       /* Command post-processing step */
+       switch (command) {
+
+       case NAND_CMD_RESET:
+               break;
+
+       case NAND_CMD_READOOB:
+       case NAND_CMD_READ0:
+               if (host->pagesize_2k) {
+                       /* send read confirm command */
+                       send_cmd(host, NAND_CMD_READSTART, true);
+                       /* read for each AREA */
+                       send_read_page(host, 0, host->spare_only);
+                       send_read_page(host, 1, host->spare_only);
+                       send_read_page(host, 2, host->spare_only);
+                       send_read_page(host, 3, host->spare_only);
+               } else
+                       send_read_page(host, 0, host->spare_only);
+               break;
+
+       case NAND_CMD_READID:
+               send_read_id(host);
+               break;
+
+       case NAND_CMD_PAGEPROG:
+               break;
+
+       case NAND_CMD_STATUS:
+               break;
+
+       case NAND_CMD_ERASE2:
+               break;
+       }
+}
+
+static int __init mxcnd_probe(struct platform_device *pdev)
+{
+       struct nand_chip *this;
+       struct mtd_info *mtd;
+       struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
+       struct mxc_nand_host *host;
+       struct resource *res;
+       uint16_t tmp;
+       int err = 0, nr_parts = 0;
+
+       /* Allocate memory for MTD device structure and private data */
+       host = kzalloc(sizeof(struct mxc_nand_host), GFP_KERNEL);
+       if (!host)
+               return -ENOMEM;
+
+       host->dev = &pdev->dev;
+       /* structures must be linked */
+       this = &host->nand;
+       mtd = &host->mtd;
+       mtd->priv = this;
+       mtd->owner = THIS_MODULE;
+
+       /* 50 us command delay time */
+       this->chip_delay = 5;
+
+       this->priv = host;
+       this->dev_ready = mxc_nand_dev_ready;
+       this->cmdfunc = mxc_nand_command;
+       this->select_chip = mxc_nand_select_chip;
+       this->read_byte = mxc_nand_read_byte;
+       this->read_word = mxc_nand_read_word;
+       this->write_buf = mxc_nand_write_buf;
+       this->read_buf = mxc_nand_read_buf;
+       this->verify_buf = mxc_nand_verify_buf;
+
+       host->clk = clk_get(&pdev->dev, "nfc_clk");
+       if (IS_ERR(host->clk))
+               goto eclk;
+
+       clk_enable(host->clk);
+       host->clk_act = 1;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               err = -ENODEV;
+               goto eres;
+       }
+
+       host->regs = ioremap(res->start, res->end - res->start + 1);
+       if (!host->regs) {
+               err = -EIO;
+               goto eres;
+       }
+
+       tmp = readw(host->regs + NFC_CONFIG1);
+       tmp |= NFC_INT_MSK;
+       writew(tmp, host->regs + NFC_CONFIG1);
+
+       init_waitqueue_head(&host->irq_waitq);
+
+       host->irq = platform_get_irq(pdev, 0);
+
+       err = request_irq(host->irq, mxc_nfc_irq, 0, "mxc_nd", host);
+       if (err)
+               goto eirq;
+
+       if (pdata->hw_ecc) {
+               this->ecc.calculate = mxc_nand_calculate_ecc;
+               this->ecc.hwctl = mxc_nand_enable_hwecc;
+               this->ecc.correct = mxc_nand_correct_data;
+               this->ecc.mode = NAND_ECC_HW;
+               this->ecc.size = 512;
+               this->ecc.bytes = 3;
+               this->ecc.layout = &nand_hw_eccoob_8;
+               tmp = readw(host->regs + NFC_CONFIG1);
+               tmp |= NFC_ECC_EN;
+               writew(tmp, host->regs + NFC_CONFIG1);
+       } else {
+               this->ecc.size = 512;
+               this->ecc.bytes = 3;
+               this->ecc.layout = &nand_hw_eccoob_8;
+               this->ecc.mode = NAND_ECC_SOFT;
+               tmp = readw(host->regs + NFC_CONFIG1);
+               tmp &= ~NFC_ECC_EN;
+               writew(tmp, host->regs + NFC_CONFIG1);
+       }
+
+       /* Reset NAND */
+       this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+       /* preset operation */
+       /* Unlock the internal RAM Buffer */
+       writew(0x2, host->regs + NFC_CONFIG);
+
+       /* Blocks to be unlocked */
+       writew(0x0, host->regs + NFC_UNLOCKSTART_BLKADDR);
+       writew(0x4000, host->regs + NFC_UNLOCKEND_BLKADDR);
+
+       /* Unlock Block Command for given address range */
+       writew(0x4, host->regs + NFC_WRPROT);
+
+       /* NAND bus width determines access funtions used by upper layer */
+       if (pdata->width == 2) {
+               this->options |= NAND_BUSWIDTH_16;
+               this->ecc.layout = &nand_hw_eccoob_16;
+       }
+
+       host->pagesize_2k = 0;
+
+       /* Scan to find existence of the device */
+       if (nand_scan(mtd, 1)) {
+               DEBUG(MTD_DEBUG_LEVEL0,
+                     "MXC_ND: Unable to find any NAND device.\n");
+               err = -ENXIO;
+               goto escan;
+       }
+
+       /* Register the partitions */
+#ifdef CONFIG_MTD_PARTITIONS
+       nr_parts =
+           parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
+       if (nr_parts > 0)
+               add_mtd_partitions(mtd, host->parts, nr_parts);
+       else
+#endif
+       {
+               pr_info("Registering %s as whole device\n", mtd->name);
+               add_mtd_device(mtd);
+       }
+
+       platform_set_drvdata(pdev, host);
+
+       return 0;
+
+escan:
+       free_irq(host->irq, NULL);
+eirq:
+       iounmap(host->regs);
+eres:
+       clk_put(host->clk);
+eclk:
+       kfree(host);
+
+       return err;
+}
+
+static int __devexit mxcnd_remove(struct platform_device *pdev)
+{
+       struct mxc_nand_host *host = platform_get_drvdata(pdev);
+
+       clk_put(host->clk);
+
+       platform_set_drvdata(pdev, NULL);
+
+       nand_release(&host->mtd);
+       free_irq(host->irq, NULL);
+       iounmap(host->regs);
+       kfree(host);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct mtd_info *info = platform_get_drvdata(pdev);
+       int ret = 0;
+
+       DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
+       if (info)
+               ret = info->suspend(info);
+
+       /* Disable the NFC clock */
+       clk_disable(nfc_clk);   /* FIXME */
+
+       return ret;
+}
+
+static int mxcnd_resume(struct platform_device *pdev)
+{
+       struct mtd_info *info = platform_get_drvdata(pdev);
+       int ret = 0;
+
+       DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
+       /* Enable the NFC clock */
+       clk_enable(nfc_clk);    /* FIXME */
+
+       if (info)
+               info->resume(info);
+
+       return ret;
+}
+
+#else
+# define mxcnd_suspend   NULL
+# define mxcnd_resume    NULL
+#endif                         /* CONFIG_PM */
+
+static struct platform_driver mxcnd_driver = {
+       .driver = {
+                  .name = DRIVER_NAME,
+                  },
+       .remove = __exit_p(mxcnd_remove),
+       .suspend = mxcnd_suspend,
+       .resume = mxcnd_resume,
+};
+
+static int __init mxc_nd_init(void)
+{
+       /* Register the device driver structure. */
+       pr_info("MXC MTD nand Driver\n");
+       if (platform_driver_probe(&mxcnd_driver, mxcnd_probe) != 0) {
+               printk(KERN_ERR "Driver register failed for mxcnd_driver\n");
+               return -ENODEV;
+       }
+       return 0;
+}
+
+static void __exit mxc_nd_cleanup(void)
+{
+       /* Unregister the device structure */
+       platform_driver_unregister(&mxcnd_driver);
+}
+
+module_init(mxc_nd_init);
+module_exit(mxc_nd_cleanup);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXC NAND MTD driver");
+MODULE_LICENSE("GPL");
index d1129bae6c27d20731ef0ead6b86a863e590e7f4..0a9c9cd33f96b0f15f7f1d6f87260baaf9fb05df 100644 (file)
@@ -801,9 +801,9 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
  * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
  * @mtd:       mtd info structure
  * @chip:      nand chip info structure
- * @dataofs    offset of requested data within the page
- * @readlen    data length
- * @buf:       buffer to store read data
+ * @data_offs: offset of requested data within the page
+ * @readlen:   data length
+ * @bufpoi:    buffer to store read data
  */
 static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi)
 {
@@ -2042,7 +2042,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
                return -EINVAL;
        }
 
-       instr->fail_addr = 0xffffffff;
+       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 
        /* Grab the lock and see if the device is available */
        nand_get_device(chip, mtd, FL_ERASING);
@@ -2318,6 +2318,12 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
        /* Select the device */
        chip->select_chip(mtd, 0);
 
+       /*
+        * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
+        * after power-up
+        */
+       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
        /* Send the command for reading device ID */
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 
@@ -2488,6 +2494,8 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips)
        /* Check for a chip array */
        for (i = 1; i < maxchips; i++) {
                chip->select_chip(mtd, i);
+               /* See comment in nand_get_flash_type for reset */
+               chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
                /* Send the command for reading device ID */
                chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
                /* Read manufacturer and device IDs */
index 918a806a8471f7aaa1b68b29e5e401a15737d4a4..868147acce2cec19677605e2bdcf67d8b5e9a14c 100644 (file)
@@ -1,13 +1,18 @@
 /*
- * This file contains an ECC algorithm from Toshiba that detects and
- * corrects 1 bit errors in a 256 byte block of data.
+ * This file contains an ECC algorithm that detects and corrects 1 bit
+ * errors in a 256 byte block of data.
  *
  * drivers/mtd/nand/nand_ecc.c
  *
- * Copyright (C) 2000-2004 Steven J. Hill (sjhill@realitydiluted.com)
- *                         Toshiba America Electronics Components, Inc.
+ * Copyright Â© 2008 Koninklijke Philips Electronics NV.
+ *                  Author: Frans Meulenbroeks
  *
- * Copyright (C) 2006 Thomas Gleixner <tglx@linutronix.de>
+ * Completely replaces the previous ECC implementation which was written by:
+ *   Steven J. Hill (sjhill@realitydiluted.com)
+ *   Thomas Gleixner (tglx@linutronix.de)
+ *
+ * Information on how this algorithm works and how it was developed
+ * can be found in Documentation/mtd/nand_ecc.txt
  *
  * This file is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * with this file; if not, write to the Free Software Foundation, Inc.,
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  *
- * As a special exception, if other files instantiate templates or use
- * macros or inline functions from these files, or you compile these
- * files and link them with other works to produce a work based on these
- * files, these files do not by themselves cause the resulting work to be
- * covered by the GNU General Public License. However the source code for
- * these files must still be made available in accordance with section (3)
- * of the GNU General Public License.
- *
- * This exception does not invalidate any other reasons why a work based on
- * this file might be covered by the GNU General Public License.
  */
 
+/*
+ * The STANDALONE macro is useful when running the code outside the kernel
+ * e.g. when running the code in a testbed or a benchmark program.
+ * When STANDALONE is used, the module related macros are commented out
+ * as well as the linux include files.
+ * Instead a private definition of mtd_info is given to satisfy the compiler
+ * (the code does not use mtd_info, so the code does not care)
+ */
+#ifndef STANDALONE
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
+#include <asm/byteorder.h>
+#else
+#include <stdint.h>
+struct mtd_info;
+#define EXPORT_SYMBOL(x)  /* x */
+
+#define MODULE_LICENSE(x)      /* x */
+#define MODULE_AUTHOR(x)       /* x */
+#define MODULE_DESCRIPTION(x)  /* x */
+
+#define printk printf
+#define KERN_ERR               ""
+#endif
+
+/*
+ * invparity is a 256 byte table that contains the odd parity
+ * for each byte. So if the number of bits in a byte is even,
+ * the array element is 1, and when the number of bits is odd
+ * the array eleemnt is 0.
+ */
+static const char invparity[256] = {
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
+       1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
+};
+
+/*
+ * bitsperbyte contains the number of bits per byte
+ * this is only used for testing and repairing parity
+ * (a precalculated value slightly improves performance)
+ */
+static const char bitsperbyte[256] = {
+       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
+};
 
 /*
- * Pre-calculated 256-way 1 byte column parity
+ * addressbits is a lookup table to filter out the bits from the xor-ed
+ * ecc data that identify the faulty location.
+ * this is only used for repairing parity
+ * see the comments in nand_correct_data for more details
  */
-static const u_char nand_ecc_precalc_table[] = {
-       0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
-       0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-       0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-       0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-       0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-       0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-       0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-       0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-       0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
-       0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
-       0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
-       0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
-       0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
-       0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
-       0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
-       0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
+static const char addressbits[256] = {
+       0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+       0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+       0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+       0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+       0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+       0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+       0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+       0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+       0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+       0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+       0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+       0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
+       0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+       0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+       0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
+       0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
+       0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+       0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+       0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+       0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+       0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+       0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
+       0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+       0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
+       0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+       0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+       0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
+       0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
+       0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+       0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
+       0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
+       0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f
 };
 
 /**
- * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256-byte block
+ * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
+ *                      block
  * @mtd:       MTD block structure
- * @dat:       raw data
- * @ecc_code:  buffer for ECC
+ * @buf:       input buffer with raw data
+ * @code:      output buffer with ECC
  */
-int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
-                      u_char *ecc_code)
+int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+                      unsigned char *code)
 {
-       uint8_t idx, reg1, reg2, reg3, tmp1, tmp2;
        int i;
+       const uint32_t *bp = (uint32_t *)buf;
+       /* 256 or 512 bytes/ecc  */
+       const uint32_t eccsize_mult =
+                       (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
+       uint32_t cur;           /* current value in buffer */
+       /* rp0..rp15..rp17 are the various accumulated parities (per byte) */
+       uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
+       uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16;
+       uint32_t uninitialized_var(rp17);       /* to make compiler happy */
+       uint32_t par;           /* the cumulative parity for all data */
+       uint32_t tmppar;        /* the cumulative parity for this iteration;
+                                  for rp12, rp14 and rp16 at the end of the
+                                  loop */
+
+       par = 0;
+       rp4 = 0;
+       rp6 = 0;
+       rp8 = 0;
+       rp10 = 0;
+       rp12 = 0;
+       rp14 = 0;
+       rp16 = 0;
+
+       /*
+        * The loop is unrolled a number of times;
+        * This avoids if statements to decide on which rp value to update
+        * Also we process the data by longwords.
+        * Note: passing unaligned data might give a performance penalty.
+        * It is assumed that the buffers are aligned.
+        * tmppar is the cumulative sum of this iteration.
+        * needed for calculating rp12, rp14, rp16 and par
+        * also used as a performance improvement for rp6, rp8 and rp10
+        */
+       for (i = 0; i < eccsize_mult << 2; i++) {
+               cur = *bp++;
+               tmppar = cur;
+               rp4 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp6 ^= tmppar;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp4 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp8 ^= tmppar;
 
-       /* Initialize variables */
-       reg1 = reg2 = reg3 = 0;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp4 ^= cur;
+               rp6 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp6 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp4 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp10 ^= tmppar;
 
-       /* Build up column parity */
-       for(i = 0; i < 256; i++) {
-               /* Get CP0 - CP5 from table */
-               idx = nand_ecc_precalc_table[*dat++];
-               reg1 ^= (idx & 0x3f);
+               cur = *bp++;
+               tmppar ^= cur;
+               rp4 ^= cur;
+               rp6 ^= cur;
+               rp8 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp6 ^= cur;
+               rp8 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp4 ^= cur;
+               rp8 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp8 ^= cur;
 
-               /* All bit XOR = 1 ? */
-               if (idx & 0x40) {
-                       reg3 ^= (uint8_t) i;
-                       reg2 ^= ~((uint8_t) i);
-               }
+               cur = *bp++;
+               tmppar ^= cur;
+               rp4 ^= cur;
+               rp6 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp6 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+               rp4 ^= cur;
+               cur = *bp++;
+               tmppar ^= cur;
+
+               par ^= tmppar;
+               if ((i & 0x1) == 0)
+                       rp12 ^= tmppar;
+               if ((i & 0x2) == 0)
+                       rp14 ^= tmppar;
+               if (eccsize_mult == 2 && (i & 0x4) == 0)
+                       rp16 ^= tmppar;
        }
 
-       /* Create non-inverted ECC code from line parity */
-       tmp1  = (reg3 & 0x80) >> 0; /* B7 -> B7 */
-       tmp1 |= (reg2 & 0x80) >> 1; /* B7 -> B6 */
-       tmp1 |= (reg3 & 0x40) >> 1; /* B6 -> B5 */
-       tmp1 |= (reg2 & 0x40) >> 2; /* B6 -> B4 */
-       tmp1 |= (reg3 & 0x20) >> 2; /* B5 -> B3 */
-       tmp1 |= (reg2 & 0x20) >> 3; /* B5 -> B2 */
-       tmp1 |= (reg3 & 0x10) >> 3; /* B4 -> B1 */
-       tmp1 |= (reg2 & 0x10) >> 4; /* B4 -> B0 */
-
-       tmp2  = (reg3 & 0x08) << 4; /* B3 -> B7 */
-       tmp2 |= (reg2 & 0x08) << 3; /* B3 -> B6 */
-       tmp2 |= (reg3 & 0x04) << 3; /* B2 -> B5 */
-       tmp2 |= (reg2 & 0x04) << 2; /* B2 -> B4 */
-       tmp2 |= (reg3 & 0x02) << 2; /* B1 -> B3 */
-       tmp2 |= (reg2 & 0x02) << 1; /* B1 -> B2 */
-       tmp2 |= (reg3 & 0x01) << 1; /* B0 -> B1 */
-       tmp2 |= (reg2 & 0x01) << 0; /* B7 -> B0 */
-
-       /* Calculate final ECC code */
-#ifdef CONFIG_MTD_NAND_ECC_SMC
-       ecc_code[0] = ~tmp2;
-       ecc_code[1] = ~tmp1;
+       /*
+        * handle the fact that we use longword operations
+        * we'll bring rp4..rp14..rp16 back to single byte entities by
+        * shifting and xoring first fold the upper and lower 16 bits,
+        * then the upper and lower 8 bits.
+        */
+       rp4 ^= (rp4 >> 16);
+       rp4 ^= (rp4 >> 8);
+       rp4 &= 0xff;
+       rp6 ^= (rp6 >> 16);
+       rp6 ^= (rp6 >> 8);
+       rp6 &= 0xff;
+       rp8 ^= (rp8 >> 16);
+       rp8 ^= (rp8 >> 8);
+       rp8 &= 0xff;
+       rp10 ^= (rp10 >> 16);
+       rp10 ^= (rp10 >> 8);
+       rp10 &= 0xff;
+       rp12 ^= (rp12 >> 16);
+       rp12 ^= (rp12 >> 8);
+       rp12 &= 0xff;
+       rp14 ^= (rp14 >> 16);
+       rp14 ^= (rp14 >> 8);
+       rp14 &= 0xff;
+       if (eccsize_mult == 2) {
+               rp16 ^= (rp16 >> 16);
+               rp16 ^= (rp16 >> 8);
+               rp16 &= 0xff;
+       }
+
+       /*
+        * we also need to calculate the row parity for rp0..rp3
+        * This is present in par, because par is now
+        * rp3 rp3 rp2 rp2 in little endian and
+        * rp2 rp2 rp3 rp3 in big endian
+        * as well as
+        * rp1 rp0 rp1 rp0 in little endian and
+        * rp0 rp1 rp0 rp1 in big endian
+        * First calculate rp2 and rp3
+        */
+#ifdef __BIG_ENDIAN
+       rp2 = (par >> 16);
+       rp2 ^= (rp2 >> 8);
+       rp2 &= 0xff;
+       rp3 = par & 0xffff;
+       rp3 ^= (rp3 >> 8);
+       rp3 &= 0xff;
 #else
-       ecc_code[0] = ~tmp1;
-       ecc_code[1] = ~tmp2;
+       rp3 = (par >> 16);
+       rp3 ^= (rp3 >> 8);
+       rp3 &= 0xff;
+       rp2 = par & 0xffff;
+       rp2 ^= (rp2 >> 8);
+       rp2 &= 0xff;
 #endif
-       ecc_code[2] = ((~reg1) << 2) | 0x03;
 
-       return 0;
-}
-EXPORT_SYMBOL(nand_calculate_ecc);
+       /* reduce par to 16 bits then calculate rp1 and rp0 */
+       par ^= (par >> 16);
+#ifdef __BIG_ENDIAN
+       rp0 = (par >> 8) & 0xff;
+       rp1 = (par & 0xff);
+#else
+       rp1 = (par >> 8) & 0xff;
+       rp0 = (par & 0xff);
+#endif
 
-static inline int countbits(uint32_t byte)
-{
-       int res = 0;
+       /* finally reduce par to 8 bits */
+       par ^= (par >> 8);
+       par &= 0xff;
 
-       for (;byte; byte >>= 1)
-               res += byte & 0x01;
-       return res;
+       /*
+        * and calculate rp5..rp15..rp17
+        * note that par = rp4 ^ rp5 and due to the commutative property
+        * of the ^ operator we can say:
+        * rp5 = (par ^ rp4);
+        * The & 0xff seems superfluous, but benchmarking learned that
+        * leaving it out gives slightly worse results. No idea why, probably
+        * it has to do with the way the pipeline in pentium is organized.
+        */
+       rp5 = (par ^ rp4) & 0xff;
+       rp7 = (par ^ rp6) & 0xff;
+       rp9 = (par ^ rp8) & 0xff;
+       rp11 = (par ^ rp10) & 0xff;
+       rp13 = (par ^ rp12) & 0xff;
+       rp15 = (par ^ rp14) & 0xff;
+       if (eccsize_mult == 2)
+               rp17 = (par ^ rp16) & 0xff;
+
+       /*
+        * Finally calculate the ecc bits.
+        * Again here it might seem that there are performance optimisations
+        * possible, but benchmarks showed that on the system this is developed
+        * the code below is the fastest
+        */
+#ifdef CONFIG_MTD_NAND_ECC_SMC
+       code[0] =
+           (invparity[rp7] << 7) |
+           (invparity[rp6] << 6) |
+           (invparity[rp5] << 5) |
+           (invparity[rp4] << 4) |
+           (invparity[rp3] << 3) |
+           (invparity[rp2] << 2) |
+           (invparity[rp1] << 1) |
+           (invparity[rp0]);
+       code[1] =
+           (invparity[rp15] << 7) |
+           (invparity[rp14] << 6) |
+           (invparity[rp13] << 5) |
+           (invparity[rp12] << 4) |
+           (invparity[rp11] << 3) |
+           (invparity[rp10] << 2) |
+           (invparity[rp9] << 1)  |
+           (invparity[rp8]);
+#else
+       code[1] =
+           (invparity[rp7] << 7) |
+           (invparity[rp6] << 6) |
+           (invparity[rp5] << 5) |
+           (invparity[rp4] << 4) |
+           (invparity[rp3] << 3) |
+           (invparity[rp2] << 2) |
+           (invparity[rp1] << 1) |
+           (invparity[rp0]);
+       code[0] =
+           (invparity[rp15] << 7) |
+           (invparity[rp14] << 6) |
+           (invparity[rp13] << 5) |
+           (invparity[rp12] << 4) |
+           (invparity[rp11] << 3) |
+           (invparity[rp10] << 2) |
+           (invparity[rp9] << 1)  |
+           (invparity[rp8]);
+#endif
+       if (eccsize_mult == 1)
+               code[2] =
+                   (invparity[par & 0xf0] << 7) |
+                   (invparity[par & 0x0f] << 6) |
+                   (invparity[par & 0xcc] << 5) |
+                   (invparity[par & 0x33] << 4) |
+                   (invparity[par & 0xaa] << 3) |
+                   (invparity[par & 0x55] << 2) |
+                   3;
+       else
+               code[2] =
+                   (invparity[par & 0xf0] << 7) |
+                   (invparity[par & 0x0f] << 6) |
+                   (invparity[par & 0xcc] << 5) |
+                   (invparity[par & 0x33] << 4) |
+                   (invparity[par & 0xaa] << 3) |
+                   (invparity[par & 0x55] << 2) |
+                   (invparity[rp17] << 1) |
+                   (invparity[rp16] << 0);
+       return 0;
 }
+EXPORT_SYMBOL(nand_calculate_ecc);
 
 /**
  * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
  * @mtd:       MTD block structure
- * @dat:       raw data read from the chip
+ * @buf:       raw data read from the chip
  * @read_ecc:  ECC from the chip
  * @calc_ecc:  the ECC calculated from raw data
  *
- * Detect and correct a 1 bit error for 256 byte block
+ * Detect and correct a 1 bit error for 256/512 byte block
  */
-int nand_correct_data(struct mtd_info *mtd, u_char *dat,
-                     u_char *read_ecc, u_char *calc_ecc)
+int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
+                     unsigned char *read_ecc, unsigned char *calc_ecc)
 {
-       uint8_t s0, s1, s2;
+       unsigned char b0, b1, b2;
+       unsigned char byte_addr, bit_addr;
+       /* 256 or 512 bytes/ecc  */
+       const uint32_t eccsize_mult =
+                       (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
 
+       /*
+        * b0 to b2 indicate which bit is faulty (if any)
+        * we might need the xor result  more than once,
+        * so keep them in a local var
+       */
 #ifdef CONFIG_MTD_NAND_ECC_SMC
-       s0 = calc_ecc[0] ^ read_ecc[0];
-       s1 = calc_ecc[1] ^ read_ecc[1];
-       s2 = calc_ecc[2] ^ read_ecc[2];
+       b0 = read_ecc[0] ^ calc_ecc[0];
+       b1 = read_ecc[1] ^ calc_ecc[1];
 #else
-       s1 = calc_ecc[0] ^ read_ecc[0];
-       s0 = calc_ecc[1] ^ read_ecc[1];
-       s2 = calc_ecc[2] ^ read_ecc[2];
+       b0 = read_ecc[1] ^ calc_ecc[1];
+       b1 = read_ecc[0] ^ calc_ecc[0];
 #endif
-       if ((s0 | s1 | s2) == 0)
-               return 0;
-
-       /* Check for a single bit error */
-       if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
-           ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
-           ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {
+       b2 = read_ecc[2] ^ calc_ecc[2];
 
-               uint32_t byteoffs, bitnum;
+       /* check if there are any bitfaults */
 
-               byteoffs = (s1 << 0) & 0x80;
-               byteoffs |= (s1 << 1) & 0x40;
-               byteoffs |= (s1 << 2) & 0x20;
-               byteoffs |= (s1 << 3) & 0x10;
+       /* repeated if statements are slightly more efficient than switch ... */
+       /* ordered in order of likelihood */
 
-               byteoffs |= (s0 >> 4) & 0x08;
-               byteoffs |= (s0 >> 3) & 0x04;
-               byteoffs |= (s0 >> 2) & 0x02;
-               byteoffs |= (s0 >> 1) & 0x01;
-
-               bitnum = (s2 >> 5) & 0x04;
-               bitnum |= (s2 >> 4) & 0x02;
-               bitnum |= (s2 >> 3) & 0x01;
-
-               dat[byteoffs] ^= (1 << bitnum);
+       if ((b0 | b1 | b2) == 0)
+               return 0;       /* no error */
 
+       if ((((b0 ^ (b0 >> 1)) & 0x55) == 0x55) &&
+           (((b1 ^ (b1 >> 1)) & 0x55) == 0x55) &&
+           ((eccsize_mult == 1 && ((b2 ^ (b2 >> 1)) & 0x54) == 0x54) ||
+            (eccsize_mult == 2 && ((b2 ^ (b2 >> 1)) & 0x55) == 0x55))) {
+       /* single bit error */
+               /*
+                * rp17/rp15/13/11/9/7/5/3/1 indicate which byte is the faulty
+                * byte, cp 5/3/1 indicate the faulty bit.
+                * A lookup table (called addressbits) is used to filter
+                * the bits from the byte they are in.
+                * A marginal optimisation is possible by having three
+                * different lookup tables.
+                * One as we have now (for b0), one for b2
+                * (that would avoid the >> 1), and one for b1 (with all values
+                * << 4). However it was felt that introducing two more tables
+                * hardly justify the gain.
+                *
+                * The b2 shift is there to get rid of the lowest two bits.
+                * We could also do addressbits[b2] >> 1 but for the
+                * performace it does not make any difference
+                */
+               if (eccsize_mult == 1)
+                       byte_addr = (addressbits[b1] << 4) + addressbits[b0];
+               else
+                       byte_addr = (addressbits[b2 & 0x3] << 8) +
+                                   (addressbits[b1] << 4) + addressbits[b0];
+               bit_addr = addressbits[b2 >> 2];
+               /* flip the bit */
+               buf[byte_addr] ^= (1 << bit_addr);
                return 1;
-       }
 
-       if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
-               return 1;
+       }
+       /* count nr of bits; use table lookup, faster than calculating it */
+       if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
+               return 1;       /* error in ecc data; no action needed */
 
-       return -EBADMSG;
+       printk(KERN_ERR "uncorrectable error : ");
+       return -1;
 }
 EXPORT_SYMBOL(nand_correct_data);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
+MODULE_AUTHOR("Frans Meulenbroeks <fransmeulenbroeks@gmail.com>");
 MODULE_DESCRIPTION("Generic NAND ECC support");
index 556e8131ecdcd68c9a685e5f5bea5f036d839222..ae7c57781a68e76885ca286b9a68a16d218358be 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/delay.h>
 #include <linux/list.h>
 #include <linux/random.h>
-#include <asm/div64.h>
 
 /* Default simulator parameters values */
 #if !defined(CONFIG_NANDSIM_FIRST_ID_BYTE)  || \
index a64ad15b8fdd10affbde4c41c07c3c7a324af00b..c0fa9c9edf089c1a039ded475fb13740cfa52d1f 100644 (file)
@@ -115,55 +115,11 @@ enum {
        STATE_PIO_WRITING,
 };
 
-struct pxa3xx_nand_timing {
-       unsigned int    tCH;  /* Enable signal hold time */
-       unsigned int    tCS;  /* Enable signal setup time */
-       unsigned int    tWH;  /* ND_nWE high duration */
-       unsigned int    tWP;  /* ND_nWE pulse time */
-       unsigned int    tRH;  /* ND_nRE high duration */
-       unsigned int    tRP;  /* ND_nRE pulse width */
-       unsigned int    tR;   /* ND_nWE high to ND_nRE low for read */
-       unsigned int    tWHR; /* ND_nWE high to ND_nRE low for status read */
-       unsigned int    tAR;  /* ND_ALE low to ND_nRE low delay */
-};
-
-struct pxa3xx_nand_cmdset {
-       uint16_t        read1;
-       uint16_t        read2;
-       uint16_t        program;
-       uint16_t        read_status;
-       uint16_t        read_id;
-       uint16_t        erase;
-       uint16_t        reset;
-       uint16_t        lock;
-       uint16_t        unlock;
-       uint16_t        lock_status;
-};
-
-struct pxa3xx_nand_flash {
-       struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
-       struct pxa3xx_nand_cmdset *cmdset;
-
-       uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */
-       uint32_t page_size;     /* Page size in bytes (PAGE_SZ) */
-       uint32_t flash_width;   /* Width of Flash memory (DWIDTH_M) */
-       uint32_t dfc_width;     /* Width of flash controller(DWIDTH_C) */
-       uint32_t num_blocks;    /* Number of physical blocks in Flash */
-       uint32_t chip_id;
-
-       /* NOTE: these are automatically calculated, do not define */
-       size_t          oob_size;
-       size_t          read_id_bytes;
-
-       unsigned int    col_addr_cycles;
-       unsigned int    row_addr_cycles;
-};
-
 struct pxa3xx_nand_info {
        struct nand_chip        nand_chip;
 
        struct platform_device   *pdev;
-       struct pxa3xx_nand_flash *flash_info;
+       const struct pxa3xx_nand_flash *flash_info;
 
        struct clk              *clk;
        void __iomem            *mmio_base;
@@ -202,12 +158,20 @@ struct pxa3xx_nand_info {
        uint32_t                ndcb0;
        uint32_t                ndcb1;
        uint32_t                ndcb2;
+
+       /* calculated from pxa3xx_nand_flash data */
+       size_t          oob_size;
+       size_t          read_id_bytes;
+
+       unsigned int    col_addr_cycles;
+       unsigned int    row_addr_cycles;
 };
 
 static int use_dma = 1;
 module_param(use_dma, bool, 0444);
 MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");
 
+#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN
 static struct pxa3xx_nand_cmdset smallpage_cmdset = {
        .read1          = 0x0000,
        .read2          = 0x0050,
@@ -291,11 +255,35 @@ static struct pxa3xx_nand_flash micron1GbX16 = {
        .chip_id        = 0xb12c,
 };
 
+static struct pxa3xx_nand_timing stm2GbX16_timing = {
+       .tCH = 10,
+       .tCS = 35,
+       .tWH = 15,
+       .tWP = 25,
+       .tRH = 15,
+       .tRP = 25,
+       .tR = 25000,
+       .tWHR = 60,
+       .tAR = 10,
+};
+
+static struct pxa3xx_nand_flash stm2GbX16 = {
+       .timing = &stm2GbX16_timing,
+       .page_per_block = 64,
+       .page_size = 2048,
+       .flash_width = 16,
+       .dfc_width = 16,
+       .num_blocks = 2048,
+       .chip_id = 0xba20,
+};
+
 static struct pxa3xx_nand_flash *builtin_flash_types[] = {
        &samsung512MbX16,
        &micron1GbX8,
        &micron1GbX16,
+       &stm2GbX16,
 };
+#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */
 
 #define NDTR0_tCH(c)   (min((c), 7) << 19)
 #define NDTR0_tCS(c)   (min((c), 7) << 16)
@@ -312,7 +300,7 @@ static struct pxa3xx_nand_flash *builtin_flash_types[] = {
 #define ns2cycle(ns, clk)      (int)(((ns) * (clk / 1000000) / 1000) + 1)
 
 static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
-                                  struct pxa3xx_nand_timing *t)
+                                  const struct pxa3xx_nand_timing *t)
 {
        unsigned long nand_clk = clk_get_rate(info->clk);
        uint32_t ndtr0, ndtr1;
@@ -354,8 +342,8 @@ static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
 static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
                        uint16_t cmd, int column, int page_addr)
 {
-       struct pxa3xx_nand_flash *f = info->flash_info;
-       struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
+       const struct pxa3xx_nand_flash *f = info->flash_info;
+       const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
 
        /* calculate data size */
        switch (f->page_size) {
@@ -373,14 +361,14 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
        info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
        info->ndcb1 = 0;
        info->ndcb2 = 0;
-       info->ndcb0 |= NDCB0_ADDR_CYC(f->row_addr_cycles + f->col_addr_cycles);
+       info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
 
-       if (f->col_addr_cycles == 2) {
+       if (info->col_addr_cycles == 2) {
                /* large block, 2 cycles for column address
                 * row address starts from 3rd cycle
                 */
                info->ndcb1 |= (page_addr << 16) | (column & 0xffff);
-               if (f->row_addr_cycles == 3)
+               if (info->row_addr_cycles == 3)
                        info->ndcb2 = (page_addr >> 16) & 0xff;
        } else
                /* small block, 1 cycles for column address
@@ -406,7 +394,7 @@ static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
 
 static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
 {
-       struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
+       const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset;
 
        info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
        info->ndcb1 = 0;
@@ -641,8 +629,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                                int column, int page_addr)
 {
        struct pxa3xx_nand_info *info = mtd->priv;
-       struct pxa3xx_nand_flash *flash_info = info->flash_info;
-       struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
+       const struct pxa3xx_nand_flash *flash_info = info->flash_info;
+       const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset;
        int ret;
 
        info->use_dma = (use_dma) ? 1 : 0;
@@ -720,7 +708,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
                info->use_dma = 0;      /* force PIO read */
                info->buf_start = 0;
                info->buf_count = (command == NAND_CMD_READID) ?
-                               flash_info->read_id_bytes : 1;
+                               info->read_id_bytes : 1;
 
                if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
                                cmdset->read_id : cmdset->read_status))
@@ -861,8 +849,8 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
 
 static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
 {
-       struct pxa3xx_nand_flash *f = info->flash_info;
-       struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
+       const struct pxa3xx_nand_flash *f = info->flash_info;
+       const struct pxa3xx_nand_cmdset *cmdset = f->cmdset;
        uint32_t ndcr;
        uint8_t  id_buff[8];
 
@@ -891,7 +879,7 @@ fail_timeout:
 }
 
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
-                                   struct pxa3xx_nand_flash *f)
+                                   const struct pxa3xx_nand_flash *f)
 {
        struct platform_device *pdev = info->pdev;
        struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
@@ -904,25 +892,25 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
                return -EINVAL;
 
        /* calculate flash information */
-       f->oob_size = (f->page_size == 2048) ? 64 : 16;
-       f->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+       info->oob_size = (f->page_size == 2048) ? 64 : 16;
+       info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
        /* calculate addressing information */
-       f->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+       info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
 
        if (f->num_blocks * f->page_per_block > 65536)
-               f->row_addr_cycles = 3;
+               info->row_addr_cycles = 3;
        else
-               f->row_addr_cycles = 2;
+               info->row_addr_cycles = 2;
 
        ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
-       ndcr |= (f->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+       ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
        ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
        ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
        ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
        ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
 
-       ndcr |= NDCR_RD_ID_CNT(f->read_id_bytes);
+       ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
        ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
        info->reg_ndcr = ndcr;
@@ -932,12 +920,27 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
        return 0;
 }
 
-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
+                                   const struct pxa3xx_nand_platform_data *pdata)
 {
-       struct pxa3xx_nand_flash *f;
-       uint32_t id;
+       const struct pxa3xx_nand_flash *f;
+       uint32_t id = -1;
        int i;
 
+       for (i = 0; i<pdata->num_flash; ++i) {
+               f = pdata->flash + i;
+
+               if (pxa3xx_nand_config_flash(info, f))
+                       continue;
+
+               if (__readid(info, &id))
+                       continue;
+
+               if (id == f->chip_id)
+                       return 0;
+       }
+
+#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN
        for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) {
 
                f = builtin_flash_types[i];
@@ -951,7 +954,11 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info)
                if (id == f->chip_id)
                        return 0;
        }
+#endif
 
+       dev_warn(&info->pdev->dev,
+                "failed to detect configured nand flash; found %04x instead of\n",
+                id);
        return -ENODEV;
 }
 
@@ -1014,7 +1021,7 @@ static struct nand_ecclayout hw_largepage_ecclayout = {
 static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
                                 struct pxa3xx_nand_info *info)
 {
-       struct pxa3xx_nand_flash *f = info->flash_info;
+       const struct pxa3xx_nand_flash *f = info->flash_info;
        struct nand_chip *this = &info->nand_chip;
 
        this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0;
@@ -1135,7 +1142,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
                goto fail_free_buf;
        }
 
-       ret = pxa3xx_nand_detect_flash(info);
+       ret = pxa3xx_nand_detect_flash(info, pdata);
        if (ret) {
                dev_err(&pdev->dev, "failed to detect flash\n");
                ret = -ENODEV;
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
new file mode 100644 (file)
index 0000000..821acb0
--- /dev/null
@@ -0,0 +1,878 @@
+/*
+ * SuperH FLCTL nand controller
+ *
+ * Copyright Â© 2008 Renesas Solutions Corp.
+ * Copyright Â© 2008 Atom Create Engineering Co., Ltd.
+ *
+ * Based on fsl_elbc_nand.c, Copyright Â© 2006-2007 Freescale Semiconductor
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/sh_flctl.h>
+
+static struct nand_ecclayout flctl_4secc_oob_16 = {
+       .eccbytes = 10,
+       .eccpos = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+       .oobfree = {
+               {.offset = 12,
+               . length = 4} },
+};
+
+static struct nand_ecclayout flctl_4secc_oob_64 = {
+       .eccbytes = 10,
+       .eccpos = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57},
+       .oobfree = {
+               {.offset = 60,
+               . length = 4} },
+};
+
+static uint8_t scan_ff_pattern[] = { 0xff, 0xff };
+
+static struct nand_bbt_descr flctl_4secc_smallpage = {
+       .options = NAND_BBT_SCAN2NDPAGE,
+       .offs = 11,
+       .len = 1,
+       .pattern = scan_ff_pattern,
+};
+
+static struct nand_bbt_descr flctl_4secc_largepage = {
+       .options = 0,
+       .offs = 58,
+       .len = 2,
+       .pattern = scan_ff_pattern,
+};
+
+static void empty_fifo(struct sh_flctl *flctl)
+{
+       writel(0x000c0000, FLINTDMACR(flctl));  /* FIFO Clear */
+       writel(0x00000000, FLINTDMACR(flctl));  /* Clear Error flags */
+}
+
+static void start_translation(struct sh_flctl *flctl)
+{
+       writeb(TRSTRT, FLTRCR(flctl));
+}
+
+static void wait_completion(struct sh_flctl *flctl)
+{
+       uint32_t timeout = LOOP_TIMEOUT_MAX;
+
+       while (timeout--) {
+               if (readb(FLTRCR(flctl)) & TREND) {
+                       writeb(0x0, FLTRCR(flctl));
+                       return;
+               }
+               udelay(1);
+       }
+
+       printk(KERN_ERR "wait_completion(): Timeout occured \n");
+       writeb(0x0, FLTRCR(flctl));
+}
+
+static void set_addr(struct mtd_info *mtd, int column, int page_addr)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       uint32_t addr = 0;
+
+       if (column == -1) {
+               addr = page_addr;       /* ERASE1 */
+       } else if (page_addr != -1) {
+               /* SEQIN, READ0, etc.. */
+               if (flctl->page_size) {
+                       addr = column & 0x0FFF;
+                       addr |= (page_addr & 0xff) << 16;
+                       addr |= ((page_addr >> 8) & 0xff) << 24;
+                       /* big than 128MB */
+                       if (flctl->rw_ADRCNT == ADRCNT2_E) {
+                               uint32_t        addr2;
+                               addr2 = (page_addr >> 16) & 0xff;
+                               writel(addr2, FLADR2(flctl));
+                       }
+               } else {
+                       addr = column;
+                       addr |= (page_addr & 0xff) << 8;
+                       addr |= ((page_addr >> 8) & 0xff) << 16;
+                       addr |= ((page_addr >> 16) & 0xff) << 24;
+               }
+       }
+       writel(addr, FLADR(flctl));
+}
+
+static void wait_rfifo_ready(struct sh_flctl *flctl)
+{
+       uint32_t timeout = LOOP_TIMEOUT_MAX;
+
+       while (timeout--) {
+               uint32_t val;
+               /* check FIFO */
+               val = readl(FLDTCNTR(flctl)) >> 16;
+               if (val & 0xFF)
+                       return;
+               udelay(1);
+       }
+       printk(KERN_ERR "wait_rfifo_ready(): Timeout occured \n");
+}
+
+static void wait_wfifo_ready(struct sh_flctl *flctl)
+{
+       uint32_t len, timeout = LOOP_TIMEOUT_MAX;
+
+       while (timeout--) {
+               /* check FIFO */
+               len = (readl(FLDTCNTR(flctl)) >> 16) & 0xFF;
+               if (len >= 4)
+                       return;
+               udelay(1);
+       }
+       printk(KERN_ERR "wait_wfifo_ready(): Timeout occured \n");
+}
+
+static int wait_recfifo_ready(struct sh_flctl *flctl)
+{
+       uint32_t timeout = LOOP_TIMEOUT_MAX;
+       int checked[4];
+       void __iomem *ecc_reg[4];
+       int i;
+       uint32_t data, size;
+
+       memset(checked, 0, sizeof(checked));
+
+       while (timeout--) {
+               size = readl(FLDTCNTR(flctl)) >> 24;
+               if (size & 0xFF)
+                       return 0;       /* success */
+
+               if (readl(FL4ECCCR(flctl)) & _4ECCFA)
+                       return 1;       /* can't correct */
+
+               udelay(1);
+               if (!(readl(FL4ECCCR(flctl)) & _4ECCEND))
+                       continue;
+
+               /* start error correction */
+               ecc_reg[0] = FL4ECCRESULT0(flctl);
+               ecc_reg[1] = FL4ECCRESULT1(flctl);
+               ecc_reg[2] = FL4ECCRESULT2(flctl);
+               ecc_reg[3] = FL4ECCRESULT3(flctl);
+
+               for (i = 0; i < 3; i++) {
+                       data = readl(ecc_reg[i]);
+                       if (data != INIT_FL4ECCRESULT_VAL && !checked[i]) {
+                               uint8_t org;
+                               int index;
+
+                               index = data >> 16;
+                               org = flctl->done_buff[index];
+                               flctl->done_buff[index] = org ^ (data & 0xFF);
+                               checked[i] = 1;
+                       }
+               }
+
+               writel(0, FL4ECCCR(flctl));
+       }
+
+       printk(KERN_ERR "wait_recfifo_ready(): Timeout occured \n");
+       return 1;       /* timeout */
+}
+
+static void wait_wecfifo_ready(struct sh_flctl *flctl)
+{
+       uint32_t timeout = LOOP_TIMEOUT_MAX;
+       uint32_t len;
+
+       while (timeout--) {
+               /* check FLECFIFO */
+               len = (readl(FLDTCNTR(flctl)) >> 24) & 0xFF;
+               if (len >= 4)
+                       return;
+               udelay(1);
+       }
+       printk(KERN_ERR "wait_wecfifo_ready(): Timeout occured \n");
+}
+
+static void read_datareg(struct sh_flctl *flctl, int offset)
+{
+       unsigned long data;
+       unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
+
+       wait_completion(flctl);
+
+       data = readl(FLDATAR(flctl));
+       *buf = le32_to_cpu(data);
+}
+
+static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+{
+       int i, len_4align;
+       unsigned long *buf = (unsigned long *)&flctl->done_buff[offset];
+       void *fifo_addr = (void *)FLDTFIFO(flctl);
+
+       len_4align = (rlen + 3) / 4;
+
+       for (i = 0; i < len_4align; i++) {
+               wait_rfifo_ready(flctl);
+               buf[i] = readl(fifo_addr);
+               buf[i] = be32_to_cpu(buf[i]);
+       }
+}
+
+static int read_ecfiforeg(struct sh_flctl *flctl, uint8_t *buff)
+{
+       int i;
+       unsigned long *ecc_buf = (unsigned long *)buff;
+       void *fifo_addr = (void *)FLECFIFO(flctl);
+
+       for (i = 0; i < 4; i++) {
+               if (wait_recfifo_ready(flctl))
+                       return 1;
+               ecc_buf[i] = readl(fifo_addr);
+               ecc_buf[i] = be32_to_cpu(ecc_buf[i]);
+       }
+
+       return 0;
+}
+
+static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset)
+{
+       int i, len_4align;
+       unsigned long *data = (unsigned long *)&flctl->done_buff[offset];
+       void *fifo_addr = (void *)FLDTFIFO(flctl);
+
+       len_4align = (rlen + 3) / 4;
+       for (i = 0; i < len_4align; i++) {
+               wait_wfifo_ready(flctl);
+               writel(cpu_to_be32(data[i]), fifo_addr);
+       }
+}
+
+static void set_cmd_regs(struct mtd_info *mtd, uint32_t cmd, uint32_t flcmcdr_val)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       uint32_t flcmncr_val = readl(FLCMNCR(flctl));
+       uint32_t flcmdcr_val, addr_len_bytes = 0;
+
+       /* Set SNAND bit if page size is 2048byte */
+       if (flctl->page_size)
+               flcmncr_val |= SNAND_E;
+       else
+               flcmncr_val &= ~SNAND_E;
+
+       /* default FLCMDCR val */
+       flcmdcr_val = DOCMD1_E | DOADR_E;
+
+       /* Set for FLCMDCR */
+       switch (cmd) {
+       case NAND_CMD_ERASE1:
+               addr_len_bytes = flctl->erase_ADRCNT;
+               flcmdcr_val |= DOCMD2_E;
+               break;
+       case NAND_CMD_READ0:
+       case NAND_CMD_READOOB:
+               addr_len_bytes = flctl->rw_ADRCNT;
+               flcmdcr_val |= CDSRC_E;
+               break;
+       case NAND_CMD_SEQIN:
+               /* This case is that cmd is READ0 or READ1 or READ00 */
+               flcmdcr_val &= ~DOADR_E;        /* ONLY execute 1st cmd */
+               break;
+       case NAND_CMD_PAGEPROG:
+               addr_len_bytes = flctl->rw_ADRCNT;
+               flcmdcr_val |= DOCMD2_E | CDSRC_E | SELRW;
+               break;
+       case NAND_CMD_READID:
+               flcmncr_val &= ~SNAND_E;
+               addr_len_bytes = ADRCNT_1;
+               break;
+       case NAND_CMD_STATUS:
+       case NAND_CMD_RESET:
+               flcmncr_val &= ~SNAND_E;
+               flcmdcr_val &= ~(DOADR_E | DOSR_E);
+               break;
+       default:
+               break;
+       }
+
+       /* Set address bytes parameter */
+       flcmdcr_val |= addr_len_bytes;
+
+       /* Now actually write */
+       writel(flcmncr_val, FLCMNCR(flctl));
+       writel(flcmdcr_val, FLCMDCR(flctl));
+       writel(flcmcdr_val, FLCMCDR(flctl));
+}
+
+static int flctl_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+                               uint8_t *buf)
+{
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       uint8_t *p = buf;
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+               chip->read_buf(mtd, p, eccsize);
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               if (flctl->hwecc_cant_correct[i])
+                       mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += 0;
+       }
+
+       return 0;
+}
+
+static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
+                                  const uint8_t *buf)
+{
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       const uint8_t *p = buf;
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
+               chip->write_buf(mtd, p, eccsize);
+}
+
+static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int sector, page_sectors;
+
+       if (flctl->page_size)
+               page_sectors = 4;
+       else
+               page_sectors = 1;
+
+       writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE | _4ECCCORRECT,
+                FLCMNCR(flctl));
+
+       set_cmd_regs(mtd, NAND_CMD_READ0,
+               (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
+
+       for (sector = 0; sector < page_sectors; sector++) {
+               int ret;
+
+               empty_fifo(flctl);
+               writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
+               writel(page_addr << 2 | sector, FLADR(flctl));
+
+               start_translation(flctl);
+               read_fiforeg(flctl, 512, 512 * sector);
+
+               ret = read_ecfiforeg(flctl,
+                       &flctl->done_buff[mtd->writesize + 16 * sector]);
+
+               if (ret)
+                       flctl->hwecc_cant_correct[sector] = 1;
+
+               writel(0x0, FL4ECCCR(flctl));
+               wait_completion(flctl);
+       }
+       writel(readl(FLCMNCR(flctl)) & ~(ACM_SACCES_MODE | _4ECCCORRECT),
+                       FLCMNCR(flctl));
+}
+
+static void execmd_read_oob(struct mtd_info *mtd, int page_addr)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+
+       set_cmd_regs(mtd, NAND_CMD_READ0,
+               (NAND_CMD_READSTART << 8) | NAND_CMD_READ0);
+
+       empty_fifo(flctl);
+       if (flctl->page_size) {
+               int i;
+               /* In case that the page size is 2k */
+               for (i = 0; i < 16 * 3; i++)
+                       flctl->done_buff[i] = 0xFF;
+
+               set_addr(mtd, 3 * 528 + 512, page_addr);
+               writel(16, FLDTCNTR(flctl));
+
+               start_translation(flctl);
+               read_fiforeg(flctl, 16, 16 * 3);
+               wait_completion(flctl);
+       } else {
+               /* In case that the page size is 512b */
+               set_addr(mtd, 512, page_addr);
+               writel(16, FLDTCNTR(flctl));
+
+               start_translation(flctl);
+               read_fiforeg(flctl, 16, 0);
+               wait_completion(flctl);
+       }
+}
+
+static void execmd_write_page_sector(struct mtd_info *mtd)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int i, page_addr = flctl->seqin_page_addr;
+       int sector, page_sectors;
+
+       if (flctl->page_size)
+               page_sectors = 4;
+       else
+               page_sectors = 1;
+
+       writel(readl(FLCMNCR(flctl)) | ACM_SACCES_MODE, FLCMNCR(flctl));
+
+       set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
+                       (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
+
+       for (sector = 0; sector < page_sectors; sector++) {
+               empty_fifo(flctl);
+               writel(readl(FLCMDCR(flctl)) | 1, FLCMDCR(flctl));
+               writel(page_addr << 2 | sector, FLADR(flctl));
+
+               start_translation(flctl);
+               write_fiforeg(flctl, 512, 512 * sector);
+
+               for (i = 0; i < 4; i++) {
+                       wait_wecfifo_ready(flctl); /* wait for write ready */
+                       writel(0xFFFFFFFF, FLECFIFO(flctl));
+               }
+               wait_completion(flctl);
+       }
+
+       writel(readl(FLCMNCR(flctl)) & ~ACM_SACCES_MODE, FLCMNCR(flctl));
+}
+
+static void execmd_write_oob(struct mtd_info *mtd)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int page_addr = flctl->seqin_page_addr;
+       int sector, page_sectors;
+
+       if (flctl->page_size) {
+               sector = 3;
+               page_sectors = 4;
+       } else {
+               sector = 0;
+               page_sectors = 1;
+       }
+
+       set_cmd_regs(mtd, NAND_CMD_PAGEPROG,
+                       (NAND_CMD_PAGEPROG << 8) | NAND_CMD_SEQIN);
+
+       for (; sector < page_sectors; sector++) {
+               empty_fifo(flctl);
+               set_addr(mtd, sector * 528 + 512, page_addr);
+               writel(16, FLDTCNTR(flctl));    /* set read size */
+
+               start_translation(flctl);
+               write_fiforeg(flctl, 16, 16 * sector);
+               wait_completion(flctl);
+       }
+}
+
+static void flctl_cmdfunc(struct mtd_info *mtd, unsigned int command,
+                       int column, int page_addr)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       uint32_t read_cmd = 0;
+
+       flctl->read_bytes = 0;
+       if (command != NAND_CMD_PAGEPROG)
+               flctl->index = 0;
+
+       switch (command) {
+       case NAND_CMD_READ1:
+       case NAND_CMD_READ0:
+               if (flctl->hwecc) {
+                       /* read page with hwecc */
+                       execmd_read_page_sector(mtd, page_addr);
+                       break;
+               }
+               empty_fifo(flctl);
+               if (flctl->page_size)
+                       set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8)
+                               | command);
+               else
+                       set_cmd_regs(mtd, command, command);
+
+               set_addr(mtd, 0, page_addr);
+
+               flctl->read_bytes = mtd->writesize + mtd->oobsize;
+               flctl->index += column;
+               goto read_normal_exit;
+
+       case NAND_CMD_READOOB:
+               if (flctl->hwecc) {
+                       /* read page with hwecc */
+                       execmd_read_oob(mtd, page_addr);
+                       break;
+               }
+
+               empty_fifo(flctl);
+               if (flctl->page_size) {
+                       set_cmd_regs(mtd, command, (NAND_CMD_READSTART << 8)
+                               | NAND_CMD_READ0);
+                       set_addr(mtd, mtd->writesize, page_addr);
+               } else {
+                       set_cmd_regs(mtd, command, command);
+                       set_addr(mtd, 0, page_addr);
+               }
+               flctl->read_bytes = mtd->oobsize;
+               goto read_normal_exit;
+
+       case NAND_CMD_READID:
+               empty_fifo(flctl);
+               set_cmd_regs(mtd, command, command);
+               set_addr(mtd, 0, 0);
+
+               flctl->read_bytes = 4;
+               writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
+               start_translation(flctl);
+               read_datareg(flctl, 0); /* read and end */
+               break;
+
+       case NAND_CMD_ERASE1:
+               flctl->erase1_page_addr = page_addr;
+               break;
+
+       case NAND_CMD_ERASE2:
+               set_cmd_regs(mtd, NAND_CMD_ERASE1,
+                       (command << 8) | NAND_CMD_ERASE1);
+               set_addr(mtd, -1, flctl->erase1_page_addr);
+               start_translation(flctl);
+               wait_completion(flctl);
+               break;
+
+       case NAND_CMD_SEQIN:
+               if (!flctl->page_size) {
+                       /* output read command */
+                       if (column >= mtd->writesize) {
+                               column -= mtd->writesize;
+                               read_cmd = NAND_CMD_READOOB;
+                       } else if (column < 256) {
+                               read_cmd = NAND_CMD_READ0;
+                       } else {
+                               column -= 256;
+                               read_cmd = NAND_CMD_READ1;
+                       }
+               }
+               flctl->seqin_column = column;
+               flctl->seqin_page_addr = page_addr;
+               flctl->seqin_read_cmd = read_cmd;
+               break;
+
+       case NAND_CMD_PAGEPROG:
+               empty_fifo(flctl);
+               if (!flctl->page_size) {
+                       set_cmd_regs(mtd, NAND_CMD_SEQIN,
+                                       flctl->seqin_read_cmd);
+                       set_addr(mtd, -1, -1);
+                       writel(0, FLDTCNTR(flctl));     /* set 0 size */
+                       start_translation(flctl);
+                       wait_completion(flctl);
+               }
+               if (flctl->hwecc) {
+                       /* write page with hwecc */
+                       if (flctl->seqin_column == mtd->writesize)
+                               execmd_write_oob(mtd);
+                       else if (!flctl->seqin_column)
+                               execmd_write_page_sector(mtd);
+                       else
+                               printk(KERN_ERR "Invalid address !?\n");
+                       break;
+               }
+               set_cmd_regs(mtd, command, (command << 8) | NAND_CMD_SEQIN);
+               set_addr(mtd, flctl->seqin_column, flctl->seqin_page_addr);
+               writel(flctl->index, FLDTCNTR(flctl));  /* set write size */
+               start_translation(flctl);
+               write_fiforeg(flctl, flctl->index, 0);
+               wait_completion(flctl);
+               break;
+
+       case NAND_CMD_STATUS:
+               set_cmd_regs(mtd, command, command);
+               set_addr(mtd, -1, -1);
+
+               flctl->read_bytes = 1;
+               writel(flctl->read_bytes, FLDTCNTR(flctl)); /* set read size */
+               start_translation(flctl);
+               read_datareg(flctl, 0); /* read and end */
+               break;
+
+       case NAND_CMD_RESET:
+               set_cmd_regs(mtd, command, command);
+               set_addr(mtd, -1, -1);
+
+               writel(0, FLDTCNTR(flctl));     /* set 0 size */
+               start_translation(flctl);
+               wait_completion(flctl);
+               break;
+
+       default:
+               break;
+       }
+       return;
+
+read_normal_exit:
+       writel(flctl->read_bytes, FLDTCNTR(flctl));     /* set read size */
+       start_translation(flctl);
+       read_fiforeg(flctl, flctl->read_bytes, 0);
+       wait_completion(flctl);
+       return;
+}
+
+static void flctl_select_chip(struct mtd_info *mtd, int chipnr)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       uint32_t flcmncr_val = readl(FLCMNCR(flctl));
+
+       switch (chipnr) {
+       case -1:
+               flcmncr_val &= ~CE0_ENABLE;
+               writel(flcmncr_val, FLCMNCR(flctl));
+               break;
+       case 0:
+               flcmncr_val |= CE0_ENABLE;
+               writel(flcmncr_val, FLCMNCR(flctl));
+               break;
+       default:
+               BUG();
+       }
+}
+
+static void flctl_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int i, index = flctl->index;
+
+       for (i = 0; i < len; i++)
+               flctl->done_buff[index + i] = buf[i];
+       flctl->index += len;
+}
+
+static uint8_t flctl_read_byte(struct mtd_info *mtd)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       int index = flctl->index;
+       uint8_t data;
+
+       data = flctl->done_buff[index];
+       flctl->index++;
+       return data;
+}
+
+static void flctl_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               buf[i] = flctl_read_byte(mtd);
+}
+
+static int flctl_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               if (buf[i] != flctl_read_byte(mtd))
+                       return -EFAULT;
+       return 0;
+}
+
+static void flctl_register_init(struct sh_flctl *flctl, unsigned long val)
+{
+       writel(val, FLCMNCR(flctl));
+}
+
+static int flctl_chip_init_tail(struct mtd_info *mtd)
+{
+       struct sh_flctl *flctl = mtd_to_flctl(mtd);
+       struct nand_chip *chip = &flctl->chip;
+
+       if (mtd->writesize == 512) {
+               flctl->page_size = 0;
+               if (chip->chipsize > (32 << 20)) {
+                       /* big than 32MB */
+                       flctl->rw_ADRCNT = ADRCNT_4;
+                       flctl->erase_ADRCNT = ADRCNT_3;
+               } else if (chip->chipsize > (2 << 16)) {
+                       /* big than 128KB */
+                       flctl->rw_ADRCNT = ADRCNT_3;
+                       flctl->erase_ADRCNT = ADRCNT_2;
+               } else {
+                       flctl->rw_ADRCNT = ADRCNT_2;
+                       flctl->erase_ADRCNT = ADRCNT_1;
+               }
+       } else {
+               flctl->page_size = 1;
+               if (chip->chipsize > (128 << 20)) {
+                       /* big than 128MB */
+                       flctl->rw_ADRCNT = ADRCNT2_E;
+                       flctl->erase_ADRCNT = ADRCNT_3;
+               } else if (chip->chipsize > (8 << 16)) {
+                       /* big than 512KB */
+                       flctl->rw_ADRCNT = ADRCNT_4;
+                       flctl->erase_ADRCNT = ADRCNT_2;
+               } else {
+                       flctl->rw_ADRCNT = ADRCNT_3;
+                       flctl->erase_ADRCNT = ADRCNT_1;
+               }
+       }
+
+       if (flctl->hwecc) {
+               if (mtd->writesize == 512) {
+                       chip->ecc.layout = &flctl_4secc_oob_16;
+                       chip->badblock_pattern = &flctl_4secc_smallpage;
+               } else {
+                       chip->ecc.layout = &flctl_4secc_oob_64;
+                       chip->badblock_pattern = &flctl_4secc_largepage;
+               }
+
+               chip->ecc.size = 512;
+               chip->ecc.bytes = 10;
+               chip->ecc.read_page = flctl_read_page_hwecc;
+               chip->ecc.write_page = flctl_write_page_hwecc;
+               chip->ecc.mode = NAND_ECC_HW;
+
+               /* 4 symbols ECC enabled */
+               writel(readl(FLCMNCR(flctl)) | _4ECCEN | ECCPOS2 | ECCPOS_02,
+                               FLCMNCR(flctl));
+       } else {
+               chip->ecc.mode = NAND_ECC_SOFT;
+       }
+
+       return 0;
+}
+
+static int __init flctl_probe(struct platform_device *pdev)
+{
+       struct resource *res;
+       struct sh_flctl *flctl;
+       struct mtd_info *flctl_mtd;
+       struct nand_chip *nand;
+       struct sh_flctl_platform_data *pdata;
+       int ret;
+
+       pdata = pdev->dev.platform_data;
+       if (pdata == NULL) {
+               printk(KERN_ERR "sh_flctl platform_data not found.\n");
+               return -ENODEV;
+       }
+
+       flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
+       if (!flctl) {
+               printk(KERN_ERR "Unable to allocate NAND MTD dev structure.\n");
+               return -ENOMEM;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               printk(KERN_ERR "%s: resource not found.\n", __func__);
+               ret = -ENODEV;
+               goto err;
+       }
+
+       flctl->reg = ioremap(res->start, res->end - res->start + 1);
+       if (flctl->reg == NULL) {
+               printk(KERN_ERR "%s: ioremap error.\n", __func__);
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       platform_set_drvdata(pdev, flctl);
+       flctl_mtd = &flctl->mtd;
+       nand = &flctl->chip;
+       flctl_mtd->priv = nand;
+       flctl->hwecc = pdata->has_hwecc;
+
+       flctl_register_init(flctl, pdata->flcmncr_val);
+
+       nand->options = NAND_NO_AUTOINCR;
+
+       /* Set address of hardware control function */
+       /* 20 us command delay time */
+       nand->chip_delay = 20;
+
+       nand->read_byte = flctl_read_byte;
+       nand->write_buf = flctl_write_buf;
+       nand->read_buf = flctl_read_buf;
+       nand->verify_buf = flctl_verify_buf;
+       nand->select_chip = flctl_select_chip;
+       nand->cmdfunc = flctl_cmdfunc;
+
+       ret = nand_scan_ident(flctl_mtd, 1);
+       if (ret)
+               goto err;
+
+       ret = flctl_chip_init_tail(flctl_mtd);
+       if (ret)
+               goto err;
+
+       ret = nand_scan_tail(flctl_mtd);
+       if (ret)
+               goto err;
+
+       add_mtd_partitions(flctl_mtd, pdata->parts, pdata->nr_parts);
+
+       return 0;
+
+err:
+       kfree(flctl);
+       return ret;
+}
+
+static int __exit flctl_remove(struct platform_device *pdev)
+{
+       struct sh_flctl *flctl = platform_get_drvdata(pdev);
+
+       nand_release(&flctl->mtd);
+       kfree(flctl);
+
+       return 0;
+}
+
+static struct platform_driver flctl_driver = {
+       .probe          = flctl_probe,
+       .remove         = flctl_remove,
+       .driver = {
+               .name   = "sh_flctl",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init flctl_nand_init(void)
+{
+       return platform_driver_register(&flctl_driver);
+}
+
+static void __exit flctl_nand_cleanup(void)
+{
+       platform_driver_unregister(&flctl_driver);
+}
+
+module_init(flctl_nand_init);
+module_exit(flctl_nand_cleanup);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_DESCRIPTION("SuperH FLCTL driver");
+MODULE_ALIAS("platform:sh_flctl");
diff --git a/drivers/mtd/nand/toto.c b/drivers/mtd/nand/toto.c
deleted file mode 100644 (file)
index bbf492e..0000000
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- *  drivers/mtd/nand/toto.c
- *
- *  Copyright (c) 2003 Texas Instruments
- *
- *  Derived from drivers/mtd/autcpu12.c
- *
- *  Copyright (c) 2002 Thomas Gleixner <tgxl@linutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   TI fido board. It supports 32MiB and 64MiB cards
- */
-
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <asm/arch/hardware.h>
-#include <asm/sizes.h>
-#include <asm/arch/toto.h>
-#include <asm/arch-omap1510/hardware.h>
-#include <asm/arch/gpio.h>
-
-#define CONFIG_NAND_WORKAROUND 1
-
-/*
- * MTD structure for TOTO board
- */
-static struct mtd_info *toto_mtd = NULL;
-
-static unsigned long toto_io_base = OMAP_FLASH_1_BASE;
-
-/*
- * Define partitions for flash devices
- */
-
-static struct mtd_partition partition_info64M[] = {
-       { .name =       "toto kernel partition 1",
-         .offset =     0,
-         .size =       2 * SZ_1M },
-       { .name =       "toto file sys partition 2",
-         .offset =     2 * SZ_1M,
-         .size =       14 * SZ_1M },
-       { .name =       "toto user partition 3",
-         .offset =     16 * SZ_1M,
-         .size =       16 * SZ_1M },
-       { .name =       "toto devboard extra partition 4",
-         .offset =     32 * SZ_1M,
-         .size =       32 * SZ_1M },
-};
-
-static struct mtd_partition partition_info32M[] = {
-       { .name =       "toto kernel partition 1",
-         .offset =     0,
-         .size =       2 * SZ_1M },
-       { .name =       "toto file sys partition 2",
-         .offset =     2 * SZ_1M,
-         .size =       14 * SZ_1M },
-       { .name =       "toto user partition 3",
-         .offset =     16 * SZ_1M,
-         .size =       16 * SZ_1M },
-};
-
-#define NUM_PARTITIONS32M 3
-#define NUM_PARTITIONS64M 4
-
-/*
- *     hardware specific access to control-lines
- *
- *     ctrl:
- *     NAND_NCE: bit 0 -> bit 14 (0x4000)
- *     NAND_CLE: bit 1 -> bit 12 (0x1000)
- *     NAND_ALE: bit 2 -> bit 1  (0x0002)
- */
-static void toto_hwcontrol(struct mtd_info *mtd, int cmd,
-                          unsigned int ctrl)
-{
-       struct nand_chip *chip = mtd->priv;
-
-       if (ctrl & NAND_CTRL_CHANGE) {
-               unsigned long bits;
-
-               /* hopefully enough time for tc make proceding write to clear */
-               udelay(1);
-
-               bits = (~ctrl & NAND_NCE) << 14;
-               bits |= (ctrl & NAND_CLE) << 12;
-               bits |= (ctrl & NAND_ALE) >> 1;
-
-#warning Wild guess as gpiosetout() is nowhere defined in the kernel source - tglx
-               gpiosetout(0x5002, bits);
-
-#ifdef CONFIG_NAND_WORKAROUND
-               /* "some" dev boards busted, blue wired to rts2 :( */
-               rts2setout(2, (ctrl & NAND_CLE) << 1);
-#endif
-               /* allow time to ensure gpio state to over take memory write */
-               udelay(1);
-       }
-
-       if (cmd != NAND_CMD_NONE)
-               writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- * Main initialization routine
- */
-static int __init toto_init(void)
-{
-       struct nand_chip *this;
-       int err = 0;
-
-       /* Allocate memory for MTD device structure and private data */
-       toto_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-       if (!toto_mtd) {
-               printk(KERN_WARNING "Unable to allocate toto NAND MTD device structure.\n");
-               err = -ENOMEM;
-               goto out;
-       }
-
-       /* Get pointer to private data */
-       this = (struct nand_chip *)(&toto_mtd[1]);
-
-       /* Initialize structures */
-       memset(toto_mtd, 0, sizeof(struct mtd_info));
-       memset(this, 0, sizeof(struct nand_chip));
-
-       /* Link the private data with the MTD structure */
-       toto_mtd->priv = this;
-       toto_mtd->owner = THIS_MODULE;
-
-       /* Set address of NAND IO lines */
-       this->IO_ADDR_R = toto_io_base;
-       this->IO_ADDR_W = toto_io_base;
-       this->cmd_ctrl = toto_hwcontrol;
-       this->dev_ready = NULL;
-       /* 25 us command delay time */
-       this->chip_delay = 30;
-       this->ecc.mode = NAND_ECC_SOFT;
-
-       /* Scan to find existance of the device */
-       if (nand_scan(toto_mtd, 1)) {
-               err = -ENXIO;
-               goto out_mtd;
-       }
-
-       /* Register the partitions */
-       switch (toto_mtd->size) {
-       case SZ_64M:
-               add_mtd_partitions(toto_mtd, partition_info64M, NUM_PARTITIONS64M);
-               break;
-       case SZ_32M:
-               add_mtd_partitions(toto_mtd, partition_info32M, NUM_PARTITIONS32M);
-               break;
-       default:{
-                       printk(KERN_WARNING "Unsupported Nand device\n");
-                       err = -ENXIO;
-                       goto out_buf;
-               }
-       }
-
-       gpioreserve(NAND_MASK); /* claim our gpios */
-       archflashwp(0, 0);      /* open up flash for writing */
-
-       goto out;
-
- out_mtd:
-       kfree(toto_mtd);
- out:
-       return err;
-}
-
-module_init(toto_init);
-
-/*
- * Clean up routine
- */
-static void __exit toto_cleanup(void)
-{
-       /* Release resources, unregister device */
-       nand_release(toto_mtd);
-
-       /* Free the MTD device structure */
-       kfree(toto_mtd);
-
-       /* stop flash writes */
-       archflashwp(0, 1);
-
-       /* release gpios to system */
-       gpiorelease(NAND_MASK);
-}
-
-module_exit(toto_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Richard Woodruff <r-woodruff2@ti.com>");
-MODULE_DESCRIPTION("Glue layer for NAND flash on toto board");
index 4f80c2fd89af71a0a0c9e5bae77c013a663a4c7b..9e45b3f39c0e7e6cf4f4417f874376e5bfdda9df 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mtd/partitions.h>
 
 int __devinit of_mtd_parse_partitions(struct device *dev,
-                                      struct mtd_info *mtd,
                                       struct device_node *node,
                                       struct mtd_partition **pparts)
 {
index cb41cbca64f7e63394f352820eb90cc610bac6f8..79fa79e8f8de9b67a5949888d029f93b7dbebb27 100644 (file)
@@ -27,8 +27,16 @@ config MTD_ONENAND_GENERIC
        help
          Support for OneNAND flash via platform device driver.
 
+config MTD_ONENAND_OMAP2
+       tristate "OneNAND on OMAP2/OMAP3 support"
+       depends on MTD_ONENAND && (ARCH_OMAP2 || ARCH_OMAP3)
+       help
+         Support for a OneNAND flash device connected to an OMAP2/OMAP3 CPU
+         via the GPMC memory controller.
+
 config MTD_ONENAND_OTP
        bool "OneNAND OTP Support"
+       select HAVE_MTD_OTP
        help
          One Block of the NAND Flash Array memory is reserved as
          a One-Time Programmable Block memory area.
index 4d2eacfd7e11a761c3cec319f34c735d0fc0222b..64b6cc61a5209241145a4a3e1856dcb39a96d19c 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_MTD_ONENAND)               += onenand.o
 
 # Board specific.
 obj-$(CONFIG_MTD_ONENAND_GENERIC)      += generic.o
+obj-$(CONFIG_MTD_ONENAND_OMAP2)                += omap2.o
 
 # Simulator
 obj-$(CONFIG_MTD_ONENAND_SIM)          += onenand_sim.o
diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
new file mode 100644 (file)
index 0000000..8387e05
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ *  linux/drivers/mtd/onenand/omap2.c
+ *
+ *  OneNAND driver for OMAP2 / OMAP3
+ *
+ *  Copyright Â© 2005-2006 Nokia Corporation
+ *
+ *  Author: Jarkko Lavinen <jarkko.lavinen@nokia.com> and Juha Yrjölä
+ *  IRQ and DMA support written by Timo Teras
+ *
+ * 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; see the file COPYING. If not, write to the Free Software
+ * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/onenand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/io.h>
+#include <asm/mach/flash.h>
+#include <asm/arch/gpmc.h>
+#include <asm/arch/onenand.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/gpmc.h>
+#include <asm/arch/pm.h>
+
+#include <linux/dma-mapping.h>
+#include <asm/dma-mapping.h>
+#include <asm/arch/dma.h>
+
+#include <asm/arch/board.h>
+
+#define DRIVER_NAME "omap2-onenand"
+
+#define ONENAND_IO_SIZE                SZ_128K
+#define ONENAND_BUFRAM_SIZE    (1024 * 5)
+
+struct omap2_onenand {
+       struct platform_device *pdev;
+       int gpmc_cs;
+       unsigned long phys_base;
+       int gpio_irq;
+       struct mtd_info mtd;
+       struct mtd_partition *parts;
+       struct onenand_chip onenand;
+       struct completion irq_done;
+       struct completion dma_done;
+       int dma_channel;
+       int freq;
+       int (*setup)(void __iomem *base, int freq);
+};
+
+static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
+{
+       struct omap2_onenand *c = data;
+
+       complete(&c->dma_done);
+}
+
+static irqreturn_t omap2_onenand_interrupt(int irq, void *dev_id)
+{
+       struct omap2_onenand *c = dev_id;
+
+       complete(&c->irq_done);
+
+       return IRQ_HANDLED;
+}
+
+static inline unsigned short read_reg(struct omap2_onenand *c, int reg)
+{
+       return readw(c->onenand.base + reg);
+}
+
+static inline void write_reg(struct omap2_onenand *c, unsigned short value,
+                            int reg)
+{
+       writew(value, c->onenand.base + reg);
+}
+
+static void wait_err(char *msg, int state, unsigned int ctrl, unsigned int intr)
+{
+       printk(KERN_ERR "onenand_wait: %s! state %d ctrl 0x%04x intr 0x%04x\n",
+              msg, state, ctrl, intr);
+}
+
+static void wait_warn(char *msg, int state, unsigned int ctrl,
+                     unsigned int intr)
+{
+       printk(KERN_WARNING "onenand_wait: %s! state %d ctrl 0x%04x "
+              "intr 0x%04x\n", msg, state, ctrl, intr);
+}
+
+static int omap2_onenand_wait(struct mtd_info *mtd, int state)
+{
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       unsigned int intr = 0;
+       unsigned int ctrl;
+       unsigned long timeout;
+       u32 syscfg;
+
+       if (state == FL_RESETING) {
+               int i;
+
+               for (i = 0; i < 20; i++) {
+                       udelay(1);
+                       intr = read_reg(c, ONENAND_REG_INTERRUPT);
+                       if (intr & ONENAND_INT_MASTER)
+                               break;
+               }
+               ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+               if (ctrl & ONENAND_CTRL_ERROR) {
+                       wait_err("controller error", state, ctrl, intr);
+                       return -EIO;
+               }
+               if (!(intr & ONENAND_INT_RESET)) {
+                       wait_err("timeout", state, ctrl, intr);
+                       return -EIO;
+               }
+               return 0;
+       }
+
+       if (state != FL_READING) {
+               int result;
+
+               /* Turn interrupts on */
+               syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
+               if (!(syscfg & ONENAND_SYS_CFG1_IOBE)) {
+                       syscfg |= ONENAND_SYS_CFG1_IOBE;
+                       write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
+                       if (cpu_is_omap34xx())
+                               /* Add a delay to let GPIO settle */
+                               syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
+               }
+
+               INIT_COMPLETION(c->irq_done);
+               if (c->gpio_irq) {
+                       result = omap_get_gpio_datain(c->gpio_irq);
+                       if (result == -1) {
+                               ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+                               intr = read_reg(c, ONENAND_REG_INTERRUPT);
+                               wait_err("gpio error", state, ctrl, intr);
+                               return -EIO;
+                       }
+               } else
+                       result = 0;
+               if (result == 0) {
+                       int retry_cnt = 0;
+retry:
+                       result = wait_for_completion_timeout(&c->irq_done,
+                                                   msecs_to_jiffies(20));
+                       if (result == 0) {
+                               /* Timeout after 20ms */
+                               ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+                               if (ctrl & ONENAND_CTRL_ONGO) {
+                                       /*
+                                        * The operation seems to be still going
+                                        * so give it some more time.
+                                        */
+                                       retry_cnt += 1;
+                                       if (retry_cnt < 3)
+                                               goto retry;
+                                       intr = read_reg(c,
+                                                       ONENAND_REG_INTERRUPT);
+                                       wait_err("timeout", state, ctrl, intr);
+                                       return -EIO;
+                               }
+                               intr = read_reg(c, ONENAND_REG_INTERRUPT);
+                               if ((intr & ONENAND_INT_MASTER) == 0)
+                                       wait_warn("timeout", state, ctrl, intr);
+                       }
+               }
+       } else {
+               int retry_cnt = 0;
+
+               /* Turn interrupts off */
+               syscfg = read_reg(c, ONENAND_REG_SYS_CFG1);
+               syscfg &= ~ONENAND_SYS_CFG1_IOBE;
+               write_reg(c, syscfg, ONENAND_REG_SYS_CFG1);
+
+               timeout = jiffies + msecs_to_jiffies(20);
+               while (1) {
+                       if (time_before(jiffies, timeout)) {
+                               intr = read_reg(c, ONENAND_REG_INTERRUPT);
+                               if (intr & ONENAND_INT_MASTER)
+                                       break;
+                       } else {
+                               /* Timeout after 20ms */
+                               ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+                               if (ctrl & ONENAND_CTRL_ONGO) {
+                                       /*
+                                        * The operation seems to be still going
+                                        * so give it some more time.
+                                        */
+                                       retry_cnt += 1;
+                                       if (retry_cnt < 3) {
+                                               timeout = jiffies +
+                                                         msecs_to_jiffies(20);
+                                               continue;
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+
+       intr = read_reg(c, ONENAND_REG_INTERRUPT);
+       ctrl = read_reg(c, ONENAND_REG_CTRL_STATUS);
+
+       if (intr & ONENAND_INT_READ) {
+               int ecc = read_reg(c, ONENAND_REG_ECC_STATUS);
+
+               if (ecc) {
+                       unsigned int addr1, addr8;
+
+                       addr1 = read_reg(c, ONENAND_REG_START_ADDRESS1);
+                       addr8 = read_reg(c, ONENAND_REG_START_ADDRESS8);
+                       if (ecc & ONENAND_ECC_2BIT_ALL) {
+                               printk(KERN_ERR "onenand_wait: ECC error = "
+                                      "0x%04x, addr1 %#x, addr8 %#x\n",
+                                      ecc, addr1, addr8);
+                               mtd->ecc_stats.failed++;
+                               return -EBADMSG;
+                       } else if (ecc & ONENAND_ECC_1BIT_ALL) {
+                               printk(KERN_NOTICE "onenand_wait: correctable "
+                                      "ECC error = 0x%04x, addr1 %#x, "
+                                      "addr8 %#x\n", ecc, addr1, addr8);
+                               mtd->ecc_stats.corrected++;
+                       }
+               }
+       } else if (state == FL_READING) {
+               wait_err("timeout", state, ctrl, intr);
+               return -EIO;
+       }
+
+       if (ctrl & ONENAND_CTRL_ERROR) {
+               wait_err("controller error", state, ctrl, intr);
+               if (ctrl & ONENAND_CTRL_LOCK)
+                       printk(KERN_ERR "onenand_wait: "
+                                       "Device is write protected!!!\n");
+               return -EIO;
+       }
+
+       if (ctrl & 0xFE9F)
+               wait_warn("unexpected controller status", state, ctrl, intr);
+
+       return 0;
+}
+
+static inline int omap2_onenand_bufferram_offset(struct mtd_info *mtd, int area)
+{
+       struct onenand_chip *this = mtd->priv;
+
+       if (ONENAND_CURRENT_BUFFERRAM(this)) {
+               if (area == ONENAND_DATARAM)
+                       return mtd->writesize;
+               if (area == ONENAND_SPARERAM)
+                       return mtd->oobsize;
+       }
+
+       return 0;
+}
+
+#if defined(CONFIG_ARCH_OMAP3) || defined(MULTI_OMAP2)
+
+static int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
+                                       unsigned char *buffer, int offset,
+                                       size_t count)
+{
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       struct onenand_chip *this = mtd->priv;
+       dma_addr_t dma_src, dma_dst;
+       int bram_offset;
+       unsigned long timeout;
+       void *buf = (void *)buffer;
+       size_t xtra;
+       volatile unsigned *done;
+
+       bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+       if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
+               goto out_copy;
+
+       if (buf >= high_memory) {
+               struct page *p1;
+
+               if (((size_t)buf & PAGE_MASK) !=
+                   ((size_t)(buf + count - 1) & PAGE_MASK))
+                       goto out_copy;
+               p1 = vmalloc_to_page(buf);
+               if (!p1)
+                       goto out_copy;
+               buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
+       }
+
+       xtra = count & 3;
+       if (xtra) {
+               count -= xtra;
+               memcpy(buf + count, this->base + bram_offset + count, xtra);
+       }
+
+       dma_src = c->phys_base + bram_offset;
+       dma_dst = dma_map_single(&c->pdev->dev, buf, count, DMA_FROM_DEVICE);
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+               dev_err(&c->pdev->dev,
+                       "Couldn't DMA map a %d byte buffer\n",
+                       count);
+               goto out_copy;
+       }
+
+       omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
+                                    count >> 2, 1, 0, 0, 0);
+       omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                               dma_src, 0, 0);
+       omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                                dma_dst, 0, 0);
+
+       INIT_COMPLETION(c->dma_done);
+       omap_start_dma(c->dma_channel);
+
+       timeout = jiffies + msecs_to_jiffies(20);
+       done = &c->dma_done.done;
+       while (time_before(jiffies, timeout))
+               if (*done)
+                       break;
+
+       dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
+
+       if (!*done) {
+               dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
+               goto out_copy;
+       }
+
+       return 0;
+
+out_copy:
+       memcpy(buf, this->base + bram_offset, count);
+       return 0;
+}
+
+static int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
+                                        const unsigned char *buffer,
+                                        int offset, size_t count)
+{
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       struct onenand_chip *this = mtd->priv;
+       dma_addr_t dma_src, dma_dst;
+       int bram_offset;
+       unsigned long timeout;
+       void *buf = (void *)buffer;
+       volatile unsigned *done;
+
+       bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+       if (bram_offset & 3 || (size_t)buf & 3 || count < 384)
+               goto out_copy;
+
+       /* panic_write() may be in an interrupt context */
+       if (in_interrupt())
+               goto out_copy;
+
+       if (buf >= high_memory) {
+               struct page *p1;
+
+               if (((size_t)buf & PAGE_MASK) !=
+                   ((size_t)(buf + count - 1) & PAGE_MASK))
+                       goto out_copy;
+               p1 = vmalloc_to_page(buf);
+               if (!p1)
+                       goto out_copy;
+               buf = page_address(p1) + ((size_t)buf & ~PAGE_MASK);
+       }
+
+       dma_src = dma_map_single(&c->pdev->dev, buf, count, DMA_TO_DEVICE);
+       dma_dst = c->phys_base + bram_offset;
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+               dev_err(&c->pdev->dev,
+                       "Couldn't DMA map a %d byte buffer\n",
+                       count);
+               return -1;
+       }
+
+       omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
+                                    count >> 2, 1, 0, 0, 0);
+       omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                               dma_src, 0, 0);
+       omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                                dma_dst, 0, 0);
+
+       INIT_COMPLETION(c->dma_done);
+       omap_start_dma(c->dma_channel);
+
+       timeout = jiffies + msecs_to_jiffies(20);
+       done = &c->dma_done.done;
+       while (time_before(jiffies, timeout))
+               if (*done)
+                       break;
+
+       dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
+
+       if (!*done) {
+               dev_err(&c->pdev->dev, "timeout waiting for DMA\n");
+               goto out_copy;
+       }
+
+       return 0;
+
+out_copy:
+       memcpy(this->base + bram_offset, buf, count);
+       return 0;
+}
+
+#else
+
+int omap3_onenand_read_bufferram(struct mtd_info *mtd, int area,
+                                unsigned char *buffer, int offset,
+                                size_t count);
+
+int omap3_onenand_write_bufferram(struct mtd_info *mtd, int area,
+                                 const unsigned char *buffer,
+                                 int offset, size_t count);
+
+#endif
+
+#if defined(CONFIG_ARCH_OMAP2) || defined(MULTI_OMAP2)
+
+static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+                                       unsigned char *buffer, int offset,
+                                       size_t count)
+{
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       struct onenand_chip *this = mtd->priv;
+       dma_addr_t dma_src, dma_dst;
+       int bram_offset;
+
+       bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+       /* DMA is not used.  Revisit PM requirements before enabling it. */
+       if (1 || (c->dma_channel < 0) ||
+           ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
+           (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
+               memcpy(buffer, (__force void *)(this->base + bram_offset),
+                      count);
+               return 0;
+       }
+
+       dma_src = c->phys_base + bram_offset;
+       dma_dst = dma_map_single(&c->pdev->dev, buffer, count,
+                                DMA_FROM_DEVICE);
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+               dev_err(&c->pdev->dev,
+                       "Couldn't DMA map a %d byte buffer\n",
+                       count);
+               return -1;
+       }
+
+       omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S32,
+                                    count / 4, 1, 0, 0, 0);
+       omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                               dma_src, 0, 0);
+       omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                                dma_dst, 0, 0);
+
+       INIT_COMPLETION(c->dma_done);
+       omap_start_dma(c->dma_channel);
+       wait_for_completion(&c->dma_done);
+
+       dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_FROM_DEVICE);
+
+       return 0;
+}
+
+static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+                                        const unsigned char *buffer,
+                                        int offset, size_t count)
+{
+       struct omap2_onenand *c = container_of(mtd, struct omap2_onenand, mtd);
+       struct onenand_chip *this = mtd->priv;
+       dma_addr_t dma_src, dma_dst;
+       int bram_offset;
+
+       bram_offset = omap2_onenand_bufferram_offset(mtd, area) + area + offset;
+       /* DMA is not used.  Revisit PM requirements before enabling it. */
+       if (1 || (c->dma_channel < 0) ||
+           ((void *) buffer >= (void *) high_memory) || (bram_offset & 3) ||
+           (((unsigned int) buffer) & 3) || (count < 1024) || (count & 3)) {
+               memcpy((__force void *)(this->base + bram_offset), buffer,
+                      count);
+               return 0;
+       }
+
+       dma_src = dma_map_single(&c->pdev->dev, (void *) buffer, count,
+                                DMA_TO_DEVICE);
+       dma_dst = c->phys_base + bram_offset;
+       if (dma_mapping_error(&c->pdev->dev, dma_dst)) {
+               dev_err(&c->pdev->dev,
+                       "Couldn't DMA map a %d byte buffer\n",
+                       count);
+               return -1;
+       }
+
+       omap_set_dma_transfer_params(c->dma_channel, OMAP_DMA_DATA_TYPE_S16,
+                                    count / 2, 1, 0, 0, 0);
+       omap_set_dma_src_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                               dma_src, 0, 0);
+       omap_set_dma_dest_params(c->dma_channel, 0, OMAP_DMA_AMODE_POST_INC,
+                                dma_dst, 0, 0);
+
+       INIT_COMPLETION(c->dma_done);
+       omap_start_dma(c->dma_channel);
+       wait_for_completion(&c->dma_done);
+
+       dma_unmap_single(&c->pdev->dev, dma_dst, count, DMA_TO_DEVICE);
+
+       return 0;
+}
+
+#else
+
+int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
+                                unsigned char *buffer, int offset,
+                                size_t count);
+
+int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
+                                 const unsigned char *buffer,
+                                 int offset, size_t count);
+
+#endif
+
+static struct platform_driver omap2_onenand_driver;
+
+static int __adjust_timing(struct device *dev, void *data)
+{
+       int ret = 0;
+       struct omap2_onenand *c;
+
+       c = dev_get_drvdata(dev);
+
+       BUG_ON(c->setup == NULL);
+
+       /* DMA is not in use so this is all that is needed */
+       /* Revisit for OMAP3! */
+       ret = c->setup(c->onenand.base, c->freq);
+
+       return ret;
+}
+
+int omap2_onenand_rephase(void)
+{
+       return driver_for_each_device(&omap2_onenand_driver.driver, NULL,
+                                     NULL, __adjust_timing);
+}
+
+static void __devexit omap2_onenand_shutdown(struct platform_device *pdev)
+{
+       struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
+
+       /* With certain content in the buffer RAM, the OMAP boot ROM code
+        * can recognize the flash chip incorrectly. Zero it out before
+        * soft reset.
+        */
+       memset((__force void *)c->onenand.base, 0, ONENAND_BUFRAM_SIZE);
+}
+
+static int __devinit omap2_onenand_probe(struct platform_device *pdev)
+{
+       struct omap_onenand_platform_data *pdata;
+       struct omap2_onenand *c;
+       int r;
+
+       pdata = pdev->dev.platform_data;
+       if (pdata == NULL) {
+               dev_err(&pdev->dev, "platform data missing\n");
+               return -ENODEV;
+       }
+
+       c = kzalloc(sizeof(struct omap2_onenand), GFP_KERNEL);
+       if (!c)
+               return -ENOMEM;
+
+       init_completion(&c->irq_done);
+       init_completion(&c->dma_done);
+       c->gpmc_cs = pdata->cs;
+       c->gpio_irq = pdata->gpio_irq;
+       c->dma_channel = pdata->dma_channel;
+       if (c->dma_channel < 0) {
+               /* if -1, don't use DMA */
+               c->gpio_irq = 0;
+       }
+
+       r = gpmc_cs_request(c->gpmc_cs, ONENAND_IO_SIZE, &c->phys_base);
+       if (r < 0) {
+               dev_err(&pdev->dev, "Cannot request GPMC CS\n");
+               goto err_kfree;
+       }
+
+       if (request_mem_region(c->phys_base, ONENAND_IO_SIZE,
+                              pdev->dev.driver->name) == NULL) {
+               dev_err(&pdev->dev, "Cannot reserve memory region at 0x%08lx, "
+                       "size: 0x%x\n", c->phys_base, ONENAND_IO_SIZE);
+               r = -EBUSY;
+               goto err_free_cs;
+       }
+       c->onenand.base = ioremap(c->phys_base, ONENAND_IO_SIZE);
+       if (c->onenand.base == NULL) {
+               r = -ENOMEM;
+               goto err_release_mem_region;
+       }
+
+       if (pdata->onenand_setup != NULL) {
+               r = pdata->onenand_setup(c->onenand.base, c->freq);
+               if (r < 0) {
+                       dev_err(&pdev->dev, "Onenand platform setup failed: "
+                               "%d\n", r);
+                       goto err_iounmap;
+               }
+               c->setup = pdata->onenand_setup;
+       }
+
+       if (c->gpio_irq) {
+               if ((r = omap_request_gpio(c->gpio_irq)) < 0) {
+                       dev_err(&pdev->dev,  "Failed to request GPIO%d for "
+                               "OneNAND\n", c->gpio_irq);
+                       goto err_iounmap;
+       }
+       omap_set_gpio_direction(c->gpio_irq, 1);
+
+       if ((r = request_irq(OMAP_GPIO_IRQ(c->gpio_irq),
+                            omap2_onenand_interrupt, IRQF_TRIGGER_RISING,
+                            pdev->dev.driver->name, c)) < 0)
+               goto err_release_gpio;
+       }
+
+       if (c->dma_channel >= 0) {
+               r = omap_request_dma(0, pdev->dev.driver->name,
+                                    omap2_onenand_dma_cb, (void *) c,
+                                    &c->dma_channel);
+               if (r == 0) {
+                       omap_set_dma_write_mode(c->dma_channel,
+                                               OMAP_DMA_WRITE_NON_POSTED);
+                       omap_set_dma_src_data_pack(c->dma_channel, 1);
+                       omap_set_dma_src_burst_mode(c->dma_channel,
+                                                   OMAP_DMA_DATA_BURST_8);
+                       omap_set_dma_dest_data_pack(c->dma_channel, 1);
+                       omap_set_dma_dest_burst_mode(c->dma_channel,
+                                                    OMAP_DMA_DATA_BURST_8);
+               } else {
+                       dev_info(&pdev->dev,
+                                "failed to allocate DMA for OneNAND, "
+                                "using PIO instead\n");
+                       c->dma_channel = -1;
+               }
+       }
+
+       dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual "
+                "base %p\n", c->gpmc_cs, c->phys_base,
+                c->onenand.base);
+
+       c->pdev = pdev;
+       c->mtd.name = pdev->dev.bus_id;
+       c->mtd.priv = &c->onenand;
+       c->mtd.owner = THIS_MODULE;
+
+       if (c->dma_channel >= 0) {
+               struct onenand_chip *this = &c->onenand;
+
+               this->wait = omap2_onenand_wait;
+               if (cpu_is_omap34xx()) {
+                       this->read_bufferram = omap3_onenand_read_bufferram;
+                       this->write_bufferram = omap3_onenand_write_bufferram;
+               } else {
+                       this->read_bufferram = omap2_onenand_read_bufferram;
+                       this->write_bufferram = omap2_onenand_write_bufferram;
+               }
+       }
+
+       if ((r = onenand_scan(&c->mtd, 1)) < 0)
+               goto err_release_dma;
+
+       switch ((c->onenand.version_id >> 4) & 0xf) {
+       case 0:
+               c->freq = 40;
+               break;
+       case 1:
+               c->freq = 54;
+               break;
+       case 2:
+               c->freq = 66;
+               break;
+       case 3:
+               c->freq = 83;
+               break;
+       }
+
+#ifdef CONFIG_MTD_PARTITIONS
+       if (pdata->parts != NULL)
+               r = add_mtd_partitions(&c->mtd, pdata->parts,
+                                      pdata->nr_parts);
+       else
+#endif
+               r = add_mtd_device(&c->mtd);
+       if (r < 0)
+               goto err_release_onenand;
+
+       platform_set_drvdata(pdev, c);
+
+       return 0;
+
+err_release_onenand:
+       onenand_release(&c->mtd);
+err_release_dma:
+       if (c->dma_channel != -1)
+               omap_free_dma(c->dma_channel);
+       if (c->gpio_irq)
+               free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
+err_release_gpio:
+       if (c->gpio_irq)
+               omap_free_gpio(c->gpio_irq);
+err_iounmap:
+       iounmap(c->onenand.base);
+err_release_mem_region:
+       release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+err_free_cs:
+       gpmc_cs_free(c->gpmc_cs);
+err_kfree:
+       kfree(c);
+
+       return r;
+}
+
+static int __devexit omap2_onenand_remove(struct platform_device *pdev)
+{
+       struct omap2_onenand *c = dev_get_drvdata(&pdev->dev);
+
+       BUG_ON(c == NULL);
+
+#ifdef CONFIG_MTD_PARTITIONS
+       if (c->parts)
+               del_mtd_partitions(&c->mtd);
+       else
+               del_mtd_device(&c->mtd);
+#else
+       del_mtd_device(&c->mtd);
+#endif
+
+       onenand_release(&c->mtd);
+       if (c->dma_channel != -1)
+               omap_free_dma(c->dma_channel);
+       omap2_onenand_shutdown(pdev);
+       platform_set_drvdata(pdev, NULL);
+       if (c->gpio_irq) {
+               free_irq(OMAP_GPIO_IRQ(c->gpio_irq), c);
+               omap_free_gpio(c->gpio_irq);
+       }
+       iounmap(c->onenand.base);
+       release_mem_region(c->phys_base, ONENAND_IO_SIZE);
+       kfree(c);
+
+       return 0;
+}
+
+static struct platform_driver omap2_onenand_driver = {
+       .probe          = omap2_onenand_probe,
+       .remove         = omap2_onenand_remove,
+       .shutdown       = omap2_onenand_shutdown,
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init omap2_onenand_init(void)
+{
+       printk(KERN_INFO "OneNAND driver initializing\n");
+       return platform_driver_register(&omap2_onenand_driver);
+}
+
+static void __exit omap2_onenand_exit(void)
+{
+       platform_driver_unregister(&omap2_onenand_driver);
+}
+
+module_init(omap2_onenand_init);
+module_exit(omap2_onenand_exit);
+
+MODULE_ALIAS(DRIVER_NAME);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
+MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP2 / OMAP3");
index 926cf3a4135d1ca84094c40d018803709d059334..90ed319f26e6843c98d26dafba79762b2fd4abbc 100644 (file)
@@ -1794,7 +1794,7 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr)
                return -EINVAL;
        }
 
-       instr->fail_addr = 0xffffffff;
+       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 
        /* Grab the lock and see if the device is available */
        onenand_get_device(mtd, FL_ERASING);
index a5f3d60047d47f50da60ce7b8569ef326542173d..33a5d6ed6f18aa66181feb4ac84774343e68d5d3 100644 (file)
@@ -321,8 +321,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        DEBUG(MTD_DEBUG_LEVEL1,
                "SSFDC_RO: cis_block=%d,erase_size=%d,map_len=%d,n_zones=%d\n",
                ssfdc->cis_block, ssfdc->erase_size, ssfdc->map_len,
-               (ssfdc->map_len + MAX_PHYS_BLK_PER_ZONE - 1) /
-               MAX_PHYS_BLK_PER_ZONE);
+               DIV_ROUND_UP(ssfdc->map_len, MAX_PHYS_BLK_PER_ZONE));
 
        /* Set geometry */
        ssfdc->heads = 16;
index 03c759b4eeb5e852b192794f242020bc45792c22..b30a0b83d7f193ab5cf29ad20cbd7c7e44669f22 100644 (file)
@@ -104,12 +104,9 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
        struct ubi_volume_desc *desc;
        int vol_id = iminor(inode) - 1, mode, ubi_num;
 
-       lock_kernel();
        ubi_num = ubi_major2num(imajor(inode));
-       if (ubi_num < 0) {
-               unlock_kernel();
+       if (ubi_num < 0)
                return ubi_num;
-       }
 
        if (file->f_mode & FMODE_WRITE)
                mode = UBI_READWRITE;
@@ -119,7 +116,6 @@ static int vol_cdev_open(struct inode *inode, struct file *file)
        dbg_gen("open volume %d, mode %d", vol_id, mode);
 
        desc = ubi_open_volume(ubi_num, vol_id, mode);
-       unlock_kernel();
        if (IS_ERR(desc))
                return PTR_ERR(desc);
 
index 967bb4406df9e01c48aa5e5e0ff71a514558412d..4f2daa5bbecfbafe646da17a586cacd3328b5d07 100644 (file)
@@ -387,7 +387,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
                pnum, vol_id, lnum, ec, sqnum, bitflips);
 
        sv = add_volume(si, vol_id, pnum, vid_hdr);
-       if (IS_ERR(sv) < 0)
+       if (IS_ERR(sv))
                return PTR_ERR(sv);
 
        if (si->max_sqnum < sqnum)
index 217d0e111b2a4652212f563cb9baf5255f2bbdca..333c8941552fbe3067be1a9a40fd3c0f704386ad 100644 (file)
@@ -244,8 +244,8 @@ static int vtbl_check(const struct ubi_device *ubi,
                }
 
                if (reserved_pebs > ubi->good_peb_count) {
-                       dbg_err("too large reserved_pebs, good PEBs %d",
-                               ubi->good_peb_count);
+                       dbg_err("too large reserved_pebs %d, good PEBs %d",
+                               reserved_pebs, ubi->good_peb_count);
                        err = 9;
                        goto bad;
                }
index b39d1cc1ef04b022537ded766f1490bdcb83a342..a24bb68887ab24eb399137d8d6cf45366fa2b704 100644 (file)
@@ -1205,11 +1205,12 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
                devno = 0;
 
        ndev->dma = -1;
-       ndev->irq = platform_get_irq(pdev, 0);
-       if (ndev->irq < 0) {
+       ret = platform_get_irq(pdev, 0);
+       if (ret < 0) {
                ret = -ENODEV;
                goto out_release;
        }
+       ndev->irq = ret;
 
        SET_NETDEV_DEV(ndev, &pdev->dev);
 
index fc5f2dbf532383b637258a3aec52024654d6693e..8b51e10b7783d589b1d7893bb6febd052b3ee23b 100644 (file)
@@ -563,7 +563,7 @@ static int __iommu_flush_context(struct intel_iommu *iommu,
 
        spin_unlock_irqrestore(&iommu->register_lock, flag);
 
-       /* flush context entry will implictly flush write buffer */
+       /* flush context entry will implicitly flush write buffer */
        return 0;
 }
 
@@ -656,7 +656,7 @@ static int __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
        if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
                pr_debug("IOMMU: tlb flush request %Lx, actual %Lx\n",
                        DMA_TLB_IIRG(type), DMA_TLB_IAIG(val));
-       /* flush context entry will implictly flush write buffer */
+       /* flush iotlb entry will implicitly flush write buffer */
        return 0;
 }
 
index c9884bba22decf5a34926caa7d05a81b06a8bd90..dbe9f39f44363b3eb50d9cc7bcac0a50bd701315 100644 (file)
@@ -1358,11 +1358,10 @@ int pci_request_region(struct pci_dev *pdev, int bar, const char *res_name)
        return 0;
 
 err_out:
-       dev_warn(&pdev->dev, "BAR %d: can't reserve %s region [%#llx-%#llx]\n",
+       dev_warn(&pdev->dev, "BAR %d: can't reserve %s region %pR\n",
                 bar,
                 pci_resource_flags(pdev, bar) & IORESOURCE_IO ? "I/O" : "mem",
-                (unsigned long long)pci_resource_start(pdev, bar),
-                (unsigned long long)pci_resource_end(pdev, bar));
+                &pdev->resource[bar]);
        return -EBUSY;
 }
 
index dd9161a054e1c1264891a918a634d5a60fa0d062..d3db8b24972995750eef5043b2ca700e779dedeb 100644 (file)
@@ -304,9 +304,8 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                } else {
                        res->start = l64;
                        res->end = l64 + sz64;
-                       printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: [%llx, %llx]\n",
-                               pci_name(dev), pos, (unsigned long long)res->start,
-                               (unsigned long long)res->end);
+                       printk(KERN_DEBUG "PCI: %s reg %x 64bit mmio: %pR\n",
+                               pci_name(dev), pos, res);
                }
        } else {
                sz = pci_size(l, sz, mask);
@@ -316,9 +315,10 @@ static int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
 
                res->start = l;
                res->end = l + sz;
-               printk(KERN_DEBUG "PCI: %s reg %x %s: [%llx, %llx]\n", pci_name(dev),
-                       pos, (res->flags & IORESOURCE_IO) ? "io port":"32bit mmio",
-                       (unsigned long long)res->start, (unsigned long long)res->end);
+               printk(KERN_DEBUG "PCI: %s reg %x %s: %pR\n",
+                      pci_name(dev), pos,
+                      (res->flags & IORESOURCE_IO) ? "io port":"32bit mmio",
+                      res);
        }
 
  out:
@@ -389,9 +389,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
                        res->start = base;
                if (!res->end)
                        res->end = limit + 0xfff;
-               printk(KERN_DEBUG "PCI: bridge %s io port: [%llx, %llx]\n",
-                       pci_name(dev), (unsigned long long) res->start,
-                       (unsigned long long) res->end);
+               printk(KERN_DEBUG "PCI: bridge %s io port: %pR\n",
+                      pci_name(dev), res);
        }
 
        res = child->resource[1];
@@ -403,9 +402,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
                res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM;
                res->start = base;
                res->end = limit + 0xfffff;
-               printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: [%llx, %llx]\n",
-                       pci_name(dev), (unsigned long long) res->start,
-                       (unsigned long long) res->end);
+               printk(KERN_DEBUG "PCI: bridge %s 32bit mmio: %pR\n",
+                      pci_name(dev), res);
        }
 
        res = child->resource[2];
@@ -441,9 +439,9 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
                res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH;
                res->start = base;
                res->end = limit + 0xfffff;
-               printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n",
-                       pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64" : "32",
-                       (unsigned long long) res->start, (unsigned long long) res->end);
+               printk(KERN_DEBUG "PCI: bridge %s %sbit mmio pref: %pR\n",
+                      pci_name(dev),
+                      (res->flags & PCI_PREF_RANGE_TYPE_64) ? "64":"32", res);
        }
 }
 
index bd5c0e031398e9b50404380076b69c0c25889c71..1f5f6143f35cdcb8fe7777d72409eb3ed8ba6395 100644 (file)
@@ -21,7 +21,7 @@
  * between the ROM and other resources, so enabling it may disable access
  * to MMIO registers or other card memory.
  */
-static int pci_enable_rom(struct pci_dev *pdev)
+int pci_enable_rom(struct pci_dev *pdev)
 {
        struct resource *res = pdev->resource + PCI_ROM_RESOURCE;
        struct pci_bus_region region;
@@ -45,7 +45,7 @@ static int pci_enable_rom(struct pci_dev *pdev)
  * Disable ROM decoding on a PCI device by turning off the last bit in the
  * ROM BAR.
  */
-static void pci_disable_rom(struct pci_dev *pdev)
+void pci_disable_rom(struct pci_dev *pdev)
 {
        u32 rom_addr;
        pci_read_config_dword(pdev, pdev->rom_base_reg, &rom_addr);
@@ -260,3 +260,5 @@ void pci_cleanup_rom(struct pci_dev *pdev)
 
 EXPORT_SYMBOL(pci_map_rom);
 EXPORT_SYMBOL(pci_unmap_rom);
+EXPORT_SYMBOL_GPL(pci_enable_rom);
+EXPORT_SYMBOL_GPL(pci_disable_rom);
index d5e2106760f81743267dd85169553c4158c1373b..471a429d7a20fec7b116537ed5e90c912da8b7b7 100644 (file)
@@ -356,10 +356,7 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, unsigned long
                        order = __ffs(align) - 20;
                        if (order > 11) {
                                dev_warn(&dev->dev, "BAR %d bad alignment %llx: "
-                                      "%#016llx-%#016llx\n", i,
-                                      (unsigned long long)align,
-                                      (unsigned long long)r->start,
-                                      (unsigned long long)r->end);
+                                        "%pR\n", i, (unsigned long long)align, r);
                                r->flags = 0;
                                continue;
                        }
@@ -539,11 +536,9 @@ static void pci_bus_dump_res(struct pci_bus *bus)
                 if (!res)
                         continue;
 
-               printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n",
-                       bus->number, i,
-                       (res->flags & IORESOURCE_IO) ? "io port" : "mmio",
-                       (unsigned long long) res->start,
-                       (unsigned long long) res->end);
+               printk(KERN_INFO "bus: %02x index %x %s: %pR\n",
+                      bus->number, i,
+                      (res->flags & IORESOURCE_IO) ? "io port" : "mmio", res);
         }
 }
 
index 1a5fc83c71b36fec69fe45a30006a27db9bc1300..d4b5c690eaa776112c46cc8f9ca993a49e233d50 100644 (file)
@@ -49,10 +49,8 @@ void pci_update_resource(struct pci_dev *dev, struct resource *res, int resno)
 
        pcibios_resource_to_bus(dev, &region, res);
 
-       dev_dbg(&dev->dev, "BAR %d: got res [%#llx-%#llx] bus [%#llx-%#llx] "
-               "flags %#lx\n", resno,
-                (unsigned long long)res->start,
-                (unsigned long long)res->end,
+       dev_dbg(&dev->dev, "BAR %d: got res %pR bus [%#llx-%#llx] "
+               "flags %#lx\n", resno, res,
                 (unsigned long long)region.start,
                 (unsigned long long)region.end,
                 (unsigned long)res->flags);
@@ -114,13 +112,11 @@ int pci_claim_resource(struct pci_dev *dev, int resource)
                err = insert_resource(root, res);
 
        if (err) {
-               dev_err(&dev->dev, "BAR %d: %s of %s [%#llx-%#llx]\n",
+               dev_err(&dev->dev, "BAR %d: %s of %s %pR\n",
                        resource,
                        root ? "address space collision on" :
                                "no parent found for",
-                       dtype,
-                       (unsigned long long)res->start,
-                       (unsigned long long)res->end);
+                       dtype, res);
        }
 
        return err;
@@ -139,9 +135,8 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        align = resource_alignment(res);
        if (!align) {
                dev_err(&dev->dev, "BAR %d: can't allocate resource (bogus "
-                       "alignment) [%#llx-%#llx] flags %#lx\n",
-                       resno, (unsigned long long)res->start,
-                       (unsigned long long)res->end, res->flags);
+                       "alignment) %pR flags %#lx\n",
+                       resno, res, res->flags);
                return -EINVAL;
        }
 
@@ -162,11 +157,8 @@ int pci_assign_resource(struct pci_dev *dev, int resno)
        }
 
        if (ret) {
-               dev_err(&dev->dev, "BAR %d: can't allocate %s resource "
-                       "[%#llx-%#llx]\n", resno,
-                       res->flags & IORESOURCE_IO ? "I/O" : "mem",
-                       (unsigned long long)res->start,
-                       (unsigned long long)res->end);
+               dev_err(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
+                       resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
        } else {
                res->flags &= ~IORESOURCE_STARTALIGN;
                if (resno < PCI_BRIDGE_RESOURCES)
@@ -202,11 +194,8 @@ int pci_assign_resource_fixed(struct pci_dev *dev, int resno)
        }
 
        if (ret) {
-               dev_err(&dev->dev, "BAR %d: can't allocate %s resource "
-                       "[%#llx-%#llx\n]", resno,
-                       res->flags & IORESOURCE_IO ? "I/O" : "mem",
-                       (unsigned long long)res->start,
-                       (unsigned long long)res->end);
+               dev_err(&dev->dev, "BAR %d: can't allocate %s resource %pR\n",
+                       resno, res->flags & IORESOURCE_IO ? "I/O" : "mem", res);
        } else if (resno < PCI_BRIDGE_RESOURCES) {
                pci_update_resource(dev, res, resno);
        }
@@ -237,9 +226,8 @@ void pdev_sort_resources(struct pci_dev *dev, struct resource_list *head)
                r_align = resource_alignment(r);
                if (!r_align) {
                        dev_warn(&dev->dev, "BAR %d: bogus alignment "
-                               "[%#llx-%#llx] flags %#lx\n",
-                               i, (unsigned long long)r->start,
-                               (unsigned long long)r->end, r->flags);
+                               "%pR flags %#lx\n",
+                               i, r, r->flags);
                        continue;
                }
                for (list = head; ; list = list->next) {
@@ -287,9 +275,7 @@ int pci_enable_resources(struct pci_dev *dev, int mask)
 
                if (!r->parent) {
                        dev_err(&dev->dev, "device not available because of "
-                               "BAR %d [%#llx-%#llx] collisions\n", i,
-                               (unsigned long long) r->start,
-                               (unsigned long long) r->end);
+                               "BAR %d %pR collisions\n", i, r);
                        return -EINVAL;
                }
 
index fe2aeb11939b3d9a327167e3d162043a6c0f9914..23ae8460f5c1a71f7b794745837799ac1fc21f25 100644 (file)
@@ -30,7 +30,7 @@
 
 #define POWER_SUPPLY_ATTR(_name)                                       \
 {                                                                      \
-       .attr = { .name = #_name, .mode = 0444, .owner = THIS_MODULE }, \
+       .attr = { .name = #_name, .mode = 0444 },       \
        .show = power_supply_show_property,                             \
        .store = NULL,                                                  \
 }
index 6f2f90ebb020db95256f2bc135414ada5ca77d83..06848b254d5752d3a5d40ad2a68b8c4bb686b01e 100644 (file)
@@ -915,6 +915,22 @@ int ps3av_video_mute(int mute)
 
 EXPORT_SYMBOL_GPL(ps3av_video_mute);
 
+/* mute analog output only */
+int ps3av_audio_mute_analog(int mute)
+{
+       int i, res;
+
+       for (i = 0; i < ps3av->av_hw_conf.num_of_avmulti; i++) {
+               res = ps3av_cmd_av_audio_mute(1,
+                       &ps3av->av_port[i + ps3av->av_hw_conf.num_of_hdmi],
+                       mute);
+               if (res < 0)
+                       return -1;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(ps3av_audio_mute_analog);
+
 int ps3av_audio_mute(int mute)
 {
        return ps3av_set_audio_mute(mute ? PS3AV_CMD_MUTE_ON
index 7f880c26122f36a11b7390a14587693f10898229..11eb50318fec9ce093e6b9ef99e6fd858c4ead20 100644 (file)
@@ -660,9 +660,10 @@ u32 ps3av_cmd_set_av_audio_param(void *p, u32 port,
 }
 
 /* default cs val */
-static const u8 ps3av_mode_cs_info[] = {
+u8 ps3av_mode_cs_info[] = {
        0x00, 0x09, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00
 };
+EXPORT_SYMBOL_GPL(ps3av_mode_cs_info);
 
 #define CS_44  0x00
 #define CS_48  0x02
@@ -677,7 +678,7 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
                              u32 ch, u32 fs, u32 word_bits, u32 format,
                              u32 source)
 {
-       int spdif_through, spdif_bitstream;
+       int spdif_through;
        int i;
 
        if (!(ch | fs | format | word_bits | source)) {
@@ -687,7 +688,6 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
                format = PS3AV_CMD_AUDIO_FORMAT_PCM;
                source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
        }
-       spdif_through = spdif_bitstream = 0;    /* XXX not supported */
 
        /* audio mode */
        memset(audio, 0, sizeof(*audio));
@@ -777,16 +777,17 @@ void ps3av_cmd_set_audio_mode(struct ps3av_pkt_audio_mode *audio, u32 avport,
                break;
        }
 
+       /* non-audio bit */
+       spdif_through = audio->audio_cs_info[0] & 0x02;
+
        /* pass through setting */
        if (spdif_through &&
            (avport == PS3AV_CMD_AVPORT_SPDIF_0 ||
-            avport == PS3AV_CMD_AVPORT_SPDIF_1)) {
+            avport == PS3AV_CMD_AVPORT_SPDIF_1 ||
+            avport == PS3AV_CMD_AVPORT_HDMI_0 ||
+            avport == PS3AV_CMD_AVPORT_HDMI_1)) {
                audio->audio_word_bits = PS3AV_CMD_AUDIO_WORD_BITS_16;
-               audio->audio_source = PS3AV_CMD_AUDIO_SOURCE_SPDIF;
-               if (spdif_bitstream) {
-                       audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
-                       audio->audio_cs_info[0] |= CS_BIT;
-               }
+               audio->audio_format = PS3AV_CMD_AUDIO_FORMAT_BITSTREAM;
        }
 }
 
index 37082616482bd7a79ad3162ba00ca82bd260894e..b5bf937069134937d064306b92e8e885948feaf0 100644 (file)
@@ -53,21 +53,21 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
        } while ((time != at91_sys_read(timereg)) ||
                        (date != at91_sys_read(calreg)));
 
-       tm->tm_sec  = BCD2BIN((time & AT91_RTC_SEC) >> 0);
-       tm->tm_min  = BCD2BIN((time & AT91_RTC_MIN) >> 8);
-       tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16);
+       tm->tm_sec  = bcd2bin((time & AT91_RTC_SEC) >> 0);
+       tm->tm_min  = bcd2bin((time & AT91_RTC_MIN) >> 8);
+       tm->tm_hour = bcd2bin((time & AT91_RTC_HOUR) >> 16);
 
        /*
         * The Calendar Alarm register does not have a field for
         * the year - so these will return an invalid value.  When an
         * alarm is set, at91_alarm_year wille store the current year.
         */
-       tm->tm_year  = BCD2BIN(date & AT91_RTC_CENT) * 100;     /* century */
-       tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8);    /* year */
+       tm->tm_year  = bcd2bin(date & AT91_RTC_CENT) * 100;     /* century */
+       tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8);    /* year */
 
-       tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
-       tm->tm_mon  = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1;
-       tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24);
+       tm->tm_wday = bcd2bin((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
+       tm->tm_mon  = bcd2bin((date & AT91_RTC_MONTH) >> 16) - 1;
+       tm->tm_mday = bcd2bin((date & AT91_RTC_DATE) >> 24);
 }
 
 /*
@@ -106,16 +106,16 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
        at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
 
        at91_sys_write(AT91_RTC_TIMR,
-                         BIN2BCD(tm->tm_sec) << 0
-                       | BIN2BCD(tm->tm_min) << 8
-                       | BIN2BCD(tm->tm_hour) << 16);
+                         bin2bcd(tm->tm_sec) << 0
+                       | bin2bcd(tm->tm_min) << 8
+                       | bin2bcd(tm->tm_hour) << 16);
 
        at91_sys_write(AT91_RTC_CALR,
-                         BIN2BCD((tm->tm_year + 1900) / 100)   /* century */
-                       | BIN2BCD(tm->tm_year % 100) << 8       /* year */
-                       | BIN2BCD(tm->tm_mon + 1) << 16         /* tm_mon starts at zero */
-                       | BIN2BCD(tm->tm_wday + 1) << 21        /* day of the week [0-6], Sunday=0 */
-                       | BIN2BCD(tm->tm_mday) << 24);
+                         bin2bcd((tm->tm_year + 1900) / 100)   /* century */
+                       | bin2bcd(tm->tm_year % 100) << 8       /* year */
+                       | bin2bcd(tm->tm_mon + 1) << 16         /* tm_mon starts at zero */
+                       | bin2bcd(tm->tm_wday + 1) << 21        /* day of the week [0-6], Sunday=0 */
+                       | bin2bcd(tm->tm_mday) << 24);
 
        /* Restart Time/Calendar */
        cr = at91_sys_read(AT91_RTC_CR);
@@ -162,13 +162,13 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
        at91_sys_write(AT91_RTC_TIMALR,
-                 BIN2BCD(tm.tm_sec) << 0
-               | BIN2BCD(tm.tm_min) << 8
-               | BIN2BCD(tm.tm_hour) << 16
+                 bin2bcd(tm.tm_sec) << 0
+               | bin2bcd(tm.tm_min) << 8
+               | bin2bcd(tm.tm_hour) << 16
                | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
        at91_sys_write(AT91_RTC_CALALR,
-                 BIN2BCD(tm.tm_mon + 1) << 16          /* tm_mon starts at zero */
-               | BIN2BCD(tm.tm_mday) << 24
+                 bin2bcd(tm.tm_mon + 1) << 16          /* tm_mon starts at zero */
+               | bin2bcd(tm.tm_mday) << 24
                | AT91_RTC_DATEEN | AT91_RTC_MTHEN);
 
        if (alrm->enabled) {
index 189a018bdf34ac2a731c11b86f06cb897194e9ba..d00a274df8fcedf76d00d52d668493e9e9e068cf 100644 (file)
@@ -71,14 +71,14 @@ static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
 
        spin_unlock_irqrestore(&p->lock, flags);
 
-       BCD_TO_BIN(tm->tm_sec);
-       BCD_TO_BIN(tm->tm_min);
-       BCD_TO_BIN(tm->tm_hour);
-       BCD_TO_BIN(tm->tm_mday);
-       BCD_TO_BIN(tm->tm_mon);
-       BCD_TO_BIN(tm->tm_year);
-       BCD_TO_BIN(tm->tm_wday);
-       BCD_TO_BIN(century);
+       tm->tm_sec = bcd2bin(tm->tm_sec);
+       tm->tm_min = bcd2bin(tm->tm_min);
+       tm->tm_hour = bcd2bin(tm->tm_hour);
+       tm->tm_mday = bcd2bin(tm->tm_mday);
+       tm->tm_mon = bcd2bin(tm->tm_mon);
+       tm->tm_year = bcd2bin(tm->tm_year);
+       tm->tm_wday = bcd2bin(tm->tm_wday);
+       century = bcd2bin(century);
 
        tm->tm_year += (century * 100);
        tm->tm_year -= 1900;
@@ -106,13 +106,13 @@ static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
        min = tm->tm_min;
        sec = tm->tm_sec;
 
-       BIN_TO_BCD(sec);
-       BIN_TO_BCD(min);
-       BIN_TO_BCD(hrs);
-       BIN_TO_BCD(day);
-       BIN_TO_BCD(mon);
-       BIN_TO_BCD(yrs);
-       BIN_TO_BCD(century);
+       sec = bin2bcd(sec);
+       min = bin2bcd(min);
+       hrs = bin2bcd(hrs);
+       day = bin2bcd(day);
+       mon = bin2bcd(mon);
+       yrs = bin2bcd(yrs);
+       century = bin2bcd(century);
 
        spin_lock_irqsave(&p->lock, flags);
 
index 963ad0b6a4e9da64ff911cba52508e5c39b8085a..5549231179a2dacb955357e69cd6b521d5e7954f 100644 (file)
@@ -143,6 +143,43 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler)
 
 /*----------------------------------------------------------------*/
 
+#ifdef RTC_PORT
+
+/* Most newer x86 systems have two register banks, the first used
+ * for RTC and NVRAM and the second only for NVRAM.  Caller must
+ * own rtc_lock ... and we won't worry about access during NMI.
+ */
+#define can_bank2      true
+
+static inline unsigned char cmos_read_bank2(unsigned char addr)
+{
+       outb(addr, RTC_PORT(2));
+       return inb(RTC_PORT(3));
+}
+
+static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
+{
+       outb(addr, RTC_PORT(2));
+       outb(val, RTC_PORT(2));
+}
+
+#else
+
+#define can_bank2      false
+
+static inline unsigned char cmos_read_bank2(unsigned char addr)
+{
+       return 0;
+}
+
+static inline void cmos_write_bank2(unsigned char val, unsigned char addr)
+{
+}
+
+#endif
+
+/*----------------------------------------------------------------*/
+
 static int cmos_read_time(struct device *dev, struct rtc_time *t)
 {
        /* REVISIT:  if the clock has a "century" register, use
@@ -203,26 +240,26 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        /* REVISIT this assumes PC style usage:  always BCD */
 
        if (((unsigned)t->time.tm_sec) < 0x60)
-               t->time.tm_sec = BCD2BIN(t->time.tm_sec);
+               t->time.tm_sec = bcd2bin(t->time.tm_sec);
        else
                t->time.tm_sec = -1;
        if (((unsigned)t->time.tm_min) < 0x60)
-               t->time.tm_min = BCD2BIN(t->time.tm_min);
+               t->time.tm_min = bcd2bin(t->time.tm_min);
        else
                t->time.tm_min = -1;
        if (((unsigned)t->time.tm_hour) < 0x24)
-               t->time.tm_hour = BCD2BIN(t->time.tm_hour);
+               t->time.tm_hour = bcd2bin(t->time.tm_hour);
        else
                t->time.tm_hour = -1;
 
        if (cmos->day_alrm) {
                if (((unsigned)t->time.tm_mday) <= 0x31)
-                       t->time.tm_mday = BCD2BIN(t->time.tm_mday);
+                       t->time.tm_mday = bcd2bin(t->time.tm_mday);
                else
                        t->time.tm_mday = -1;
                if (cmos->mon_alrm) {
                        if (((unsigned)t->time.tm_mon) <= 0x12)
-                               t->time.tm_mon = BCD2BIN(t->time.tm_mon) - 1;
+                               t->time.tm_mon = bcd2bin(t->time.tm_mon) - 1;
                        else
                                t->time.tm_mon = -1;
                }
@@ -294,19 +331,19 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        /* Writing 0xff means "don't care" or "match all".  */
 
        mon = t->time.tm_mon + 1;
-       mon = (mon <= 12) ? BIN2BCD(mon) : 0xff;
+       mon = (mon <= 12) ? bin2bcd(mon) : 0xff;
 
        mday = t->time.tm_mday;
-       mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+       mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
 
        hrs = t->time.tm_hour;
-       hrs = (hrs < 24) ? BIN2BCD(hrs) : 0xff;
+       hrs = (hrs < 24) ? bin2bcd(hrs) : 0xff;
 
        min = t->time.tm_min;
-       min = (min < 60) ? BIN2BCD(min) : 0xff;
+       min = (min < 60) ? bin2bcd(min) : 0xff;
 
        sec = t->time.tm_sec;
-       sec = (sec < 60) ? BIN2BCD(sec) : 0xff;
+       sec = (sec < 60) ? bin2bcd(sec) : 0xff;
 
        spin_lock_irq(&rtc_lock);
 
@@ -491,12 +528,21 @@ cmos_nvram_read(struct kobject *kobj, struct bin_attribute *attr,
 
        if (unlikely(off >= attr->size))
                return 0;
+       if (unlikely(off < 0))
+               return -EINVAL;
        if ((off + count) > attr->size)
                count = attr->size - off;
 
+       off += NVRAM_OFFSET;
        spin_lock_irq(&rtc_lock);
-       for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++)
-               *buf++ = CMOS_READ(off);
+       for (retval = 0; count; count--, off++, retval++) {
+               if (off < 128)
+                       *buf++ = CMOS_READ(off);
+               else if (can_bank2)
+                       *buf++ = cmos_read_bank2(off);
+               else
+                       break;
+       }
        spin_unlock_irq(&rtc_lock);
 
        return retval;
@@ -512,6 +558,8 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
        cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
        if (unlikely(off >= attr->size))
                return -EFBIG;
+       if (unlikely(off < 0))
+               return -EINVAL;
        if ((off + count) > attr->size)
                count = attr->size - off;
 
@@ -520,15 +568,20 @@ cmos_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
         * here.  If userspace is smart enough to know what fields of
         * NVRAM to update, updating checksums is also part of its job.
         */
+       off += NVRAM_OFFSET;
        spin_lock_irq(&rtc_lock);
-       for (retval = 0, off += NVRAM_OFFSET; count--; retval++, off++) {
+       for (retval = 0; count; count--, off++, retval++) {
                /* don't trash RTC registers */
                if (off == cmos->day_alrm
                                || off == cmos->mon_alrm
                                || off == cmos->century)
                        buf++;
-               else
+               else if (off < 128)
                        CMOS_WRITE(*buf++, off);
+               else if (can_bank2)
+                       cmos_write_bank2(*buf++, off);
+               else
+                       break;
        }
        spin_unlock_irq(&rtc_lock);
 
@@ -539,7 +592,6 @@ static struct bin_attribute nvram = {
        .attr = {
                .name   = "nvram",
                .mode   = S_IRUGO | S_IWUSR,
-               .owner  = THIS_MODULE,
        },
 
        .read   = cmos_nvram_read,
@@ -631,8 +683,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
 
        /* Heuristic to deduce NVRAM size ... do what the legacy NVRAM
         * driver did, but don't reject unknown configs.   Old hardware
-        * won't address 128 bytes, and for now we ignore the way newer
-        * chips can address 256 bytes (using two more i/o ports).
+        * won't address 128 bytes.  Newer chips have multiple banks,
+        * though they may not be listed in one I/O resource.
         */
 #if    defined(CONFIG_ATARI)
        address_space = 64;
@@ -642,6 +694,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
 #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes.
        address_space = 128;
 #endif
+       if (can_bank2 && ports->end > (ports->start + 1))
+               address_space = 256;
 
        /* For ACPI systems extension info comes from the FADT.  On others,
         * board specific setup provides it as appropriate.  Systems where
@@ -740,7 +794,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
                goto cleanup2;
        }
 
-       pr_info("%s: alarms up to one %s%s%s\n",
+       pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n",
                        cmos_rtc.rtc->dev.bus_id,
                        is_valid_irq(rtc_irq)
                                ?  (cmos_rtc.mon_alrm
@@ -749,6 +803,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
                                                ? "month" : "day"))
                                : "no",
                        cmos_rtc.century ? ", y3k" : "",
+                       nvram.size,
                        is_hpet_enabled() ? ", hpet irqs" : "");
 
        return 0;
index 0b17770b032be69eb27d3e86f2621cd752ebdcb1..9a234a4ec06dbdf0a964acae4bc6a58be3588871 100644 (file)
@@ -86,19 +86,19 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
        ds1216_switch_ds_to_clock(priv->ioaddr);
        ds1216_read(priv->ioaddr, (u8 *)&regs);
 
-       tm->tm_sec = BCD2BIN(regs.sec);
-       tm->tm_min = BCD2BIN(regs.min);
+       tm->tm_sec = bcd2bin(regs.sec);
+       tm->tm_min = bcd2bin(regs.min);
        if (regs.hour & DS1216_HOUR_1224) {
                /* AM/PM mode */
-               tm->tm_hour = BCD2BIN(regs.hour & 0x1f);
+               tm->tm_hour = bcd2bin(regs.hour & 0x1f);
                if (regs.hour & DS1216_HOUR_AMPM)
                        tm->tm_hour += 12;
        } else
-               tm->tm_hour = BCD2BIN(regs.hour & 0x3f);
+               tm->tm_hour = bcd2bin(regs.hour & 0x3f);
        tm->tm_wday = (regs.wday & 7) - 1;
-       tm->tm_mday = BCD2BIN(regs.mday & 0x3f);
-       tm->tm_mon = BCD2BIN(regs.month & 0x1f);
-       tm->tm_year = BCD2BIN(regs.year);
+       tm->tm_mday = bcd2bin(regs.mday & 0x3f);
+       tm->tm_mon = bcd2bin(regs.month & 0x1f);
+       tm->tm_year = bcd2bin(regs.year);
        if (tm->tm_year < 70)
                tm->tm_year += 100;
        return 0;
@@ -114,19 +114,19 @@ static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
        ds1216_read(priv->ioaddr, (u8 *)&regs);
 
        regs.tsec = 0; /* clear 0.1 and 0.01 seconds */
-       regs.sec = BIN2BCD(tm->tm_sec);
-       regs.min = BIN2BCD(tm->tm_min);
+       regs.sec = bin2bcd(tm->tm_sec);
+       regs.min = bin2bcd(tm->tm_min);
        regs.hour &= DS1216_HOUR_1224;
        if (regs.hour && tm->tm_hour > 12) {
                regs.hour |= DS1216_HOUR_AMPM;
                tm->tm_hour -= 12;
        }
-       regs.hour |= BIN2BCD(tm->tm_hour);
+       regs.hour |= bin2bcd(tm->tm_hour);
        regs.wday &= ~7;
        regs.wday |= tm->tm_wday;
-       regs.mday = BIN2BCD(tm->tm_mday);
-       regs.month = BIN2BCD(tm->tm_mon);
-       regs.year = BIN2BCD(tm->tm_year % 100);
+       regs.mday = bin2bcd(tm->tm_mday);
+       regs.month = bin2bcd(tm->tm_mon);
+       regs.year = bin2bcd(tm->tm_year % 100);
 
        ds1216_switch_ds_to_clock(priv->ioaddr);
        ds1216_write(priv->ioaddr, (u8 *)&regs);
index b9397818f73a6fd22b118a5643fd768a15b4d5ee..184556620778c5da5f8ec45dc3144d3b611a47ca 100644 (file)
@@ -40,7 +40,7 @@
 #define        RTC_SCLK        0x0400
 
 #ifdef CONFIG_SH_SECUREEDGE5410
-#include <asm/snapgear.h>
+#include <mach/snapgear.h>
 #define set_dp(x)      SECUREEDGE_WRITE_IOPORT(x, 0x1c00)
 #define get_dp()       SECUREEDGE_READ_IOPORT()
 #else
@@ -107,13 +107,13 @@ static int ds1302_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
        spin_lock_irq(&rtc->lock);
 
-       tm->tm_sec      = BCD2BIN(ds1302_readbyte(RTC_ADDR_SEC));
-       tm->tm_min      = BCD2BIN(ds1302_readbyte(RTC_ADDR_MIN));
-       tm->tm_hour     = BCD2BIN(ds1302_readbyte(RTC_ADDR_HOUR));
-       tm->tm_wday     = BCD2BIN(ds1302_readbyte(RTC_ADDR_DAY));
-       tm->tm_mday     = BCD2BIN(ds1302_readbyte(RTC_ADDR_DATE));
-       tm->tm_mon      = BCD2BIN(ds1302_readbyte(RTC_ADDR_MON)) - 1;
-       tm->tm_year     = BCD2BIN(ds1302_readbyte(RTC_ADDR_YEAR));
+       tm->tm_sec      = bcd2bin(ds1302_readbyte(RTC_ADDR_SEC));
+       tm->tm_min      = bcd2bin(ds1302_readbyte(RTC_ADDR_MIN));
+       tm->tm_hour     = bcd2bin(ds1302_readbyte(RTC_ADDR_HOUR));
+       tm->tm_wday     = bcd2bin(ds1302_readbyte(RTC_ADDR_DAY));
+       tm->tm_mday     = bcd2bin(ds1302_readbyte(RTC_ADDR_DATE));
+       tm->tm_mon      = bcd2bin(ds1302_readbyte(RTC_ADDR_MON)) - 1;
+       tm->tm_year     = bcd2bin(ds1302_readbyte(RTC_ADDR_YEAR));
 
        if (tm->tm_year < 70)
                tm->tm_year += 100;
@@ -141,13 +141,13 @@ static int ds1302_rtc_set_time(struct device *dev, struct rtc_time *tm)
        /* Stop RTC */
        ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) | 0x80);
 
-       ds1302_writebyte(RTC_ADDR_SEC, BIN2BCD(tm->tm_sec));
-       ds1302_writebyte(RTC_ADDR_MIN, BIN2BCD(tm->tm_min));
-       ds1302_writebyte(RTC_ADDR_HOUR, BIN2BCD(tm->tm_hour));
-       ds1302_writebyte(RTC_ADDR_DAY, BIN2BCD(tm->tm_wday));
-       ds1302_writebyte(RTC_ADDR_DATE, BIN2BCD(tm->tm_mday));
-       ds1302_writebyte(RTC_ADDR_MON, BIN2BCD(tm->tm_mon + 1));
-       ds1302_writebyte(RTC_ADDR_YEAR, BIN2BCD(tm->tm_year % 100));
+       ds1302_writebyte(RTC_ADDR_SEC, bin2bcd(tm->tm_sec));
+       ds1302_writebyte(RTC_ADDR_MIN, bin2bcd(tm->tm_min));
+       ds1302_writebyte(RTC_ADDR_HOUR, bin2bcd(tm->tm_hour));
+       ds1302_writebyte(RTC_ADDR_DAY, bin2bcd(tm->tm_wday));
+       ds1302_writebyte(RTC_ADDR_DATE, bin2bcd(tm->tm_mday));
+       ds1302_writebyte(RTC_ADDR_MON, bin2bcd(tm->tm_mon + 1));
+       ds1302_writebyte(RTC_ADDR_YEAR, bin2bcd(tm->tm_year % 100));
 
        /* Start RTC */
        ds1302_writebyte(RTC_ADDR_SEC, ds1302_readbyte(RTC_ADDR_SEC) & ~0x80);
index b91d02a3ace9d89846c83a257294294d8df36b98..fc372df6534b5e93b3296913be692188cd5c1d41 100644 (file)
@@ -114,10 +114,10 @@ static unsigned bcd2hour(u8 bcd)
                        hour = 12;
                        bcd &= ~DS1305_HR_PM;
                }
-               hour += BCD2BIN(bcd);
+               hour += bcd2bin(bcd);
                return hour - 1;
        }
-       return BCD2BIN(bcd);
+       return bcd2bin(bcd);
 }
 
 static u8 hour2bcd(bool hr12, int hour)
@@ -125,11 +125,11 @@ static u8 hour2bcd(bool hr12, int hour)
        if (hr12) {
                hour++;
                if (hour <= 12)
-                       return DS1305_HR_12 | BIN2BCD(hour);
+                       return DS1305_HR_12 | bin2bcd(hour);
                hour -= 12;
-               return DS1305_HR_12 | DS1305_HR_PM | BIN2BCD(hour);
+               return DS1305_HR_12 | DS1305_HR_PM | bin2bcd(hour);
        }
-       return BIN2BCD(hour);
+       return bin2bcd(hour);
 }
 
 /*----------------------------------------------------------------------*/
@@ -206,13 +206,13 @@ static int ds1305_get_time(struct device *dev, struct rtc_time *time)
                buf[4], buf[5], buf[6]);
 
        /* Decode the registers */
-       time->tm_sec = BCD2BIN(buf[DS1305_SEC]);
-       time->tm_min = BCD2BIN(buf[DS1305_MIN]);
+       time->tm_sec = bcd2bin(buf[DS1305_SEC]);
+       time->tm_min = bcd2bin(buf[DS1305_MIN]);
        time->tm_hour = bcd2hour(buf[DS1305_HOUR]);
        time->tm_wday = buf[DS1305_WDAY] - 1;
-       time->tm_mday = BCD2BIN(buf[DS1305_MDAY]);
-       time->tm_mon = BCD2BIN(buf[DS1305_MON]) - 1;
-       time->tm_year = BCD2BIN(buf[DS1305_YEAR]) + 100;
+       time->tm_mday = bcd2bin(buf[DS1305_MDAY]);
+       time->tm_mon = bcd2bin(buf[DS1305_MON]) - 1;
+       time->tm_year = bcd2bin(buf[DS1305_YEAR]) + 100;
 
        dev_vdbg(dev, "%s secs=%d, mins=%d, "
                "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -239,13 +239,13 @@ static int ds1305_set_time(struct device *dev, struct rtc_time *time)
        /* Write registers starting at the first time/date address. */
        *bp++ = DS1305_WRITE | DS1305_SEC;
 
-       *bp++ = BIN2BCD(time->tm_sec);
-       *bp++ = BIN2BCD(time->tm_min);
+       *bp++ = bin2bcd(time->tm_sec);
+       *bp++ = bin2bcd(time->tm_min);
        *bp++ = hour2bcd(ds1305->hr12, time->tm_hour);
        *bp++ = (time->tm_wday < 7) ? (time->tm_wday + 1) : 1;
-       *bp++ = BIN2BCD(time->tm_mday);
-       *bp++ = BIN2BCD(time->tm_mon + 1);
-       *bp++ = BIN2BCD(time->tm_year - 100);
+       *bp++ = bin2bcd(time->tm_mday);
+       *bp++ = bin2bcd(time->tm_mon + 1);
+       *bp++ = bin2bcd(time->tm_year - 100);
 
        dev_dbg(dev, "%s: %02x %02x %02x, %02x %02x %02x %02x\n",
                "write", buf[1], buf[2], buf[3],
@@ -329,8 +329,8 @@ static int ds1305_get_alarm(struct device *dev, struct rtc_wkalrm *alm)
         * fill in the rest ... and also handle rollover to tomorrow when
         * that's needed.
         */
-       alm->time.tm_sec = BCD2BIN(buf[DS1305_SEC]);
-       alm->time.tm_min = BCD2BIN(buf[DS1305_MIN]);
+       alm->time.tm_sec = bcd2bin(buf[DS1305_SEC]);
+       alm->time.tm_min = bcd2bin(buf[DS1305_MIN]);
        alm->time.tm_hour = bcd2hour(buf[DS1305_HOUR]);
        alm->time.tm_mday = -1;
        alm->time.tm_mon = -1;
@@ -387,8 +387,8 @@ static int ds1305_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 
        /* write alarm */
        buf[0] = DS1305_WRITE | DS1305_ALM0(DS1305_SEC);
-       buf[1 + DS1305_SEC] = BIN2BCD(alm->time.tm_sec);
-       buf[1 + DS1305_MIN] = BIN2BCD(alm->time.tm_min);
+       buf[1 + DS1305_SEC] = bin2bcd(alm->time.tm_sec);
+       buf[1 + DS1305_MIN] = bin2bcd(alm->time.tm_min);
        buf[1 + DS1305_HOUR] = hour2bcd(ds1305->hr12, alm->time.tm_hour);
        buf[1 + DS1305_WDAY] = DS1305_ALM_DISABLE;
 
@@ -606,7 +606,6 @@ ds1305_nvram_write(struct kobject *kobj, struct bin_attribute *attr,
 static struct bin_attribute nvram = {
        .attr.name      = "nvram",
        .attr.mode      = S_IRUGO | S_IWUSR,
-       .attr.owner     = THIS_MODULE,
        .read           = ds1305_nvram_read,
        .write          = ds1305_nvram_write,
        .size           = DS1305_NVRAM_LEN,
index 4fcf0734a6ef088f5bf162de0f09341bac979349..162330b9d1dc0069ab94397e071d1d04e5c78865 100644 (file)
@@ -222,17 +222,17 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
                        ds1307->regs[4], ds1307->regs[5],
                        ds1307->regs[6]);
 
-       t->tm_sec = BCD2BIN(ds1307->regs[DS1307_REG_SECS] & 0x7f);
-       t->tm_min = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+       t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);
+       t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
        tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
-       t->tm_hour = BCD2BIN(tmp);
-       t->tm_wday = BCD2BIN(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
-       t->tm_mday = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+       t->tm_hour = bcd2bin(tmp);
+       t->tm_wday = bcd2bin(ds1307->regs[DS1307_REG_WDAY] & 0x07) - 1;
+       t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
        tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
-       t->tm_mon = BCD2BIN(tmp) - 1;
+       t->tm_mon = bcd2bin(tmp) - 1;
 
        /* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
-       t->tm_year = BCD2BIN(ds1307->regs[DS1307_REG_YEAR]) + 100;
+       t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100;
 
        dev_dbg(dev, "%s secs=%d, mins=%d, "
                "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -258,16 +258,16 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
                t->tm_mon, t->tm_year, t->tm_wday);
 
        *buf++ = 0;             /* first register addr */
-       buf[DS1307_REG_SECS] = BIN2BCD(t->tm_sec);
-       buf[DS1307_REG_MIN] = BIN2BCD(t->tm_min);
-       buf[DS1307_REG_HOUR] = BIN2BCD(t->tm_hour);
-       buf[DS1307_REG_WDAY] = BIN2BCD(t->tm_wday + 1);
-       buf[DS1307_REG_MDAY] = BIN2BCD(t->tm_mday);
-       buf[DS1307_REG_MONTH] = BIN2BCD(t->tm_mon + 1);
+       buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
+       buf[DS1307_REG_MIN] = bin2bcd(t->tm_min);
+       buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
+       buf[DS1307_REG_WDAY] = bin2bcd(t->tm_wday + 1);
+       buf[DS1307_REG_MDAY] = bin2bcd(t->tm_mday);
+       buf[DS1307_REG_MONTH] = bin2bcd(t->tm_mon + 1);
 
        /* assume 20YY not 19YY */
        tmp = t->tm_year - 100;
-       buf[DS1307_REG_YEAR] = BIN2BCD(tmp);
+       buf[DS1307_REG_YEAR] = bin2bcd(tmp);
 
        switch (ds1307->type) {
        case ds_1337:
@@ -551,7 +551,6 @@ static struct bin_attribute nvram = {
        .attr = {
                .name   = "nvram",
                .mode   = S_IRUGO | S_IWUSR,
-               .owner  = THIS_MODULE,
        },
 
        .read   = ds1307_nvram_read,
@@ -709,18 +708,18 @@ read_rtc:
        }
 
        tmp = ds1307->regs[DS1307_REG_SECS];
-       tmp = BCD2BIN(tmp & 0x7f);
+       tmp = bcd2bin(tmp & 0x7f);
        if (tmp > 60)
                goto exit_bad;
-       tmp = BCD2BIN(ds1307->regs[DS1307_REG_MIN] & 0x7f);
+       tmp = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
        if (tmp > 60)
                goto exit_bad;
 
-       tmp = BCD2BIN(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
+       tmp = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
        if (tmp == 0 || tmp > 31)
                goto exit_bad;
 
-       tmp = BCD2BIN(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
+       tmp = bcd2bin(ds1307->regs[DS1307_REG_MONTH] & 0x1f);
        if (tmp == 0 || tmp > 12)
                goto exit_bad;
 
@@ -739,14 +738,14 @@ read_rtc:
                /* Be sure we're in 24 hour mode.  Multi-master systems
                 * take note...
                 */
-               tmp = BCD2BIN(tmp & 0x1f);
+               tmp = bcd2bin(tmp & 0x1f);
                if (tmp == 12)
                        tmp = 0;
                if (ds1307->regs[DS1307_REG_HOUR] & DS1307_BIT_PM)
                        tmp += 12;
                i2c_smbus_write_byte_data(client,
                                DS1307_REG_HOUR,
-                               BIN2BCD(tmp));
+                               bin2bcd(tmp));
        }
 
        ds1307->rtc = rtc_device_register(client->name, &client->dev,
index 86981d34fbb6717a66d47a11db1287b4e3a4c7f5..25caada78398e76ee83d58507a6fed256eb306ef 100644 (file)
@@ -153,8 +153,8 @@ ds1511_wdog_set(unsigned long deciseconds)
        /*
         * set the wdog values in the wdog registers
         */
-       rtc_write(BIN2BCD(deciseconds % 100), DS1511_WD_MSEC);
-       rtc_write(BIN2BCD(deciseconds / 100), DS1511_WD_SEC);
+       rtc_write(bin2bcd(deciseconds % 100), DS1511_WD_MSEC);
+       rtc_write(bin2bcd(deciseconds / 100), DS1511_WD_SEC);
        /*
         * set wdog enable and wdog 'steering' bit to issue a reset
         */
@@ -220,13 +220,13 @@ static int ds1511_rtc_set_time(struct device *dev, struct rtc_time *rtc_tm)
        /*
         * each register is a different number of valid bits
         */
-       sec = BIN2BCD(sec) & 0x7f;
-       min = BIN2BCD(min) & 0x7f;
-       hrs = BIN2BCD(hrs) & 0x3f;
-       day = BIN2BCD(day) & 0x3f;
-       mon = BIN2BCD(mon) & 0x1f;
-       yrs = BIN2BCD(yrs) & 0xff;
-       cen = BIN2BCD(cen) & 0xff;
+       sec = bin2bcd(sec) & 0x7f;
+       min = bin2bcd(min) & 0x7f;
+       hrs = bin2bcd(hrs) & 0x3f;
+       day = bin2bcd(day) & 0x3f;
+       mon = bin2bcd(mon) & 0x1f;
+       yrs = bin2bcd(yrs) & 0xff;
+       cen = bin2bcd(cen) & 0xff;
 
        spin_lock_irqsave(&ds1511_lock, flags);
        rtc_disable_update();
@@ -264,14 +264,14 @@ static int ds1511_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
        rtc_enable_update();
        spin_unlock_irqrestore(&ds1511_lock, flags);
 
-       rtc_tm->tm_sec = BCD2BIN(rtc_tm->tm_sec);
-       rtc_tm->tm_min = BCD2BIN(rtc_tm->tm_min);
-       rtc_tm->tm_hour = BCD2BIN(rtc_tm->tm_hour);
-       rtc_tm->tm_mday = BCD2BIN(rtc_tm->tm_mday);
-       rtc_tm->tm_wday = BCD2BIN(rtc_tm->tm_wday);
-       rtc_tm->tm_mon = BCD2BIN(rtc_tm->tm_mon);
-       rtc_tm->tm_year = BCD2BIN(rtc_tm->tm_year);
-       century = BCD2BIN(century) * 100;
+       rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+       rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+       rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+       rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+       rtc_tm->tm_wday = bcd2bin(rtc_tm->tm_wday);
+       rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+       rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
+       century = bcd2bin(century) * 100;
 
        /*
         * Account for differences between how the RTC uses the values
@@ -304,16 +304,16 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata)
 
        spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
        rtc_write(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_mday) & 0x3f,
+              0x80 : bin2bcd(pdata->alrm_mday) & 0x3f,
               RTC_ALARM_DATE);
        rtc_write(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_hour) & 0x3f,
+              0x80 : bin2bcd(pdata->alrm_hour) & 0x3f,
               RTC_ALARM_HOUR);
        rtc_write(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_min) & 0x7f,
+              0x80 : bin2bcd(pdata->alrm_min) & 0x7f,
               RTC_ALARM_MIN);
        rtc_write(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_sec) & 0x7f,
+              0x80 : bin2bcd(pdata->alrm_sec) & 0x7f,
               RTC_ALARM_SEC);
        rtc_write(rtc_read(RTC_CMD) | (pdata->irqen ? RTC_TIE : 0), RTC_CMD);
        rtc_read(RTC_CMD1);     /* clear interrupts */
@@ -481,7 +481,6 @@ static struct bin_attribute ds1511_nvram_attr = {
        .attr = {
                .name = "nvram",
                .mode = S_IRUGO | S_IWUGO,
-               .owner = THIS_MODULE,
        },
        .size = DS1511_RAM_MAX,
        .read = ds1511_nvram_read,
index 4ef59285b489ec28d05b9c038ae35d28e49a0b40..b9475cd2021063b926d8ff4cd16764589dfa2aac 100644 (file)
@@ -78,17 +78,17 @@ static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
        void __iomem *ioaddr = pdata->ioaddr;
        u8 century;
 
-       century = BIN2BCD((tm->tm_year + 1900) / 100);
+       century = bin2bcd((tm->tm_year + 1900) / 100);
 
        writeb(RTC_WRITE, pdata->ioaddr + RTC_CONTROL);
 
-       writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
-       writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
-       writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
-       writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
-       writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
-       writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
-       writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+       writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
+       writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+       writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+       writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
+       writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
+       writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
+       writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
 
        /* RTC_CENTURY and RTC_CONTROL share same register */
        writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
@@ -118,14 +118,14 @@ static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
        year = readb(ioaddr + RTC_YEAR);
        century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
        writeb(0, ioaddr + RTC_CONTROL);
-       tm->tm_sec = BCD2BIN(second);
-       tm->tm_min = BCD2BIN(minute);
-       tm->tm_hour = BCD2BIN(hour);
-       tm->tm_mday = BCD2BIN(day);
-       tm->tm_wday = BCD2BIN(week);
-       tm->tm_mon = BCD2BIN(month) - 1;
+       tm->tm_sec = bcd2bin(second);
+       tm->tm_min = bcd2bin(minute);
+       tm->tm_hour = bcd2bin(hour);
+       tm->tm_mday = bcd2bin(day);
+       tm->tm_wday = bcd2bin(week);
+       tm->tm_mon = bcd2bin(month) - 1;
        /* year is 1900 + tm->tm_year */
-       tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+       tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
 
        if (rtc_valid_tm(tm) < 0) {
                dev_err(dev, "retrieved date/time is not valid.\n");
@@ -141,16 +141,16 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
 
        spin_lock_irqsave(&pdata->rtc->irq_lock, flags);
        writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_mday),
+              0x80 : bin2bcd(pdata->alrm_mday),
               ioaddr + RTC_DATE_ALARM);
        writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_hour),
+              0x80 : bin2bcd(pdata->alrm_hour),
               ioaddr + RTC_HOURS_ALARM);
        writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_min),
+              0x80 : bin2bcd(pdata->alrm_min),
               ioaddr + RTC_MINUTES_ALARM);
        writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_sec),
+              0x80 : bin2bcd(pdata->alrm_sec),
               ioaddr + RTC_SECONDS_ALARM);
        writeb(pdata->irqen ? RTC_INTS_AE : 0, ioaddr + RTC_INTERRUPTS);
        readb(ioaddr + RTC_FLAGS);      /* clear interrupts */
index 24d35ede2dbff92de8fca76f3354337895eba97c..8bc8501bffc81f4b8996a17ef939de553f027938 100644 (file)
@@ -66,17 +66,17 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
        void __iomem *ioaddr = pdata->ioaddr_rtc;
        u8 century;
 
-       century = BIN2BCD((tm->tm_year + 1900) / 100);
+       century = bin2bcd((tm->tm_year + 1900) / 100);
 
        writeb(RTC_WRITE, ioaddr + RTC_CONTROL);
 
-       writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
-       writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
-       writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
-       writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
-       writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
-       writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
-       writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+       writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
+       writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+       writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+       writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
+       writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
+       writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
+       writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
 
        /* RTC_CENTURY and RTC_CONTROL share same register */
        writeb(RTC_WRITE | (century & RTC_CENTURY_MASK), ioaddr + RTC_CENTURY);
@@ -106,14 +106,14 @@ static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
        year = readb(ioaddr + RTC_YEAR);
        century = readb(ioaddr + RTC_CENTURY) & RTC_CENTURY_MASK;
        writeb(0, ioaddr + RTC_CONTROL);
-       tm->tm_sec = BCD2BIN(second);
-       tm->tm_min = BCD2BIN(minute);
-       tm->tm_hour = BCD2BIN(hour);
-       tm->tm_mday = BCD2BIN(day);
-       tm->tm_wday = BCD2BIN(week);
-       tm->tm_mon = BCD2BIN(month) - 1;
+       tm->tm_sec = bcd2bin(second);
+       tm->tm_min = bcd2bin(minute);
+       tm->tm_hour = bcd2bin(hour);
+       tm->tm_mday = bcd2bin(day);
+       tm->tm_wday = bcd2bin(week);
+       tm->tm_mon = bcd2bin(month) - 1;
        /* year is 1900 + tm->tm_year */
-       tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+       tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
 
        if (rtc_valid_tm(tm) < 0) {
                dev_err(dev, "retrieved date/time is not valid.\n");
index abfdfcbaa059f2334dea356dd5b094924783315e..3a7be11cc6b93e1a5315a40ffc25624792679443 100644 (file)
@@ -131,17 +131,17 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t)
                        fm3130->regs[0xc], fm3130->regs[0xd],
                        fm3130->regs[0xe]);
 
-       t->tm_sec = BCD2BIN(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
-       t->tm_min = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
+       t->tm_sec = bcd2bin(fm3130->regs[FM3130_RTC_SECONDS] & 0x7f);
+       t->tm_min = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
        tmp = fm3130->regs[FM3130_RTC_HOURS] & 0x3f;
-       t->tm_hour = BCD2BIN(tmp);
-       t->tm_wday = BCD2BIN(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
-       t->tm_mday = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
+       t->tm_hour = bcd2bin(tmp);
+       t->tm_wday = bcd2bin(fm3130->regs[FM3130_RTC_DAY] & 0x07) - 1;
+       t->tm_mday = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
        tmp = fm3130->regs[FM3130_RTC_MONTHS] & 0x1f;
-       t->tm_mon = BCD2BIN(tmp) - 1;
+       t->tm_mon = bcd2bin(tmp) - 1;
 
        /* assume 20YY not 19YY, and ignore CF bit */
-       t->tm_year = BCD2BIN(fm3130->regs[FM3130_RTC_YEARS]) + 100;
+       t->tm_year = bcd2bin(fm3130->regs[FM3130_RTC_YEARS]) + 100;
 
        dev_dbg(dev, "%s secs=%d, mins=%d, "
                "hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -167,16 +167,16 @@ static int fm3130_set_time(struct device *dev, struct rtc_time *t)
                t->tm_mon, t->tm_year, t->tm_wday);
 
        /* first register addr */
-       buf[FM3130_RTC_SECONDS] = BIN2BCD(t->tm_sec);
-       buf[FM3130_RTC_MINUTES] = BIN2BCD(t->tm_min);
-       buf[FM3130_RTC_HOURS] = BIN2BCD(t->tm_hour);
-       buf[FM3130_RTC_DAY] = BIN2BCD(t->tm_wday + 1);
-       buf[FM3130_RTC_DATE] = BIN2BCD(t->tm_mday);
-       buf[FM3130_RTC_MONTHS] = BIN2BCD(t->tm_mon + 1);
+       buf[FM3130_RTC_SECONDS] = bin2bcd(t->tm_sec);
+       buf[FM3130_RTC_MINUTES] = bin2bcd(t->tm_min);
+       buf[FM3130_RTC_HOURS] = bin2bcd(t->tm_hour);
+       buf[FM3130_RTC_DAY] = bin2bcd(t->tm_wday + 1);
+       buf[FM3130_RTC_DATE] = bin2bcd(t->tm_mday);
+       buf[FM3130_RTC_MONTHS] = bin2bcd(t->tm_mon + 1);
 
        /* assume 20YY not 19YY */
        tmp = t->tm_year - 100;
-       buf[FM3130_RTC_YEARS] = BIN2BCD(tmp);
+       buf[FM3130_RTC_YEARS] = bin2bcd(tmp);
 
        dev_dbg(dev, "%s: %02x %02x %02x %02x %02x %02x %02x"
                "%02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -222,11 +222,11 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
                        fm3130->regs[FM3130_ALARM_MONTHS]);
 
 
-       tm->tm_sec      = BCD2BIN(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
-       tm->tm_min      = BCD2BIN(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
-       tm->tm_hour     = BCD2BIN(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
-       tm->tm_mday     = BCD2BIN(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
-       tm->tm_mon      = BCD2BIN(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
+       tm->tm_sec      = bcd2bin(fm3130->regs[FM3130_ALARM_SECONDS] & 0x7F);
+       tm->tm_min      = bcd2bin(fm3130->regs[FM3130_ALARM_MINUTES] & 0x7F);
+       tm->tm_hour     = bcd2bin(fm3130->regs[FM3130_ALARM_HOURS] & 0x3F);
+       tm->tm_mday     = bcd2bin(fm3130->regs[FM3130_ALARM_DATE] & 0x3F);
+       tm->tm_mon      = bcd2bin(fm3130->regs[FM3130_ALARM_MONTHS] & 0x1F);
        if (tm->tm_mon > 0)
                tm->tm_mon -= 1; /* RTC is 1-12, tm_mon is 0-11 */
        dev_dbg(dev, "%s secs=%d, mins=%d, "
@@ -252,23 +252,23 @@ static int fm3130_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        if (tm->tm_sec != -1)
                fm3130->regs[FM3130_ALARM_SECONDS] =
-                       BIN2BCD(tm->tm_sec) | 0x80;
+                       bin2bcd(tm->tm_sec) | 0x80;
 
        if (tm->tm_min != -1)
                fm3130->regs[FM3130_ALARM_MINUTES] =
-                       BIN2BCD(tm->tm_min) | 0x80;
+                       bin2bcd(tm->tm_min) | 0x80;
 
        if (tm->tm_hour != -1)
                fm3130->regs[FM3130_ALARM_HOURS] =
-                       BIN2BCD(tm->tm_hour) | 0x80;
+                       bin2bcd(tm->tm_hour) | 0x80;
 
        if (tm->tm_mday != -1)
                fm3130->regs[FM3130_ALARM_DATE] =
-                       BIN2BCD(tm->tm_mday) | 0x80;
+                       bin2bcd(tm->tm_mday) | 0x80;
 
        if (tm->tm_mon != -1)
                fm3130->regs[FM3130_ALARM_MONTHS] =
-                       BIN2BCD(tm->tm_mon + 1) | 0x80;
+                       bin2bcd(tm->tm_mon + 1) | 0x80;
 
        dev_dbg(dev, "alarm write %02x %02x %02x %02x %02x\n",
                        fm3130->regs[FM3130_ALARM_SECONDS],
@@ -414,18 +414,18 @@ static int __devinit fm3130_probe(struct i2c_client *client,
        /* TODO */
        /* TODO need to sanity check alarm */
        tmp = fm3130->regs[FM3130_RTC_SECONDS];
-       tmp = BCD2BIN(tmp & 0x7f);
+       tmp = bcd2bin(tmp & 0x7f);
        if (tmp > 60)
                goto exit_bad;
-       tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
+       tmp = bcd2bin(fm3130->regs[FM3130_RTC_MINUTES] & 0x7f);
        if (tmp > 60)
                goto exit_bad;
 
-       tmp = BCD2BIN(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
+       tmp = bcd2bin(fm3130->regs[FM3130_RTC_DATE] & 0x3f);
        if (tmp == 0 || tmp > 31)
                goto exit_bad;
 
-       tmp = BCD2BIN(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
+       tmp = bcd2bin(fm3130->regs[FM3130_RTC_MONTHS] & 0x1f);
        if (tmp == 0 || tmp > 12)
                goto exit_bad;
 
index a81adab6e515849306d9fb9e245eebc0e8532784..2cd77ab8fc66b06e43d3b908884a9f4fe8603ca1 100644 (file)
@@ -259,26 +259,26 @@ isl1208_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
                return sr;
        }
 
-       tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SC]);
-       tm->tm_min = BCD2BIN(regs[ISL1208_REG_MN]);
+       tm->tm_sec = bcd2bin(regs[ISL1208_REG_SC]);
+       tm->tm_min = bcd2bin(regs[ISL1208_REG_MN]);
 
        /* HR field has a more complex interpretation */
        {
                const u8 _hr = regs[ISL1208_REG_HR];
                if (_hr & ISL1208_REG_HR_MIL)   /* 24h format */
-                       tm->tm_hour = BCD2BIN(_hr & 0x3f);
+                       tm->tm_hour = bcd2bin(_hr & 0x3f);
                else {
                        /* 12h format */
-                       tm->tm_hour = BCD2BIN(_hr & 0x1f);
+                       tm->tm_hour = bcd2bin(_hr & 0x1f);
                        if (_hr & ISL1208_REG_HR_PM)    /* PM flag set */
                                tm->tm_hour += 12;
                }
        }
 
-       tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DT]);
-       tm->tm_mon = BCD2BIN(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */
-       tm->tm_year = BCD2BIN(regs[ISL1208_REG_YR]) + 100;
-       tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DW]);
+       tm->tm_mday = bcd2bin(regs[ISL1208_REG_DT]);
+       tm->tm_mon = bcd2bin(regs[ISL1208_REG_MO]) - 1; /* rtc starts at 1 */
+       tm->tm_year = bcd2bin(regs[ISL1208_REG_YR]) + 100;
+       tm->tm_wday = bcd2bin(regs[ISL1208_REG_DW]);
 
        return 0;
 }
@@ -305,13 +305,13 @@ isl1208_i2c_read_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
        }
 
        /* MSB of each alarm register is an enable bit */
-       tm->tm_sec = BCD2BIN(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f);
-       tm->tm_min = BCD2BIN(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f);
-       tm->tm_hour = BCD2BIN(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f);
-       tm->tm_mday = BCD2BIN(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f);
+       tm->tm_sec = bcd2bin(regs[ISL1208_REG_SCA - ISL1208_REG_SCA] & 0x7f);
+       tm->tm_min = bcd2bin(regs[ISL1208_REG_MNA - ISL1208_REG_SCA] & 0x7f);
+       tm->tm_hour = bcd2bin(regs[ISL1208_REG_HRA - ISL1208_REG_SCA] & 0x3f);
+       tm->tm_mday = bcd2bin(regs[ISL1208_REG_DTA - ISL1208_REG_SCA] & 0x3f);
        tm->tm_mon =
-               BCD2BIN(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
-       tm->tm_wday = BCD2BIN(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
+               bcd2bin(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
+       tm->tm_wday = bcd2bin(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
 
        return 0;
 }
@@ -328,15 +328,15 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
        int sr;
        u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, };
 
-       regs[ISL1208_REG_SC] = BIN2BCD(tm->tm_sec);
-       regs[ISL1208_REG_MN] = BIN2BCD(tm->tm_min);
-       regs[ISL1208_REG_HR] = BIN2BCD(tm->tm_hour) | ISL1208_REG_HR_MIL;
+       regs[ISL1208_REG_SC] = bin2bcd(tm->tm_sec);
+       regs[ISL1208_REG_MN] = bin2bcd(tm->tm_min);
+       regs[ISL1208_REG_HR] = bin2bcd(tm->tm_hour) | ISL1208_REG_HR_MIL;
 
-       regs[ISL1208_REG_DT] = BIN2BCD(tm->tm_mday);
-       regs[ISL1208_REG_MO] = BIN2BCD(tm->tm_mon + 1);
-       regs[ISL1208_REG_YR] = BIN2BCD(tm->tm_year - 100);
+       regs[ISL1208_REG_DT] = bin2bcd(tm->tm_mday);
+       regs[ISL1208_REG_MO] = bin2bcd(tm->tm_mon + 1);
+       regs[ISL1208_REG_YR] = bin2bcd(tm->tm_year - 100);
 
-       regs[ISL1208_REG_DW] = BIN2BCD(tm->tm_wday & 7);
+       regs[ISL1208_REG_DW] = bin2bcd(tm->tm_wday & 7);
 
        sr = isl1208_i2c_get_sr(client);
        if (sr < 0) {
index 470fb2d295452a7be54f92747076107c0c025436..893f7dece239522afcca4579d2524dba58f645a0 100644 (file)
@@ -110,15 +110,15 @@ static int m41t80_get_datetime(struct i2c_client *client,
                return -EIO;
        }
 
-       tm->tm_sec = BCD2BIN(buf[M41T80_REG_SEC] & 0x7f);
-       tm->tm_min = BCD2BIN(buf[M41T80_REG_MIN] & 0x7f);
-       tm->tm_hour = BCD2BIN(buf[M41T80_REG_HOUR] & 0x3f);
-       tm->tm_mday = BCD2BIN(buf[M41T80_REG_DAY] & 0x3f);
+       tm->tm_sec = bcd2bin(buf[M41T80_REG_SEC] & 0x7f);
+       tm->tm_min = bcd2bin(buf[M41T80_REG_MIN] & 0x7f);
+       tm->tm_hour = bcd2bin(buf[M41T80_REG_HOUR] & 0x3f);
+       tm->tm_mday = bcd2bin(buf[M41T80_REG_DAY] & 0x3f);
        tm->tm_wday = buf[M41T80_REG_WDAY] & 0x07;
-       tm->tm_mon = BCD2BIN(buf[M41T80_REG_MON] & 0x1f) - 1;
+       tm->tm_mon = bcd2bin(buf[M41T80_REG_MON] & 0x1f) - 1;
 
        /* assume 20YY not 19YY, and ignore the Century Bit */
-       tm->tm_year = BCD2BIN(buf[M41T80_REG_YEAR]) + 100;
+       tm->tm_year = bcd2bin(buf[M41T80_REG_YEAR]) + 100;
        return 0;
 }
 
@@ -161,19 +161,19 @@ static int m41t80_set_datetime(struct i2c_client *client, struct rtc_time *tm)
        /* Merge time-data and register flags into buf[0..7] */
        buf[M41T80_REG_SSEC] = 0;
        buf[M41T80_REG_SEC] =
-               BIN2BCD(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
+               bin2bcd(tm->tm_sec) | (buf[M41T80_REG_SEC] & ~0x7f);
        buf[M41T80_REG_MIN] =
-               BIN2BCD(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
+               bin2bcd(tm->tm_min) | (buf[M41T80_REG_MIN] & ~0x7f);
        buf[M41T80_REG_HOUR] =
-               BIN2BCD(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ;
+               bin2bcd(tm->tm_hour) | (buf[M41T80_REG_HOUR] & ~0x3f) ;
        buf[M41T80_REG_WDAY] =
                (tm->tm_wday & 0x07) | (buf[M41T80_REG_WDAY] & ~0x07);
        buf[M41T80_REG_DAY] =
-               BIN2BCD(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
+               bin2bcd(tm->tm_mday) | (buf[M41T80_REG_DAY] & ~0x3f);
        buf[M41T80_REG_MON] =
-               BIN2BCD(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
+               bin2bcd(tm->tm_mon + 1) | (buf[M41T80_REG_MON] & ~0x1f);
        /* assume 20YY not 19YY */
-       buf[M41T80_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+       buf[M41T80_REG_YEAR] = bin2bcd(tm->tm_year % 100);
 
        if (i2c_transfer(client->adapter, msgs, 1) != 1) {
                dev_err(&client->dev, "write error\n");
@@ -288,15 +288,15 @@ static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 
        wbuf[0] = M41T80_REG_ALARM_MON; /* offset into rtc's regs */
        reg[M41T80_REG_ALARM_SEC] |= t->time.tm_sec >= 0 ?
-               BIN2BCD(t->time.tm_sec) : 0x80;
+               bin2bcd(t->time.tm_sec) : 0x80;
        reg[M41T80_REG_ALARM_MIN] |= t->time.tm_min >= 0 ?
-               BIN2BCD(t->time.tm_min) : 0x80;
+               bin2bcd(t->time.tm_min) : 0x80;
        reg[M41T80_REG_ALARM_HOUR] |= t->time.tm_hour >= 0 ?
-               BIN2BCD(t->time.tm_hour) : 0x80;
+               bin2bcd(t->time.tm_hour) : 0x80;
        reg[M41T80_REG_ALARM_DAY] |= t->time.tm_mday >= 0 ?
-               BIN2BCD(t->time.tm_mday) : 0x80;
+               bin2bcd(t->time.tm_mday) : 0x80;
        if (t->time.tm_mon >= 0)
-               reg[M41T80_REG_ALARM_MON] |= BIN2BCD(t->time.tm_mon + 1);
+               reg[M41T80_REG_ALARM_MON] |= bin2bcd(t->time.tm_mon + 1);
        else
                reg[M41T80_REG_ALARM_DAY] |= 0x40;
 
@@ -347,15 +347,15 @@ static int m41t80_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *t)
        t->time.tm_mday = -1;
        t->time.tm_mon = -1;
        if (!(reg[M41T80_REG_ALARM_SEC] & 0x80))
-               t->time.tm_sec = BCD2BIN(reg[M41T80_REG_ALARM_SEC] & 0x7f);
+               t->time.tm_sec = bcd2bin(reg[M41T80_REG_ALARM_SEC] & 0x7f);
        if (!(reg[M41T80_REG_ALARM_MIN] & 0x80))
-               t->time.tm_min = BCD2BIN(reg[M41T80_REG_ALARM_MIN] & 0x7f);
+               t->time.tm_min = bcd2bin(reg[M41T80_REG_ALARM_MIN] & 0x7f);
        if (!(reg[M41T80_REG_ALARM_HOUR] & 0x80))
-               t->time.tm_hour = BCD2BIN(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
+               t->time.tm_hour = bcd2bin(reg[M41T80_REG_ALARM_HOUR] & 0x3f);
        if (!(reg[M41T80_REG_ALARM_DAY] & 0x80))
-               t->time.tm_mday = BCD2BIN(reg[M41T80_REG_ALARM_DAY] & 0x3f);
+               t->time.tm_mday = bcd2bin(reg[M41T80_REG_ALARM_DAY] & 0x3f);
        if (!(reg[M41T80_REG_ALARM_DAY] & 0x40))
-               t->time.tm_mon = BCD2BIN(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
+               t->time.tm_mon = bcd2bin(reg[M41T80_REG_ALARM_MON] & 0x1f) - 1;
        t->time.tm_year = -1;
        t->time.tm_wday = -1;
        t->time.tm_yday = -1;
index 9b19499c829e5a7008a64a9d43de58e0429a6bd5..c3a18c58daf6ed80745f2c2c7fc7f8d5dcf2bde4 100644 (file)
@@ -41,17 +41,17 @@ static int m41t94_set_time(struct device *dev, struct rtc_time *tm)
                tm->tm_mon, tm->tm_year, tm->tm_wday);
 
        buf[0] = 0x80 | M41T94_REG_SECONDS; /* write time + date */
-       buf[M41T94_REG_SECONDS] = BIN2BCD(tm->tm_sec);
-       buf[M41T94_REG_MINUTES] = BIN2BCD(tm->tm_min);
-       buf[M41T94_REG_HOURS]   = BIN2BCD(tm->tm_hour);
-       buf[M41T94_REG_WDAY]    = BIN2BCD(tm->tm_wday + 1);
-       buf[M41T94_REG_DAY]     = BIN2BCD(tm->tm_mday);
-       buf[M41T94_REG_MONTH]   = BIN2BCD(tm->tm_mon + 1);
+       buf[M41T94_REG_SECONDS] = bin2bcd(tm->tm_sec);
+       buf[M41T94_REG_MINUTES] = bin2bcd(tm->tm_min);
+       buf[M41T94_REG_HOURS]   = bin2bcd(tm->tm_hour);
+       buf[M41T94_REG_WDAY]    = bin2bcd(tm->tm_wday + 1);
+       buf[M41T94_REG_DAY]     = bin2bcd(tm->tm_mday);
+       buf[M41T94_REG_MONTH]   = bin2bcd(tm->tm_mon + 1);
 
        buf[M41T94_REG_HOURS] |= M41T94_BIT_CEB;
        if (tm->tm_year >= 100)
                buf[M41T94_REG_HOURS] |= M41T94_BIT_CB;
-       buf[M41T94_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+       buf[M41T94_REG_YEAR] = bin2bcd(tm->tm_year % 100);
 
        return spi_write(spi, buf, 8);
 }
@@ -82,14 +82,14 @@ static int m41t94_read_time(struct device *dev, struct rtc_time *tm)
                spi_write(spi, buf, 2);
        }
 
-       tm->tm_sec  = BCD2BIN(spi_w8r8(spi, M41T94_REG_SECONDS));
-       tm->tm_min  = BCD2BIN(spi_w8r8(spi, M41T94_REG_MINUTES));
+       tm->tm_sec  = bcd2bin(spi_w8r8(spi, M41T94_REG_SECONDS));
+       tm->tm_min  = bcd2bin(spi_w8r8(spi, M41T94_REG_MINUTES));
        hour = spi_w8r8(spi, M41T94_REG_HOURS);
-       tm->tm_hour = BCD2BIN(hour & 0x3f);
-       tm->tm_wday = BCD2BIN(spi_w8r8(spi, M41T94_REG_WDAY)) - 1;
-       tm->tm_mday = BCD2BIN(spi_w8r8(spi, M41T94_REG_DAY));
-       tm->tm_mon  = BCD2BIN(spi_w8r8(spi, M41T94_REG_MONTH)) - 1;
-       tm->tm_year = BCD2BIN(spi_w8r8(spi, M41T94_REG_YEAR));
+       tm->tm_hour = bcd2bin(hour & 0x3f);
+       tm->tm_wday = bcd2bin(spi_w8r8(spi, M41T94_REG_WDAY)) - 1;
+       tm->tm_mday = bcd2bin(spi_w8r8(spi, M41T94_REG_DAY));
+       tm->tm_mon  = bcd2bin(spi_w8r8(spi, M41T94_REG_MONTH)) - 1;
+       tm->tm_year = bcd2bin(spi_w8r8(spi, M41T94_REG_YEAR));
        if ((hour & M41T94_BIT_CB) || !(hour & M41T94_BIT_CEB))
                tm->tm_year += 100;
 
index ce4eff6a8d51bd57057c4d0e8f24f49304c4ab60..04b63dab693254885893ea622a7cf99cebc1b3cf 100644 (file)
@@ -76,10 +76,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
        /* Issue the READ command */
        M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
 
-       tm->tm_year     = BCD2BIN(M48T59_READ(M48T59_YEAR));
+       tm->tm_year     = bcd2bin(M48T59_READ(M48T59_YEAR));
        /* tm_mon is 0-11 */
-       tm->tm_mon      = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
-       tm->tm_mday     = BCD2BIN(M48T59_READ(M48T59_MDAY));
+       tm->tm_mon      = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
+       tm->tm_mday     = bcd2bin(M48T59_READ(M48T59_MDAY));
 
        val = M48T59_READ(M48T59_WDAY);
        if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
@@ -88,10 +88,10 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
                tm->tm_year += 100;     /* one century */
        }
 
-       tm->tm_wday     = BCD2BIN(val & 0x07);
-       tm->tm_hour     = BCD2BIN(M48T59_READ(M48T59_HOUR) & 0x3F);
-       tm->tm_min      = BCD2BIN(M48T59_READ(M48T59_MIN) & 0x7F);
-       tm->tm_sec      = BCD2BIN(M48T59_READ(M48T59_SEC) & 0x7F);
+       tm->tm_wday     = bcd2bin(val & 0x07);
+       tm->tm_hour     = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F);
+       tm->tm_min      = bcd2bin(M48T59_READ(M48T59_MIN) & 0x7F);
+       tm->tm_sec      = bcd2bin(M48T59_READ(M48T59_SEC) & 0x7F);
 
        /* Clear the READ bit */
        M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
@@ -119,17 +119,17 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
        /* Issue the WRITE command */
        M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
 
-       M48T59_WRITE((BIN2BCD(tm->tm_sec) & 0x7F), M48T59_SEC);
-       M48T59_WRITE((BIN2BCD(tm->tm_min) & 0x7F), M48T59_MIN);
-       M48T59_WRITE((BIN2BCD(tm->tm_hour) & 0x3F), M48T59_HOUR);
-       M48T59_WRITE((BIN2BCD(tm->tm_mday) & 0x3F), M48T59_MDAY);
+       M48T59_WRITE((bin2bcd(tm->tm_sec) & 0x7F), M48T59_SEC);
+       M48T59_WRITE((bin2bcd(tm->tm_min) & 0x7F), M48T59_MIN);
+       M48T59_WRITE((bin2bcd(tm->tm_hour) & 0x3F), M48T59_HOUR);
+       M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY);
        /* tm_mon is 0-11 */
-       M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
-       M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR);
+       M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
+       M48T59_WRITE(bin2bcd(tm->tm_year % 100), M48T59_YEAR);
 
        if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100))
                val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
-       val |= (BIN2BCD(tm->tm_wday) & 0x07);
+       val |= (bin2bcd(tm->tm_wday) & 0x07);
        M48T59_WRITE(val, M48T59_WDAY);
 
        /* Clear the WRITE bit */
@@ -158,18 +158,18 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
        /* Issue the READ command */
        M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
 
-       tm->tm_year = BCD2BIN(M48T59_READ(M48T59_YEAR));
+       tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
        /* tm_mon is 0-11 */
-       tm->tm_mon = BCD2BIN(M48T59_READ(M48T59_MONTH)) - 1;
+       tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
 
        val = M48T59_READ(M48T59_WDAY);
        if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
                tm->tm_year += 100;     /* one century */
 
-       tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_ALARM_DATE));
-       tm->tm_hour = BCD2BIN(M48T59_READ(M48T59_ALARM_HOUR));
-       tm->tm_min = BCD2BIN(M48T59_READ(M48T59_ALARM_MIN));
-       tm->tm_sec = BCD2BIN(M48T59_READ(M48T59_ALARM_SEC));
+       tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE));
+       tm->tm_hour = bcd2bin(M48T59_READ(M48T59_ALARM_HOUR));
+       tm->tm_min = bcd2bin(M48T59_READ(M48T59_ALARM_MIN));
+       tm->tm_sec = bcd2bin(M48T59_READ(M48T59_ALARM_SEC));
 
        /* Clear the READ bit */
        M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
@@ -201,18 +201,18 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
         * 0xff means "always match"
         */
        mday = tm->tm_mday;
-       mday = (mday >= 1 && mday <= 31) ? BIN2BCD(mday) : 0xff;
+       mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
        if (mday == 0xff)
                mday = M48T59_READ(M48T59_MDAY);
 
        hour = tm->tm_hour;
-       hour = (hour < 24) ? BIN2BCD(hour) : 0x00;
+       hour = (hour < 24) ? bin2bcd(hour) : 0x00;
 
        min = tm->tm_min;
-       min = (min < 60) ? BIN2BCD(min) : 0x00;
+       min = (min < 60) ? bin2bcd(min) : 0x00;
 
        sec = tm->tm_sec;
-       sec = (sec < 60) ? BIN2BCD(sec) : 0x00;
+       sec = (sec < 60) ? bin2bcd(sec) : 0x00;
 
        spin_lock_irqsave(&m48t59->lock, flags);
        /* Issue the WRITE command */
@@ -360,7 +360,6 @@ static struct bin_attribute m48t59_nvram_attr = {
        .attr = {
                .name = "nvram",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .read = m48t59_nvram_read,
        .write = m48t59_nvram_write,
index 3f7f99a5d96aa596d59258497f6bb1c6f01e1566..7c045cffa9ff64ae9e2e1e2a7c9f0ce75b7b9c18 100644 (file)
@@ -62,14 +62,14 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
                tm->tm_wday     = ops->readbyte(M48T86_REG_DOW);
        } else {
                /* bcd mode */
-               tm->tm_sec      = BCD2BIN(ops->readbyte(M48T86_REG_SEC));
-               tm->tm_min      = BCD2BIN(ops->readbyte(M48T86_REG_MIN));
-               tm->tm_hour     = BCD2BIN(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
-               tm->tm_mday     = BCD2BIN(ops->readbyte(M48T86_REG_DOM));
+               tm->tm_sec      = bcd2bin(ops->readbyte(M48T86_REG_SEC));
+               tm->tm_min      = bcd2bin(ops->readbyte(M48T86_REG_MIN));
+               tm->tm_hour     = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
+               tm->tm_mday     = bcd2bin(ops->readbyte(M48T86_REG_DOM));
                /* tm_mon is 0-11 */
-               tm->tm_mon      = BCD2BIN(ops->readbyte(M48T86_REG_MONTH)) - 1;
-               tm->tm_year     = BCD2BIN(ops->readbyte(M48T86_REG_YEAR)) + 100;
-               tm->tm_wday     = BCD2BIN(ops->readbyte(M48T86_REG_DOW));
+               tm->tm_mon      = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1;
+               tm->tm_year     = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100;
+               tm->tm_wday     = bcd2bin(ops->readbyte(M48T86_REG_DOW));
        }
 
        /* correct the hour if the clock is in 12h mode */
@@ -103,13 +103,13 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
                ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
        } else {
                /* bcd mode */
-               ops->writebyte(BIN2BCD(tm->tm_sec), M48T86_REG_SEC);
-               ops->writebyte(BIN2BCD(tm->tm_min), M48T86_REG_MIN);
-               ops->writebyte(BIN2BCD(tm->tm_hour), M48T86_REG_HOUR);
-               ops->writebyte(BIN2BCD(tm->tm_mday), M48T86_REG_DOM);
-               ops->writebyte(BIN2BCD(tm->tm_mon + 1), M48T86_REG_MONTH);
-               ops->writebyte(BIN2BCD(tm->tm_year % 100), M48T86_REG_YEAR);
-               ops->writebyte(BIN2BCD(tm->tm_wday), M48T86_REG_DOW);
+               ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC);
+               ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN);
+               ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
+               ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM);
+               ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
+               ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
+               ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW);
        }
 
        /* update ended */
index 12c9cd25cad8b2b3df1843ba74d247f592334e41..80782798763fa2528993ed652b0cf337e9d79008 100644 (file)
@@ -150,14 +150,14 @@ static int max6900_i2c_read_time(struct i2c_client *client, struct rtc_time *tm)
        if (rc < 0)
                return rc;
 
-       tm->tm_sec = BCD2BIN(regs[MAX6900_REG_SC]);
-       tm->tm_min = BCD2BIN(regs[MAX6900_REG_MN]);
-       tm->tm_hour = BCD2BIN(regs[MAX6900_REG_HR] & 0x3f);
-       tm->tm_mday = BCD2BIN(regs[MAX6900_REG_DT]);
-       tm->tm_mon = BCD2BIN(regs[MAX6900_REG_MO]) - 1;
-       tm->tm_year = BCD2BIN(regs[MAX6900_REG_YR]) +
-           BCD2BIN(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
-       tm->tm_wday = BCD2BIN(regs[MAX6900_REG_DW]);
+       tm->tm_sec = bcd2bin(regs[MAX6900_REG_SC]);
+       tm->tm_min = bcd2bin(regs[MAX6900_REG_MN]);
+       tm->tm_hour = bcd2bin(regs[MAX6900_REG_HR] & 0x3f);
+       tm->tm_mday = bcd2bin(regs[MAX6900_REG_DT]);
+       tm->tm_mon = bcd2bin(regs[MAX6900_REG_MO]) - 1;
+       tm->tm_year = bcd2bin(regs[MAX6900_REG_YR]) +
+                     bcd2bin(regs[MAX6900_REG_CENTURY]) * 100 - 1900;
+       tm->tm_wday = bcd2bin(regs[MAX6900_REG_DW]);
 
        return 0;
 }
@@ -184,14 +184,14 @@ max6900_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
        if (rc < 0)
                return rc;
 
-       regs[MAX6900_REG_SC] = BIN2BCD(tm->tm_sec);
-       regs[MAX6900_REG_MN] = BIN2BCD(tm->tm_min);
-       regs[MAX6900_REG_HR] = BIN2BCD(tm->tm_hour);
-       regs[MAX6900_REG_DT] = BIN2BCD(tm->tm_mday);
-       regs[MAX6900_REG_MO] = BIN2BCD(tm->tm_mon + 1);
-       regs[MAX6900_REG_DW] = BIN2BCD(tm->tm_wday);
-       regs[MAX6900_REG_YR] = BIN2BCD(tm->tm_year % 100);
-       regs[MAX6900_REG_CENTURY] = BIN2BCD((tm->tm_year + 1900) / 100);
+       regs[MAX6900_REG_SC] = bin2bcd(tm->tm_sec);
+       regs[MAX6900_REG_MN] = bin2bcd(tm->tm_min);
+       regs[MAX6900_REG_HR] = bin2bcd(tm->tm_hour);
+       regs[MAX6900_REG_DT] = bin2bcd(tm->tm_mday);
+       regs[MAX6900_REG_MO] = bin2bcd(tm->tm_mon + 1);
+       regs[MAX6900_REG_DW] = bin2bcd(tm->tm_wday);
+       regs[MAX6900_REG_YR] = bin2bcd(tm->tm_year % 100);
+       regs[MAX6900_REG_CENTURY] = bin2bcd((tm->tm_year + 1900) / 100);
        /* set write protect */
        regs[MAX6900_REG_CT] = MAX6900_REG_CT_WP;
 
index 78b2551fb19def5e380aa73f70f424c6e500e91e..2f6507df7b49bddbc517130d645183948c7ceec8 100644 (file)
@@ -124,15 +124,15 @@ static int max6902_get_datetime(struct device *dev, struct rtc_time *dt)
 
        /* The chip sends data in this order:
         * Seconds, Minutes, Hours, Date, Month, Day, Year */
-       dt->tm_sec      = BCD2BIN(chip->buf[1]);
-       dt->tm_min      = BCD2BIN(chip->buf[2]);
-       dt->tm_hour     = BCD2BIN(chip->buf[3]);
-       dt->tm_mday     = BCD2BIN(chip->buf[4]);
-       dt->tm_mon      = BCD2BIN(chip->buf[5]) - 1;
-       dt->tm_wday     = BCD2BIN(chip->buf[6]);
-       dt->tm_year = BCD2BIN(chip->buf[7]);
+       dt->tm_sec      = bcd2bin(chip->buf[1]);
+       dt->tm_min      = bcd2bin(chip->buf[2]);
+       dt->tm_hour     = bcd2bin(chip->buf[3]);
+       dt->tm_mday     = bcd2bin(chip->buf[4]);
+       dt->tm_mon      = bcd2bin(chip->buf[5]) - 1;
+       dt->tm_wday     = bcd2bin(chip->buf[6]);
+       dt->tm_year = bcd2bin(chip->buf[7]);
 
-       century = BCD2BIN(tmp) * 100;
+       century = bcd2bin(tmp) * 100;
 
        dt->tm_year += century;
        dt->tm_year -= 1900;
@@ -168,15 +168,15 @@ static int max6902_set_datetime(struct device *dev, struct rtc_time *dt)
        /* Remove write protection */
        max6902_set_reg(dev, 0xF, 0);
 
-       max6902_set_reg(dev, 0x01, BIN2BCD(dt->tm_sec));
-       max6902_set_reg(dev, 0x03, BIN2BCD(dt->tm_min));
-       max6902_set_reg(dev, 0x05, BIN2BCD(dt->tm_hour));
+       max6902_set_reg(dev, 0x01, bin2bcd(dt->tm_sec));
+       max6902_set_reg(dev, 0x03, bin2bcd(dt->tm_min));
+       max6902_set_reg(dev, 0x05, bin2bcd(dt->tm_hour));
 
-       max6902_set_reg(dev, 0x07, BIN2BCD(dt->tm_mday));
-       max6902_set_reg(dev, 0x09, BIN2BCD(dt->tm_mon+1));
-       max6902_set_reg(dev, 0x0B, BIN2BCD(dt->tm_wday));
-       max6902_set_reg(dev, 0x0D, BIN2BCD(dt->tm_year%100));
-       max6902_set_reg(dev, 0x13, BIN2BCD(dt->tm_year/100));
+       max6902_set_reg(dev, 0x07, bin2bcd(dt->tm_mday));
+       max6902_set_reg(dev, 0x09, bin2bcd(dt->tm_mon+1));
+       max6902_set_reg(dev, 0x0B, bin2bcd(dt->tm_wday));
+       max6902_set_reg(dev, 0x0D, bin2bcd(dt->tm_year%100));
+       max6902_set_reg(dev, 0x13, bin2bcd(dt->tm_year/100));
 
        /* Compulab used a delay here. However, the datasheet
         * does not mention a delay being required anywhere... */
index 8876605d4d4bbc746a56da23169e4c190cbb4e6c..2cbeb0794f142f2172b75566ed6e4929315f99f1 100644 (file)
@@ -186,30 +186,30 @@ static int tm2bcd(struct rtc_time *tm)
        if (rtc_valid_tm(tm) != 0)
                return -EINVAL;
 
-       tm->tm_sec = BIN2BCD(tm->tm_sec);
-       tm->tm_min = BIN2BCD(tm->tm_min);
-       tm->tm_hour = BIN2BCD(tm->tm_hour);
-       tm->tm_mday = BIN2BCD(tm->tm_mday);
+       tm->tm_sec = bin2bcd(tm->tm_sec);
+       tm->tm_min = bin2bcd(tm->tm_min);
+       tm->tm_hour = bin2bcd(tm->tm_hour);
+       tm->tm_mday = bin2bcd(tm->tm_mday);
 
-       tm->tm_mon = BIN2BCD(tm->tm_mon + 1);
+       tm->tm_mon = bin2bcd(tm->tm_mon + 1);
 
        /* epoch == 1900 */
        if (tm->tm_year < 100 || tm->tm_year > 199)
                return -EINVAL;
-       tm->tm_year = BIN2BCD(tm->tm_year - 100);
+       tm->tm_year = bin2bcd(tm->tm_year - 100);
 
        return 0;
 }
 
 static void bcd2tm(struct rtc_time *tm)
 {
-       tm->tm_sec = BCD2BIN(tm->tm_sec);
-       tm->tm_min = BCD2BIN(tm->tm_min);
-       tm->tm_hour = BCD2BIN(tm->tm_hour);
-       tm->tm_mday = BCD2BIN(tm->tm_mday);
-       tm->tm_mon = BCD2BIN(tm->tm_mon) - 1;
+       tm->tm_sec = bcd2bin(tm->tm_sec);
+       tm->tm_min = bcd2bin(tm->tm_min);
+       tm->tm_hour = bcd2bin(tm->tm_hour);
+       tm->tm_mday = bcd2bin(tm->tm_mday);
+       tm->tm_mon = bcd2bin(tm->tm_mon) - 1;
        /* epoch == 1900 */
-       tm->tm_year = BCD2BIN(tm->tm_year) + 100;
+       tm->tm_year = bcd2bin(tm->tm_year) + 100;
 }
 
 
index a829f20ad6d6eb140d56d246ab620af0640507d7..b725913ccbe805ecb843252277c02ae8fc4169b0 100644 (file)
@@ -97,13 +97,13 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)
                buf[8]);
 
 
-       tm->tm_sec = BCD2BIN(buf[PCF8563_REG_SC] & 0x7F);
-       tm->tm_min = BCD2BIN(buf[PCF8563_REG_MN] & 0x7F);
-       tm->tm_hour = BCD2BIN(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
-       tm->tm_mday = BCD2BIN(buf[PCF8563_REG_DM] & 0x3F);
+       tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
+       tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
+       tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
+       tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F);
        tm->tm_wday = buf[PCF8563_REG_DW] & 0x07;
-       tm->tm_mon = BCD2BIN(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
-       tm->tm_year = BCD2BIN(buf[PCF8563_REG_YR]);
+       tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
+       tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]);
        if (tm->tm_year < 70)
                tm->tm_year += 100;     /* assume we are in 1970...2069 */
        /* detect the polarity heuristically. see note above. */
@@ -138,17 +138,17 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
        /* hours, minutes and seconds */
-       buf[PCF8563_REG_SC] = BIN2BCD(tm->tm_sec);
-       buf[PCF8563_REG_MN] = BIN2BCD(tm->tm_min);
-       buf[PCF8563_REG_HR] = BIN2BCD(tm->tm_hour);
+       buf[PCF8563_REG_SC] = bin2bcd(tm->tm_sec);
+       buf[PCF8563_REG_MN] = bin2bcd(tm->tm_min);
+       buf[PCF8563_REG_HR] = bin2bcd(tm->tm_hour);
 
-       buf[PCF8563_REG_DM] = BIN2BCD(tm->tm_mday);
+       buf[PCF8563_REG_DM] = bin2bcd(tm->tm_mday);
 
        /* month, 1 - 12 */
-       buf[PCF8563_REG_MO] = BIN2BCD(tm->tm_mon + 1);
+       buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1);
 
        /* year and century */
-       buf[PCF8563_REG_YR] = BIN2BCD(tm->tm_year % 100);
+       buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100);
        if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100))
                buf[PCF8563_REG_MO] |= PCF8563_MO_C;
 
index d388c662bf4b6b630909187a9fbc5370e3c97c7f..7d33cda3f8f6cc5f00331635cc86ca32ddd62283 100644 (file)
@@ -76,11 +76,11 @@ static int pcf8583_get_datetime(struct i2c_client *client, struct rtc_time *dt)
                buf[4] &= 0x3f;
                buf[5] &= 0x1f;
 
-               dt->tm_sec = BCD2BIN(buf[1]);
-               dt->tm_min = BCD2BIN(buf[2]);
-               dt->tm_hour = BCD2BIN(buf[3]);
-               dt->tm_mday = BCD2BIN(buf[4]);
-               dt->tm_mon = BCD2BIN(buf[5]) - 1;
+               dt->tm_sec = bcd2bin(buf[1]);
+               dt->tm_min = bcd2bin(buf[2]);
+               dt->tm_hour = bcd2bin(buf[3]);
+               dt->tm_mday = bcd2bin(buf[4]);
+               dt->tm_mon = bcd2bin(buf[5]) - 1;
        }
 
        return ret == 2 ? 0 : -EIO;
@@ -94,14 +94,14 @@ static int pcf8583_set_datetime(struct i2c_client *client, struct rtc_time *dt,
        buf[0] = 0;
        buf[1] = get_ctrl(client) | 0x80;
        buf[2] = 0;
-       buf[3] = BIN2BCD(dt->tm_sec);
-       buf[4] = BIN2BCD(dt->tm_min);
-       buf[5] = BIN2BCD(dt->tm_hour);
+       buf[3] = bin2bcd(dt->tm_sec);
+       buf[4] = bin2bcd(dt->tm_min);
+       buf[5] = bin2bcd(dt->tm_hour);
 
        if (datetoo) {
                len = 8;
-               buf[6] = BIN2BCD(dt->tm_mday) | (dt->tm_year << 6);
-               buf[7] = BIN2BCD(dt->tm_mon + 1)  | (dt->tm_wday << 5);
+               buf[6] = bin2bcd(dt->tm_mday) | (dt->tm_year << 6);
+               buf[7] = bin2bcd(dt->tm_mon + 1)  | (dt->tm_wday << 5);
        }
 
        ret = i2c_master_send(client, (char *)buf, len);
index 395985b339c933a2c0afa17bff1f38fc78e6bf17..42028f233bef6d596ae05c632cb50cbbd1845892 100644 (file)
@@ -80,13 +80,13 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
 
        memset(dt, 0, sizeof(*dt));
 
-       dt->tm_sec = BCD2BIN(buf[0]); /* RSECCNT */
-       dt->tm_min = BCD2BIN(buf[1]); /* RMINCNT */
-       dt->tm_hour = BCD2BIN(buf[2]); /* RHRCNT */
+       dt->tm_sec = bcd2bin(buf[0]); /* RSECCNT */
+       dt->tm_min = bcd2bin(buf[1]); /* RMINCNT */
+       dt->tm_hour = bcd2bin(buf[2]); /* RHRCNT */
 
-       dt->tm_mday = BCD2BIN(buf[3]); /* RDAYCNT */
-       dt->tm_mon = BCD2BIN(buf[4]) - 1; /* RMONCNT */
-       dt->tm_year = BCD2BIN(buf[5]) + 100; /* RYRCNT */
+       dt->tm_mday = bcd2bin(buf[3]); /* RDAYCNT */
+       dt->tm_mon = bcd2bin(buf[4]) - 1; /* RMONCNT */
+       dt->tm_year = bcd2bin(buf[5]) + 100; /* RYRCNT */
 
        /* the rtc device may contain illegal values on power up
         * according to the data sheet. make sure they are valid.
@@ -103,12 +103,12 @@ static int r9701_set_datetime(struct device *dev, struct rtc_time *dt)
        if (year >= 2100 || year < 2000)
                return -EINVAL;
 
-       ret = write_reg(dev, RHRCNT, BIN2BCD(dt->tm_hour));
-       ret = ret ? ret : write_reg(dev, RMINCNT, BIN2BCD(dt->tm_min));
-       ret = ret ? ret : write_reg(dev, RSECCNT, BIN2BCD(dt->tm_sec));
-       ret = ret ? ret : write_reg(dev, RDAYCNT, BIN2BCD(dt->tm_mday));
-       ret = ret ? ret : write_reg(dev, RMONCNT, BIN2BCD(dt->tm_mon + 1));
-       ret = ret ? ret : write_reg(dev, RYRCNT, BIN2BCD(dt->tm_year - 100));
+       ret = write_reg(dev, RHRCNT, bin2bcd(dt->tm_hour));
+       ret = ret ? ret : write_reg(dev, RMINCNT, bin2bcd(dt->tm_min));
+       ret = ret ? ret : write_reg(dev, RSECCNT, bin2bcd(dt->tm_sec));
+       ret = ret ? ret : write_reg(dev, RDAYCNT, bin2bcd(dt->tm_mday));
+       ret = ret ? ret : write_reg(dev, RMONCNT, bin2bcd(dt->tm_mon + 1));
+       ret = ret ? ret : write_reg(dev, RYRCNT, bin2bcd(dt->tm_year - 100));
        ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday);
 
        return ret;
index 1c14d4497c4db8bffc37148b138e8b17070eaf28..e6ea3f5ee1eb84836999111aff709888e9012c55 100644 (file)
@@ -235,33 +235,33 @@ static int rs5c313_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
        data = rs5c313_read_reg(RS5C313_ADDR_SEC);
        data |= (rs5c313_read_reg(RS5C313_ADDR_SEC10) << 4);
-       tm->tm_sec = BCD2BIN(data);
+       tm->tm_sec = bcd2bin(data);
 
        data = rs5c313_read_reg(RS5C313_ADDR_MIN);
        data |= (rs5c313_read_reg(RS5C313_ADDR_MIN10) << 4);
-       tm->tm_min = BCD2BIN(data);
+       tm->tm_min = bcd2bin(data);
 
        data = rs5c313_read_reg(RS5C313_ADDR_HOUR);
        data |= (rs5c313_read_reg(RS5C313_ADDR_HOUR10) << 4);
-       tm->tm_hour = BCD2BIN(data);
+       tm->tm_hour = bcd2bin(data);
 
        data = rs5c313_read_reg(RS5C313_ADDR_DAY);
        data |= (rs5c313_read_reg(RS5C313_ADDR_DAY10) << 4);
-       tm->tm_mday = BCD2BIN(data);
+       tm->tm_mday = bcd2bin(data);
 
        data = rs5c313_read_reg(RS5C313_ADDR_MON);
        data |= (rs5c313_read_reg(RS5C313_ADDR_MON10) << 4);
-       tm->tm_mon = BCD2BIN(data) - 1;
+       tm->tm_mon = bcd2bin(data) - 1;
 
        data = rs5c313_read_reg(RS5C313_ADDR_YEAR);
        data |= (rs5c313_read_reg(RS5C313_ADDR_YEAR10) << 4);
-       tm->tm_year = BCD2BIN(data);
+       tm->tm_year = bcd2bin(data);
 
        if (tm->tm_year < 70)
                tm->tm_year += 100;
 
        data = rs5c313_read_reg(RS5C313_ADDR_WEEK);
-       tm->tm_wday = BCD2BIN(data);
+       tm->tm_wday = bcd2bin(data);
 
        RS5C313_CEDISABLE;
        ndelay(700);            /* CE:L */
@@ -294,31 +294,31 @@ static int rs5c313_rtc_set_time(struct device *dev, struct rtc_time *tm)
                }
        }
 
-       data = BIN2BCD(tm->tm_sec);
+       data = bin2bcd(tm->tm_sec);
        rs5c313_write_reg(RS5C313_ADDR_SEC, data);
        rs5c313_write_reg(RS5C313_ADDR_SEC10, (data >> 4));
 
-       data = BIN2BCD(tm->tm_min);
+       data = bin2bcd(tm->tm_min);
        rs5c313_write_reg(RS5C313_ADDR_MIN, data );
        rs5c313_write_reg(RS5C313_ADDR_MIN10, (data >> 4));
 
-       data = BIN2BCD(tm->tm_hour);
+       data = bin2bcd(tm->tm_hour);
        rs5c313_write_reg(RS5C313_ADDR_HOUR, data);
        rs5c313_write_reg(RS5C313_ADDR_HOUR10, (data >> 4));
 
-       data = BIN2BCD(tm->tm_mday);
+       data = bin2bcd(tm->tm_mday);
        rs5c313_write_reg(RS5C313_ADDR_DAY, data);
        rs5c313_write_reg(RS5C313_ADDR_DAY10, (data>> 4));
 
-       data = BIN2BCD(tm->tm_mon + 1);
+       data = bin2bcd(tm->tm_mon + 1);
        rs5c313_write_reg(RS5C313_ADDR_MON, data);
        rs5c313_write_reg(RS5C313_ADDR_MON10, (data >> 4));
 
-       data = BIN2BCD(tm->tm_year % 100);
+       data = bin2bcd(tm->tm_year % 100);
        rs5c313_write_reg(RS5C313_ADDR_YEAR, data);
        rs5c313_write_reg(RS5C313_ADDR_YEAR10, (data >> 4));
 
-       data = BIN2BCD(tm->tm_wday);
+       data = bin2bcd(tm->tm_wday);
        rs5c313_write_reg(RS5C313_ADDR_WEEK, data);
 
        RS5C313_CEDISABLE;      /* CE:H */
index 839462659afa4c386c46758c5eed872a61df27d1..dd1e2bc7a472093a77e76719478e6ea1c6f02ae7 100644 (file)
@@ -74,20 +74,20 @@ rs5c348_rtc_set_time(struct device *dev, struct rtc_time *tm)
        txbuf[3] = 0;   /* dummy */
        txbuf[4] = RS5C348_CMD_MW(RS5C348_REG_SECS); /* cmd, sec, ... */
        txp = &txbuf[5];
-       txp[RS5C348_REG_SECS] = BIN2BCD(tm->tm_sec);
-       txp[RS5C348_REG_MINS] = BIN2BCD(tm->tm_min);
+       txp[RS5C348_REG_SECS] = bin2bcd(tm->tm_sec);
+       txp[RS5C348_REG_MINS] = bin2bcd(tm->tm_min);
        if (pdata->rtc_24h) {
-               txp[RS5C348_REG_HOURS] = BIN2BCD(tm->tm_hour);
+               txp[RS5C348_REG_HOURS] = bin2bcd(tm->tm_hour);
        } else {
                /* hour 0 is AM12, noon is PM12 */
-               txp[RS5C348_REG_HOURS] = BIN2BCD((tm->tm_hour + 11) % 12 + 1) |
+               txp[RS5C348_REG_HOURS] = bin2bcd((tm->tm_hour + 11) % 12 + 1) |
                        (tm->tm_hour >= 12 ? RS5C348_BIT_PM : 0);
        }
-       txp[RS5C348_REG_WDAY] = BIN2BCD(tm->tm_wday);
-       txp[RS5C348_REG_DAY] = BIN2BCD(tm->tm_mday);
-       txp[RS5C348_REG_MONTH] = BIN2BCD(tm->tm_mon + 1) |
+       txp[RS5C348_REG_WDAY] = bin2bcd(tm->tm_wday);
+       txp[RS5C348_REG_DAY] = bin2bcd(tm->tm_mday);
+       txp[RS5C348_REG_MONTH] = bin2bcd(tm->tm_mon + 1) |
                (tm->tm_year >= 100 ? RS5C348_BIT_Y2K : 0);
-       txp[RS5C348_REG_YEAR] = BIN2BCD(tm->tm_year % 100);
+       txp[RS5C348_REG_YEAR] = bin2bcd(tm->tm_year % 100);
        /* write in one transfer to avoid data inconsistency */
        ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), NULL, 0);
        udelay(62);     /* Tcsr 62us */
@@ -116,20 +116,20 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm)
        if (ret < 0)
                return ret;
 
-       tm->tm_sec = BCD2BIN(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK);
-       tm->tm_min = BCD2BIN(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
-       tm->tm_hour = BCD2BIN(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
+       tm->tm_sec = bcd2bin(rxbuf[RS5C348_REG_SECS] & RS5C348_SECS_MASK);
+       tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK);
+       tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK);
        if (!pdata->rtc_24h) {
                tm->tm_hour %= 12;
                if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM)
                        tm->tm_hour += 12;
        }
-       tm->tm_wday = BCD2BIN(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
-       tm->tm_mday = BCD2BIN(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
+       tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK);
+       tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK);
        tm->tm_mon =
-               BCD2BIN(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1;
+               bcd2bin(rxbuf[RS5C348_REG_MONTH] & RS5C348_MONTH_MASK) - 1;
        /* year is 1900 + tm->tm_year */
-       tm->tm_year = BCD2BIN(rxbuf[RS5C348_REG_YEAR]) +
+       tm->tm_year = bcd2bin(rxbuf[RS5C348_REG_YEAR]) +
                ((rxbuf[RS5C348_REG_MONTH] & RS5C348_BIT_Y2K) ? 100 : 0);
 
        if (rtc_valid_tm(tm) < 0) {
index 8b561958fb1e62056c62ef2aabe37742ab2cd395..2f2c68d476daa924028e167be775859d35ce21b4 100644 (file)
@@ -148,9 +148,9 @@ static unsigned rs5c_reg2hr(struct rs5c372 *rs5c, unsigned reg)
        unsigned        hour;
 
        if (rs5c->time24)
-               return BCD2BIN(reg & 0x3f);
+               return bcd2bin(reg & 0x3f);
 
-       hour = BCD2BIN(reg & 0x1f);
+       hour = bcd2bin(reg & 0x1f);
        if (hour == 12)
                hour = 0;
        if (reg & 0x20)
@@ -161,15 +161,15 @@ static unsigned rs5c_reg2hr(struct rs5c372 *rs5c, unsigned reg)
 static unsigned rs5c_hr2reg(struct rs5c372 *rs5c, unsigned hour)
 {
        if (rs5c->time24)
-               return BIN2BCD(hour);
+               return bin2bcd(hour);
 
        if (hour > 12)
-               return 0x20 | BIN2BCD(hour - 12);
+               return 0x20 | bin2bcd(hour - 12);
        if (hour == 12)
-               return 0x20 | BIN2BCD(12);
+               return 0x20 | bin2bcd(12);
        if (hour == 0)
-               return BIN2BCD(12);
-       return BIN2BCD(hour);
+               return bin2bcd(12);
+       return bin2bcd(hour);
 }
 
 static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
@@ -180,18 +180,18 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        if (status < 0)
                return status;
 
-       tm->tm_sec = BCD2BIN(rs5c->regs[RS5C372_REG_SECS] & 0x7f);
-       tm->tm_min = BCD2BIN(rs5c->regs[RS5C372_REG_MINS] & 0x7f);
+       tm->tm_sec = bcd2bin(rs5c->regs[RS5C372_REG_SECS] & 0x7f);
+       tm->tm_min = bcd2bin(rs5c->regs[RS5C372_REG_MINS] & 0x7f);
        tm->tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C372_REG_HOURS]);
 
-       tm->tm_wday = BCD2BIN(rs5c->regs[RS5C372_REG_WDAY] & 0x07);
-       tm->tm_mday = BCD2BIN(rs5c->regs[RS5C372_REG_DAY] & 0x3f);
+       tm->tm_wday = bcd2bin(rs5c->regs[RS5C372_REG_WDAY] & 0x07);
+       tm->tm_mday = bcd2bin(rs5c->regs[RS5C372_REG_DAY] & 0x3f);
 
        /* tm->tm_mon is zero-based */
-       tm->tm_mon = BCD2BIN(rs5c->regs[RS5C372_REG_MONTH] & 0x1f) - 1;
+       tm->tm_mon = bcd2bin(rs5c->regs[RS5C372_REG_MONTH] & 0x1f) - 1;
 
        /* year is 1900 + tm->tm_year */
-       tm->tm_year = BCD2BIN(rs5c->regs[RS5C372_REG_YEAR]) + 100;
+       tm->tm_year = bcd2bin(rs5c->regs[RS5C372_REG_YEAR]) + 100;
 
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
                "mday=%d, mon=%d, year=%d, wday=%d\n",
@@ -216,13 +216,13 @@ static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
                tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
        addr   = RS5C_ADDR(RS5C372_REG_SECS);
-       buf[0] = BIN2BCD(tm->tm_sec);
-       buf[1] = BIN2BCD(tm->tm_min);
+       buf[0] = bin2bcd(tm->tm_sec);
+       buf[1] = bin2bcd(tm->tm_min);
        buf[2] = rs5c_hr2reg(rs5c, tm->tm_hour);
-       buf[3] = BIN2BCD(tm->tm_wday);
-       buf[4] = BIN2BCD(tm->tm_mday);
-       buf[5] = BIN2BCD(tm->tm_mon + 1);
-       buf[6] = BIN2BCD(tm->tm_year - 100);
+       buf[3] = bin2bcd(tm->tm_wday);
+       buf[4] = bin2bcd(tm->tm_mday);
+       buf[5] = bin2bcd(tm->tm_mon + 1);
+       buf[6] = bin2bcd(tm->tm_year - 100);
 
        if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) {
                dev_err(&client->dev, "%s: write error\n", __func__);
@@ -367,7 +367,7 @@ static int rs5c_read_alarm(struct device *dev, struct rtc_wkalrm *t)
 
        /* report alarm time */
        t->time.tm_sec = 0;
-       t->time.tm_min = BCD2BIN(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
+       t->time.tm_min = bcd2bin(rs5c->regs[RS5C_REG_ALARM_A_MIN] & 0x7f);
        t->time.tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C_REG_ALARM_A_HOURS]);
        t->time.tm_mday = -1;
        t->time.tm_mon = -1;
@@ -413,7 +413,7 @@ static int rs5c_set_alarm(struct device *dev, struct rtc_wkalrm *t)
        }
 
        /* set alarm */
-       buf[0] = BIN2BCD(t->time.tm_min);
+       buf[0] = bin2bcd(t->time.tm_min);
        buf[1] = rs5c_hr2reg(rs5c, t->time.tm_hour);
        buf[2] = 0x7f;  /* any/all days */
 
index a6fa1f2f2ca6b59726ab099e46a698b4e26cae2d..def4d396d0b096cef968a5572f2b5122d92eeb33 100644 (file)
@@ -104,12 +104,12 @@ static int s35390a_disable_test_mode(struct s35390a *s35390a)
 static char s35390a_hr2reg(struct s35390a *s35390a, int hour)
 {
        if (s35390a->twentyfourhour)
-               return BIN2BCD(hour);
+               return bin2bcd(hour);
 
        if (hour < 12)
-               return BIN2BCD(hour);
+               return bin2bcd(hour);
 
-       return 0x40 | BIN2BCD(hour - 12);
+       return 0x40 | bin2bcd(hour - 12);
 }
 
 static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
@@ -117,9 +117,9 @@ static int s35390a_reg2hr(struct s35390a *s35390a, char reg)
        unsigned hour;
 
        if (s35390a->twentyfourhour)
-               return BCD2BIN(reg & 0x3f);
+               return bcd2bin(reg & 0x3f);
 
-       hour = BCD2BIN(reg & 0x3f);
+       hour = bcd2bin(reg & 0x3f);
        if (reg & 0x40)
                hour += 12;
 
@@ -137,13 +137,13 @@ static int s35390a_set_datetime(struct i2c_client *client, struct rtc_time *tm)
                tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year,
                tm->tm_wday);
 
-       buf[S35390A_BYTE_YEAR] = BIN2BCD(tm->tm_year - 100);
-       buf[S35390A_BYTE_MONTH] = BIN2BCD(tm->tm_mon + 1);
-       buf[S35390A_BYTE_DAY] = BIN2BCD(tm->tm_mday);
-       buf[S35390A_BYTE_WDAY] = BIN2BCD(tm->tm_wday);
+       buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100);
+       buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1);
+       buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday);
+       buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday);
        buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour);
-       buf[S35390A_BYTE_MINS] = BIN2BCD(tm->tm_min);
-       buf[S35390A_BYTE_SECS] = BIN2BCD(tm->tm_sec);
+       buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min);
+       buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec);
 
        /* This chip expects the bits of each byte to be in reverse order */
        for (i = 0; i < 7; ++i)
@@ -168,13 +168,13 @@ static int s35390a_get_datetime(struct i2c_client *client, struct rtc_time *tm)
        for (i = 0; i < 7; ++i)
                buf[i] = bitrev8(buf[i]);
 
-       tm->tm_sec = BCD2BIN(buf[S35390A_BYTE_SECS]);
-       tm->tm_min = BCD2BIN(buf[S35390A_BYTE_MINS]);
+       tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]);
+       tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]);
        tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]);
-       tm->tm_wday = BCD2BIN(buf[S35390A_BYTE_WDAY]);
-       tm->tm_mday = BCD2BIN(buf[S35390A_BYTE_DAY]);
-       tm->tm_mon = BCD2BIN(buf[S35390A_BYTE_MONTH]) - 1;
-       tm->tm_year = BCD2BIN(buf[S35390A_BYTE_YEAR]) + 100;
+       tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]);
+       tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]);
+       tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1;
+       tm->tm_year = bcd2bin(buf[S35390A_BYTE_YEAR]) + 100;
 
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, mday=%d, "
                "mon=%d, year=%d, wday=%d\n", __func__, tm->tm_sec,
index e7d19b6c265af6e5a285778309d2047f46c82585..910bc704939c2c77c7448149819d5284dfe64a67 100644 (file)
@@ -134,12 +134,12 @@ static int s3c_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
                 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
                 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
 
-       BCD_TO_BIN(rtc_tm->tm_sec);
-       BCD_TO_BIN(rtc_tm->tm_min);
-       BCD_TO_BIN(rtc_tm->tm_hour);
-       BCD_TO_BIN(rtc_tm->tm_mday);
-       BCD_TO_BIN(rtc_tm->tm_mon);
-       BCD_TO_BIN(rtc_tm->tm_year);
+       rtc_tm->tm_sec = bcd2bin(rtc_tm->tm_sec);
+       rtc_tm->tm_min = bcd2bin(rtc_tm->tm_min);
+       rtc_tm->tm_hour = bcd2bin(rtc_tm->tm_hour);
+       rtc_tm->tm_mday = bcd2bin(rtc_tm->tm_mday);
+       rtc_tm->tm_mon = bcd2bin(rtc_tm->tm_mon);
+       rtc_tm->tm_year = bcd2bin(rtc_tm->tm_year);
 
        rtc_tm->tm_year += 100;
        rtc_tm->tm_mon -= 1;
@@ -163,12 +163,12 @@ static int s3c_rtc_settime(struct device *dev, struct rtc_time *tm)
                return -EINVAL;
        }
 
-       writeb(BIN2BCD(tm->tm_sec),  base + S3C2410_RTCSEC);
-       writeb(BIN2BCD(tm->tm_min),  base + S3C2410_RTCMIN);
-       writeb(BIN2BCD(tm->tm_hour), base + S3C2410_RTCHOUR);
-       writeb(BIN2BCD(tm->tm_mday), base + S3C2410_RTCDATE);
-       writeb(BIN2BCD(tm->tm_mon + 1), base + S3C2410_RTCMON);
-       writeb(BIN2BCD(year), base + S3C2410_RTCYEAR);
+       writeb(bin2bcd(tm->tm_sec),  base + S3C2410_RTCSEC);
+       writeb(bin2bcd(tm->tm_min),  base + S3C2410_RTCMIN);
+       writeb(bin2bcd(tm->tm_hour), base + S3C2410_RTCHOUR);
+       writeb(bin2bcd(tm->tm_mday), base + S3C2410_RTCDATE);
+       writeb(bin2bcd(tm->tm_mon + 1), base + S3C2410_RTCMON);
+       writeb(bin2bcd(year), base + S3C2410_RTCYEAR);
 
        return 0;
 }
@@ -199,34 +199,34 @@ static int s3c_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
        /* decode the alarm enable field */
 
        if (alm_en & S3C2410_RTCALM_SECEN)
-               BCD_TO_BIN(alm_tm->tm_sec);
+               alm_tm->tm_sec = bcd2bin(alm_tm->tm_sec);
        else
                alm_tm->tm_sec = 0xff;
 
        if (alm_en & S3C2410_RTCALM_MINEN)
-               BCD_TO_BIN(alm_tm->tm_min);
+               alm_tm->tm_min = bcd2bin(alm_tm->tm_min);
        else
                alm_tm->tm_min = 0xff;
 
        if (alm_en & S3C2410_RTCALM_HOUREN)
-               BCD_TO_BIN(alm_tm->tm_hour);
+               alm_tm->tm_hour = bcd2bin(alm_tm->tm_hour);
        else
                alm_tm->tm_hour = 0xff;
 
        if (alm_en & S3C2410_RTCALM_DAYEN)
-               BCD_TO_BIN(alm_tm->tm_mday);
+               alm_tm->tm_mday = bcd2bin(alm_tm->tm_mday);
        else
                alm_tm->tm_mday = 0xff;
 
        if (alm_en & S3C2410_RTCALM_MONEN) {
-               BCD_TO_BIN(alm_tm->tm_mon);
+               alm_tm->tm_mon = bcd2bin(alm_tm->tm_mon);
                alm_tm->tm_mon -= 1;
        } else {
                alm_tm->tm_mon = 0xff;
        }
 
        if (alm_en & S3C2410_RTCALM_YEAREN)
-               BCD_TO_BIN(alm_tm->tm_year);
+               alm_tm->tm_year = bcd2bin(alm_tm->tm_year);
        else
                alm_tm->tm_year = 0xffff;
 
@@ -250,17 +250,17 @@ static int s3c_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 
        if (tm->tm_sec < 60 && tm->tm_sec >= 0) {
                alrm_en |= S3C2410_RTCALM_SECEN;
-               writeb(BIN2BCD(tm->tm_sec), base + S3C2410_ALMSEC);
+               writeb(bin2bcd(tm->tm_sec), base + S3C2410_ALMSEC);
        }
 
        if (tm->tm_min < 60 && tm->tm_min >= 0) {
                alrm_en |= S3C2410_RTCALM_MINEN;
-               writeb(BIN2BCD(tm->tm_min), base + S3C2410_ALMMIN);
+               writeb(bin2bcd(tm->tm_min), base + S3C2410_ALMMIN);
        }
 
        if (tm->tm_hour < 24 && tm->tm_hour >= 0) {
                alrm_en |= S3C2410_RTCALM_HOUREN;
-               writeb(BIN2BCD(tm->tm_hour), base + S3C2410_ALMHOUR);
+               writeb(bin2bcd(tm->tm_hour), base + S3C2410_ALMHOUR);
        }
 
        pr_debug("setting S3C2410_RTCALM to %08x\n", alrm_en);
index fcead4c4cd1f339b59b84de1c2d34ea95f38f9f1..aaf9d6a337cc78181e89413353026e56b9bde272 100644 (file)
@@ -324,23 +324,23 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
                sec128 = readb(rtc->regbase + R64CNT);
 
-               tm->tm_sec      = BCD2BIN(readb(rtc->regbase + RSECCNT));
-               tm->tm_min      = BCD2BIN(readb(rtc->regbase + RMINCNT));
-               tm->tm_hour     = BCD2BIN(readb(rtc->regbase + RHRCNT));
-               tm->tm_wday     = BCD2BIN(readb(rtc->regbase + RWKCNT));
-               tm->tm_mday     = BCD2BIN(readb(rtc->regbase + RDAYCNT));
-               tm->tm_mon      = BCD2BIN(readb(rtc->regbase + RMONCNT)) - 1;
+               tm->tm_sec      = bcd2bin(readb(rtc->regbase + RSECCNT));
+               tm->tm_min      = bcd2bin(readb(rtc->regbase + RMINCNT));
+               tm->tm_hour     = bcd2bin(readb(rtc->regbase + RHRCNT));
+               tm->tm_wday     = bcd2bin(readb(rtc->regbase + RWKCNT));
+               tm->tm_mday     = bcd2bin(readb(rtc->regbase + RDAYCNT));
+               tm->tm_mon      = bcd2bin(readb(rtc->regbase + RMONCNT)) - 1;
 
                if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
                        yr  = readw(rtc->regbase + RYRCNT);
-                       yr100 = BCD2BIN(yr >> 8);
+                       yr100 = bcd2bin(yr >> 8);
                        yr &= 0xff;
                } else {
                        yr  = readb(rtc->regbase + RYRCNT);
-                       yr100 = BCD2BIN((yr == 0x99) ? 0x19 : 0x20);
+                       yr100 = bcd2bin((yr == 0x99) ? 0x19 : 0x20);
                }
 
-               tm->tm_year = (yr100 * 100 + BCD2BIN(yr)) - 1900;
+               tm->tm_year = (yr100 * 100 + bcd2bin(yr)) - 1900;
 
                sec2 = readb(rtc->regbase + R64CNT);
                cf_bit = readb(rtc->regbase + RCR1) & RCR1_CF;
@@ -382,20 +382,20 @@ static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
        tmp &= ~RCR2_START;
        writeb(tmp, rtc->regbase + RCR2);
 
-       writeb(BIN2BCD(tm->tm_sec),  rtc->regbase + RSECCNT);
-       writeb(BIN2BCD(tm->tm_min),  rtc->regbase + RMINCNT);
-       writeb(BIN2BCD(tm->tm_hour), rtc->regbase + RHRCNT);
-       writeb(BIN2BCD(tm->tm_wday), rtc->regbase + RWKCNT);
-       writeb(BIN2BCD(tm->tm_mday), rtc->regbase + RDAYCNT);
-       writeb(BIN2BCD(tm->tm_mon + 1), rtc->regbase + RMONCNT);
+       writeb(bin2bcd(tm->tm_sec),  rtc->regbase + RSECCNT);
+       writeb(bin2bcd(tm->tm_min),  rtc->regbase + RMINCNT);
+       writeb(bin2bcd(tm->tm_hour), rtc->regbase + RHRCNT);
+       writeb(bin2bcd(tm->tm_wday), rtc->regbase + RWKCNT);
+       writeb(bin2bcd(tm->tm_mday), rtc->regbase + RDAYCNT);
+       writeb(bin2bcd(tm->tm_mon + 1), rtc->regbase + RMONCNT);
 
        if (rtc->capabilities & RTC_CAP_4_DIGIT_YEAR) {
-               year = (BIN2BCD((tm->tm_year + 1900) / 100) << 8) |
-                       BIN2BCD(tm->tm_year % 100);
+               year = (bin2bcd((tm->tm_year + 1900) / 100) << 8) |
+                       bin2bcd(tm->tm_year % 100);
                writew(year, rtc->regbase + RYRCNT);
        } else {
                year = tm->tm_year % 100;
-               writeb(BIN2BCD(year), rtc->regbase + RYRCNT);
+               writeb(bin2bcd(year), rtc->regbase + RYRCNT);
        }
 
        /* Start RTC */
@@ -417,7 +417,7 @@ static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off)
        byte = readb(rtc->regbase + reg_off);
        if (byte & AR_ENB) {
                byte &= ~AR_ENB;        /* strip the enable bit */
-               value = BCD2BIN(byte);
+               value = bcd2bin(byte);
        }
 
        return value;
@@ -455,7 +455,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
        if (value < 0)
                writeb(0, rtc->regbase + reg_off);
        else
-               writeb(BIN2BCD(value) | AR_ENB,  rtc->regbase + reg_off);
+               writeb(bin2bcd(value) | AR_ENB,  rtc->regbase + reg_off);
 }
 
 static int sh_rtc_check_alarm(struct rtc_time *tm)
@@ -568,7 +568,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
        struct sh_rtc *rtc;
        struct resource *res;
        unsigned int tmp;
-       int ret = -ENOENT;
+       int ret;
 
        rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL);
        if (unlikely(!rtc))
@@ -577,26 +577,33 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev)
        spin_lock_init(&rtc->lock);
 
        /* get periodic/carry/alarm irqs */
-       rtc->periodic_irq = platform_get_irq(pdev, 0);
-       if (unlikely(rtc->periodic_irq < 0)) {
+       ret = platform_get_irq(pdev, 0);
+       if (unlikely(ret < 0)) {
+               ret = -ENOENT;
                dev_err(&pdev->dev, "No IRQ for period\n");
                goto err_badres;
        }
+       rtc->periodic_irq = ret;
 
-       rtc->carry_irq = platform_get_irq(pdev, 1);
-       if (unlikely(rtc->carry_irq < 0)) {
+       ret = platform_get_irq(pdev, 1);
+       if (unlikely(ret < 0)) {
+               ret = -ENOENT;
                dev_err(&pdev->dev, "No IRQ for carry\n");
                goto err_badres;
        }
+       rtc->carry_irq = ret;
 
-       rtc->alarm_irq = platform_get_irq(pdev, 2);
-       if (unlikely(rtc->alarm_irq < 0)) {
+       ret = platform_get_irq(pdev, 2);
+       if (unlikely(ret < 0)) {
+               ret = -ENOENT;
                dev_err(&pdev->dev, "No IRQ for alarm\n");
                goto err_badres;
        }
+       rtc->alarm_irq = ret;
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
        if (unlikely(res == NULL)) {
+               ret = -ENOENT;
                dev_err(&pdev->dev, "No IO resource\n");
                goto err_badres;
        }
index 9a7e920315fa76c6af27d307c913df0b184dadad..f4cd46e15af98830ac3c580c52563119e7bc103e 100644 (file)
@@ -82,14 +82,14 @@ static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm)
        flags = readb(pdata->ioaddr + RTC_FLAGS);
        writeb(flags | RTC_WRITE, pdata->ioaddr + RTC_FLAGS);
 
-       writeb(BIN2BCD(tm->tm_year % 100), ioaddr + RTC_YEAR);
-       writeb(BIN2BCD(tm->tm_mon + 1), ioaddr + RTC_MONTH);
-       writeb(BIN2BCD(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
-       writeb(BIN2BCD(tm->tm_mday), ioaddr + RTC_DATE);
-       writeb(BIN2BCD(tm->tm_hour), ioaddr + RTC_HOURS);
-       writeb(BIN2BCD(tm->tm_min), ioaddr + RTC_MINUTES);
-       writeb(BIN2BCD(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
-       writeb(BIN2BCD((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY);
+       writeb(bin2bcd(tm->tm_year % 100), ioaddr + RTC_YEAR);
+       writeb(bin2bcd(tm->tm_mon + 1), ioaddr + RTC_MONTH);
+       writeb(bin2bcd(tm->tm_wday) & RTC_DAY_MASK, ioaddr + RTC_DAY);
+       writeb(bin2bcd(tm->tm_mday), ioaddr + RTC_DATE);
+       writeb(bin2bcd(tm->tm_hour), ioaddr + RTC_HOURS);
+       writeb(bin2bcd(tm->tm_min), ioaddr + RTC_MINUTES);
+       writeb(bin2bcd(tm->tm_sec) & RTC_SECONDS_MASK, ioaddr + RTC_SECONDS);
+       writeb(bin2bcd((tm->tm_year + 1900) / 100), ioaddr + RTC_CENTURY);
 
        writeb(flags & ~RTC_WRITE, pdata->ioaddr + RTC_FLAGS);
        return 0;
@@ -120,14 +120,14 @@ static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm)
        year = readb(ioaddr + RTC_YEAR);
        century = readb(ioaddr + RTC_CENTURY);
        writeb(flags & ~RTC_READ, ioaddr + RTC_FLAGS);
-       tm->tm_sec = BCD2BIN(second);
-       tm->tm_min = BCD2BIN(minute);
-       tm->tm_hour = BCD2BIN(hour);
-       tm->tm_mday = BCD2BIN(day);
-       tm->tm_wday = BCD2BIN(week);
-       tm->tm_mon = BCD2BIN(month) - 1;
+       tm->tm_sec = bcd2bin(second);
+       tm->tm_min = bcd2bin(minute);
+       tm->tm_hour = bcd2bin(hour);
+       tm->tm_mday = bcd2bin(day);
+       tm->tm_wday = bcd2bin(week);
+       tm->tm_mon = bcd2bin(month) - 1;
        /* year is 1900 + tm->tm_year */
-       tm->tm_year = BCD2BIN(year) + BCD2BIN(century) * 100 - 1900;
+       tm->tm_year = bcd2bin(year) + bcd2bin(century) * 100 - 1900;
 
        if (rtc_valid_tm(tm) < 0) {
                dev_err(dev, "retrieved date/time is not valid.\n");
@@ -148,16 +148,16 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata)
        writeb(flags | RTC_WRITE, ioaddr + RTC_FLAGS);
 
        writeb(pdata->alrm_mday < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_mday),
+              0x80 : bin2bcd(pdata->alrm_mday),
               ioaddr + RTC_DATE_ALARM);
        writeb(pdata->alrm_hour < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_hour),
+              0x80 : bin2bcd(pdata->alrm_hour),
               ioaddr + RTC_HOURS_ALARM);
        writeb(pdata->alrm_min < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_min),
+              0x80 : bin2bcd(pdata->alrm_min),
               ioaddr + RTC_MINUTES_ALARM);
        writeb(pdata->alrm_sec < 0 || (pdata->irqen & RTC_UF) ?
-              0x80 : BIN2BCD(pdata->alrm_sec),
+              0x80 : bin2bcd(pdata->alrm_sec),
               ioaddr + RTC_SECONDS_ALARM);
        writeb(pdata->irqen ? RTC_INTS_AIE : 0, ioaddr + RTC_INTERRUPTS);
        readb(ioaddr + RTC_FLAGS);      /* clear interrupts */
@@ -280,7 +280,6 @@ static struct bin_attribute stk17ta8_nvram_attr = {
        .attr = {
                .name = "nvram",
                .mode = S_IRUGO | S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = RTC_OFFSET,
        .read = stk17ta8_nvram_read,
index 10025d84026812e0eab2fe1f3fa5179e411b2aca..14d4f036a7686e7c637752c95ae620df99458f77 100644 (file)
@@ -92,19 +92,19 @@ static int v3020_read_time(struct device *dev, struct rtc_time *dt)
 
        /* ...and then read constant values. */
        tmp = v3020_get_reg(chip, V3020_SECONDS);
-       dt->tm_sec      = BCD2BIN(tmp);
+       dt->tm_sec      = bcd2bin(tmp);
        tmp = v3020_get_reg(chip, V3020_MINUTES);
-       dt->tm_min      = BCD2BIN(tmp);
+       dt->tm_min      = bcd2bin(tmp);
        tmp = v3020_get_reg(chip, V3020_HOURS);
-       dt->tm_hour     = BCD2BIN(tmp);
+       dt->tm_hour     = bcd2bin(tmp);
        tmp = v3020_get_reg(chip, V3020_MONTH_DAY);
-       dt->tm_mday     = BCD2BIN(tmp);
+       dt->tm_mday     = bcd2bin(tmp);
        tmp = v3020_get_reg(chip, V3020_MONTH);
-       dt->tm_mon    = BCD2BIN(tmp) - 1;
+       dt->tm_mon    = bcd2bin(tmp) - 1;
        tmp = v3020_get_reg(chip, V3020_WEEK_DAY);
-       dt->tm_wday     = BCD2BIN(tmp);
+       dt->tm_wday     = bcd2bin(tmp);
        tmp = v3020_get_reg(chip, V3020_YEAR);
-       dt->tm_year = BCD2BIN(tmp)+100;
+       dt->tm_year = bcd2bin(tmp)+100;
 
 #ifdef DEBUG
        printk("\n%s : Read RTC values\n",__func__);
@@ -136,13 +136,13 @@ static int v3020_set_time(struct device *dev, struct rtc_time *dt)
 #endif
 
        /* Write all the values to ram... */
-       v3020_set_reg(chip, V3020_SECONDS,      BIN2BCD(dt->tm_sec));
-       v3020_set_reg(chip, V3020_MINUTES,      BIN2BCD(dt->tm_min));
-       v3020_set_reg(chip, V3020_HOURS,        BIN2BCD(dt->tm_hour));
-       v3020_set_reg(chip, V3020_MONTH_DAY,    BIN2BCD(dt->tm_mday));
-       v3020_set_reg(chip, V3020_MONTH,     BIN2BCD(dt->tm_mon + 1));
-       v3020_set_reg(chip, V3020_WEEK_DAY,     BIN2BCD(dt->tm_wday));
-       v3020_set_reg(chip, V3020_YEAR,         BIN2BCD(dt->tm_year % 100));
+       v3020_set_reg(chip, V3020_SECONDS,      bin2bcd(dt->tm_sec));
+       v3020_set_reg(chip, V3020_MINUTES,      bin2bcd(dt->tm_min));
+       v3020_set_reg(chip, V3020_HOURS,        bin2bcd(dt->tm_hour));
+       v3020_set_reg(chip, V3020_MONTH_DAY,    bin2bcd(dt->tm_mday));
+       v3020_set_reg(chip, V3020_MONTH,     bin2bcd(dt->tm_mon + 1));
+       v3020_set_reg(chip, V3020_WEEK_DAY,     bin2bcd(dt->tm_wday));
+       v3020_set_reg(chip, V3020_YEAR,         bin2bcd(dt->tm_year % 100));
 
        /* ...and set the clock. */
        v3020_set_reg(chip, V3020_CMD_RAM2CLOCK, 0);
index 7dcfba1bbfe131539af2aba38d361e53d036280e..310c10795e9a81cf0c37960a1d40fb46a743369a 100644 (file)
@@ -118,13 +118,13 @@ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
                for (i = 0; i <= 4; i++)
                        buf[i] &= 0x7F;
 
-       tm->tm_sec = BCD2BIN(buf[CCR_SEC]);
-       tm->tm_min = BCD2BIN(buf[CCR_MIN]);
-       tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
-       tm->tm_mday = BCD2BIN(buf[CCR_MDAY]);
-       tm->tm_mon = BCD2BIN(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
-       tm->tm_year = BCD2BIN(buf[CCR_YEAR])
-                       + (BCD2BIN(buf[CCR_Y2K]) * 100) - 1900;
+       tm->tm_sec = bcd2bin(buf[CCR_SEC]);
+       tm->tm_min = bcd2bin(buf[CCR_MIN]);
+       tm->tm_hour = bcd2bin(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */
+       tm->tm_mday = bcd2bin(buf[CCR_MDAY]);
+       tm->tm_mon = bcd2bin(buf[CCR_MONTH]) - 1; /* mon is 0-11 */
+       tm->tm_year = bcd2bin(buf[CCR_YEAR])
+                       + (bcd2bin(buf[CCR_Y2K]) * 100) - 1900;
        tm->tm_wday = buf[CCR_WDAY];
 
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
@@ -174,11 +174,11 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
                __func__,
                tm->tm_sec, tm->tm_min, tm->tm_hour);
 
-       buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
-       buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+       buf[CCR_SEC] = bin2bcd(tm->tm_sec);
+       buf[CCR_MIN] = bin2bcd(tm->tm_min);
 
        /* set hour and 24hr bit */
-       buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL;
+       buf[CCR_HOUR] = bin2bcd(tm->tm_hour) | X1205_HR_MIL;
 
        /* should we also set the date? */
        if (datetoo) {
@@ -187,15 +187,15 @@ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
                        __func__,
                        tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
 
-               buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+               buf[CCR_MDAY] = bin2bcd(tm->tm_mday);
 
                /* month, 1 - 12 */
-               buf[CCR_MONTH] = BIN2BCD(tm->tm_mon + 1);
+               buf[CCR_MONTH] = bin2bcd(tm->tm_mon + 1);
 
                /* year, since the rtc epoch*/
-               buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100);
+               buf[CCR_YEAR] = bin2bcd(tm->tm_year % 100);
                buf[CCR_WDAY] = tm->tm_wday & 0x07;
-               buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100);
+               buf[CCR_Y2K] = bin2bcd(tm->tm_year / 100);
        }
 
        /* If writing alarm registers, set compare bits on registers 0-4 */
@@ -437,7 +437,7 @@ static int x1205_validate_client(struct i2c_client *client)
                        return -EIO;
                }
 
-               value = BCD2BIN(reg & probe_limits_pattern[i].mask);
+               value = bcd2bin(reg & probe_limits_pattern[i].mask);
 
                if (value > probe_limits_pattern[i].max ||
                        value < probe_limits_pattern[i].min) {
index 69f8346aa288348a86a8d9885dbfd1759867c5ad..5877f29a600541d7acfaf44b8ea91fae8d74243c 100644 (file)
@@ -189,7 +189,6 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = {
        .attr = {
                .name = "mu_read",
                .mode = S_IRUSR ,
-               .owner = THIS_MODULE,
        },
        .size = 1032,
        .read = arcmsr_sysfs_iop_message_read,
@@ -199,7 +198,6 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = {
        .attr = {
                .name = "mu_write",
                .mode = S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 1032,
        .write = arcmsr_sysfs_iop_message_write,
@@ -209,7 +207,6 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = {
        .attr = {
                .name = "mu_clear",
                .mode = S_IWUSR,
-               .owner = THIS_MODULE,
        },
        .size = 1,
        .write = arcmsr_sysfs_iop_message_clear,
index 4eb3da996b369518edb0a1efa924f5c97657a614..4ad3e017213f868ed85af9a7032912194836abea 100644 (file)
@@ -223,9 +223,9 @@ int sr_cd_check(struct cdrom_device_info *cdi)
                                no_multi = 1;
                                break;
                        }
-                       min = BCD2BIN(buffer[15]);
-                       sec = BCD2BIN(buffer[16]);
-                       frame = BCD2BIN(buffer[17]);
+                       min = bcd2bin(buffer[15]);
+                       sec = bcd2bin(buffer[16]);
+                       frame = bcd2bin(buffer[17]);
                        sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
                        break;
                }
@@ -252,9 +252,9 @@ int sr_cd_check(struct cdrom_device_info *cdi)
                        }
                        if (rc != 0)
                                break;
-                       min = BCD2BIN(buffer[1]);
-                       sec = BCD2BIN(buffer[2]);
-                       frame = BCD2BIN(buffer[3]);
+                       min = bcd2bin(buffer[1]);
+                       sec = bcd2bin(buffer[2]);
+                       frame = bcd2bin(buffer[3]);
                        sector = min * CD_SECS * CD_FRAMES + sec * CD_FRAMES + frame;
                        if (sector)
                                sector -= CD_MSF_OFFSET;
index 0416ad3bc127bd6f45b3302319dd7f15aff7fafd..418b4fe9a0a1f40cbf3403974ebe2fab935802cf 100644 (file)
@@ -111,7 +111,7 @@ static struct parisc_driver serial_driver = {
        .probe          = serial_init_chip,
 };
 
-int __init probe_serial_gsc(void)
+static int __init probe_serial_gsc(void)
 {
        register_parisc_driver(&lasi_driver);
        register_parisc_driver(&serial_driver);
index 8fcb4c5b9a263b2db8897fe9360dec3943552569..7313c2edcb831b873d89156bb6200179dd642fb8 100644 (file)
@@ -1039,7 +1039,7 @@ static int __devinit serial_txx9_probe(struct platform_device *dev)
                ret = serial_txx9_register_port(&port);
                if (ret < 0) {
                        dev_err(&dev->dev, "unable to register port at index %d "
-                               "(IO%x MEM%llx IRQ%d): %d\n", i,
+                               "(IO%lx MEM%llx IRQ%d): %d\n", i,
                                p->iobase, (unsigned long long)p->mapbase,
                                p->irq, ret);
                }
index 3df2aaec829fe874a633fecc3def9d5369e64446..3b9d2d83b59008df447dfcff84bb1fc33e5f4425 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SuperH on-chip serial module support.  (SCI with no FIFO / with FIFO)
  *
- *  Copyright (C) 2002 - 2006  Paul Mundt
+ *  Copyright (C) 2002 - 2008  Paul Mundt
  *  Modified to support SH7720 SCIF. Markus Brunner, Mark Jonas (Jul 2007).
  *
  * based off of the old drivers/char/sh-sci.c by:
@@ -46,6 +46,7 @@
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/ctype.h>
+#include <linux/err.h>
 
 #ifdef CONFIG_SUPERH
 #include <asm/clock.h>
@@ -78,7 +79,7 @@ struct sci_port {
        struct timer_list       break_timer;
        int                     break_flag;
 
-#ifdef CONFIG_SUPERH
+#ifdef CONFIG_HAVE_CLK
        /* Port clock */
        struct clk              *clk;
 #endif
@@ -831,7 +832,7 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK)
 /*
  * Here we define a transistion notifier so that we can update all of our
  * ports' baud rate when the peripheral clock changes.
@@ -860,7 +861,7 @@ static int sci_notifier(struct notifier_block *self,
                         * Clean this up later..
                         */
                        clk = clk_get(NULL, "module_clk");
-                       port->uartclk = clk_get_rate(clk) * 16;
+                       port->uartclk = clk_get_rate(clk);
                        clk_put(clk);
                }
 
@@ -873,7 +874,7 @@ static int sci_notifier(struct notifier_block *self,
 }
 
 static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 };
-#endif /* CONFIG_CPU_FREQ */
+#endif /* CONFIG_CPU_FREQ && CONFIG_HAVE_CLK */
 
 static int sci_request_irq(struct sci_port *port)
 {
@@ -1008,7 +1009,7 @@ static int sci_startup(struct uart_port *port)
        if (s->enable)
                s->enable(port);
 
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#ifdef CONFIG_HAVE_CLK
        s->clk = clk_get(NULL, "module_clk");
 #endif
 
@@ -1030,7 +1031,7 @@ static void sci_shutdown(struct uart_port *port)
        if (s->disable)
                s->disable(port);
 
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#ifdef CONFIG_HAVE_CLK
        clk_put(s->clk);
        s->clk = NULL;
 #endif
@@ -1041,24 +1042,11 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
 {
        struct sci_port *s = &sci_ports[port->line];
        unsigned int status, baud, smr_val;
-       int t;
+       int t = -1;
 
        baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
-
-       switch (baud) {
-               case 0:
-                       t = -1;
-                       break;
-               default:
-               {
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
-                       t = SCBRR_VALUE(baud, clk_get_rate(s->clk));
-#else
-                       t = SCBRR_VALUE(baud);
-#endif
-                       break;
-               }
-       }
+       if (likely(baud))
+               t = SCBRR_VALUE(baud, port->uartclk);
 
        do {
                status = sci_in(port, SCxSR);
@@ -1113,7 +1101,7 @@ static const char *sci_type(struct uart_port *port)
                case PORT_IRDA: return "irda";
        }
 
-       return 0;
+       return NULL;
 }
 
 static void sci_release_port(struct uart_port *port)
@@ -1145,12 +1133,16 @@ static void sci_config_port(struct uart_port *port, int flags)
                break;
        }
 
-#if defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
-       if (port->mapbase == 0)
+       if (port->flags & UPF_IOREMAP && !port->membase) {
+#if defined(CONFIG_SUPERH64)
                port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF");
-
-       port->membase = (void __iomem *)port->mapbase;
+               port->membase = (void __iomem *)port->mapbase;
+#else
+               port->membase = ioremap_nocache(port->mapbase, 0x40);
 #endif
+
+               printk(KERN_ERR "sci: can't remap port#%d\n", port->line);
+       }
 }
 
 static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
@@ -1207,17 +1199,17 @@ static void __init sci_init_ports(void)
                sci_ports[i].disable    = h8300_sci_disable;
 #endif
                sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK;
-#elif defined(CONFIG_SUPERH64)
-               sci_ports[i].port.uartclk = current_cpu_data.module_clock * 16;
-#else
+#elif defined(CONFIG_HAVE_CLK)
                /*
                 * XXX: We should use a proper SCI/SCIF clock
                 */
                {
                        struct clk *clk = clk_get(NULL, "module_clk");
-                       sci_ports[i].port.uartclk = clk_get_rate(clk) * 16;
+                       sci_ports[i].port.uartclk = clk_get_rate(clk);
                        clk_put(clk);
                }
+#else
+#error "Need a valid uartclk"
 #endif
 
                sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i];
@@ -1285,7 +1277,7 @@ static int __init serial_console_setup(struct console *co, char *options)
 
        port->type = serial_console_port->type;
 
-#if defined(CONFIG_SUPERH) && !defined(CONFIG_SUPERH64)
+#ifdef CONFIG_HAVE_CLK
        if (!serial_console_port->clk)
                serial_console_port->clk = clk_get(NULL, "module_clk");
 #endif
@@ -1436,7 +1428,7 @@ static struct uart_driver sci_uart_driver = {
 static int __devinit sci_probe(struct platform_device *dev)
 {
        struct plat_sci_port *p = dev->dev.platform_data;
-       int i;
+       int i, ret = -EINVAL;
 
        for (i = 0; p && p->flags != 0; p++, i++) {
                struct sci_port *sciport = &sci_ports[i];
@@ -1453,12 +1445,22 @@ static int __devinit sci_probe(struct platform_device *dev)
 
                sciport->port.mapbase   = p->mapbase;
 
-               /*
-                * For the simple (and majority of) cases where we don't need
-                * to do any remapping, just cast the cookie directly.
-                */
-               if (p->mapbase && !p->membase && !(p->flags & UPF_IOREMAP))
-                       p->membase = (void __iomem *)p->mapbase;
+               if (p->mapbase && !p->membase) {
+                       if (p->flags & UPF_IOREMAP) {
+                               p->membase = ioremap_nocache(p->mapbase, 0x40);
+                               if (IS_ERR(p->membase)) {
+                                       ret = PTR_ERR(p->membase);
+                                       goto err_unreg;
+                               }
+                       } else {
+                               /*
+                                * For the simple (and majority of) cases
+                                * where we don't need to do any remapping,
+                                * just cast the cookie directly.
+                                */
+                               p->membase = (void __iomem *)p->mapbase;
+                       }
+               }
 
                sciport->port.membase   = p->membase;
 
@@ -1479,7 +1481,7 @@ static int __devinit sci_probe(struct platform_device *dev)
        kgdb_putchar    = kgdb_sci_putchar;
 #endif
 
-#ifdef CONFIG_CPU_FREQ
+#if defined(CONFIG_CPU_FREQ) && defined(CONFIG_HAVE_CLK)
        cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER);
        dev_info(&dev->dev, "CPU frequency notifier registered\n");
 #endif
@@ -1489,6 +1491,12 @@ static int __devinit sci_probe(struct platform_device *dev)
 #endif
 
        return 0;
+
+err_unreg:
+       for (i = i - 1; i >= 0; i--)
+               uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port);
+
+       return ret;
 }
 
 static int __devexit sci_remove(struct platform_device *dev)
index 8a0749e34ca3fe4e1646bc359777f97dae1bca2c..7cd28b2268001f3bea61c965f95049570f3902bf 100644 (file)
 #define SCI_EVENT_WRITE_WAKEUP 0
 
 #define SCI_IN(size, offset)                                   \
-  unsigned int addr = port->mapbase + (offset);                        \
   if ((size) == 8) {                                           \
-    return ctrl_inb(addr);                                     \
+    return ioread8(port->membase + (offset));                  \
   } else {                                                     \
-    return ctrl_inw(addr);                                     \
+    return ioread16(port->membase + (offset));                 \
   }
 #define SCI_OUT(size, offset, value)                           \
-  unsigned int addr = port->mapbase + (offset);                        \
   if ((size) == 8) {                                           \
-    ctrl_outb(value, addr);                                    \
+    iowrite8(value, port->membase + (offset));                 \
   } else if ((size) == 16) {                                   \
-    ctrl_outw(value, addr);                                    \
+    iowrite16(value, port->membase + (offset));                        \
   }
 
 #define CPU_SCIx_FNS(name, sci_offset, sci_size, scif_offset, scif_size)\
@@ -791,11 +789,16 @@ static inline int sci_rxd_in(struct uart_port *port)
       defined(CONFIG_CPU_SUBTYPE_SH7721)
 #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7723)
-#define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(16*bps)-1)
+static inline int scbrr_calc(struct uart_port *port, int bps, int clk)
+{
+       if (port->type == PORT_SCIF)
+               return (clk+16*bps)/(32*bps)-1;
+       else
+               return ((clk*2)+16*bps)/(16*bps)-1;
+}
+#define SCBRR_VALUE(bps, clk) scbrr_calc(port, bps, clk)
 #elif defined(__H8300H__) || defined(__H8300S__)
-#define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1)
-#elif defined(CONFIG_SUPERH64)
-#define SCBRR_VALUE(bps) ((current_cpu_data.module_clock+16*bps)/(32*bps)-1)
+#define SCBRR_VALUE(bps, clk) (((clk*1000/32)/bps)-1)
 #else /* Generic SH */
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(32*bps)-1)
 #endif
index b73e3c0056cd77531248a89dc2925809e61faae6..d5276c012f78f529348af32a4d227c2d969ff879 100644 (file)
@@ -61,7 +61,7 @@
 #define SN_SAL_BUFFER_SIZE (64 * (1 << 10))
 
 #define SN_SAL_UART_FIFO_DEPTH 16
-#define SN_SAL_UART_FIFO_SPEED_CPS 9600/10
+#define SN_SAL_UART_FIFO_SPEED_CPS (9600/10)
 
 /* sn_transmit_chars() calling args */
 #define TRANSMIT_BUFFERED      0
index a96f4a8cfeb8b1eec01b6e61d304bb6f441768fb..6a025cefe6dc03cfcc8ea74f4a79ba77f43314b8 100644 (file)
@@ -1,6 +1,6 @@
 #
 # Makefile for the SuperH specific drivers.
 #
-
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_MAPLE)            += maple/
+obj-y                          += intc.o
similarity index 96%
rename from arch/sh/kernel/cpu/irq/intc.c
rename to drivers/sh/intc.c
index 8c70e201bde0ff61994fc179ec02e70746b13bcc..58d24c5a76cea5732d9a8b13cca5294dc95700a0 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/bootmem.h>
+#include <linux/sh_intc.h>
 
 #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
        ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -86,24 +87,24 @@ static inline unsigned int set_field(unsigned int value,
 
 static void write_8(unsigned long addr, unsigned long h, unsigned long data)
 {
-       ctrl_outb(set_field(0, data, h), addr);
+       __raw_writeb(set_field(0, data, h), addr);
 }
 
 static void write_16(unsigned long addr, unsigned long h, unsigned long data)
 {
-       ctrl_outw(set_field(0, data, h), addr);
+       __raw_writew(set_field(0, data, h), addr);
 }
 
 static void write_32(unsigned long addr, unsigned long h, unsigned long data)
 {
-       ctrl_outl(set_field(0, data, h), addr);
+       __raw_writel(set_field(0, data, h), addr);
 }
 
 static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
 {
        unsigned long flags;
        local_irq_save(flags);
-       ctrl_outb(set_field(ctrl_inb(addr), data, h), addr);
+       __raw_writeb(set_field(__raw_readb(addr), data, h), addr);
        local_irq_restore(flags);
 }
 
@@ -111,7 +112,7 @@ static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
 {
        unsigned long flags;
        local_irq_save(flags);
-       ctrl_outw(set_field(ctrl_inw(addr), data, h), addr);
+       __raw_writew(set_field(__raw_readw(addr), data, h), addr);
        local_irq_restore(flags);
 }
 
@@ -119,7 +120,7 @@ static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
 {
        unsigned long flags;
        local_irq_save(flags);
-       ctrl_outl(set_field(ctrl_inl(addr), data, h), addr);
+       __raw_writel(set_field(__raw_readl(addr), data, h), addr);
        local_irq_restore(flags);
 }
 
@@ -246,16 +247,16 @@ static void intc_mask_ack(unsigned int irq)
                addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
                switch (_INTC_FN(handle)) {
                case REG_FN_MODIFY_BASE + 0:    /* 8bit */
-                       ctrl_inb(addr);
-                       ctrl_outb(0xff ^ set_field(0, 1, handle), addr);
+                       __raw_readb(addr);
+                       __raw_writeb(0xff ^ set_field(0, 1, handle), addr);
                        break;
                case REG_FN_MODIFY_BASE + 1:    /* 16bit */
-                       ctrl_inw(addr);
-                       ctrl_outw(0xffff ^ set_field(0, 1, handle), addr);
+                       __raw_readw(addr);
+                       __raw_writew(0xffff ^ set_field(0, 1, handle), addr);
                        break;
                case REG_FN_MODIFY_BASE + 3:    /* 32bit */
-                       ctrl_inl(addr);
-                       ctrl_outl(0xffffffff ^ set_field(0, 1, handle), addr);
+                       __raw_readl(addr);
+                       __raw_writel(0xffffffff ^ set_field(0, 1, handle), addr);
                        break;
                default:
                        BUG();
@@ -464,9 +465,10 @@ static unsigned int __init intc_prio_data(struct intc_desc *desc,
                        }
 
                        fn += (pr->reg_width >> 3) - 1;
-                       bit = pr->reg_width - ((j + 1) * pr->field_width);
 
-                       BUG_ON(bit < 0);
+                       BUG_ON((j + 1) * pr->field_width > pr->reg_width);
+
+                       bit = pr->reg_width - ((j + 1) * pr->field_width);
 
                        return _INTC_MK(fn, mode,
                                        intc_get_reg(d, reg_e),
@@ -531,9 +533,10 @@ static unsigned int __init intc_sense_data(struct intc_desc *desc,
 
                        fn = REG_FN_MODIFY_BASE;
                        fn += (sr->reg_width >> 3) - 1;
-                       bit = sr->reg_width - ((j + 1) * sr->field_width);
 
-                       BUG_ON(bit < 0);
+                       BUG_ON((j + 1) * sr->field_width > sr->reg_width);
+
+                       bit = sr->reg_width - ((j + 1) * sr->field_width);
 
                        return _INTC_MK(fn, 0, intc_get_reg(d, sr->reg),
                                        0, sr->field_width, bit);
index 57a121c338c44c61d0874a689802398afbedf65f..593fdb767aad2a6f87ddd3092d9170a8c9414c68 100644 (file)
@@ -1,10 +1,12 @@
 config VIDEO_GO7007
        tristate "Go 7007 support"
        depends on VIDEO_DEV && PCI && I2C && INPUT
+       depends on SND
        select VIDEOBUF_DMA_SG
        select VIDEO_IR
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
+       select SND_PCM
        select CRC32
        default N
        ---help---
index 1ae3508066003f99fc94abb8d14423acf00ebc09..6e6cf0b9ef99100824cd802c1135188fb738dd50 100644 (file)
@@ -1,6 +1,7 @@
 config SXG
        tristate "Alacritech SLIC Technology Non-Accelerated 10Gbe support"
        depends on PCI && NETDEV_10000
+       depends on X86
        default n
        help
          This driver supports the Alacritech SLIC Technology Non-Accelerated
index 4d74ba36c3a12b0d8acd19cd7115b154522f862b..37caf4d690370489cd7dcbd880f035c67c0c4bd2 100644 (file)
@@ -54,7 +54,6 @@ static int phone_open(struct inode *inode, struct file *file)
        if (minor >= PHONE_NUM_DEVICES)
                return -ENODEV;
 
-       lock_kernel();
        mutex_lock(&phone_lock);
        p = phone_device[minor];
        if (p)
@@ -81,7 +80,6 @@ static int phone_open(struct inode *inode, struct file *file)
        fops_put(old_fops);
 end:
        mutex_unlock(&phone_lock);
-       unlock_kernel();
        return err;
 }
 
index 6fa0b9d5559ac712c033eb0508fd21ca9a4dc08e..d4cfed0b26d5f8a83242c73769ca650805a521a5 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/backlight.h>
 
 #include <cpu/dac.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
 #include <asm/hd64461.h>
 
 #define HP680_MAX_INTENSITY 255
index 217c5118ae9e71818ea80014cb2b54cb8c63c707..cd5f20da738a0cb4e579a046c2a352a58791ea86 100644 (file)
@@ -1002,101 +1002,132 @@ fb_blank(struct fb_info *info, int blank)
        return ret;
 }
 
-static int 
-fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+static long
+fb_ioctl(struct file *file, unsigned int cmd,
         unsigned long arg)
 {
+       struct inode *inode = file->f_path.dentry->d_inode;
        int fbidx = iminor(inode);
-       struct fb_info *info = registered_fb[fbidx];
-       struct fb_ops *fb = info->fbops;
+       struct fb_info *info;
+       struct fb_ops *fb;
        struct fb_var_screeninfo var;
        struct fb_fix_screeninfo fix;
        struct fb_con2fbmap con2fb;
        struct fb_cmap_user cmap;
        struct fb_event event;
        void __user *argp = (void __user *)arg;
-       int i;
-       
-       if (!fb)
+       long ret = 0;
+
+       info = registered_fb[fbidx];
+       mutex_lock(&info->lock);
+       fb = info->fbops;
+
+       if (!fb) {
+               mutex_unlock(&info->lock);
                return -ENODEV;
+       }
        switch (cmd) {
        case FBIOGET_VSCREENINFO:
-               return copy_to_user(argp, &info->var,
+               ret = copy_to_user(argp, &info->var,
                                    sizeof(var)) ? -EFAULT : 0;
+               break;
        case FBIOPUT_VSCREENINFO:
-               if (copy_from_user(&var, argp, sizeof(var)))
-                       return -EFAULT;
+               if (copy_from_user(&var, argp, sizeof(var))) {
+                       ret =  -EFAULT;
+                       break;
+               }
                acquire_console_sem();
                info->flags |= FBINFO_MISC_USEREVENT;
-               i = fb_set_var(info, &var);
+               ret = fb_set_var(info, &var);
                info->flags &= ~FBINFO_MISC_USEREVENT;
                release_console_sem();
-               if (i) return i;
-               if (copy_to_user(argp, &var, sizeof(var)))
-                       return -EFAULT;
-               return 0;
+               if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+                       ret = -EFAULT;
+               break;
        case FBIOGET_FSCREENINFO:
-               return copy_to_user(argp, &info->fix,
+               ret = copy_to_user(argp, &info->fix,
                                    sizeof(fix)) ? -EFAULT : 0;
+               break;
        case FBIOPUTCMAP:
                if (copy_from_user(&cmap, argp, sizeof(cmap)))
-                       return -EFAULT;
-               return (fb_set_user_cmap(&cmap, info));
+                       ret = -EFAULT;
+               else
+                       ret = fb_set_user_cmap(&cmap, info);
+               break;
        case FBIOGETCMAP:
                if (copy_from_user(&cmap, argp, sizeof(cmap)))
-                       return -EFAULT;
-               return fb_cmap_to_user(&info->cmap, &cmap);
+                       ret = -EFAULT;
+               else
+                       ret = fb_cmap_to_user(&info->cmap, &cmap);
+               break;
        case FBIOPAN_DISPLAY:
-               if (copy_from_user(&var, argp, sizeof(var)))
-                       return -EFAULT;
+               if (copy_from_user(&var, argp, sizeof(var))) {
+                       ret = -EFAULT;
+                       break;
+               }
                acquire_console_sem();
-               i = fb_pan_display(info, &var);
+               ret = fb_pan_display(info, &var);
                release_console_sem();
-               if (i)
-                       return i;
-               if (copy_to_user(argp, &var, sizeof(var)))
-                       return -EFAULT;
-               return 0;
+               if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
+                       ret = -EFAULT;
+               break;
        case FBIO_CURSOR:
-               return -EINVAL;
+               ret = -EINVAL;
+               break;
        case FBIOGET_CON2FBMAP:
                if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
-                       return -EFAULT;
-               if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
-                   return -EINVAL;
-               con2fb.framebuffer = -1;
-               event.info = info;
-               event.data = &con2fb;
-               fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP, &event);
-               return copy_to_user(argp, &con2fb,
+                       ret = -EFAULT;
+               else if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
+                       ret = -EINVAL;
+               else {
+                       con2fb.framebuffer = -1;
+                       event.info = info;
+                       event.data = &con2fb;
+                       fb_notifier_call_chain(FB_EVENT_GET_CONSOLE_MAP,
+                                                               &event);
+                       ret = copy_to_user(argp, &con2fb,
                                    sizeof(con2fb)) ? -EFAULT : 0;
+               }
+               break;
        case FBIOPUT_CON2FBMAP:
-               if (copy_from_user(&con2fb, argp, sizeof(con2fb)))
-                       return - EFAULT;
-               if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES)
-                   return -EINVAL;
-               if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX)
-                   return -EINVAL;
-               if (!registered_fb[con2fb.framebuffer])
-                   request_module("fb%d", con2fb.framebuffer);
+               if (copy_from_user(&con2fb, argp, sizeof(con2fb))) {
+                       ret = -EFAULT;
+                       break;
+               }
+               if (con2fb.console < 1 || con2fb.console > MAX_NR_CONSOLES) {
+                       ret = -EINVAL;
+                       break;
+               }
+               if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) {
+                       ret = -EINVAL;
+                       break;
+               }
                if (!registered_fb[con2fb.framebuffer])
-                   return -EINVAL;
+                       request_module("fb%d", con2fb.framebuffer);
+               if (!registered_fb[con2fb.framebuffer]) {
+                       ret = -EINVAL;
+                       break;
+               }
                event.info = info;
                event.data = &con2fb;
-               return fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
+               ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP,
                                              &event);
+               break;
        case FBIOBLANK:
                acquire_console_sem();
                info->flags |= FBINFO_MISC_USEREVENT;
-               i = fb_blank(info, arg);
+               ret = fb_blank(info, arg);
                info->flags &= ~FBINFO_MISC_USEREVENT;
                release_console_sem();
-               return i;
+               break;;
        default:
                if (fb->fb_ioctl == NULL)
-                       return -EINVAL;
-               return fb->fb_ioctl(info, cmd, arg);
+                       ret = -ENOTTY;
+               else
+                       ret = fb->fb_ioctl(info, cmd, arg);
        }
+       mutex_unlock(&info->lock);
+       return ret;
 }
 
 #ifdef CONFIG_COMPAT
@@ -1150,7 +1181,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file,
            put_user(compat_ptr(data), &cmap->transp))
                return -EFAULT;
 
-       err = fb_ioctl(inode, file, cmd, (unsigned long) cmap);
+       err = fb_ioctl(file, cmd, (unsigned long) cmap);
 
        if (!err) {
                if (copy_in_user(&cmap32->start,
@@ -1204,7 +1235,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file,
 
        old_fs = get_fs();
        set_fs(KERNEL_DS);
-       err = fb_ioctl(inode, file, cmd, (unsigned long) &fix);
+       err = fb_ioctl(file, cmd, (unsigned long) &fix);
        set_fs(old_fs);
 
        if (!err)
@@ -1222,7 +1253,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        struct fb_ops *fb = info->fbops;
        long ret = -ENOIOCTLCMD;
 
-       lock_kernel();
+       mutex_lock(&info->lock);
        switch(cmd) {
        case FBIOGET_VSCREENINFO:
        case FBIOPUT_VSCREENINFO:
@@ -1231,7 +1262,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case FBIOPUT_CON2FBMAP:
                arg = (unsigned long) compat_ptr(arg);
        case FBIOBLANK:
-               ret = fb_ioctl(inode, file, cmd, arg);
+               ret = fb_ioctl(file, cmd, arg);
                break;
 
        case FBIOGET_FSCREENINFO:
@@ -1248,7 +1279,7 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                        ret = fb->fb_compat_ioctl(info, cmd, arg);
                break;
        }
-       unlock_kernel();
+       mutex_unlock(&info->lock);
        return ret;
 }
 #endif
@@ -1270,13 +1301,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
                return -ENODEV;
        if (fb->fb_mmap) {
                int res;
-               lock_kernel();
+               mutex_lock(&info->lock);
                res = fb->fb_mmap(info, vma);
-               unlock_kernel();
+               mutex_unlock(&info->lock);
                return res;
        }
 
-       lock_kernel();
+       mutex_lock(&info->lock);
 
        /* frame buffer memory */
        start = info->fix.smem_start;
@@ -1285,13 +1316,13 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
                /* memory mapped io */
                off -= len;
                if (info->var.accel_flags) {
-                       unlock_kernel();
+                       mutex_unlock(&info->lock);
                        return -EINVAL;
                }
                start = info->fix.mmio_start;
                len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
        }
-       unlock_kernel();
+       mutex_unlock(&info->lock);
        start &= PAGE_MASK;
        if ((vma->vm_end - vma->vm_start + off) > len)
                return -EINVAL;
@@ -1315,13 +1346,13 @@ fb_open(struct inode *inode, struct file *file)
 
        if (fbidx >= FB_MAX)
                return -ENODEV;
-       lock_kernel();
-       if (!(info = registered_fb[fbidx]))
+       info = registered_fb[fbidx];
+       if (!info)
                request_module("fb%d", fbidx);
-       if (!(info = registered_fb[fbidx])) {
-               res = -ENODEV;
-               goto out;
-       }
+       info = registered_fb[fbidx];
+       if (!info)
+               return -ENODEV;
+       mutex_lock(&info->lock);
        if (!try_module_get(info->fbops->owner)) {
                res = -ENODEV;
                goto out;
@@ -1337,7 +1368,7 @@ fb_open(struct inode *inode, struct file *file)
                fb_deferred_io_open(info, inode, file);
 #endif
 out:
-       unlock_kernel();
+       mutex_unlock(&info->lock);
        return res;
 }
 
@@ -1346,11 +1377,11 @@ fb_release(struct inode *inode, struct file *file)
 {
        struct fb_info * const info = file->private_data;
 
-       lock_kernel();
+       mutex_lock(&info->lock);
        if (info->fbops->fb_release)
                info->fbops->fb_release(info,1);
        module_put(info->fbops->owner);
-       unlock_kernel();
+       mutex_unlock(&info->lock);
        return 0;
 }
 
@@ -1358,7 +1389,7 @@ static const struct file_operations fb_fops = {
        .owner =        THIS_MODULE,
        .read =         fb_read,
        .write =        fb_write,
-       .ioctl =        fb_ioctl,
+       .unlocked_ioctl = fb_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl = fb_compat_ioctl,
 #endif
@@ -1429,6 +1460,7 @@ register_framebuffer(struct fb_info *fb_info)
                if (!registered_fb[i])
                        break;
        fb_info->node = i;
+       mutex_init(&fb_info->lock);
 
        fb_info->dev = device_create(fb_class, fb_info->device,
                                     MKDEV(FB_MAJOR, i), NULL, "fb%d", i);
index 4c32c06579a04c7826e56f5f5b4f87acf95eeab6..efff672fd7b8e580657440f6bb84744ae05ef1bf 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <asm/sh_mobile_lcdc.h>
+#include <video/sh_mobile_lcdc.h>
 
 #define PALETTE_NR 16
 
@@ -34,7 +34,9 @@ struct sh_mobile_lcdc_chan {
 
 struct sh_mobile_lcdc_priv {
        void __iomem *base;
+#ifdef CONFIG_HAVE_CLK
        struct clk *clk;
+#endif
        unsigned long lddckr;
        struct sh_mobile_lcdc_chan ch[2];
 };
@@ -260,6 +262,11 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
                tmp = ch->ldmt1r_value;
                tmp |= (lcd_cfg->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 1 << 28;
                tmp |= (lcd_cfg->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 1 << 27;
+               tmp |= (ch->cfg.flags & LCDC_FLAGS_DWPOL) ? 1 << 26 : 0;
+               tmp |= (ch->cfg.flags & LCDC_FLAGS_DIPOL) ? 1 << 25 : 0;
+               tmp |= (ch->cfg.flags & LCDC_FLAGS_DAPOL) ? 1 << 24 : 0;
+               tmp |= (ch->cfg.flags & LCDC_FLAGS_HSCNT) ? 1 << 17 : 0;
+               tmp |= (ch->cfg.flags & LCDC_FLAGS_DWCNT) ? 1 << 16 : 0;
                lcdc_write_chan(ch, LDMT1R, tmp);
 
                /* setup SYS bus */
@@ -422,6 +429,7 @@ static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
 
        priv->lddckr = icksel << 16;
 
+#ifdef CONFIG_HAVE_CLK
        if (str) {
                priv->clk = clk_get(dev, str);
                if (IS_ERR(priv->clk)) {
@@ -431,6 +439,7 @@ static int sh_mobile_lcdc_setup_clocks(struct device *dev, int clock_source,
 
                clk_enable(priv->clk);
        }
+#endif
 
        return 0;
 }
@@ -585,7 +594,6 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev)
                goto err1;
        }
 
-       priv->lddckr = pdata->lddckr;
        priv->base = ioremap_nocache(res->start, (res->end - res->start) + 1);
 
        for (i = 0; i < j; i++) {
@@ -688,10 +696,12 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
                fb_dealloc_cmap(&info->cmap);
        }
 
+#ifdef CONFIG_HAVE_CLK
        if (priv->clk) {
                clk_disable(priv->clk);
                clk_put(priv->clk);
        }
+#endif
 
        if (priv->base)
                iounmap(priv->base);
index ed6b0576208c27ca237670999ba328a267b350f9..1f09d4e4144c23598f3cf7560a28630fa9f6a6d3 100644 (file)
@@ -80,7 +80,6 @@ static struct bin_attribute w1_ds2760_bin_attr = {
        .attr = {
                .name = "w1_slave",
                .mode = S_IRUGO,
-               .owner = THIS_MODULE,
        },
        .size = DS2760_DATA_SIZE,
        .read = w1_ds2760_read_bin,
index d0a1174fb516c14f63862e42919d74c044df7882..4eca61c201f01a0fc81f6596fa6cd6a48417a41d 100644 (file)
@@ -1168,195 +1168,7 @@ config EFS_FS
          To compile the EFS file system support as a module, choose M here: the
          module will be called efs.
 
-config JFFS2_FS
-       tristate "Journalling Flash File System v2 (JFFS2) support"
-       select CRC32
-       depends on MTD
-       help
-         JFFS2 is the second generation of the Journalling Flash File System
-         for use on diskless embedded devices. It provides improved wear
-         levelling, compression and support for hard links. You cannot use
-         this on normal block devices, only on 'MTD' devices.
-
-         Further information on the design and implementation of JFFS2 is
-         available at <http://sources.redhat.com/jffs2/>.
-
-config JFFS2_FS_DEBUG
-       int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)"
-       depends on JFFS2_FS
-       default "0"
-       help
-         This controls the amount of debugging messages produced by the JFFS2
-         code. Set it to zero for use in production systems. For evaluation,
-         testing and debugging, it's advisable to set it to one. This will
-         enable a few assertions and will print debugging messages at the
-         KERN_DEBUG loglevel, where they won't normally be visible. Level 2
-         is unlikely to be useful - it enables extra debugging in certain
-         areas which at one point needed debugging, but when the bugs were
-         located and fixed, the detailed messages were relegated to level 2.
-
-         If reporting bugs, please try to have available a full dump of the
-         messages at debug level 1 while the misbehaviour was occurring.
-
-config JFFS2_FS_WRITEBUFFER
-       bool "JFFS2 write-buffering support"
-       depends on JFFS2_FS
-       default y
-       help
-         This enables the write-buffering support in JFFS2.
-
-         This functionality is required to support JFFS2 on the following
-         types of flash devices:
-           - NAND flash
-           - NOR flash with transparent ECC
-           - DataFlash
-
-config JFFS2_FS_WBUF_VERIFY
-       bool "Verify JFFS2 write-buffer reads"
-       depends on JFFS2_FS_WRITEBUFFER
-       default n
-       help
-         This causes JFFS2 to read back every page written through the
-         write-buffer, and check for errors.
-
-config JFFS2_SUMMARY
-       bool "JFFS2 summary support (EXPERIMENTAL)"
-       depends on JFFS2_FS && EXPERIMENTAL
-       default n
-       help
-         This feature makes it possible to use summary information
-         for faster filesystem mount.
-
-         The summary information can be inserted into a filesystem image
-         by the utility 'sumtool'.
-
-         If unsure, say 'N'.
-
-config JFFS2_FS_XATTR
-       bool "JFFS2 XATTR support (EXPERIMENTAL)"
-       depends on JFFS2_FS && EXPERIMENTAL
-       default n
-       help
-         Extended attributes are name:value pairs associated with inodes by
-         the kernel or by users (see the attr(5) manual page, or visit
-         <http://acl.bestbits.at/> for details).
-
-         If unsure, say N.
-
-config JFFS2_FS_POSIX_ACL
-       bool "JFFS2 POSIX Access Control Lists"
-       depends on JFFS2_FS_XATTR
-       default y
-       select FS_POSIX_ACL
-       help
-         Posix Access Control Lists (ACLs) support permissions for users and
-         groups beyond the owner/group/world scheme.
-
-         To learn more about Access Control Lists, visit the Posix ACLs for
-         Linux website <http://acl.bestbits.at/>.
-
-         If you don't know what Access Control Lists are, say N
-
-config JFFS2_FS_SECURITY
-       bool "JFFS2 Security Labels"
-       depends on JFFS2_FS_XATTR
-       default y
-       help
-         Security labels support alternative access control models
-         implemented by security modules like SELinux.  This option
-         enables an extended attribute handler for file security
-         labels in the jffs2 filesystem.
-
-         If you are not using a security module that requires using
-         extended attributes for file security labels, say N.
-
-config JFFS2_COMPRESSION_OPTIONS
-       bool "Advanced compression options for JFFS2"
-       depends on JFFS2_FS
-       default n
-       help
-         Enabling this option allows you to explicitly choose which
-         compression modules, if any, are enabled in JFFS2. Removing
-         compressors can mean you cannot read existing file systems,
-         and enabling experimental compressors can mean that you
-         write a file system which cannot be read by a standard kernel.
-
-         If unsure, you should _definitely_ say 'N'.
-
-config JFFS2_ZLIB
-       bool "JFFS2 ZLIB compression support" if JFFS2_COMPRESSION_OPTIONS
-       select ZLIB_INFLATE
-       select ZLIB_DEFLATE
-       depends on JFFS2_FS
-       default y
-       help
-         Zlib is designed to be a free, general-purpose, legally unencumbered,
-         lossless data-compression library for use on virtually any computer
-         hardware and operating system. See <http://www.gzip.org/zlib/> for
-         further information.
-
-         Say 'Y' if unsure.
-
-config JFFS2_LZO
-       bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
-       select LZO_COMPRESS
-       select LZO_DECOMPRESS
-       depends on JFFS2_FS
-       default n
-       help
-         minilzo-based compression. Generally works better than Zlib.
-
-         This feature was added in July, 2007. Say 'N' if you need
-         compatibility with older bootloaders or kernels.
-
-config JFFS2_RTIME
-       bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
-       depends on JFFS2_FS
-       default y
-       help
-         Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
-
-config JFFS2_RUBIN
-       bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
-       depends on JFFS2_FS
-       default n
-       help
-         RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
-
-choice
-       prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
-       default JFFS2_CMODE_PRIORITY
-       depends on JFFS2_FS
-       help
-         You can set here the default compression mode of JFFS2 from
-         the available compression modes. Don't touch if unsure.
-
-config JFFS2_CMODE_NONE
-       bool "no compression"
-       help
-         Uses no compression.
-
-config JFFS2_CMODE_PRIORITY
-       bool "priority"
-       help
-         Tries the compressors in a predefined order and chooses the first
-         successful one.
-
-config JFFS2_CMODE_SIZE
-       bool "size (EXPERIMENTAL)"
-       help
-         Tries all compressors and chooses the one which has the smallest
-         result.
-
-config JFFS2_CMODE_FAVOURLZO
-       bool "Favour LZO"
-       help
-         Tries all compressors and chooses the one which has the smallest
-         result but gives some preference to LZO (which has faster
-         decompression) at the expense of size.
-
-endchoice
-
+source "fs/jffs2/Kconfig"
 # UBIFS File system configuration
 source "fs/ubifs/Kconfig"
 
@@ -1913,148 +1725,7 @@ config SMB_NLS_REMOTE
 
          smbmount from samba 2.2.0 or later supports this.
 
-config CIFS
-       tristate "CIFS support (advanced network filesystem, SMBFS successor)"
-       depends on INET
-       select NLS
-       help
-         This is the client VFS module for the Common Internet File System
-         (CIFS) protocol which is the successor to the Server Message Block 
-         (SMB) protocol, the native file sharing mechanism for most early
-         PC operating systems.  The CIFS protocol is fully supported by 
-         file servers such as Windows 2000 (including Windows 2003, NT 4  
-         and Windows XP) as well by Samba (which provides excellent CIFS
-         server support for Linux and many other operating systems). Limited
-         support for OS/2 and Windows ME and similar servers is provided as
-         well.
-
-         The cifs module provides an advanced network file system
-         client for mounting to CIFS compliant servers.  It includes
-         support for DFS (hierarchical name space), secure per-user
-         session establishment via Kerberos or NTLM or NTLMv2,
-         safe distributed caching (oplock), optional packet
-         signing, Unicode and other internationalization improvements.
-         If you need to mount to Samba or Windows from this machine, say Y.
-
-config CIFS_STATS
-        bool "CIFS statistics"
-        depends on CIFS
-        help
-          Enabling this option will cause statistics for each server share
-         mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
-
-config CIFS_STATS2
-       bool "Extended statistics"
-       depends on CIFS_STATS
-       help
-         Enabling this option will allow more detailed statistics on SMB
-         request timing to be displayed in /proc/fs/cifs/DebugData and also
-         allow optional logging of slow responses to dmesg (depending on the
-         value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details).
-         These additional statistics may have a minor effect on performance
-         and memory utilization.
-
-         Unless you are a developer or are doing network performance analysis
-         or tuning, say N.
-
-config CIFS_WEAK_PW_HASH
-       bool "Support legacy servers which use weaker LANMAN security"
-       depends on CIFS
-       help
-         Modern CIFS servers including Samba and most Windows versions
-         (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
-         security mechanisms. These hash the password more securely
-         than the mechanisms used in the older LANMAN version of the
-         SMB protocol but LANMAN based authentication is needed to
-         establish sessions with some old SMB servers.
-
-         Enabling this option allows the cifs module to mount to older
-         LANMAN based servers such as OS/2 and Windows 95, but such
-         mounts may be less secure than mounts using NTLM or more recent
-         security mechanisms if you are on a public network.  Unless you
-         have a need to access old SMB servers (and are on a private
-         network) you probably want to say N.  Even if this support
-         is enabled in the kernel build, LANMAN authentication will not be
-         used automatically. At runtime LANMAN mounts are disabled but
-         can be set to required (or optional) either in
-         /proc/fs/cifs (see fs/cifs/README for more detail) or via an
-         option on the mount command. This support is disabled by
-         default in order to reduce the possibility of a downgrade
-         attack.
-
-         If unsure, say N.
-
-config CIFS_UPCALL
-         bool "Kerberos/SPNEGO advanced session setup"
-         depends on CIFS && KEYS
-         help
-           Enables an upcall mechanism for CIFS which accesses
-           userspace helper utilities to provide SPNEGO packaged (RFC 4178)
-           Kerberos tickets which are needed to mount to certain secure servers
-           (for which more secure Kerberos authentication is required). If
-           unsure, say N.
-
-config CIFS_XATTR
-        bool "CIFS extended attributes"
-        depends on CIFS
-        help
-          Extended attributes are name:value pairs associated with inodes by
-          the kernel or by users (see the attr(5) manual page, or visit
-          <http://acl.bestbits.at/> for details).  CIFS maps the name of
-          extended attributes beginning with the user namespace prefix
-          to SMB/CIFS EAs. EAs are stored on Windows servers without the
-          user namespace prefix, but their names are seen by Linux cifs clients
-          prefaced by the user namespace prefix. The system namespace
-          (used by some filesystems to store ACLs) is not supported at
-          this time.
-
-          If unsure, say N.
-
-config CIFS_POSIX
-        bool "CIFS POSIX Extensions"
-        depends on CIFS_XATTR
-        help
-          Enabling this option will cause the cifs client to attempt to
-         negotiate a newer dialect with servers, such as Samba 3.0.5
-         or later, that optionally can handle more POSIX like (rather
-         than Windows like) file behavior.  It also enables
-         support for POSIX ACLs (getfacl and setfacl) to servers
-         (such as Samba 3.10 and later) which can negotiate
-         CIFS POSIX ACL support.  If unsure, say N.
-
-config CIFS_DEBUG2
-       bool "Enable additional CIFS debugging routines"
-       depends on CIFS
-       help
-          Enabling this option adds a few more debugging routines
-          to the cifs code which slightly increases the size of
-          the cifs module and can cause additional logging of debug
-          messages in some error paths, slowing performance. This
-          option can be turned off unless you are debugging
-          cifs problems.  If unsure, say N.
-
-config CIFS_EXPERIMENTAL
-         bool "CIFS Experimental Features (EXPERIMENTAL)"
-         depends on CIFS && EXPERIMENTAL
-         help
-           Enables cifs features under testing. These features are
-           experimental and currently include DFS support and directory 
-           change notification ie fcntl(F_DNOTIFY), as well as the upcall
-           mechanism which will be used for Kerberos session negotiation
-           and uid remapping.  Some of these features also may depend on 
-           setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
-           (which is disabled by default). See the file fs/cifs/README 
-           for more details.  If unsure, say N.
-
-config CIFS_DFS_UPCALL
-         bool "DFS feature support (EXPERIMENTAL)"
-         depends on CIFS_EXPERIMENTAL
-         depends on KEYS
-         help
-           Enables an upcall mechanism for CIFS which contacts userspace
-           helper utilities to provide server name resolution (host names to
-           IP addresses) which is needed for implicit mounts of DFS junction
-           points. If unsure, say N.
+source "fs/cifs/Kconfig"
 
 config NCP_FS
        tristate "NCP file system support (to mount NetWare volumes)"
index 801db1341811d6eace2732c7238bfd9190ffff1f..ce9fb3fbfae4c3f392b17a1b3bb792c81e318380 100644 (file)
@@ -40,6 +40,28 @@ config BINFMT_ELF_FDPIC
 
          It is also possible to run FDPIC ELF binaries on MMU linux also.
 
+config CORE_DUMP_DEFAULT_ELF_HEADERS
+       bool "Write ELF core dumps with partial segments"
+       default n
+       depends on BINFMT_ELF
+       help
+         ELF core dump files describe each memory mapping of the crashed
+         process, and can contain or omit the memory contents of each one.
+         The contents of an unmodified text mapping are omitted by default.
+
+         For an unmodified text mapping of an ELF object, including just
+         the first page of the file in a core dump makes it possible to
+         identify the build ID bits in the file, without paying the i/o
+         cost and disk space to dump all the text.  However, versions of
+         GDB before 6.7 are confused by ELF core dump files in this format.
+
+         The core dump behavior can be controlled per process using
+         the /proc/PID/coredump_filter pseudo-file; this setting is
+         inherited.  See Documentation/filesystems/proc.txt for details.
+
+         This config option changes the default setting of coredump_filter
+         seen at boot time.  If unsure, say N.
+
 config BINFMT_FLAT
        bool "Kernel support for flat binaries"
        depends on !MMU && (!FRV || BROKEN)
index c76afa26edf735c7644e32b931ac675cbbf08454..e2159063198a072ef75545130ced4eb21e56accf 100644 (file)
@@ -1156,16 +1156,24 @@ static int dump_seek(struct file *file, loff_t off)
 static unsigned long vma_dump_size(struct vm_area_struct *vma,
                                   unsigned long mm_flags)
 {
+#define FILTER(type)   (mm_flags & (1UL << MMF_DUMP_##type))
+
        /* The vma can be set up to tell us the answer directly.  */
        if (vma->vm_flags & VM_ALWAYSDUMP)
                goto whole;
 
+       /* Hugetlb memory check */
+       if (vma->vm_flags & VM_HUGETLB) {
+               if ((vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_SHARED))
+                       goto whole;
+               if (!(vma->vm_flags & VM_SHARED) && FILTER(HUGETLB_PRIVATE))
+                       goto whole;
+       }
+
        /* Do not dump I/O mapped devices or special mappings */
        if (vma->vm_flags & (VM_IO | VM_RESERVED))
                return 0;
 
-#define FILTER(type)   (mm_flags & (1UL << MMF_DUMP_##type))
-
        /* By default, dump shared memory if mapped from an anonymous file. */
        if (vma->vm_flags & VM_SHARED) {
                if (vma->vm_file->f_path.dentry->d_inode->i_nlink == 0 ?
index ac78d4c19b3b3b27e812f13c0bd7669e962cea04..6569fda5cfed892c7e4ed53daa2e9677e60c36d5 100644 (file)
@@ -76,8 +76,7 @@ EXPORT_SYMBOL(__lock_buffer);
 
 void unlock_buffer(struct buffer_head *bh)
 {
-       smp_mb__before_clear_bit();
-       clear_buffer_locked(bh);
+       clear_bit_unlock(BH_Lock, &bh->b_state);
        smp_mb__after_clear_bit();
        wake_up_bit(&bh->b_state, BH_Lock);
 }
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig
new file mode 100644 (file)
index 0000000..341a989
--- /dev/null
@@ -0,0 +1,142 @@
+config CIFS
+       tristate "CIFS support (advanced network filesystem, SMBFS successor)"
+       depends on INET
+       select NLS
+       help
+         This is the client VFS module for the Common Internet File System
+         (CIFS) protocol which is the successor to the Server Message Block
+         (SMB) protocol, the native file sharing mechanism for most early
+         PC operating systems.  The CIFS protocol is fully supported by
+         file servers such as Windows 2000 (including Windows 2003, NT 4
+         and Windows XP) as well by Samba (which provides excellent CIFS
+         server support for Linux and many other operating systems). Limited
+         support for OS/2 and Windows ME and similar servers is provided as
+         well.
+
+         The cifs module provides an advanced network file system
+         client for mounting to CIFS compliant servers.  It includes
+         support for DFS (hierarchical name space), secure per-user
+         session establishment via Kerberos or NTLM or NTLMv2,
+         safe distributed caching (oplock), optional packet
+         signing, Unicode and other internationalization improvements.
+         If you need to mount to Samba or Windows from this machine, say Y.
+
+config CIFS_STATS
+        bool "CIFS statistics"
+        depends on CIFS
+        help
+          Enabling this option will cause statistics for each server share
+         mounted by the cifs client to be displayed in /proc/fs/cifs/Stats
+
+config CIFS_STATS2
+       bool "Extended statistics"
+       depends on CIFS_STATS
+       help
+         Enabling this option will allow more detailed statistics on SMB
+         request timing to be displayed in /proc/fs/cifs/DebugData and also
+         allow optional logging of slow responses to dmesg (depending on the
+         value of /proc/fs/cifs/cifsFYI, see fs/cifs/README for more details).
+         These additional statistics may have a minor effect on performance
+         and memory utilization.
+
+         Unless you are a developer or are doing network performance analysis
+         or tuning, say N.
+
+config CIFS_WEAK_PW_HASH
+       bool "Support legacy servers which use weaker LANMAN security"
+       depends on CIFS
+       help
+         Modern CIFS servers including Samba and most Windows versions
+         (since 1997) support stronger NTLM (and even NTLMv2 and Kerberos)
+         security mechanisms. These hash the password more securely
+         than the mechanisms used in the older LANMAN version of the
+         SMB protocol but LANMAN based authentication is needed to
+         establish sessions with some old SMB servers.
+
+         Enabling this option allows the cifs module to mount to older
+         LANMAN based servers such as OS/2 and Windows 95, but such
+         mounts may be less secure than mounts using NTLM or more recent
+         security mechanisms if you are on a public network.  Unless you
+         have a need to access old SMB servers (and are on a private
+         network) you probably want to say N.  Even if this support
+         is enabled in the kernel build, LANMAN authentication will not be
+         used automatically. At runtime LANMAN mounts are disabled but
+         can be set to required (or optional) either in
+         /proc/fs/cifs (see fs/cifs/README for more detail) or via an
+         option on the mount command. This support is disabled by
+         default in order to reduce the possibility of a downgrade
+         attack.
+
+         If unsure, say N.
+
+config CIFS_UPCALL
+         bool "Kerberos/SPNEGO advanced session setup"
+         depends on CIFS && KEYS
+         help
+           Enables an upcall mechanism for CIFS which accesses
+           userspace helper utilities to provide SPNEGO packaged (RFC 4178)
+           Kerberos tickets which are needed to mount to certain secure servers
+           (for which more secure Kerberos authentication is required). If
+           unsure, say N.
+
+config CIFS_XATTR
+        bool "CIFS extended attributes"
+        depends on CIFS
+        help
+          Extended attributes are name:value pairs associated with inodes by
+          the kernel or by users (see the attr(5) manual page, or visit
+          <http://acl.bestbits.at/> for details).  CIFS maps the name of
+          extended attributes beginning with the user namespace prefix
+          to SMB/CIFS EAs. EAs are stored on Windows servers without the
+          user namespace prefix, but their names are seen by Linux cifs clients
+          prefaced by the user namespace prefix. The system namespace
+          (used by some filesystems to store ACLs) is not supported at
+          this time.
+
+          If unsure, say N.
+
+config CIFS_POSIX
+        bool "CIFS POSIX Extensions"
+        depends on CIFS_XATTR
+        help
+          Enabling this option will cause the cifs client to attempt to
+         negotiate a newer dialect with servers, such as Samba 3.0.5
+         or later, that optionally can handle more POSIX like (rather
+         than Windows like) file behavior.  It also enables
+         support for POSIX ACLs (getfacl and setfacl) to servers
+         (such as Samba 3.10 and later) which can negotiate
+         CIFS POSIX ACL support.  If unsure, say N.
+
+config CIFS_DEBUG2
+       bool "Enable additional CIFS debugging routines"
+       depends on CIFS
+       help
+          Enabling this option adds a few more debugging routines
+          to the cifs code which slightly increases the size of
+          the cifs module and can cause additional logging of debug
+          messages in some error paths, slowing performance. This
+          option can be turned off unless you are debugging
+          cifs problems.  If unsure, say N.
+
+config CIFS_EXPERIMENTAL
+         bool "CIFS Experimental Features (EXPERIMENTAL)"
+         depends on CIFS && EXPERIMENTAL
+         help
+           Enables cifs features under testing. These features are
+           experimental and currently include DFS support and directory
+           change notification ie fcntl(F_DNOTIFY), as well as the upcall
+           mechanism which will be used for Kerberos session negotiation
+           and uid remapping.  Some of these features also may depend on
+           setting a value of 1 to the pseudo-file /proc/fs/cifs/Experimental
+           (which is disabled by default). See the file fs/cifs/README
+           for more details.  If unsure, say N.
+
+config CIFS_DFS_UPCALL
+         bool "DFS feature support (EXPERIMENTAL)"
+         depends on CIFS_EXPERIMENTAL
+         depends on KEYS
+         help
+           Enables an upcall mechanism for CIFS which contacts userspace
+           helper utilities to provide server name resolution (host names to
+           IP addresses) which is needed for implicit mounts of DFS junction
+           points. If unsure, say N.
index c4a8a0605125aa3c2f93359ac98b43de5060bed9..62d8bd8f14c086f1c9f53640b9144f1cca349289 100644 (file)
@@ -1791,7 +1791,7 @@ static void cifs_copy_cache_pages(struct address_space *mapping,
                SetPageUptodate(page);
                unlock_page(page);
                if (!pagevec_add(plru_pvec, page))
-                       __pagevec_lru_add(plru_pvec);
+                       __pagevec_lru_add_file(plru_pvec);
                data += PAGE_CACHE_SIZE;
        }
        return;
@@ -1925,7 +1925,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
                bytes_read = 0;
        }
 
-       pagevec_lru_add(&lru_pvec);
+       pagevec_lru_add_file(&lru_pvec);
 
 /* need to free smb_read_data buf before exit */
        if (smb_read_data) {
index a41e7902ed0bf9ef9e2cd600c31b1acda0576ed4..4e834f16d9da7d49c0f232b9fd46a7db2c680070 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1386,7 +1386,7 @@ EXPORT_SYMBOL(set_binfmt);
  * name into corename, which must have space for at least
  * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator.
  */
-static int format_corename(char *corename, int nr_threads, long signr)
+static int format_corename(char *corename, long signr)
 {
        const char *pat_ptr = core_pattern;
        int ispipe = (*pat_ptr == '|');
@@ -1493,8 +1493,7 @@ static int format_corename(char *corename, int nr_threads, long signr)
         * If core_pattern does not include a %p (as is the default)
         * and core_uses_pid is set, then .%pid will be appended to
         * the filename. Do not do this for piped commands. */
-       if (!ispipe && !pid_in_pattern
-           && (core_uses_pid || nr_threads)) {
+       if (!ispipe && !pid_in_pattern && core_uses_pid) {
                rc = snprintf(out_ptr, out_end - out_ptr,
                              ".%d", task_tgid_vnr(current));
                if (rc > out_end - out_ptr)
@@ -1757,7 +1756,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
         * uses lock_kernel()
         */
        lock_kernel();
-       ispipe = format_corename(corename, retval, signr);
+       ispipe = format_corename(corename, signr);
        unlock_kernel();
        /*
         * Don't bother to check the RLIMIT_CORE value if core_pattern points
index 92fd0338a6ebe3df16739b65feec4e4ef034206f..f5b57a2ca35a5c4cb10a369933bec40291c78109 100644 (file)
@@ -1547,6 +1547,7 @@ retry_alloc:
         * turn off reservation for this allocation
         */
        if (my_rsv && (free_blocks < windowsz)
+               && (free_blocks > 0)
                && (rsv_is_empty(&my_rsv->rsv_window)))
                my_rsv = NULL;
 
@@ -1585,7 +1586,7 @@ retry_alloc:
                 * free blocks is less than half of the reservation
                 * window size.
                 */
-               if (free_blocks <= (windowsz/2))
+               if (my_rsv && (free_blocks <= (windowsz/2)))
                        continue;
 
                brelse(bitmap_bh);
index 2eea96ec78ed218f4fbe14b8e4c1b169e1dfe1ac..4c82531ea0a8b0d13ce61b63eb7daeecbe5d1423 100644 (file)
@@ -102,6 +102,7 @@ static int ext3_readdir(struct file * filp,
        int err;
        struct inode *inode = filp->f_path.dentry->d_inode;
        int ret = 0;
+       int dir_has_error = 0;
 
        sb = inode->i_sb;
 
@@ -148,9 +149,12 @@ static int ext3_readdir(struct file * filp,
                 * of recovering data when there's a bad sector
                 */
                if (!bh) {
-                       ext3_error (sb, "ext3_readdir",
-                               "directory #%lu contains a hole at offset %lu",
-                               inode->i_ino, (unsigned long)filp->f_pos);
+                       if (!dir_has_error) {
+                               ext3_error(sb, __func__, "directory #%lu "
+                                       "contains a hole at offset %lld",
+                                       inode->i_ino, filp->f_pos);
+                               dir_has_error = 1;
+                       }
                        /* corrupt size?  Maybe no more blocks to read */
                        if (filp->f_pos > inode->i_blocks << 9)
                                break;
@@ -410,7 +414,7 @@ static int call_filldir(struct file * filp, void * dirent,
                                get_dtype(sb, fname->file_type));
                if (error) {
                        filp->f_pos = curr_pos;
-                       info->extra_fname = fname->next;
+                       info->extra_fname = fname;
                        return error;
                }
                fname = fname->next;
@@ -449,11 +453,21 @@ static int ext3_dx_readdir(struct file * filp,
         * If there are any leftover names on the hash collision
         * chain, return them first.
         */
-       if (info->extra_fname &&
-           call_filldir(filp, dirent, filldir, info->extra_fname))
-               goto finished;
+       if (info->extra_fname) {
+               if (call_filldir(filp, dirent, filldir, info->extra_fname))
+                       goto finished;
 
-       if (!info->curr_node)
+               info->extra_fname = NULL;
+               info->curr_node = rb_next(info->curr_node);
+               if (!info->curr_node) {
+                       if (info->next_hash == ~0) {
+                               filp->f_pos = EXT3_HTREE_EOF;
+                               goto finished;
+                       }
+                       info->curr_hash = info->next_hash;
+                       info->curr_minor_hash = 0;
+               }
+       } else if (!info->curr_node)
                info->curr_node = rb_first(&info->root);
 
        while (1) {
index ebfec4d0148e9e272e2a25efd0e3b551381408c6..f8424ad8997195f0cdd2d2c1c53196f16651d7c8 100644 (file)
@@ -1186,6 +1186,13 @@ write_begin_failed:
                ext3_journal_stop(handle);
                unlock_page(page);
                page_cache_release(page);
+               /*
+                * block_write_begin may have instantiated a few blocks
+                * outside i_size.  Trim these off again. Don't need
+                * i_size_read because we hold i_mutex.
+                */
+               if (pos + len > inode->i_size)
+                       vmtruncate(inode, inode->i_size);
        }
        if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries))
                goto retry;
index 77278e947e9416d8b1165cfab6d7554f21131a67..78fdf383637022566f62267759629d250e04712c 100644 (file)
@@ -790,7 +790,8 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input)
 
        if (reserved_gdb || gdb_off == 0) {
                if (!EXT3_HAS_COMPAT_FEATURE(sb,
-                                            EXT3_FEATURE_COMPAT_RESIZE_INODE)){
+                                            EXT3_FEATURE_COMPAT_RESIZE_INODE)
+                   || !le16_to_cpu(es->s_reserved_gdt_blocks)) {
                        ext3_warning(sb, __func__,
                                     "No reserved GDT blocks, can't resize");
                        return -EPERM;
index 399a96a6c5561666f61c7a8f7cae3a71dbc5b52f..3a260af5544d24dfc85f0dffc03b42771c322295 100644 (file)
@@ -625,6 +625,9 @@ static int ext3_show_options(struct seq_file *seq, struct vfsmount *vfs)
        else if (test_opt(sb, DATA_FLAGS) == EXT3_MOUNT_WRITEBACK_DATA)
                seq_puts(seq, ",data=writeback");
 
+       if (test_opt(sb, DATA_ERR_ABORT))
+               seq_puts(seq, ",data_err=abort");
+
        ext3_show_quota_options(seq, sb);
 
        return 0;
@@ -754,6 +757,7 @@ enum {
        Opt_reservation, Opt_noreservation, Opt_noload, Opt_nobh, Opt_bh,
        Opt_commit, Opt_journal_update, Opt_journal_inum, Opt_journal_dev,
        Opt_abort, Opt_data_journal, Opt_data_ordered, Opt_data_writeback,
+       Opt_data_err_abort, Opt_data_err_ignore,
        Opt_usrjquota, Opt_grpjquota, Opt_offusrjquota, Opt_offgrpjquota,
        Opt_jqfmt_vfsold, Opt_jqfmt_vfsv0, Opt_quota, Opt_noquota,
        Opt_ignore, Opt_barrier, Opt_err, Opt_resize, Opt_usrquota,
@@ -796,6 +800,8 @@ static const match_table_t tokens = {
        {Opt_data_journal, "data=journal"},
        {Opt_data_ordered, "data=ordered"},
        {Opt_data_writeback, "data=writeback"},
+       {Opt_data_err_abort, "data_err=abort"},
+       {Opt_data_err_ignore, "data_err=ignore"},
        {Opt_offusrjquota, "usrjquota="},
        {Opt_usrjquota, "usrjquota=%s"},
        {Opt_offgrpjquota, "grpjquota="},
@@ -1011,6 +1017,12 @@ static int parse_options (char *options, struct super_block *sb,
                                sbi->s_mount_opt |= data_opt;
                        }
                        break;
+               case Opt_data_err_abort:
+                       set_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
+                       break;
+               case Opt_data_err_ignore:
+                       clear_opt(sbi->s_mount_opt, DATA_ERR_ABORT);
+                       break;
 #ifdef CONFIG_QUOTA
                case Opt_usrjquota:
                        qtype = USRQUOTA;
@@ -1986,6 +1998,10 @@ static void ext3_init_journal_params(struct super_block *sb, journal_t *journal)
                journal->j_flags |= JFS_BARRIER;
        else
                journal->j_flags &= ~JFS_BARRIER;
+       if (test_opt(sb, DATA_ERR_ABORT))
+               journal->j_flags |= JFS_ABORT_ON_SYNCDATA_ERR;
+       else
+               journal->j_flags &= ~JFS_ABORT_ON_SYNCDATA_ERR;
        spin_unlock(&journal->j_state_lock);
 }
 
index fec8f61227ffb28792a7b94f30417f003d786882..0022eec63cdacd97c2a438b8d9f623ff6be88dd4 100644 (file)
@@ -199,6 +199,9 @@ int hfsplus_get_block(struct inode *inode, sector_t iblock,
                goto done;
        }
 
+       if (inode->i_ino == HFSPLUS_EXT_CNID)
+               return -EIO;
+
        mutex_lock(&HFSPLUS_I(inode).extents_lock);
        res = hfsplus_ext_read_extent(inode, ablock);
        if (!res) {
index b085d64a2b672580e328be86af33475e87544f6e..963be644297aeb45c2d376721c5cc70ee8ce28f5 100644 (file)
@@ -254,6 +254,8 @@ static int hfsplus_file_open(struct inode *inode, struct file *file)
 {
        if (HFSPLUS_IS_RSRC(inode))
                inode = HFSPLUS_I(inode).rsrc_inode;
+       if (!(file->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
+               return -EOVERFLOW;
        atomic_inc(&HFSPLUS_I(inode).opencnt);
        return 0;
 }
index ae08c057e751454ad2f0d922faa9be08d3c6d80d..25719d902c5116a6ff50248b272e5603c196f0f7 100644 (file)
@@ -482,6 +482,8 @@ void journal_commit_transaction(journal_t *journal)
                printk(KERN_WARNING
                        "JBD: Detected IO errors while flushing file data "
                        "on %s\n", bdevname(journal->j_fs_dev, b));
+               if (journal->j_flags & JFS_ABORT_ON_SYNCDATA_ERR)
+                       journal_abort(journal, err);
                err = 0;
        }
 
@@ -518,9 +520,10 @@ void journal_commit_transaction(journal_t *journal)
                jh = commit_transaction->t_buffers;
 
                /* If we're in abort mode, we just un-journal the buffer and
-                  release it for background writing. */
+                  release it. */
 
                if (is_journal_aborted(journal)) {
+                       clear_buffer_jbddirty(jh2bh(jh));
                        JBUFFER_TRACE(jh, "journal is aborting: refile");
                        journal_refile_buffer(journal, jh);
                        /* If that was the last one, we need to clean up
@@ -762,6 +765,9 @@ wait_for_iobuf:
                /* AKPM: bforget here */
        }
 
+       if (err)
+               journal_abort(journal, err);
+
        jbd_debug(3, "JBD: commit phase 6\n");
 
        if (journal_write_commit_record(journal, commit_transaction))
@@ -852,6 +858,8 @@ restart_loop:
                if (buffer_jbddirty(bh)) {
                        JBUFFER_TRACE(jh, "add to new checkpointing trans");
                        __journal_insert_checkpoint(jh, commit_transaction);
+                       if (is_journal_aborted(journal))
+                               clear_buffer_jbddirty(bh);
                        JBUFFER_TRACE(jh, "refile for checkpoint writeback");
                        __journal_refile_buffer(jh);
                        jbd_unlock_bh_state(bh);
index 0540ca27a4464060e9c230095f664cd9937b21a1..d15cd6e7251ee03347f25f14f53e371ff7936d09 100644 (file)
@@ -954,9 +954,10 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
        journal_t *journal = handle->h_transaction->t_journal;
        int need_brelse = 0;
        struct journal_head *jh;
+       int ret = 0;
 
        if (is_handle_aborted(handle))
-               return 0;
+               return ret;
 
        jh = journal_add_journal_head(bh);
        JBUFFER_TRACE(jh, "entry");
@@ -1067,7 +1068,16 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh)
                                   time if it is redirtied */
                        }
 
-                       /* journal_clean_data_list() may have got there first */
+                       /*
+                        * We cannot remove the buffer with io error from the
+                        * committing transaction, because otherwise it would
+                        * miss the error and the commit would not abort.
+                        */
+                       if (unlikely(!buffer_uptodate(bh))) {
+                               ret = -EIO;
+                               goto no_journal;
+                       }
+
                        if (jh->b_transaction != NULL) {
                                JBUFFER_TRACE(jh, "unfile from commit");
                                __journal_temp_unlink_buffer(jh);
@@ -1108,7 +1118,7 @@ no_journal:
        }
        JBUFFER_TRACE(jh, "exit");
        journal_put_journal_head(jh);
-       return 0;
+       return ret;
 }
 
 /**
diff --git a/fs/jffs2/Kconfig b/fs/jffs2/Kconfig
new file mode 100644 (file)
index 0000000..6ae169c
--- /dev/null
@@ -0,0 +1,188 @@
+config JFFS2_FS
+       tristate "Journalling Flash File System v2 (JFFS2) support"
+       select CRC32
+       depends on MTD
+       help
+         JFFS2 is the second generation of the Journalling Flash File System
+         for use on diskless embedded devices. It provides improved wear
+         levelling, compression and support for hard links. You cannot use
+         this on normal block devices, only on 'MTD' devices.
+
+         Further information on the design and implementation of JFFS2 is
+         available at <http://sources.redhat.com/jffs2/>.
+
+config JFFS2_FS_DEBUG
+       int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)"
+       depends on JFFS2_FS
+       default "0"
+       help
+         This controls the amount of debugging messages produced by the JFFS2
+         code. Set it to zero for use in production systems. For evaluation,
+         testing and debugging, it's advisable to set it to one. This will
+         enable a few assertions and will print debugging messages at the
+         KERN_DEBUG loglevel, where they won't normally be visible. Level 2
+         is unlikely to be useful - it enables extra debugging in certain
+         areas which at one point needed debugging, but when the bugs were
+         located and fixed, the detailed messages were relegated to level 2.
+
+         If reporting bugs, please try to have available a full dump of the
+         messages at debug level 1 while the misbehaviour was occurring.
+
+config JFFS2_FS_WRITEBUFFER
+       bool "JFFS2 write-buffering support"
+       depends on JFFS2_FS
+       default y
+       help
+         This enables the write-buffering support in JFFS2.
+
+         This functionality is required to support JFFS2 on the following
+         types of flash devices:
+           - NAND flash
+           - NOR flash with transparent ECC
+           - DataFlash
+
+config JFFS2_FS_WBUF_VERIFY
+       bool "Verify JFFS2 write-buffer reads"
+       depends on JFFS2_FS_WRITEBUFFER
+       default n
+       help
+         This causes JFFS2 to read back every page written through the
+         write-buffer, and check for errors.
+
+config JFFS2_SUMMARY
+       bool "JFFS2 summary support (EXPERIMENTAL)"
+       depends on JFFS2_FS && EXPERIMENTAL
+       default n
+       help
+         This feature makes it possible to use summary information
+         for faster filesystem mount.
+
+         The summary information can be inserted into a filesystem image
+         by the utility 'sumtool'.
+
+         If unsure, say 'N'.
+
+config JFFS2_FS_XATTR
+       bool "JFFS2 XATTR support (EXPERIMENTAL)"
+       depends on JFFS2_FS && EXPERIMENTAL
+       default n
+       help
+         Extended attributes are name:value pairs associated with inodes by
+         the kernel or by users (see the attr(5) manual page, or visit
+         <http://acl.bestbits.at/> for details).
+
+         If unsure, say N.
+
+config JFFS2_FS_POSIX_ACL
+       bool "JFFS2 POSIX Access Control Lists"
+       depends on JFFS2_FS_XATTR
+       default y
+       select FS_POSIX_ACL
+       help
+         Posix Access Control Lists (ACLs) support permissions for users and
+         groups beyond the owner/group/world scheme.
+
+         To learn more about Access Control Lists, visit the Posix ACLs for
+         Linux website <http://acl.bestbits.at/>.
+
+         If you don't know what Access Control Lists are, say N
+
+config JFFS2_FS_SECURITY
+       bool "JFFS2 Security Labels"
+       depends on JFFS2_FS_XATTR
+       default y
+       help
+         Security labels support alternative access control models
+         implemented by security modules like SELinux.  This option
+         enables an extended attribute handler for file security
+         labels in the jffs2 filesystem.
+
+         If you are not using a security module that requires using
+         extended attributes for file security labels, say N.
+
+config JFFS2_COMPRESSION_OPTIONS
+       bool "Advanced compression options for JFFS2"
+       depends on JFFS2_FS
+       default n
+       help
+         Enabling this option allows you to explicitly choose which
+         compression modules, if any, are enabled in JFFS2. Removing
+         compressors can mean you cannot read existing file systems,
+         and enabling experimental compressors can mean that you
+         write a file system which cannot be read by a standard kernel.
+
+         If unsure, you should _definitely_ say 'N'.
+
+config JFFS2_ZLIB
+       bool "JFFS2 ZLIB compression support" if JFFS2_COMPRESSION_OPTIONS
+       select ZLIB_INFLATE
+       select ZLIB_DEFLATE
+       depends on JFFS2_FS
+       default y
+       help
+         Zlib is designed to be a free, general-purpose, legally unencumbered,
+         lossless data-compression library for use on virtually any computer
+         hardware and operating system. See <http://www.gzip.org/zlib/> for
+         further information.
+
+         Say 'Y' if unsure.
+
+config JFFS2_LZO
+       bool "JFFS2 LZO compression support" if JFFS2_COMPRESSION_OPTIONS
+       select LZO_COMPRESS
+       select LZO_DECOMPRESS
+       depends on JFFS2_FS
+       default n
+       help
+         minilzo-based compression. Generally works better than Zlib.
+
+         This feature was added in July, 2007. Say 'N' if you need
+         compatibility with older bootloaders or kernels.
+
+config JFFS2_RTIME
+       bool "JFFS2 RTIME compression support" if JFFS2_COMPRESSION_OPTIONS
+       depends on JFFS2_FS
+       default y
+       help
+         Rtime does manage to recompress already-compressed data. Say 'Y' if unsure.
+
+config JFFS2_RUBIN
+       bool "JFFS2 RUBIN compression support" if JFFS2_COMPRESSION_OPTIONS
+       depends on JFFS2_FS
+       default n
+       help
+         RUBINMIPS and DYNRUBIN compressors. Say 'N' if unsure.
+
+choice
+       prompt "JFFS2 default compression mode" if JFFS2_COMPRESSION_OPTIONS
+       default JFFS2_CMODE_PRIORITY
+       depends on JFFS2_FS
+       help
+         You can set here the default compression mode of JFFS2 from
+         the available compression modes. Don't touch if unsure.
+
+config JFFS2_CMODE_NONE
+       bool "no compression"
+       help
+         Uses no compression.
+
+config JFFS2_CMODE_PRIORITY
+       bool "priority"
+       help
+         Tries the compressors in a predefined order and chooses the first
+         successful one.
+
+config JFFS2_CMODE_SIZE
+       bool "size (EXPERIMENTAL)"
+       help
+         Tries all compressors and chooses the one which has the smallest
+         result.
+
+config JFFS2_CMODE_FAVOURLZO
+       bool "Favour LZO"
+       help
+         Tries all compressors and chooses the one which has the smallest
+         result but gives some preference to LZO (which has faster
+         decompression) at the expense of size.
+
+endchoice
index 86739ee53b37336c15cbc341180c47d195d9081a..f25e70c1b51c5854d987558ec5c84c0c94410b73 100644 (file)
@@ -53,8 +53,8 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this,
 }
 
 /* jffs2_compress:
- * @data: Pointer to uncompressed data
- * @cdata: Pointer to returned pointer to buffer for compressed data
+ * @data_in: Pointer to uncompressed data
+ * @cpage_out: Pointer to returned pointer to buffer for compressed data
  * @datalen: On entry, holds the amount of data available for compression.
  *     On exit, expected to hold the amount of data actually compressed.
  * @cdatalen: On entry, holds the amount of space available for compressed
index cd219ef552543cdc98d0a392f95cd6dc1c3ec4fd..b1aaae823a5227de63ebb0175e904f435ab27772 100644 (file)
@@ -311,7 +311,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        /* FIXME: If you care. We'd need to use frags for the target
           if it grows much more than this */
        if (targetlen > 254)
-               return -EINVAL;
+               return -ENAMETOOLONG;
 
        ri = jffs2_alloc_raw_inode();
 
index dddb2a6c9e2cfc087b6becc7f88d9e85ab1d02b4..259461b910afec4542ea5f13af00bf0c63b3bf42 100644 (file)
@@ -68,7 +68,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c,
        instr->len = c->sector_size;
        instr->callback = jffs2_erase_callback;
        instr->priv = (unsigned long)(&instr[1]);
-       instr->fail_addr = 0xffffffff;
+       instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
 
        ((struct erase_priv_struct *)instr->priv)->jeb = jeb;
        ((struct erase_priv_struct *)instr->priv)->c = c;
@@ -175,7 +175,7 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock
 {
        /* For NAND, if the failure did not occur at the device level for a
           specific physical page, don't bother updating the bad block table. */
-       if (jffs2_cleanmarker_oob(c) && (bad_offset != 0xffffffff)) {
+       if (jffs2_cleanmarker_oob(c) && (bad_offset != MTD_FAIL_ADDR_UNKNOWN)) {
                /* We had a device-level failure to erase.  Let's see if we've
                   failed too many times. */
                if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) {
index 086c4383022181f3624f333143daf9d5ddf99081..249305d65d5bd663017fac0b6c637faeb7eebfa2 100644 (file)
@@ -207,6 +207,8 @@ int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_files = 0;
        buf->f_ffree = 0;
        buf->f_namelen = JFFS2_MAX_NAME_LEN;
+       buf->f_fsid.val[0] = JFFS2_SUPER_MAGIC;
+       buf->f_fsid.val[1] = c->mtd->index;
 
        spin_lock(&c->erase_completion_lock);
        avail = c->dirty_size + c->free_size;
@@ -440,14 +442,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
 
        memset(ri, 0, sizeof(*ri));
        /* Set OS-specific defaults for new inodes */
-       ri->uid = cpu_to_je16(current->fsuid);
+       ri->uid = cpu_to_je16(current_fsuid());
 
        if (dir_i->i_mode & S_ISGID) {
                ri->gid = cpu_to_je16(dir_i->i_gid);
                if (S_ISDIR(mode))
                        mode |= S_ISGID;
        } else {
-               ri->gid = cpu_to_je16(current->fsgid);
+               ri->gid = cpu_to_je16(current_fsgid());
        }
 
        /* POSIX ACLs have to be processed now, at least partly.
index a9bf9603c1ba0cca4fac8d56ea2dae4bbfe33b91..0875b60b4bf700cc8fda2fad76437d0dc9ea7420 100644 (file)
@@ -261,6 +261,10 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
 
        jffs2_sum_reset_collected(c->summary); /* reset collected summary */
 
+       /* adjust write buffer offset, else we get a non contiguous write bug */
+       if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len)
+               c->wbuf_ofs = 0xffffffff;
+
        D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset));
 
        return 0;
index 0e78b00035e47a313ba43bafba87dfffbe9cf1b4..d9a721e6db70139073ca055cbea471769f6a83dd 100644 (file)
@@ -679,10 +679,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 
        memset(c->wbuf,0xff,c->wbuf_pagesize);
        /* adjust write buffer offset, else we get a non contiguous write bug */
-       if (SECTOR_ADDR(c->wbuf_ofs) == SECTOR_ADDR(c->wbuf_ofs+c->wbuf_pagesize))
-               c->wbuf_ofs += c->wbuf_pagesize;
-       else
-               c->wbuf_ofs = 0xffffffff;
+       c->wbuf_ofs += c->wbuf_pagesize;
        c->wbuf_len = 0;
        return 0;
 }
index 2ab70d46ecbc7ac43a0585183adcfe248ac5b127..efdba2e802d78bcdf520794e964e873fce793280 100644 (file)
@@ -1517,7 +1517,7 @@ static int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *sym
        if (!add_to_page_cache(page, dentry->d_inode->i_mapping, 0,
                                                        GFP_KERNEL)) {
                pagevec_add(&lru_pvec, page);
-               pagevec_lru_add(&lru_pvec);
+               pagevec_lru_add_file(&lru_pvec);
                SetPageUptodate(page);
                unlock_page(page);
        } else
index d020866d42320dddd0ed6a8b9a9d31e572a42cab..3140a4429af12febede2a87e204086b7dd310d22 100644 (file)
@@ -439,7 +439,7 @@ static inline int __ntfs_grab_cache_pages(struct address_space *mapping,
                        pages[nr] = *cached_page;
                        page_cache_get(*cached_page);
                        if (unlikely(!pagevec_add(lru_pvec, *cached_page)))
-                               __pagevec_lru_add(lru_pvec);
+                               __pagevec_lru_add_file(lru_pvec);
                        *cached_page = NULL;
                }
                index++;
@@ -2084,7 +2084,7 @@ err_out:
                                                OSYNC_METADATA|OSYNC_DATA);
                }
        }
-       pagevec_lru_add(&lru_pvec);
+       pagevec_lru_add_file(&lru_pvec);
        ntfs_debug("Done.  Returning %s (written 0x%lx, status %li).",
                        written ? "written" : "status", (unsigned long)written,
                        (long)status);
index 59ea42e1ef03a0a4acdf3f73283d913b740415fd..61b25f4eabe6635bdf013e4879dd8e725f10f01d 100644 (file)
@@ -136,6 +136,8 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
        unsigned long allowed;
        struct vmalloc_info vmi;
        long cached;
+       unsigned long pages[NR_LRU_LISTS];
+       int lru;
 
 /*
  * display in kilobytes.
@@ -154,51 +156,70 @@ static int meminfo_read_proc(char *page, char **start, off_t off,
 
        get_vmalloc_info(&vmi);
 
+       for (lru = LRU_BASE; lru < NR_LRU_LISTS; lru++)
+               pages[lru] = global_page_state(NR_LRU_BASE + lru);
+
        /*
         * Tagged format, for easy grepping and expansion.
         */
        len = sprintf(page,
-               "MemTotal:     %8lu kB\n"
-               "MemFree:      %8lu kB\n"
-               "Buffers:      %8lu kB\n"
-               "Cached:       %8lu kB\n"
-               "SwapCached:   %8lu kB\n"
-               "Active:       %8lu kB\n"
-               "Inactive:     %8lu kB\n"
+               "MemTotal:       %8lu kB\n"
+               "MemFree:        %8lu kB\n"
+               "Buffers:        %8lu kB\n"
+               "Cached:         %8lu kB\n"
+               "SwapCached:     %8lu kB\n"
+               "Active:         %8lu kB\n"
+               "Inactive:       %8lu kB\n"
+               "Active(anon):   %8lu kB\n"
+               "Inactive(anon): %8lu kB\n"
+               "Active(file):   %8lu kB\n"
+               "Inactive(file): %8lu kB\n"
+#ifdef CONFIG_UNEVICTABLE_LRU
+               "Unevictable:    %8lu kB\n"
+               "Mlocked:        %8lu kB\n"
+#endif
 #ifdef CONFIG_HIGHMEM
-               "HighTotal:    %8lu kB\n"
-               "HighFree:     %8lu kB\n"
-               "LowTotal:     %8lu kB\n"
-               "LowFree:      %8lu kB\n"
+               "HighTotal:      %8lu kB\n"
+               "HighFree:       %8lu kB\n"
+               "LowTotal:       %8lu kB\n"
+               "LowFree:        %8lu kB\n"
 #endif
-               "SwapTotal:    %8lu kB\n"
-               "SwapFree:     %8lu kB\n"
-               "Dirty:        %8lu kB\n"
-               "Writeback:    %8lu kB\n"
-               "AnonPages:    %8lu kB\n"
-               "Mapped:       %8lu kB\n"
-               "Slab:         %8lu kB\n"
-               "SReclaimable: %8lu kB\n"
-               "SUnreclaim:   %8lu kB\n"
-               "PageTables:   %8lu kB\n"
+               "SwapTotal:      %8lu kB\n"
+               "SwapFree:       %8lu kB\n"
+               "Dirty:          %8lu kB\n"
+               "Writeback:      %8lu kB\n"
+               "AnonPages:      %8lu kB\n"
+               "Mapped:         %8lu kB\n"
+               "Slab:           %8lu kB\n"
+               "SReclaimable:   %8lu kB\n"
+               "SUnreclaim:     %8lu kB\n"
+               "PageTables:     %8lu kB\n"
 #ifdef CONFIG_QUICKLIST
-               "Quicklists:   %8lu kB\n"
+               "Quicklists:     %8lu kB\n"
 #endif
-               "NFS_Unstable: %8lu kB\n"
-               "Bounce:       %8lu kB\n"
-               "WritebackTmp: %8lu kB\n"
-               "CommitLimit:  %8lu kB\n"
-               "Committed_AS: %8lu kB\n"
-               "VmallocTotal: %8lu kB\n"
-               "VmallocUsed:  %8lu kB\n"
-               "VmallocChunk: %8lu kB\n",
+               "NFS_Unstable:   %8lu kB\n"
+               "Bounce:         %8lu kB\n"
+               "WritebackTmp:   %8lu kB\n"
+               "CommitLimit:    %8lu kB\n"
+               "Committed_AS:   %8lu kB\n"
+               "VmallocTotal:   %8lu kB\n"
+               "VmallocUsed:    %8lu kB\n"
+               "VmallocChunk:   %8lu kB\n",
                K(i.totalram),
                K(i.freeram),
                K(i.bufferram),
                K(cached),
                K(total_swapcache_pages),
-               K(global_page_state(NR_ACTIVE)),
-               K(global_page_state(NR_INACTIVE)),
+               K(pages[LRU_ACTIVE_ANON]   + pages[LRU_ACTIVE_FILE]),
+               K(pages[LRU_INACTIVE_ANON] + pages[LRU_INACTIVE_FILE]),
+               K(pages[LRU_ACTIVE_ANON]),
+               K(pages[LRU_INACTIVE_ANON]),
+               K(pages[LRU_ACTIVE_FILE]),
+               K(pages[LRU_INACTIVE_FILE]),
+#ifdef CONFIG_UNEVICTABLE_LRU
+               K(pages[LRU_UNEVICTABLE]),
+               K(global_page_state(NR_MLOCK)),
+#endif
 #ifdef CONFIG_HIGHMEM
                K(i.totalhigh),
                K(i.freehigh),
index 841368b87a29dbb89c68c4539b6203a7e0501905..cd9ca67f841bd38d6256f14eccfd3fd6d8174522 100644 (file)
@@ -32,9 +32,6 @@ static size_t elfcorebuf_sz;
 /* Total size of vmcore file. */
 static u64 vmcore_size;
 
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
 struct proc_dir_entry *proc_vmcore = NULL;
 
 /* Reads a page from the oldmem device from given offset. */
@@ -647,7 +644,7 @@ static int __init vmcore_init(void)
        int rc = 0;
 
        /* If elfcorehdr= has been passed in cmdline, then capture the dump.*/
-       if (!(elfcorehdr_addr < ELFCORE_ADDR_MAX))
+       if (!(is_vmcore_usable()))
                return rc;
        rc = parse_crash_elf_headers();
        if (rc) {
index 5145cb9125af8c62a574b0dde476a4f7e8f8f814..76acdbc3461144512208755d4b69946d7eda76e3 100644 (file)
@@ -112,12 +112,12 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
                        goto add_error;
 
                if (!pagevec_add(&lru_pvec, page))
-                       __pagevec_lru_add(&lru_pvec);
+                       __pagevec_lru_add_file(&lru_pvec);
 
                unlock_page(page);
        }
 
-       pagevec_lru_add(&lru_pvec);
+       pagevec_lru_add_file(&lru_pvec);
        return 0;
 
  fsize_exceeded:
index b13123424e49ce169da5c729c0e327fdf2259bf8..f031d1c925f0b72ff562a5b839674eb94b4ecf94 100644 (file)
@@ -61,6 +61,7 @@ struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
                inode->i_mapping->a_ops = &ramfs_aops;
                inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
                mapping_set_gfp_mask(inode->i_mapping, GFP_HIGHUSER);
+               mapping_set_unevictable(inode->i_mapping);
                inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
                switch (mode & S_IFMT) {
                default:
index bd20f7f5a93342b57a4802010c788683deb63247..eba2eabcd2b86a40495845053d9d647e228540f9 100644 (file)
@@ -452,17 +452,34 @@ int seq_dentry(struct seq_file *m, struct dentry *dentry, char *esc)
 
 int seq_bitmap(struct seq_file *m, unsigned long *bits, unsigned int nr_bits)
 {
-       size_t len = bitmap_scnprintf_len(nr_bits);
+       if (m->count < m->size) {
+               int len = bitmap_scnprintf(m->buf + m->count,
+                               m->size - m->count, bits, nr_bits);
+               if (m->count + len < m->size) {
+                       m->count += len;
+                       return 0;
+               }
+       }
+       m->count = m->size;
+       return -1;
+}
+EXPORT_SYMBOL(seq_bitmap);
 
-       if (m->count + len < m->size) {
-               bitmap_scnprintf(m->buf + m->count, m->size - m->count,
-                                bits, nr_bits);
-               m->count += len;
-               return 0;
+int seq_bitmap_list(struct seq_file *m, unsigned long *bits,
+               unsigned int nr_bits)
+{
+       if (m->count < m->size) {
+               int len = bitmap_scnlistprintf(m->buf + m->count,
+                               m->size - m->count, bits, nr_bits);
+               if (m->count + len < m->size) {
+                       m->count += len;
+                       return 0;
+               }
        }
        m->count = m->size;
        return -1;
 }
+EXPORT_SYMBOL(seq_bitmap_list);
 
 static void *single_start(struct seq_file *p, loff_t *pos)
 {
index 73db464cd08b7a213365c0331824ce478a69e4d1..1a4973e106643dd2badce2eaeb805f82be0744a4 100644 (file)
@@ -414,19 +414,21 @@ static int do_budget_space(struct ubifs_info *c)
         *    @c->lst.empty_lebs + @c->freeable_cnt + @c->idx_gc_cnt -
         *    @c->lst.taken_empty_lebs
         *
-        * @empty_lebs are available because they are empty. @freeable_cnt are
-        * available because they contain only free and dirty space and the
-        * index allocation always occurs after wbufs are synch'ed.
-        * @idx_gc_cnt are available because they are index LEBs that have been
-        * garbage collected (including trivial GC) and are awaiting the commit
-        * before they can be unmapped - note that the in-the-gaps method will
-        * grab these if it needs them. @taken_empty_lebs are empty_lebs that
-        * have already been allocated for some purpose (also includes those
-        * LEBs on the @idx_gc list).
+        * @c->lst.empty_lebs are available because they are empty.
+        * @c->freeable_cnt are available because they contain only free and
+        * dirty space, @c->idx_gc_cnt are available because they are index
+        * LEBs that have been garbage collected and are awaiting the commit
+        * before they can be used. And the in-the-gaps method will grab these
+        * if it needs them. @c->lst.taken_empty_lebs are empty LEBs that have
+        * already been allocated for some purpose.
         *
-        * Note, @taken_empty_lebs may temporarily be higher by one because of
-        * the way we serialize LEB allocations and budgeting. See a comment in
-        * 'ubifs_find_free_space()'.
+        * Note, @c->idx_gc_cnt is included to both @c->lst.empty_lebs (because
+        * these LEBs are empty) and to @c->lst.taken_empty_lebs (because they
+        * are taken until after the commit).
+        *
+        * Note, @c->lst.taken_empty_lebs may temporarily be higher by one
+        * because of the way we serialize LEB allocations and budgeting. See a
+        * comment in 'ubifs_find_free_space()'.
         */
        lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
               c->lst.taken_empty_lebs;
index 5bb51dac3c165f3e9df9962ac20411aae2ab2422..a0ada596b17c4a5d9180b515e5fd7e524b72a642 100644 (file)
@@ -91,8 +91,6 @@ struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
  *
  * Note, if the input buffer was not compressed, it is copied to the output
  * buffer and %UBIFS_COMPR_NONE is returned in @compr_type.
- *
- * This functions returns %0 on success or a negative error code on failure.
  */
 void ubifs_compress(const void *in_buf, int in_len, void *out_buf, int *out_len,
                    int *compr_type)
index d7f7645779f2bab707af9c0a38e96288fe65bebf..7186400750e775ad18bd2e9975a373ecb7803e62 100644 (file)
@@ -222,30 +222,38 @@ void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
 {
        const struct ubifs_inode *ui = ubifs_inode(inode);
 
-       printk(KERN_DEBUG "inode      %lu\n", inode->i_ino);
-       printk(KERN_DEBUG "size       %llu\n",
+       printk(KERN_DEBUG "Dump in-memory inode:");
+       printk(KERN_DEBUG "\tinode          %lu\n", inode->i_ino);
+       printk(KERN_DEBUG "\tsize           %llu\n",
               (unsigned long long)i_size_read(inode));
-       printk(KERN_DEBUG "nlink      %u\n", inode->i_nlink);
-       printk(KERN_DEBUG "uid        %u\n", (unsigned int)inode->i_uid);
-       printk(KERN_DEBUG "gid        %u\n", (unsigned int)inode->i_gid);
-       printk(KERN_DEBUG "atime      %u.%u\n",
+       printk(KERN_DEBUG "\tnlink          %u\n", inode->i_nlink);
+       printk(KERN_DEBUG "\tuid            %u\n", (unsigned int)inode->i_uid);
+       printk(KERN_DEBUG "\tgid            %u\n", (unsigned int)inode->i_gid);
+       printk(KERN_DEBUG "\tatime          %u.%u\n",
               (unsigned int)inode->i_atime.tv_sec,
               (unsigned int)inode->i_atime.tv_nsec);
-       printk(KERN_DEBUG "mtime      %u.%u\n",
+       printk(KERN_DEBUG "\tmtime          %u.%u\n",
               (unsigned int)inode->i_mtime.tv_sec,
               (unsigned int)inode->i_mtime.tv_nsec);
-       printk(KERN_DEBUG "ctime       %u.%u\n",
+       printk(KERN_DEBUG "\tctime          %u.%u\n",
               (unsigned int)inode->i_ctime.tv_sec,
               (unsigned int)inode->i_ctime.tv_nsec);
-       printk(KERN_DEBUG "creat_sqnum %llu\n", ui->creat_sqnum);
-       printk(KERN_DEBUG "xattr_size  %u\n", ui->xattr_size);
-       printk(KERN_DEBUG "xattr_cnt   %u\n", ui->xattr_cnt);
-       printk(KERN_DEBUG "xattr_names %u\n", ui->xattr_names);
-       printk(KERN_DEBUG "dirty       %u\n", ui->dirty);
-       printk(KERN_DEBUG "xattr       %u\n", ui->xattr);
-       printk(KERN_DEBUG "flags       %d\n", ui->flags);
-       printk(KERN_DEBUG "compr_type  %d\n", ui->compr_type);
-       printk(KERN_DEBUG "data_len    %d\n", ui->data_len);
+       printk(KERN_DEBUG "\tcreat_sqnum    %llu\n", ui->creat_sqnum);
+       printk(KERN_DEBUG "\txattr_size     %u\n", ui->xattr_size);
+       printk(KERN_DEBUG "\txattr_cnt      %u\n", ui->xattr_cnt);
+       printk(KERN_DEBUG "\txattr_names    %u\n", ui->xattr_names);
+       printk(KERN_DEBUG "\tdirty          %u\n", ui->dirty);
+       printk(KERN_DEBUG "\txattr          %u\n", ui->xattr);
+       printk(KERN_DEBUG "\tbulk_read      %u\n", ui->xattr);
+       printk(KERN_DEBUG "\tsynced_i_size  %llu\n",
+              (unsigned long long)ui->synced_i_size);
+       printk(KERN_DEBUG "\tui_size        %llu\n",
+              (unsigned long long)ui->ui_size);
+       printk(KERN_DEBUG "\tflags          %d\n", ui->flags);
+       printk(KERN_DEBUG "\tcompr_type     %d\n", ui->compr_type);
+       printk(KERN_DEBUG "\tlast_page_read %lu\n", ui->last_page_read);
+       printk(KERN_DEBUG "\tread_in_a_row  %lu\n", ui->read_in_a_row);
+       printk(KERN_DEBUG "\tdata_len       %d\n", ui->data_len);
 }
 
 void dbg_dump_node(const struct ubifs_info *c, const void *node)
@@ -647,6 +655,43 @@ void dbg_dump_lprops(struct ubifs_info *c)
        }
 }
 
+void dbg_dump_lpt_info(struct ubifs_info *c)
+{
+       int i;
+
+       spin_lock(&dbg_lock);
+       printk(KERN_DEBUG "\tlpt_sz:        %lld\n", c->lpt_sz);
+       printk(KERN_DEBUG "\tpnode_sz:      %d\n", c->pnode_sz);
+       printk(KERN_DEBUG "\tnnode_sz:      %d\n", c->nnode_sz);
+       printk(KERN_DEBUG "\tltab_sz:       %d\n", c->ltab_sz);
+       printk(KERN_DEBUG "\tlsave_sz:      %d\n", c->lsave_sz);
+       printk(KERN_DEBUG "\tbig_lpt:       %d\n", c->big_lpt);
+       printk(KERN_DEBUG "\tlpt_hght:      %d\n", c->lpt_hght);
+       printk(KERN_DEBUG "\tpnode_cnt:     %d\n", c->pnode_cnt);
+       printk(KERN_DEBUG "\tnnode_cnt:     %d\n", c->nnode_cnt);
+       printk(KERN_DEBUG "\tdirty_pn_cnt:  %d\n", c->dirty_pn_cnt);
+       printk(KERN_DEBUG "\tdirty_nn_cnt:  %d\n", c->dirty_nn_cnt);
+       printk(KERN_DEBUG "\tlsave_cnt:     %d\n", c->lsave_cnt);
+       printk(KERN_DEBUG "\tspace_bits:    %d\n", c->space_bits);
+       printk(KERN_DEBUG "\tlpt_lnum_bits: %d\n", c->lpt_lnum_bits);
+       printk(KERN_DEBUG "\tlpt_offs_bits: %d\n", c->lpt_offs_bits);
+       printk(KERN_DEBUG "\tlpt_spc_bits:  %d\n", c->lpt_spc_bits);
+       printk(KERN_DEBUG "\tpcnt_bits:     %d\n", c->pcnt_bits);
+       printk(KERN_DEBUG "\tlnum_bits:     %d\n", c->lnum_bits);
+       printk(KERN_DEBUG "\tLPT root is at %d:%d\n", c->lpt_lnum, c->lpt_offs);
+       printk(KERN_DEBUG "\tLPT head is at %d:%d\n",
+              c->nhead_lnum, c->nhead_offs);
+       printk(KERN_DEBUG "\tLPT ltab is at %d:%d\n", c->ltab_lnum, c->ltab_offs);
+       if (c->big_lpt)
+               printk(KERN_DEBUG "\tLPT lsave is at %d:%d\n",
+                      c->lsave_lnum, c->lsave_offs);
+       for (i = 0; i < c->lpt_lebs; i++)
+               printk(KERN_DEBUG "\tLPT LEB %d free %d dirty %d tgc %d "
+                      "cmt %d\n", i + c->lpt_first, c->ltab[i].free,
+                      c->ltab[i].dirty, c->ltab[i].tgc, c->ltab[i].cmt);
+       spin_unlock(&dbg_lock);
+}
+
 void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 {
        struct ubifs_scan_leb *sleb;
index 50315fc571859098b34a0de156ea36f77d7e11d1..33d6b95071e4589f94c17530d0d14320920c47af 100644 (file)
@@ -224,6 +224,7 @@ void dbg_dump_lstats(const struct ubifs_lp_stats *lst);
 void dbg_dump_budg(struct ubifs_info *c);
 void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp);
 void dbg_dump_lprops(struct ubifs_info *c);
+void dbg_dump_lpt_info(struct ubifs_info *c);
 void dbg_dump_leb(const struct ubifs_info *c, int lnum);
 void dbg_dump_znode(const struct ubifs_info *c,
                    const struct ubifs_znode *znode);
@@ -249,6 +250,8 @@ int dbg_old_index_check_init(struct ubifs_info *c, struct ubifs_zbranch *zroot);
 int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot);
 int dbg_check_cats(struct ubifs_info *c);
 int dbg_check_ltab(struct ubifs_info *c);
+int dbg_chk_lpt_free_spc(struct ubifs_info *c);
+int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len);
 int dbg_check_synced_i_size(struct inode *inode);
 int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
 int dbg_check_tnc(struct ubifs_info *c, int extra);
@@ -367,6 +370,7 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
 #define dbg_dump_budg(c)                      ({})
 #define dbg_dump_lprop(c, lp)                 ({})
 #define dbg_dump_lprops(c)                    ({})
+#define dbg_dump_lpt_info(c)                  ({})
 #define dbg_dump_leb(c, lnum)                 ({})
 #define dbg_dump_znode(c, znode)              ({})
 #define dbg_dump_heap(c, heap, cat)           ({})
@@ -379,6 +383,8 @@ static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
 #define dbg_check_old_index(c, zroot)              0
 #define dbg_check_cats(c)                          0
 #define dbg_check_ltab(c)                          0
+#define dbg_chk_lpt_free_spc(c)                    0
+#define dbg_chk_lpt_sz(c, action, len)             0
 #define dbg_check_synced_i_size(inode)             0
 #define dbg_check_dir_size(c, dir)                 0
 #define dbg_check_tnc(c, x)                        0
index 3d698e2022b1ee7b2c8250fc75c89fff79785097..51cf511d44d918ccef3210c340f55fa7cc90e35b 100644 (file)
@@ -147,6 +147,12 @@ static int do_readpage(struct page *page)
                                err = ret;
                                if (err != -ENOENT)
                                        break;
+                       } else if (block + 1 == beyond) {
+                               int dlen = le32_to_cpu(dn->size);
+                               int ilen = i_size & (UBIFS_BLOCK_SIZE - 1);
+
+                               if (ilen && ilen < dlen)
+                                       memset(addr + ilen, 0, dlen - ilen);
                        }
                }
                if (++i >= UBIFS_BLOCKS_PER_PAGE)
@@ -577,8 +583,262 @@ out:
        return copied;
 }
 
+/**
+ * populate_page - copy data nodes into a page for bulk-read.
+ * @c: UBIFS file-system description object
+ * @page: page
+ * @bu: bulk-read information
+ * @n: next zbranch slot
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+static int populate_page(struct ubifs_info *c, struct page *page,
+                        struct bu_info *bu, int *n)
+{
+       int i = 0, nn = *n, offs = bu->zbranch[0].offs, hole = 0, read = 0;
+       struct inode *inode = page->mapping->host;
+       loff_t i_size = i_size_read(inode);
+       unsigned int page_block;
+       void *addr, *zaddr;
+       pgoff_t end_index;
+
+       dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
+               inode->i_ino, page->index, i_size, page->flags);
+
+       addr = zaddr = kmap(page);
+
+       end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
+       if (!i_size || page->index > end_index) {
+               hole = 1;
+               memset(addr, 0, PAGE_CACHE_SIZE);
+               goto out_hole;
+       }
+
+       page_block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT;
+       while (1) {
+               int err, len, out_len, dlen;
+
+               if (nn >= bu->cnt) {
+                       hole = 1;
+                       memset(addr, 0, UBIFS_BLOCK_SIZE);
+               } else if (key_block(c, &bu->zbranch[nn].key) == page_block) {
+                       struct ubifs_data_node *dn;
+
+                       dn = bu->buf + (bu->zbranch[nn].offs - offs);
+
+                       ubifs_assert(dn->ch.sqnum >
+                                    ubifs_inode(inode)->creat_sqnum);
+
+                       len = le32_to_cpu(dn->size);
+                       if (len <= 0 || len > UBIFS_BLOCK_SIZE)
+                               goto out_err;
+
+                       dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ;
+                       out_len = UBIFS_BLOCK_SIZE;
+                       err = ubifs_decompress(&dn->data, dlen, addr, &out_len,
+                                              le16_to_cpu(dn->compr_type));
+                       if (err || len != out_len)
+                               goto out_err;
+
+                       if (len < UBIFS_BLOCK_SIZE)
+                               memset(addr + len, 0, UBIFS_BLOCK_SIZE - len);
+
+                       nn += 1;
+                       read = (i << UBIFS_BLOCK_SHIFT) + len;
+               } else if (key_block(c, &bu->zbranch[nn].key) < page_block) {
+                       nn += 1;
+                       continue;
+               } else {
+                       hole = 1;
+                       memset(addr, 0, UBIFS_BLOCK_SIZE);
+               }
+               if (++i >= UBIFS_BLOCKS_PER_PAGE)
+                       break;
+               addr += UBIFS_BLOCK_SIZE;
+               page_block += 1;
+       }
+
+       if (end_index == page->index) {
+               int len = i_size & (PAGE_CACHE_SIZE - 1);
+
+               if (len && len < read)
+                       memset(zaddr + len, 0, read - len);
+       }
+
+out_hole:
+       if (hole) {
+               SetPageChecked(page);
+               dbg_gen("hole");
+       }
+
+       SetPageUptodate(page);
+       ClearPageError(page);
+       flush_dcache_page(page);
+       kunmap(page);
+       *n = nn;
+       return 0;
+
+out_err:
+       ClearPageUptodate(page);
+       SetPageError(page);
+       flush_dcache_page(page);
+       kunmap(page);
+       ubifs_err("bad data node (block %u, inode %lu)",
+                 page_block, inode->i_ino);
+       return -EINVAL;
+}
+
+/**
+ * ubifs_do_bulk_read - do bulk-read.
+ * @c: UBIFS file-system description object
+ * @page1: first page
+ *
+ * This function returns %1 if the bulk-read is done, otherwise %0 is returned.
+ */
+static int ubifs_do_bulk_read(struct ubifs_info *c, struct page *page1)
+{
+       pgoff_t offset = page1->index, end_index;
+       struct address_space *mapping = page1->mapping;
+       struct inode *inode = mapping->host;
+       struct ubifs_inode *ui = ubifs_inode(inode);
+       struct bu_info *bu;
+       int err, page_idx, page_cnt, ret = 0, n = 0;
+       loff_t isize;
+
+       bu = kmalloc(sizeof(struct bu_info), GFP_NOFS);
+       if (!bu)
+               return 0;
+
+       bu->buf_len = c->bulk_read_buf_size;
+       bu->buf = kmalloc(bu->buf_len, GFP_NOFS);
+       if (!bu->buf)
+               goto out_free;
+
+       data_key_init(c, &bu->key, inode->i_ino,
+                     offset << UBIFS_BLOCKS_PER_PAGE_SHIFT);
+
+       err = ubifs_tnc_get_bu_keys(c, bu);
+       if (err)
+               goto out_warn;
+
+       if (bu->eof) {
+               /* Turn off bulk-read at the end of the file */
+               ui->read_in_a_row = 1;
+               ui->bulk_read = 0;
+       }
+
+       page_cnt = bu->blk_cnt >> UBIFS_BLOCKS_PER_PAGE_SHIFT;
+       if (!page_cnt) {
+               /*
+                * This happens when there are multiple blocks per page and the
+                * blocks for the first page we are looking for, are not
+                * together. If all the pages were like this, bulk-read would
+                * reduce performance, so we turn it off for a while.
+                */
+               ui->read_in_a_row = 0;
+               ui->bulk_read = 0;
+               goto out_free;
+       }
+
+       if (bu->cnt) {
+               err = ubifs_tnc_bulk_read(c, bu);
+               if (err)
+                       goto out_warn;
+       }
+
+       err = populate_page(c, page1, bu, &n);
+       if (err)
+               goto out_warn;
+
+       unlock_page(page1);
+       ret = 1;
+
+       isize = i_size_read(inode);
+       if (isize == 0)
+               goto out_free;
+       end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
+
+       for (page_idx = 1; page_idx < page_cnt; page_idx++) {
+               pgoff_t page_offset = offset + page_idx;
+               struct page *page;
+
+               if (page_offset > end_index)
+                       break;
+               page = find_or_create_page(mapping, page_offset,
+                                          GFP_NOFS | __GFP_COLD);
+               if (!page)
+                       break;
+               if (!PageUptodate(page))
+                       err = populate_page(c, page, bu, &n);
+               unlock_page(page);
+               page_cache_release(page);
+               if (err)
+                       break;
+       }
+
+       ui->last_page_read = offset + page_idx - 1;
+
+out_free:
+       kfree(bu->buf);
+       kfree(bu);
+       return ret;
+
+out_warn:
+       ubifs_warn("ignoring error %d and skipping bulk-read", err);
+       goto out_free;
+}
+
+/**
+ * ubifs_bulk_read - determine whether to bulk-read and, if so, do it.
+ * @page: page from which to start bulk-read.
+ *
+ * Some flash media are capable of reading sequentially at faster rates. UBIFS
+ * bulk-read facility is designed to take advantage of that, by reading in one
+ * go consecutive data nodes that are also located consecutively in the same
+ * LEB. This function returns %1 if a bulk-read is done and %0 otherwise.
+ */
+static int ubifs_bulk_read(struct page *page)
+{
+       struct inode *inode = page->mapping->host;
+       struct ubifs_info *c = inode->i_sb->s_fs_info;
+       struct ubifs_inode *ui = ubifs_inode(inode);
+       pgoff_t index = page->index, last_page_read = ui->last_page_read;
+       int ret = 0;
+
+       ui->last_page_read = index;
+
+       if (!c->bulk_read)
+               return 0;
+       /*
+        * Bulk-read is protected by ui_mutex, but it is an optimization, so
+        * don't bother if we cannot lock the mutex.
+        */
+       if (!mutex_trylock(&ui->ui_mutex))
+               return 0;
+       if (index != last_page_read + 1) {
+               /* Turn off bulk-read if we stop reading sequentially */
+               ui->read_in_a_row = 1;
+               if (ui->bulk_read)
+                       ui->bulk_read = 0;
+               goto out_unlock;
+       }
+       if (!ui->bulk_read) {
+               ui->read_in_a_row += 1;
+               if (ui->read_in_a_row < 3)
+                       goto out_unlock;
+               /* Three reads in a row, so switch on bulk-read */
+               ui->bulk_read = 1;
+       }
+       ret = ubifs_do_bulk_read(c, page);
+out_unlock:
+       mutex_unlock(&ui->ui_mutex);
+       return ret;
+}
+
 static int ubifs_readpage(struct file *file, struct page *page)
 {
+       if (ubifs_bulk_read(page))
+               return 0;
        do_readpage(page);
        unlock_page(page);
        return 0;
index 47814cde24076ba1fdd3775824d0bdeda61f79a3..717d79c97c5e7b148bbf335862b2abbbfafc5699 100644 (file)
@@ -901,11 +901,11 @@ static int get_idx_gc_leb(struct ubifs_info *c)
         * it is needed now for this commit.
         */
        lp = ubifs_lpt_lookup_dirty(c, lnum);
-       if (unlikely(IS_ERR(lp)))
+       if (IS_ERR(lp))
                return PTR_ERR(lp);
        lp = ubifs_change_lp(c, lp, LPROPS_NC, LPROPS_NC,
                             lp->flags | LPROPS_INDEX, -1);
-       if (unlikely(IS_ERR(lp)))
+       if (IS_ERR(lp))
                return PTR_ERR(lp);
        dbg_find("LEB %d, dirty %d and free %d flags %#x",
                 lp->lnum, lp->dirty, lp->free, lp->flags);
index 02aba36fe3d4994ac6dbdba97d0705371cd8bf21..0bef6501d58a9f09967ad216df212a5fd88db3e8 100644 (file)
@@ -95,6 +95,48 @@ static int switch_gc_head(struct ubifs_info *c)
        return err;
 }
 
+/**
+ * joinup - bring data nodes for an inode together.
+ * @c: UBIFS file-system description object
+ * @sleb: describes scanned LEB
+ * @inum: inode number
+ * @blk: block number
+ * @data: list to which to add data nodes
+ *
+ * This function looks at the first few nodes in the scanned LEB @sleb and adds
+ * them to @data if they are data nodes from @inum and have a larger block
+ * number than @blk. This function returns %0 on success and a negative error
+ * code on failure.
+ */
+static int joinup(struct ubifs_info *c, struct ubifs_scan_leb *sleb, ino_t inum,
+                 unsigned int blk, struct list_head *data)
+{
+       int err, cnt = 6, lnum = sleb->lnum, offs;
+       struct ubifs_scan_node *snod, *tmp;
+       union ubifs_key *key;
+
+       list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
+               key = &snod->key;
+               if (key_inum(c, key) == inum &&
+                   key_type(c, key) == UBIFS_DATA_KEY &&
+                   key_block(c, key) > blk) {
+                       offs = snod->offs;
+                       err = ubifs_tnc_has_node(c, key, 0, lnum, offs, 0);
+                       if (err < 0)
+                               return err;
+                       list_del(&snod->list);
+                       if (err) {
+                               list_add_tail(&snod->list, data);
+                               blk = key_block(c, key);
+                       } else
+                               kfree(snod);
+                       cnt = 6;
+               } else if (--cnt == 0)
+                       break;
+       }
+       return 0;
+}
+
 /**
  * move_nodes - move nodes.
  * @c: UBIFS file-system description object
@@ -116,16 +158,21 @@ static int switch_gc_head(struct ubifs_info *c)
 static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
 {
        struct ubifs_scan_node *snod, *tmp;
-       struct list_head large, medium, small;
+       struct list_head data, large, medium, small;
        struct ubifs_wbuf *wbuf = &c->jheads[GCHD].wbuf;
        int avail, err, min = INT_MAX;
+       unsigned int blk = 0;
+       ino_t inum = 0;
 
+       INIT_LIST_HEAD(&data);
        INIT_LIST_HEAD(&large);
        INIT_LIST_HEAD(&medium);
        INIT_LIST_HEAD(&small);
 
-       list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
-               struct list_head *lst;
+       while (!list_empty(&sleb->nodes)) {
+               struct list_head *lst = sleb->nodes.next;
+
+               snod = list_entry(lst, struct ubifs_scan_node, list);
 
                ubifs_assert(snod->type != UBIFS_IDX_NODE);
                ubifs_assert(snod->type != UBIFS_REF_NODE);
@@ -136,7 +183,6 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
                if (err < 0)
                        goto out;
 
-               lst = &snod->list;
                list_del(lst);
                if (!err) {
                        /* The node is obsolete, remove it from the list */
@@ -145,15 +191,30 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
                }
 
                /*
-                * Sort the list of nodes so that large nodes go first, and
-                * small nodes go last.
+                * Sort the list of nodes so that data nodes go first, large
+                * nodes go second, and small nodes go last.
                 */
-               if (snod->len > MEDIUM_NODE_WM)
-                       list_add(lst, &large);
+               if (key_type(c, &snod->key) == UBIFS_DATA_KEY) {
+                       if (inum != key_inum(c, &snod->key)) {
+                               if (inum) {
+                                       /*
+                                        * Try to move data nodes from the same
+                                        * inode together.
+                                        */
+                                       err = joinup(c, sleb, inum, blk, &data);
+                                       if (err)
+                                               goto out;
+                               }
+                               inum = key_inum(c, &snod->key);
+                               blk = key_block(c, &snod->key);
+                       }
+                       list_add_tail(lst, &data);
+               } else if (snod->len > MEDIUM_NODE_WM)
+                       list_add_tail(lst, &large);
                else if (snod->len > SMALL_NODE_WM)
-                       list_add(lst, &medium);
+                       list_add_tail(lst, &medium);
                else
-                       list_add(lst, &small);
+                       list_add_tail(lst, &small);
 
                /* And find the smallest node */
                if (snod->len < min)
@@ -164,6 +225,7 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
         * Join the tree lists so that we'd have one roughly sorted list
         * ('large' will be the head of the joined list).
         */
+       list_splice(&data, &large);
        list_splice(&medium, large.prev);
        list_splice(&small, large.prev);
 
@@ -653,7 +715,7 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
         */
        while (1) {
                lp = ubifs_fast_find_freeable(c);
-               if (unlikely(IS_ERR(lp))) {
+               if (IS_ERR(lp)) {
                        err = PTR_ERR(lp);
                        goto out;
                }
@@ -665,7 +727,7 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
                if (err)
                        goto out;
                lp = ubifs_change_lp(c, lp, c->leb_size, 0, lp->flags, 0);
-               if (unlikely(IS_ERR(lp))) {
+               if (IS_ERR(lp)) {
                        err = PTR_ERR(lp);
                        goto out;
                }
@@ -680,7 +742,7 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
        /* Record index freeable LEBs for unmapping after commit */
        while (1) {
                lp = ubifs_fast_find_frdi_idx(c);
-               if (unlikely(IS_ERR(lp))) {
+               if (IS_ERR(lp)) {
                        err = PTR_ERR(lp);
                        goto out;
                }
@@ -696,7 +758,7 @@ int ubifs_gc_start_commit(struct ubifs_info *c)
                /* Don't release the LEB until after the next commit */
                flags = (lp->flags | LPROPS_TAKEN) ^ LPROPS_INDEX;
                lp = ubifs_change_lp(c, lp, c->leb_size, 0, flags, 1);
-               if (unlikely(IS_ERR(lp))) {
+               if (IS_ERR(lp)) {
                        err = PTR_ERR(lp);
                        kfree(idx_gc);
                        goto out;
index 054363f2b207398ff6110fa74a7333d84d43dbc4..01682713af69e9e4f20b9648cfc4f74380da2da8 100644 (file)
@@ -62,6 +62,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
 {
        if (!c->ro_media) {
                c->ro_media = 1;
+               c->no_chk_data_crc = 0;
                ubifs_warn("switched to read-only mode, error %d", err);
                dbg_dump_stack();
        }
@@ -74,6 +75,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
  * @lnum: logical eraseblock number
  * @offs: offset within the logical eraseblock
  * @quiet: print no messages
+ * @chk_crc: indicates whether to always check the CRC
  *
  * This function checks node magic number and CRC checksum. This function also
  * validates node length to prevent UBIFS from becoming crazy when an attacker
@@ -85,7 +87,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
  * or magic.
  */
 int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-                    int offs, int quiet)
+                    int offs, int quiet, int chk_crc)
 {
        int err = -EINVAL, type, node_len;
        uint32_t crc, node_crc, magic;
@@ -121,6 +123,10 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
                   node_len > c->ranges[type].max_len)
                goto out_len;
 
+       if (!chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc)
+               if (c->no_chk_data_crc)
+                       return 0;
+
        crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
        node_crc = le32_to_cpu(ch->crc);
        if (crc != node_crc) {
@@ -722,7 +728,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
                goto out;
        }
 
-       err = ubifs_check_node(c, buf, lnum, offs, 0);
+       err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
        if (err) {
                ubifs_err("expected node type %d", type);
                return err;
@@ -781,7 +787,7 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
                goto out;
        }
 
-       err = ubifs_check_node(c, buf, lnum, offs, 0);
+       err = ubifs_check_node(c, buf, lnum, offs, 0, 0);
        if (err) {
                ubifs_err("expected node type %d", type);
                return err;
index 8f7476007549654daf77bd1bd3a1be09b61d3e37..9ee65086f627eec8d393746bc957fc7538027b66 100644 (file)
@@ -484,7 +484,7 @@ static inline void key_copy(const struct ubifs_info *c,
  * @key2: the second key to compare
  *
  * This function compares 2 keys and returns %-1 if @key1 is less than
- * @key2, 0 if the keys are equivalent and %1 if @key1 is greater than @key2.
+ * @key2, %0 if the keys are equivalent and %1 if @key1 is greater than @key2.
  */
 static inline int keys_cmp(const struct ubifs_info *c,
                           const union ubifs_key *key1,
@@ -502,6 +502,26 @@ static inline int keys_cmp(const struct ubifs_info *c,
        return 0;
 }
 
+/**
+ * keys_eq - determine if keys are equivalent.
+ * @c: UBIFS file-system description object
+ * @key1: the first key to compare
+ * @key2: the second key to compare
+ *
+ * This function compares 2 keys and returns %1 if @key1 is equal to @key2 and
+ * %0 if not.
+ */
+static inline int keys_eq(const struct ubifs_info *c,
+                         const union ubifs_key *key1,
+                         const union ubifs_key *key2)
+{
+       if (key1->u32[0] != key2->u32[0])
+               return 0;
+       if (key1->u32[1] != key2->u32[1])
+               return 0;
+       return 1;
+}
+
 /**
  * is_hash_key - is a key vulnerable to hash collisions.
  * @c: UBIFS file-system description object
index 2ba93da71b651697b89da5cd9faa7ff6e41894c8..f27176e9b70d7208074e0825065f3a79618f9940 100644 (file)
@@ -125,6 +125,7 @@ static void adjust_lpt_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap,
                        }
                }
        }
+
        /* Not greater than parent, so compare to children */
        while (1) {
                /* Compare to left child */
@@ -459,18 +460,6 @@ static void change_category(struct ubifs_info *c, struct ubifs_lprops *lprops)
        }
 }
 
-/**
- * ubifs_get_lprops - get reference to LEB properties.
- * @c: the UBIFS file-system description object
- *
- * This function locks lprops. Lprops have to be unlocked by
- * 'ubifs_release_lprops()'.
- */
-void ubifs_get_lprops(struct ubifs_info *c)
-{
-       mutex_lock(&c->lp_mutex);
-}
-
 /**
  * calc_dark - calculate LEB dark space size.
  * @c: the UBIFS file-system description object
@@ -576,7 +565,6 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
        ubifs_assert(!(lprops->free & 7) && !(lprops->dirty & 7));
 
        spin_lock(&c->space_lock);
-
        if ((lprops->flags & LPROPS_TAKEN) && lprops->free == c->leb_size)
                c->lst.taken_empty_lebs -= 1;
 
@@ -637,30 +625,11 @@ const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
                c->lst.taken_empty_lebs += 1;
 
        change_category(c, lprops);
-
        c->idx_gc_cnt += idx_gc_cnt;
-
        spin_unlock(&c->space_lock);
-
        return lprops;
 }
 
-/**
- * ubifs_release_lprops - release lprops lock.
- * @c: the UBIFS file-system description object
- *
- * This function has to be called after each 'ubifs_get_lprops()' call to
- * unlock lprops.
- */
-void ubifs_release_lprops(struct ubifs_info *c)
-{
-       ubifs_assert(mutex_is_locked(&c->lp_mutex));
-       ubifs_assert(c->lst.empty_lebs >= 0 &&
-                    c->lst.empty_lebs <= c->main_lebs);
-
-       mutex_unlock(&c->lp_mutex);
-}
-
 /**
  * ubifs_get_lp_stats - get lprops statistics.
  * @c: UBIFS file-system description object
@@ -1262,7 +1231,6 @@ static int scan_check_cb(struct ubifs_info *c,
        }
 
        ubifs_scan_destroy(sleb);
-
        return LPT_SCAN_CONTINUE;
 
 out_print:
index 9ff2463177e503f563f6f5cd543c339444d9638e..db8bd0e518b21151c5d6f11eff7d40bac62fc9ff 100644 (file)
@@ -109,7 +109,8 @@ static void do_calc_lpt_geom(struct ubifs_info *c)
        c->lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
        c->lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
        c->lpt_sz += c->ltab_sz;
-       c->lpt_sz += c->lsave_sz;
+       if (c->big_lpt)
+               c->lpt_sz += c->lsave_sz;
 
        /* Add wastage */
        sz = c->lpt_sz;
@@ -287,25 +288,56 @@ uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits)
        const int k = 32 - nrbits;
        uint8_t *p = *addr;
        int b = *pos;
-       uint32_t val;
+       uint32_t uninitialized_var(val);
+       const int bytes = (nrbits + b + 7) >> 3;
 
        ubifs_assert(nrbits > 0);
        ubifs_assert(nrbits <= 32);
        ubifs_assert(*pos >= 0);
        ubifs_assert(*pos < 8);
        if (b) {
-               val = p[1] | ((uint32_t)p[2] << 8) | ((uint32_t)p[3] << 16) |
-                     ((uint32_t)p[4] << 24);
+               switch (bytes) {
+               case 2:
+                       val = p[1];
+                       break;
+               case 3:
+                       val = p[1] | ((uint32_t)p[2] << 8);
+                       break;
+               case 4:
+                       val = p[1] | ((uint32_t)p[2] << 8) |
+                                    ((uint32_t)p[3] << 16);
+                       break;
+               case 5:
+                       val = p[1] | ((uint32_t)p[2] << 8) |
+                                    ((uint32_t)p[3] << 16) |
+                                    ((uint32_t)p[4] << 24);
+               }
                val <<= (8 - b);
                val |= *p >> b;
                nrbits += b;
-       } else
-               val = p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) |
-                     ((uint32_t)p[3] << 24);
+       } else {
+               switch (bytes) {
+               case 1:
+                       val = p[0];
+                       break;
+               case 2:
+                       val = p[0] | ((uint32_t)p[1] << 8);
+                       break;
+               case 3:
+                       val = p[0] | ((uint32_t)p[1] << 8) |
+                                    ((uint32_t)p[2] << 16);
+                       break;
+               case 4:
+                       val = p[0] | ((uint32_t)p[1] << 8) |
+                                    ((uint32_t)p[2] << 16) |
+                                    ((uint32_t)p[3] << 24);
+                       break;
+               }
+       }
        val <<= k;
        val >>= k;
        b = nrbits & 7;
-       p += nrbits / 8;
+       p += nrbits >> 3;
        *addr = p;
        *pos = b;
        ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32);
index 5f0b83e20af6e11160a16a8a62a09bfb11023b2d..eed5a0025d63f8b3b4d21dba633f4c9b208cb6be 100644 (file)
@@ -177,8 +177,6 @@ static int alloc_lpt_leb(struct ubifs_info *c, int *lnum)
                        return 0;
                }
        }
-       dbg_err("last LEB %d", *lnum);
-       dump_stack();
        return -ENOSPC;
 }
 
@@ -193,6 +191,9 @@ static int layout_cnodes(struct ubifs_info *c)
        int lnum, offs, len, alen, done_lsave, done_ltab, err;
        struct ubifs_cnode *cnode;
 
+       err = dbg_chk_lpt_sz(c, 0, 0);
+       if (err)
+               return err;
        cnode = c->lpt_cnext;
        if (!cnode)
                return 0;
@@ -206,6 +207,7 @@ static int layout_cnodes(struct ubifs_info *c)
                c->lsave_lnum = lnum;
                c->lsave_offs = offs;
                offs += c->lsave_sz;
+               dbg_chk_lpt_sz(c, 1, c->lsave_sz);
        }
 
        if (offs + c->ltab_sz <= c->leb_size) {
@@ -213,6 +215,7 @@ static int layout_cnodes(struct ubifs_info *c)
                c->ltab_lnum = lnum;
                c->ltab_offs = offs;
                offs += c->ltab_sz;
+               dbg_chk_lpt_sz(c, 1, c->ltab_sz);
        }
 
        do {
@@ -226,9 +229,10 @@ static int layout_cnodes(struct ubifs_info *c)
                while (offs + len > c->leb_size) {
                        alen = ALIGN(offs, c->min_io_size);
                        upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
+                       dbg_chk_lpt_sz(c, 2, alen - offs);
                        err = alloc_lpt_leb(c, &lnum);
                        if (err)
-                               return err;
+                               goto no_space;
                        offs = 0;
                        ubifs_assert(lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
@@ -238,6 +242,7 @@ static int layout_cnodes(struct ubifs_info *c)
                                c->lsave_lnum = lnum;
                                c->lsave_offs = offs;
                                offs += c->lsave_sz;
+                               dbg_chk_lpt_sz(c, 1, c->lsave_sz);
                                continue;
                        }
                        if (!done_ltab) {
@@ -245,6 +250,7 @@ static int layout_cnodes(struct ubifs_info *c)
                                c->ltab_lnum = lnum;
                                c->ltab_offs = offs;
                                offs += c->ltab_sz;
+                               dbg_chk_lpt_sz(c, 1, c->ltab_sz);
                                continue;
                        }
                        break;
@@ -257,6 +263,7 @@ static int layout_cnodes(struct ubifs_info *c)
                        c->lpt_offs = offs;
                }
                offs += len;
+               dbg_chk_lpt_sz(c, 1, len);
                cnode = cnode->cnext;
        } while (cnode && cnode != c->lpt_cnext);
 
@@ -265,9 +272,10 @@ static int layout_cnodes(struct ubifs_info *c)
                if (offs + c->lsave_sz > c->leb_size) {
                        alen = ALIGN(offs, c->min_io_size);
                        upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
+                       dbg_chk_lpt_sz(c, 2, alen - offs);
                        err = alloc_lpt_leb(c, &lnum);
                        if (err)
-                               return err;
+                               goto no_space;
                        offs = 0;
                        ubifs_assert(lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
@@ -276,6 +284,7 @@ static int layout_cnodes(struct ubifs_info *c)
                c->lsave_lnum = lnum;
                c->lsave_offs = offs;
                offs += c->lsave_sz;
+               dbg_chk_lpt_sz(c, 1, c->lsave_sz);
        }
 
        /* Make sure to place LPT's own lprops table */
@@ -283,9 +292,10 @@ static int layout_cnodes(struct ubifs_info *c)
                if (offs + c->ltab_sz > c->leb_size) {
                        alen = ALIGN(offs, c->min_io_size);
                        upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
+                       dbg_chk_lpt_sz(c, 2, alen - offs);
                        err = alloc_lpt_leb(c, &lnum);
                        if (err)
-                               return err;
+                               goto no_space;
                        offs = 0;
                        ubifs_assert(lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
@@ -294,11 +304,23 @@ static int layout_cnodes(struct ubifs_info *c)
                c->ltab_lnum = lnum;
                c->ltab_offs = offs;
                offs += c->ltab_sz;
+               dbg_chk_lpt_sz(c, 1, c->ltab_sz);
        }
 
        alen = ALIGN(offs, c->min_io_size);
        upd_ltab(c, lnum, c->leb_size - alen, alen - offs);
+       dbg_chk_lpt_sz(c, 4, alen - offs);
+       err = dbg_chk_lpt_sz(c, 3, alen);
+       if (err)
+               return err;
        return 0;
+
+no_space:
+       ubifs_err("LPT out of space");
+       dbg_err("LPT out of space at LEB %d:%d needing %d, done_ltab %d, "
+               "done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
+       dbg_dump_lpt_info(c);
+       return err;
 }
 
 /**
@@ -333,8 +355,6 @@ static int realloc_lpt_leb(struct ubifs_info *c, int *lnum)
                        *lnum = i + c->lpt_first;
                        return 0;
                }
-       dbg_err("last LEB %d", *lnum);
-       dump_stack();
        return -ENOSPC;
 }
 
@@ -369,12 +389,14 @@ static int write_cnodes(struct ubifs_info *c)
                done_lsave = 1;
                ubifs_pack_lsave(c, buf + offs, c->lsave);
                offs += c->lsave_sz;
+               dbg_chk_lpt_sz(c, 1, c->lsave_sz);
        }
 
        if (offs + c->ltab_sz <= c->leb_size) {
                done_ltab = 1;
                ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
                offs += c->ltab_sz;
+               dbg_chk_lpt_sz(c, 1, c->ltab_sz);
        }
 
        /* Loop for each cnode */
@@ -392,10 +414,12 @@ static int write_cnodes(struct ubifs_info *c)
                                                       alen, UBI_SHORTTERM);
                                if (err)
                                        return err;
+                               dbg_chk_lpt_sz(c, 4, alen - wlen);
                        }
+                       dbg_chk_lpt_sz(c, 2, 0);
                        err = realloc_lpt_leb(c, &lnum);
                        if (err)
-                               return err;
+                               goto no_space;
                        offs = 0;
                        from = 0;
                        ubifs_assert(lnum >= c->lpt_first &&
@@ -408,12 +432,14 @@ static int write_cnodes(struct ubifs_info *c)
                                done_lsave = 1;
                                ubifs_pack_lsave(c, buf + offs, c->lsave);
                                offs += c->lsave_sz;
+                               dbg_chk_lpt_sz(c, 1, c->lsave_sz);
                                continue;
                        }
                        if (!done_ltab) {
                                done_ltab = 1;
                                ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
                                offs += c->ltab_sz;
+                               dbg_chk_lpt_sz(c, 1, c->ltab_sz);
                                continue;
                        }
                        break;
@@ -435,6 +461,7 @@ static int write_cnodes(struct ubifs_info *c)
                clear_bit(COW_ZNODE, &cnode->flags);
                smp_mb__after_clear_bit();
                offs += len;
+               dbg_chk_lpt_sz(c, 1, len);
                cnode = cnode->cnext;
        } while (cnode && cnode != c->lpt_cnext);
 
@@ -448,9 +475,10 @@ static int write_cnodes(struct ubifs_info *c)
                                              UBI_SHORTTERM);
                        if (err)
                                return err;
+                       dbg_chk_lpt_sz(c, 2, alen - wlen);
                        err = realloc_lpt_leb(c, &lnum);
                        if (err)
-                               return err;
+                               goto no_space;
                        offs = 0;
                        ubifs_assert(lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
@@ -461,6 +489,7 @@ static int write_cnodes(struct ubifs_info *c)
                done_lsave = 1;
                ubifs_pack_lsave(c, buf + offs, c->lsave);
                offs += c->lsave_sz;
+               dbg_chk_lpt_sz(c, 1, c->lsave_sz);
        }
 
        /* Make sure to place LPT's own lprops table */
@@ -473,9 +502,10 @@ static int write_cnodes(struct ubifs_info *c)
                                              UBI_SHORTTERM);
                        if (err)
                                return err;
+                       dbg_chk_lpt_sz(c, 2, alen - wlen);
                        err = realloc_lpt_leb(c, &lnum);
                        if (err)
-                               return err;
+                               goto no_space;
                        offs = 0;
                        ubifs_assert(lnum >= c->lpt_first &&
                                     lnum <= c->lpt_last);
@@ -486,6 +516,7 @@ static int write_cnodes(struct ubifs_info *c)
                done_ltab = 1;
                ubifs_pack_ltab(c, buf + offs, c->ltab_cmt);
                offs += c->ltab_sz;
+               dbg_chk_lpt_sz(c, 1, c->ltab_sz);
        }
 
        /* Write remaining data in buffer */
@@ -495,6 +526,12 @@ static int write_cnodes(struct ubifs_info *c)
        err = ubifs_leb_write(c, lnum, buf + from, from, alen, UBI_SHORTTERM);
        if (err)
                return err;
+
+       dbg_chk_lpt_sz(c, 4, alen - wlen);
+       err = dbg_chk_lpt_sz(c, 3, ALIGN(offs, c->min_io_size));
+       if (err)
+               return err;
+
        c->nhead_lnum = lnum;
        c->nhead_offs = ALIGN(offs, c->min_io_size);
 
@@ -503,7 +540,15 @@ static int write_cnodes(struct ubifs_info *c)
        dbg_lp("LPT ltab is at %d:%d", c->ltab_lnum, c->ltab_offs);
        if (c->big_lpt)
                dbg_lp("LPT lsave is at %d:%d", c->lsave_lnum, c->lsave_offs);
+
        return 0;
+
+no_space:
+       ubifs_err("LPT out of space mismatch");
+       dbg_err("LPT out of space mismatch at LEB %d:%d needing %d, done_ltab "
+               "%d, done_lsave %d", lnum, offs, len, done_ltab, done_lsave);
+       dbg_dump_lpt_info(c);
+       return err;
 }
 
 /**
@@ -1044,6 +1089,8 @@ static int is_a_node(struct ubifs_info *c, uint8_t *buf, int len)
        int pos = 0, node_type, node_len;
        uint16_t crc, calc_crc;
 
+       if (len < UBIFS_LPT_CRC_BYTES + (UBIFS_LPT_TYPE_BITS + 7) / 8)
+               return 0;
        node_type = ubifs_unpack_bits(&addr, &pos, UBIFS_LPT_TYPE_BITS);
        if (node_type == UBIFS_LPT_NOT_A_NODE)
                return 0;
@@ -1156,6 +1203,9 @@ int ubifs_lpt_start_commit(struct ubifs_info *c)
        dbg_lp("");
 
        mutex_lock(&c->lp_mutex);
+       err = dbg_chk_lpt_free_spc(c);
+       if (err)
+               goto out;
        err = dbg_check_ltab(c);
        if (err)
                goto out;
@@ -1645,4 +1695,121 @@ int dbg_check_ltab(struct ubifs_info *c)
        return 0;
 }
 
+/**
+ * dbg_chk_lpt_free_spc - check LPT free space is enough to write entire LPT.
+ * @c: the UBIFS file-system description object
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int dbg_chk_lpt_free_spc(struct ubifs_info *c)
+{
+       long long free = 0;
+       int i;
+
+       for (i = 0; i < c->lpt_lebs; i++) {
+               if (c->ltab[i].tgc || c->ltab[i].cmt)
+                       continue;
+               if (i + c->lpt_first == c->nhead_lnum)
+                       free += c->leb_size - c->nhead_offs;
+               else if (c->ltab[i].free == c->leb_size)
+                       free += c->leb_size;
+       }
+       if (free < c->lpt_sz) {
+               dbg_err("LPT space error: free %lld lpt_sz %lld",
+                       free, c->lpt_sz);
+               dbg_dump_lpt_info(c);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/**
+ * dbg_chk_lpt_sz - check LPT does not write more than LPT size.
+ * @c: the UBIFS file-system description object
+ * @action: action
+ * @len: length written
+ *
+ * This function returns %0 on success and a negative error code on failure.
+ */
+int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
+{
+       long long chk_lpt_sz, lpt_sz;
+       int err = 0;
+
+       switch (action) {
+       case 0:
+               c->chk_lpt_sz = 0;
+               c->chk_lpt_sz2 = 0;
+               c->chk_lpt_lebs = 0;
+               c->chk_lpt_wastage = 0;
+               if (c->dirty_pn_cnt > c->pnode_cnt) {
+                       dbg_err("dirty pnodes %d exceed max %d",
+                               c->dirty_pn_cnt, c->pnode_cnt);
+                       err = -EINVAL;
+               }
+               if (c->dirty_nn_cnt > c->nnode_cnt) {
+                       dbg_err("dirty nnodes %d exceed max %d",
+                               c->dirty_nn_cnt, c->nnode_cnt);
+                       err = -EINVAL;
+               }
+               return err;
+       case 1:
+               c->chk_lpt_sz += len;
+               return 0;
+       case 2:
+               c->chk_lpt_sz += len;
+               c->chk_lpt_wastage += len;
+               c->chk_lpt_lebs += 1;
+               return 0;
+       case 3:
+               chk_lpt_sz = c->leb_size;
+               chk_lpt_sz *= c->chk_lpt_lebs;
+               chk_lpt_sz += len - c->nhead_offs;
+               if (c->chk_lpt_sz != chk_lpt_sz) {
+                       dbg_err("LPT wrote %lld but space used was %lld",
+                               c->chk_lpt_sz, chk_lpt_sz);
+                       err = -EINVAL;
+               }
+               if (c->chk_lpt_sz > c->lpt_sz) {
+                       dbg_err("LPT wrote %lld but lpt_sz is %lld",
+                               c->chk_lpt_sz, c->lpt_sz);
+                       err = -EINVAL;
+               }
+               if (c->chk_lpt_sz2 && c->chk_lpt_sz != c->chk_lpt_sz2) {
+                       dbg_err("LPT layout size %lld but wrote %lld",
+                               c->chk_lpt_sz, c->chk_lpt_sz2);
+                       err = -EINVAL;
+               }
+               if (c->chk_lpt_sz2 && c->new_nhead_offs != len) {
+                       dbg_err("LPT new nhead offs: expected %d was %d",
+                               c->new_nhead_offs, len);
+                       err = -EINVAL;
+               }
+               lpt_sz = (long long)c->pnode_cnt * c->pnode_sz;
+               lpt_sz += (long long)c->nnode_cnt * c->nnode_sz;
+               lpt_sz += c->ltab_sz;
+               if (c->big_lpt)
+                       lpt_sz += c->lsave_sz;
+               if (c->chk_lpt_sz - c->chk_lpt_wastage > lpt_sz) {
+                       dbg_err("LPT chk_lpt_sz %lld + waste %lld exceeds %lld",
+                               c->chk_lpt_sz, c->chk_lpt_wastage, lpt_sz);
+                       err = -EINVAL;
+               }
+               if (err)
+                       dbg_dump_lpt_info(c);
+               c->chk_lpt_sz2 = c->chk_lpt_sz;
+               c->chk_lpt_sz = 0;
+               c->chk_lpt_wastage = 0;
+               c->chk_lpt_lebs = 0;
+               c->new_nhead_offs = len;
+               return err;
+       case 4:
+               c->chk_lpt_sz += len;
+               c->chk_lpt_wastage += len;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
 #endif /* CONFIG_UBIFS_FS_DEBUG */
index 4c12a9215d7f24571d13603a382179bb223a1b40..4fa81d867e4107cc726074a78762abb5f681ca63 100644 (file)
@@ -310,4 +310,31 @@ static inline int ubifs_tnc_lookup(struct ubifs_info *c,
        return ubifs_tnc_locate(c, key, node, NULL, NULL);
 }
 
+/**
+ * ubifs_get_lprops - get reference to LEB properties.
+ * @c: the UBIFS file-system description object
+ *
+ * This function locks lprops. Lprops have to be unlocked by
+ * 'ubifs_release_lprops()'.
+ */
+static inline void ubifs_get_lprops(struct ubifs_info *c)
+{
+       mutex_lock(&c->lp_mutex);
+}
+
+/**
+ * ubifs_release_lprops - release lprops lock.
+ * @c: the UBIFS file-system description object
+ *
+ * This function has to be called after each 'ubifs_get_lprops()' call to
+ * unlock lprops.
+ */
+static inline void ubifs_release_lprops(struct ubifs_info *c)
+{
+       ubifs_assert(mutex_is_locked(&c->lp_mutex));
+       ubifs_assert(c->lst.empty_lebs >= 0 &&
+                    c->lst.empty_lebs <= c->main_lebs);
+       mutex_unlock(&c->lp_mutex);
+}
+
 #endif /* __UBIFS_MISC_H__ */
index acf5c5fffc603248bc22c4bc3997bbe4f7f0878a..0ed82479b44b4daca156a80107fee1b040ec10a7 100644 (file)
@@ -87,7 +87,7 @@ int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
 
        dbg_scan("scanning %s", dbg_ntype(ch->node_type));
 
-       if (ubifs_check_node(c, buf, lnum, offs, quiet))
+       if (ubifs_check_node(c, buf, lnum, offs, quiet, 1))
                return SCANNED_A_CORRUPT_NODE;
 
        if (ch->node_type == UBIFS_PAD_NODE) {
index 9a9220333b3be51399e4fe2c28cb9a60840842fb..8780efbf40ac64fbf901fd448998361823c38be3 100644 (file)
@@ -401,6 +401,16 @@ static int ubifs_show_options(struct seq_file *s, struct vfsmount *mnt)
        else if (c->mount_opts.unmount_mode == 1)
                seq_printf(s, ",norm_unmount");
 
+       if (c->mount_opts.bulk_read == 2)
+               seq_printf(s, ",bulk_read");
+       else if (c->mount_opts.bulk_read == 1)
+               seq_printf(s, ",no_bulk_read");
+
+       if (c->mount_opts.chk_data_crc == 2)
+               seq_printf(s, ",chk_data_crc");
+       else if (c->mount_opts.chk_data_crc == 1)
+               seq_printf(s, ",no_chk_data_crc");
+
        return 0;
 }
 
@@ -408,13 +418,26 @@ static int ubifs_sync_fs(struct super_block *sb, int wait)
 {
        struct ubifs_info *c = sb->s_fs_info;
        int i, ret = 0, err;
+       long long bud_bytes;
 
-       if (c->jheads)
+       if (c->jheads) {
                for (i = 0; i < c->jhead_cnt; i++) {
                        err = ubifs_wbuf_sync(&c->jheads[i].wbuf);
                        if (err && !ret)
                                ret = err;
                }
+
+               /* Commit the journal unless it has too little data */
+               spin_lock(&c->buds_lock);
+               bud_bytes = c->bud_bytes;
+               spin_unlock(&c->buds_lock);
+               if (bud_bytes > c->leb_size) {
+                       err = ubifs_run_commit(c);
+                       if (err)
+                               return err;
+               }
+       }
+
        /*
         * We ought to call sync for c->ubi but it does not have one. If it had
         * it would in turn call mtd->sync, however mtd operations are
@@ -538,6 +561,18 @@ static int init_constants_early(struct ubifs_info *c)
         * calculations when reporting free space.
         */
        c->leb_overhead = c->leb_size % UBIFS_MAX_DATA_NODE_SZ;
+       /* Buffer size for bulk-reads */
+       c->bulk_read_buf_size = UBIFS_MAX_BULK_READ * UBIFS_MAX_DATA_NODE_SZ;
+       if (c->bulk_read_buf_size > c->leb_size)
+               c->bulk_read_buf_size = c->leb_size;
+       if (c->bulk_read_buf_size > 128 * 1024) {
+               /* Check if we can kmalloc more than 128KiB */
+               void *try = kmalloc(c->bulk_read_buf_size, GFP_KERNEL);
+
+               kfree(try);
+               if (!try)
+                       c->bulk_read_buf_size = 128 * 1024;
+       }
        return 0;
 }
 
@@ -840,17 +875,29 @@ static int check_volume_empty(struct ubifs_info *c)
  *
  * Opt_fast_unmount: do not run a journal commit before un-mounting
  * Opt_norm_unmount: run a journal commit before un-mounting
+ * Opt_bulk_read: enable bulk-reads
+ * Opt_no_bulk_read: disable bulk-reads
+ * Opt_chk_data_crc: check CRCs when reading data nodes
+ * Opt_no_chk_data_crc: do not check CRCs when reading data nodes
  * Opt_err: just end of array marker
  */
 enum {
        Opt_fast_unmount,
        Opt_norm_unmount,
+       Opt_bulk_read,
+       Opt_no_bulk_read,
+       Opt_chk_data_crc,
+       Opt_no_chk_data_crc,
        Opt_err,
 };
 
 static const match_table_t tokens = {
        {Opt_fast_unmount, "fast_unmount"},
        {Opt_norm_unmount, "norm_unmount"},
+       {Opt_bulk_read, "bulk_read"},
+       {Opt_no_bulk_read, "no_bulk_read"},
+       {Opt_chk_data_crc, "chk_data_crc"},
+       {Opt_no_chk_data_crc, "no_chk_data_crc"},
        {Opt_err, NULL},
 };
 
@@ -888,6 +935,22 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
                        c->mount_opts.unmount_mode = 1;
                        c->fast_unmount = 0;
                        break;
+               case Opt_bulk_read:
+                       c->mount_opts.bulk_read = 2;
+                       c->bulk_read = 1;
+                       break;
+               case Opt_no_bulk_read:
+                       c->mount_opts.bulk_read = 1;
+                       c->bulk_read = 0;
+                       break;
+               case Opt_chk_data_crc:
+                       c->mount_opts.chk_data_crc = 2;
+                       c->no_chk_data_crc = 0;
+                       break;
+               case Opt_no_chk_data_crc:
+                       c->mount_opts.chk_data_crc = 1;
+                       c->no_chk_data_crc = 1;
+                       break;
                default:
                        ubifs_err("unrecognized mount option \"%s\" "
                                  "or missing value", p);
@@ -996,6 +1059,8 @@ static int mount_ubifs(struct ubifs_info *c)
                        goto out_free;
        }
 
+       c->always_chk_crc = 1;
+
        err = ubifs_read_superblock(c);
        if (err)
                goto out_free;
@@ -1032,8 +1097,6 @@ static int mount_ubifs(struct ubifs_info *c)
 
                /* Create background thread */
                c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-               if (!c->bgt)
-                       c->bgt = ERR_PTR(-EINVAL);
                if (IS_ERR(c->bgt)) {
                        err = PTR_ERR(c->bgt);
                        c->bgt = NULL;
@@ -1139,24 +1202,28 @@ static int mount_ubifs(struct ubifs_info *c)
        if (err)
                goto out_infos;
 
+       c->always_chk_crc = 0;
+
        ubifs_msg("mounted UBI device %d, volume %d, name \"%s\"",
                  c->vi.ubi_num, c->vi.vol_id, c->vi.name);
        if (mounted_read_only)
                ubifs_msg("mounted read-only");
        x = (long long)c->main_lebs * c->leb_size;
-       ubifs_msg("file system size: %lld bytes (%lld KiB, %lld MiB, %d LEBs)",
-                 x, x >> 10, x >> 20, c->main_lebs);
+       ubifs_msg("file system size:   %lld bytes (%lld KiB, %lld MiB, %d "
+                 "LEBs)", x, x >> 10, x >> 20, c->main_lebs);
        x = (long long)c->log_lebs * c->leb_size + c->max_bud_bytes;
-       ubifs_msg("journal size: %lld bytes (%lld KiB, %lld MiB, %d LEBs)",
-                 x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt);
-       ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr));
-       ubifs_msg("media format %d, latest format %d",
+       ubifs_msg("journal size:       %lld bytes (%lld KiB, %lld MiB, %d "
+                 "LEBs)", x, x >> 10, x >> 20, c->log_lebs + c->max_bud_cnt);
+       ubifs_msg("media format:       %d (latest is %d)",
                  c->fmt_version, UBIFS_FORMAT_VERSION);
+       ubifs_msg("default compressor: %s", ubifs_compr_name(c->default_compr));
+       ubifs_msg("reserved for root:  %llu bytes (%llu KiB)",
+               c->report_rp_size, c->report_rp_size >> 10);
 
        dbg_msg("compiled on:         " __DATE__ " at " __TIME__);
        dbg_msg("min. I/O unit size:  %d bytes", c->min_io_size);
        dbg_msg("LEB size:            %d bytes (%d KiB)",
-               c->leb_size, c->leb_size / 1024);
+               c->leb_size, c->leb_size >> 10);
        dbg_msg("data journal heads:  %d",
                c->jhead_cnt - NONDATA_JHEADS_CNT);
        dbg_msg("UUID:                %02X%02X%02X%02X-%02X%02X"
@@ -1282,6 +1349,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 
        mutex_lock(&c->umount_mutex);
        c->remounting_rw = 1;
+       c->always_chk_crc = 1;
 
        /* Check for enough free space */
        if (ubifs_calc_available(c, c->min_idx_lebs) <= 0) {
@@ -1345,20 +1413,20 @@ static int ubifs_remount_rw(struct ubifs_info *c)
 
        /* Create background thread */
        c->bgt = kthread_create(ubifs_bg_thread, c, c->bgt_name);
-       if (!c->bgt)
-               c->bgt = ERR_PTR(-EINVAL);
        if (IS_ERR(c->bgt)) {
                err = PTR_ERR(c->bgt);
                c->bgt = NULL;
                ubifs_err("cannot spawn \"%s\", error %d",
                          c->bgt_name, err);
-               return err;
+               goto out;
        }
        wake_up_process(c->bgt);
 
        c->orph_buf = vmalloc(c->leb_size);
-       if (!c->orph_buf)
-               return -ENOMEM;
+       if (!c->orph_buf) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        /* Check for enough log space */
        lnum = c->lhead_lnum + 1;
@@ -1385,6 +1453,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        dbg_gen("re-mounted read-write");
        c->vfs_sb->s_flags &= ~MS_RDONLY;
        c->remounting_rw = 0;
+       c->always_chk_crc = 0;
        mutex_unlock(&c->umount_mutex);
        return 0;
 
@@ -1400,6 +1469,7 @@ out:
        c->ileb_buf = NULL;
        ubifs_lpt_free(c, 1);
        c->remounting_rw = 0;
+       c->always_chk_crc = 0;
        mutex_unlock(&c->umount_mutex);
        return err;
 }
@@ -1408,12 +1478,9 @@ out:
  * commit_on_unmount - commit the journal when un-mounting.
  * @c: UBIFS file-system description object
  *
- * This function is called during un-mounting and it commits the journal unless
- * the "fast unmount" mode is enabled. It also avoids committing the journal if
- * it contains too few data.
- *
- * Sometimes recovery requires the journal to be committed at least once, and
- * this function takes care about this.
+ * This function is called during un-mounting and re-mounting, and it commits
+ * the journal unless the "fast unmount" mode is enabled. It also avoids
+ * committing the journal if it contains too few data.
  */
 static void commit_on_unmount(struct ubifs_info *c)
 {
index 7634c5970887960a9555e82757bf11ffe704a5f3..d27fd918b9c935a1fd115a3f1729576c8c4ae883 100644 (file)
@@ -284,7 +284,7 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
        }
 
        zn = copy_znode(c, znode);
-       if (unlikely(IS_ERR(zn)))
+       if (IS_ERR(zn))
                return zn;
 
        if (zbr->len) {
@@ -470,6 +470,10 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
        if (node_len != len)
                return 0;
 
+       if (type == UBIFS_DATA_NODE && !c->always_chk_crc)
+               if (c->no_chk_data_crc)
+                       return 0;
+
        crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8);
        node_crc = le32_to_cpu(ch->crc);
        if (crc != node_crc)
@@ -1128,7 +1132,7 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c,
                        ubifs_assert(znode == c->zroot.znode);
                        znode = dirty_cow_znode(c, &c->zroot);
                }
-               if (unlikely(IS_ERR(znode)) || !p)
+               if (IS_ERR(znode) || !p)
                        break;
                ubifs_assert(path[p - 1] >= 0);
                ubifs_assert(path[p - 1] < znode->child_cnt);
@@ -1491,6 +1495,289 @@ out:
        return err;
 }
 
+/**
+ * ubifs_tnc_get_bu_keys - lookup keys for bulk-read.
+ * @c: UBIFS file-system description object
+ * @bu: bulk-read parameters and results
+ *
+ * Lookup consecutive data node keys for the same inode that reside
+ * consecutively in the same LEB.
+ */
+int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu)
+{
+       int n, err = 0, lnum = -1, uninitialized_var(offs);
+       int uninitialized_var(len);
+       unsigned int block = key_block(c, &bu->key);
+       struct ubifs_znode *znode;
+
+       bu->cnt = 0;
+       bu->blk_cnt = 0;
+       bu->eof = 0;
+
+       mutex_lock(&c->tnc_mutex);
+       /* Find first key */
+       err = ubifs_lookup_level0(c, &bu->key, &znode, &n);
+       if (err < 0)
+               goto out;
+       if (err) {
+               /* Key found */
+               len = znode->zbranch[n].len;
+               /* The buffer must be big enough for at least 1 node */
+               if (len > bu->buf_len) {
+                       err = -EINVAL;
+                       goto out;
+               }
+               /* Add this key */
+               bu->zbranch[bu->cnt++] = znode->zbranch[n];
+               bu->blk_cnt += 1;
+               lnum = znode->zbranch[n].lnum;
+               offs = ALIGN(znode->zbranch[n].offs + len, 8);
+       }
+       while (1) {
+               struct ubifs_zbranch *zbr;
+               union ubifs_key *key;
+               unsigned int next_block;
+
+               /* Find next key */
+               err = tnc_next(c, &znode, &n);
+               if (err)
+                       goto out;
+               zbr = &znode->zbranch[n];
+               key = &zbr->key;
+               /* See if there is another data key for this file */
+               if (key_inum(c, key) != key_inum(c, &bu->key) ||
+                   key_type(c, key) != UBIFS_DATA_KEY) {
+                       err = -ENOENT;
+                       goto out;
+               }
+               if (lnum < 0) {
+                       /* First key found */
+                       lnum = zbr->lnum;
+                       offs = ALIGN(zbr->offs + zbr->len, 8);
+                       len = zbr->len;
+                       if (len > bu->buf_len) {
+                               err = -EINVAL;
+                               goto out;
+                       }
+               } else {
+                       /*
+                        * The data nodes must be in consecutive positions in
+                        * the same LEB.
+                        */
+                       if (zbr->lnum != lnum || zbr->offs != offs)
+                               goto out;
+                       offs += ALIGN(zbr->len, 8);
+                       len = ALIGN(len, 8) + zbr->len;
+                       /* Must not exceed buffer length */
+                       if (len > bu->buf_len)
+                               goto out;
+               }
+               /* Allow for holes */
+               next_block = key_block(c, key);
+               bu->blk_cnt += (next_block - block - 1);
+               if (bu->blk_cnt >= UBIFS_MAX_BULK_READ)
+                       goto out;
+               block = next_block;
+               /* Add this key */
+               bu->zbranch[bu->cnt++] = *zbr;
+               bu->blk_cnt += 1;
+               /* See if we have room for more */
+               if (bu->cnt >= UBIFS_MAX_BULK_READ)
+                       goto out;
+               if (bu->blk_cnt >= UBIFS_MAX_BULK_READ)
+                       goto out;
+       }
+out:
+       if (err == -ENOENT) {
+               bu->eof = 1;
+               err = 0;
+       }
+       bu->gc_seq = c->gc_seq;
+       mutex_unlock(&c->tnc_mutex);
+       if (err)
+               return err;
+       /*
+        * An enormous hole could cause bulk-read to encompass too many
+        * page cache pages, so limit the number here.
+        */
+       if (bu->blk_cnt > UBIFS_MAX_BULK_READ)
+               bu->blk_cnt = UBIFS_MAX_BULK_READ;
+       /*
+        * Ensure that bulk-read covers a whole number of page cache
+        * pages.
+        */
+       if (UBIFS_BLOCKS_PER_PAGE == 1 ||
+           !(bu->blk_cnt & (UBIFS_BLOCKS_PER_PAGE - 1)))
+               return 0;
+       if (bu->eof) {
+               /* At the end of file we can round up */
+               bu->blk_cnt += UBIFS_BLOCKS_PER_PAGE - 1;
+               return 0;
+       }
+       /* Exclude data nodes that do not make up a whole page cache page */
+       block = key_block(c, &bu->key) + bu->blk_cnt;
+       block &= ~(UBIFS_BLOCKS_PER_PAGE - 1);
+       while (bu->cnt) {
+               if (key_block(c, &bu->zbranch[bu->cnt - 1].key) < block)
+                       break;
+               bu->cnt -= 1;
+       }
+       return 0;
+}
+
+/**
+ * read_wbuf - bulk-read from a LEB with a wbuf.
+ * @wbuf: wbuf that may overlap the read
+ * @buf: buffer into which to read
+ * @len: read length
+ * @lnum: LEB number from which to read
+ * @offs: offset from which to read
+ *
+ * This functions returns %0 on success or a negative error code on failure.
+ */
+static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
+                    int offs)
+{
+       const struct ubifs_info *c = wbuf->c;
+       int rlen, overlap;
+
+       dbg_io("LEB %d:%d, length %d", lnum, offs, len);
+       ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
+       ubifs_assert(!(offs & 7) && offs < c->leb_size);
+       ubifs_assert(offs + len <= c->leb_size);
+
+       spin_lock(&wbuf->lock);
+       overlap = (lnum == wbuf->lnum && offs + len > wbuf->offs);
+       if (!overlap) {
+               /* We may safely unlock the write-buffer and read the data */
+               spin_unlock(&wbuf->lock);
+               return ubi_read(c->ubi, lnum, buf, offs, len);
+       }
+
+       /* Don't read under wbuf */
+       rlen = wbuf->offs - offs;
+       if (rlen < 0)
+               rlen = 0;
+
+       /* Copy the rest from the write-buffer */
+       memcpy(buf + rlen, wbuf->buf + offs + rlen - wbuf->offs, len - rlen);
+       spin_unlock(&wbuf->lock);
+
+       if (rlen > 0)
+               /* Read everything that goes before write-buffer */
+               return ubi_read(c->ubi, lnum, buf, offs, rlen);
+
+       return 0;
+}
+
+/**
+ * validate_data_node - validate data nodes for bulk-read.
+ * @c: UBIFS file-system description object
+ * @buf: buffer containing data node to validate
+ * @zbr: zbranch of data node to validate
+ *
+ * This functions returns %0 on success or a negative error code on failure.
+ */
+static int validate_data_node(struct ubifs_info *c, void *buf,
+                             struct ubifs_zbranch *zbr)
+{
+       union ubifs_key key1;
+       struct ubifs_ch *ch = buf;
+       int err, len;
+
+       if (ch->node_type != UBIFS_DATA_NODE) {
+               ubifs_err("bad node type (%d but expected %d)",
+                         ch->node_type, UBIFS_DATA_NODE);
+               goto out_err;
+       }
+
+       err = ubifs_check_node(c, buf, zbr->lnum, zbr->offs, 0, 0);
+       if (err) {
+               ubifs_err("expected node type %d", UBIFS_DATA_NODE);
+               goto out;
+       }
+
+       len = le32_to_cpu(ch->len);
+       if (len != zbr->len) {
+               ubifs_err("bad node length %d, expected %d", len, zbr->len);
+               goto out_err;
+       }
+
+       /* Make sure the key of the read node is correct */
+       key_read(c, buf + UBIFS_KEY_OFFSET, &key1);
+       if (!keys_eq(c, &zbr->key, &key1)) {
+               ubifs_err("bad key in node at LEB %d:%d",
+                         zbr->lnum, zbr->offs);
+               dbg_tnc("looked for key %s found node's key %s",
+                       DBGKEY(&zbr->key), DBGKEY1(&key1));
+               goto out_err;
+       }
+
+       return 0;
+
+out_err:
+       err = -EINVAL;
+out:
+       ubifs_err("bad node at LEB %d:%d", zbr->lnum, zbr->offs);
+       dbg_dump_node(c, buf);
+       dbg_dump_stack();
+       return err;
+}
+
+/**
+ * ubifs_tnc_bulk_read - read a number of data nodes in one go.
+ * @c: UBIFS file-system description object
+ * @bu: bulk-read parameters and results
+ *
+ * This functions reads and validates the data nodes that were identified by the
+ * 'ubifs_tnc_get_bu_keys()' function. This functions returns %0 on success,
+ * -EAGAIN to indicate a race with GC, or another negative error code on
+ * failure.
+ */
+int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)
+{
+       int lnum = bu->zbranch[0].lnum, offs = bu->zbranch[0].offs, len, err, i;
+       struct ubifs_wbuf *wbuf;
+       void *buf;
+
+       len = bu->zbranch[bu->cnt - 1].offs;
+       len += bu->zbranch[bu->cnt - 1].len - offs;
+       if (len > bu->buf_len) {
+               ubifs_err("buffer too small %d vs %d", bu->buf_len, len);
+               return -EINVAL;
+       }
+
+       /* Do the read */
+       wbuf = ubifs_get_wbuf(c, lnum);
+       if (wbuf)
+               err = read_wbuf(wbuf, bu->buf, len, lnum, offs);
+       else
+               err = ubi_read(c->ubi, lnum, bu->buf, offs, len);
+
+       /* Check for a race with GC */
+       if (maybe_leb_gced(c, lnum, bu->gc_seq))
+               return -EAGAIN;
+
+       if (err && err != -EBADMSG) {
+               ubifs_err("failed to read from LEB %d:%d, error %d",
+                         lnum, offs, err);
+               dbg_dump_stack();
+               dbg_tnc("key %s", DBGKEY(&bu->key));
+               return err;
+       }
+
+       /* Validate the nodes read */
+       buf = bu->buf;
+       for (i = 0; i < bu->cnt; i++) {
+               err = validate_data_node(c, buf, &bu->zbranch[i]);
+               if (err)
+                       return err;
+               buf = buf + ALIGN(bu->zbranch[i].len, 8);
+       }
+
+       return 0;
+}
+
 /**
  * do_lookup_nm- look up a "hashed" node.
  * @c: UBIFS file-system description object
@@ -1675,7 +1962,7 @@ static int tnc_insert(struct ubifs_info *c, struct ubifs_znode *znode,
 {
        struct ubifs_znode *zn, *zi, *zp;
        int i, keep, move, appending = 0;
-       union ubifs_key *key = &zbr->key;
+       union ubifs_key *key = &zbr->key, *key1;
 
        ubifs_assert(n >= 0 && n <= c->fanout);
 
@@ -1716,20 +2003,33 @@ again:
        zn->level = znode->level;
 
        /* Decide where to split */
-       if (znode->level == 0 && n == c->fanout &&
-           key_type(c, key) == UBIFS_DATA_KEY) {
-               union ubifs_key *key1;
-
-               /*
-                * If this is an inode which is being appended - do not split
-                * it because no other zbranches can be inserted between
-                * zbranches of consecutive data nodes anyway.
-                */
-               key1 = &znode->zbranch[n - 1].key;
-               if (key_inum(c, key1) == key_inum(c, key) &&
-                   key_type(c, key1) == UBIFS_DATA_KEY &&
-                   key_block(c, key1) == key_block(c, key) - 1)
-                       appending = 1;
+       if (znode->level == 0 && key_type(c, key) == UBIFS_DATA_KEY) {
+               /* Try not to split consecutive data keys */
+               if (n == c->fanout) {
+                       key1 = &znode->zbranch[n - 1].key;
+                       if (key_inum(c, key1) == key_inum(c, key) &&
+                           key_type(c, key1) == UBIFS_DATA_KEY)
+                               appending = 1;
+               } else
+                       goto check_split;
+       } else if (appending && n != c->fanout) {
+               /* Try not to split consecutive data keys */
+               appending = 0;
+check_split:
+               if (n >= (c->fanout + 1) / 2) {
+                       key1 = &znode->zbranch[0].key;
+                       if (key_inum(c, key1) == key_inum(c, key) &&
+                           key_type(c, key1) == UBIFS_DATA_KEY) {
+                               key1 = &znode->zbranch[n].key;
+                               if (key_inum(c, key1) != key_inum(c, key) ||
+                                   key_type(c, key1) != UBIFS_DATA_KEY) {
+                                       keep = n;
+                                       move = c->fanout - keep;
+                                       zi = znode;
+                                       goto do_split;
+                               }
+                       }
+               }
        }
 
        if (appending) {
@@ -1759,6 +2059,8 @@ again:
                        zbr->znode->parent = zn;
        }
 
+do_split:
+
        __set_bit(DIRTY_ZNODE, &zn->flags);
        atomic_long_inc(&c->dirty_zn_cnt);
 
@@ -1785,14 +2087,11 @@ again:
 
        /* Insert new znode (produced by spitting) into the parent */
        if (zp) {
-               i = n;
+               if (n == 0 && zi == znode && znode->iip == 0)
+                       correct_parent_keys(c, znode);
+
                /* Locate insertion point */
                n = znode->iip + 1;
-               if (appending && n != c->fanout)
-                       appending = 0;
-
-               if (i == 0 && zi == znode && znode->iip == 0)
-                       correct_parent_keys(c, znode);
 
                /* Tail recursion */
                zbr->key = zn->zbranch[0].key;
index a25c1cc1f8d9df4e11fcaf6af3362f1606c9b259..b48db999903e6d34b40c5066a9f30844723b70f8 100644 (file)
@@ -480,8 +480,8 @@ int ubifs_tnc_read_node(struct ubifs_info *c, struct ubifs_zbranch *zbr,
        }
 
        /* Make sure the key of the read node is correct */
-       key_read(c, key, &key1);
-       if (memcmp(node + UBIFS_KEY_OFFSET, &key1, c->key_len)) {
+       key_read(c, node + UBIFS_KEY_OFFSET, &key1);
+       if (!keys_eq(c, key, &key1)) {
                ubifs_err("bad key in node at LEB %d:%d",
                          zbr->lnum, zbr->offs);
                dbg_tnc("looked for key %s found node's key %s",
index a9ecbd9af20dbeb9a0ddefccd21f8b7393ba1d0a..0b378042a3a28dd18737f6211e29dafbe7c5410b 100644 (file)
@@ -75,7 +75,6 @@
  */
 #define UBIFS_BLOCK_SIZE  4096
 #define UBIFS_BLOCK_SHIFT 12
-#define UBIFS_BLOCK_MASK  0x00000FFF
 
 /* UBIFS padding byte pattern (must not be first or last byte of node magic) */
 #define UBIFS_PADDING_BYTE 0xCE
index 17c620b93eec324ced7165b4b2de16482e1b8fda..a7bd32fa15b987d9510583041a7b3a6e5f6f0998 100644 (file)
 /* Maximum expected tree height for use by bottom_up_buf */
 #define BOTTOM_UP_HEIGHT 64
 
+/* Maximum number of data nodes to bulk-read */
+#define UBIFS_MAX_BULK_READ 32
+
 /*
  * Lockdep classes for UBIFS inode @ui_mutex.
  */
@@ -328,9 +331,10 @@ struct ubifs_gced_idx_leb {
  *               this inode
  * @dirty: non-zero if the inode is dirty
  * @xattr: non-zero if this is an extended attribute inode
+ * @bulk_read: non-zero if bulk-read should be used
  * @ui_mutex: serializes inode write-back with the rest of VFS operations,
- *            serializes "clean <-> dirty" state changes, protects @dirty,
- *            @ui_size, and @xattr_size
+ *            serializes "clean <-> dirty" state changes, serializes bulk-read,
+ *            protects @dirty, @bulk_read, @ui_size, and @xattr_size
  * @ui_lock: protects @synced_i_size
  * @synced_i_size: synchronized size of inode, i.e. the value of inode size
  *                 currently stored on the flash; used only for regular file
@@ -338,6 +342,8 @@ struct ubifs_gced_idx_leb {
  * @ui_size: inode size used by UBIFS when writing to flash
  * @flags: inode flags (@UBIFS_COMPR_FL, etc)
  * @compr_type: default compression type used for this inode
+ * @last_page_read: page number of last page read (for bulk read)
+ * @read_in_a_row: number of consecutive pages read in a row (for bulk read)
  * @data_len: length of the data attached to the inode
  * @data: inode's data
  *
@@ -379,12 +385,15 @@ struct ubifs_inode {
        unsigned int xattr_names;
        unsigned int dirty:1;
        unsigned int xattr:1;
+       unsigned int bulk_read:1;
        struct mutex ui_mutex;
        spinlock_t ui_lock;
        loff_t synced_i_size;
        loff_t ui_size;
        int flags;
        int compr_type;
+       pgoff_t last_page_read;
+       pgoff_t read_in_a_row;
        int data_len;
        void *data;
 };
@@ -698,8 +707,8 @@ struct ubifs_jhead {
  * struct ubifs_zbranch - key/coordinate/length branch stored in znodes.
  * @key: key
  * @znode: znode address in memory
- * @lnum: LEB number of the indexing node
- * @offs: offset of the indexing node within @lnum
+ * @lnum: LEB number of the target node (indexing node or data node)
+ * @offs: target node offset within @lnum
  * @len: target node length
  */
 struct ubifs_zbranch {
@@ -743,6 +752,28 @@ struct ubifs_znode {
        struct ubifs_zbranch zbranch[];
 };
 
+/**
+ * struct bu_info - bulk-read information
+ * @key: first data node key
+ * @zbranch: zbranches of data nodes to bulk read
+ * @buf: buffer to read into
+ * @buf_len: buffer length
+ * @gc_seq: GC sequence number to detect races with GC
+ * @cnt: number of data nodes for bulk read
+ * @blk_cnt: number of data blocks including holes
+ * @oef: end of file reached
+ */
+struct bu_info {
+       union ubifs_key key;
+       struct ubifs_zbranch zbranch[UBIFS_MAX_BULK_READ];
+       void *buf;
+       int buf_len;
+       int gc_seq;
+       int cnt;
+       int blk_cnt;
+       int eof;
+};
+
 /**
  * struct ubifs_node_range - node length range description data structure.
  * @len: fixed node length
@@ -862,9 +893,13 @@ struct ubifs_orphan {
 /**
  * struct ubifs_mount_opts - UBIFS-specific mount options information.
  * @unmount_mode: selected unmount mode (%0 default, %1 normal, %2 fast)
+ * @bulk_read: enable bulk-reads
+ * @chk_data_crc: check CRCs when reading data nodes
  */
 struct ubifs_mount_opts {
        unsigned int unmount_mode:2;
+       unsigned int bulk_read:2;
+       unsigned int chk_data_crc:2;
 };
 
 /**
@@ -905,13 +940,12 @@ struct ubifs_mount_opts {
  * @cmt_state: commit state
  * @cs_lock: commit state lock
  * @cmt_wq: wait queue to sleep on if the log is full and a commit is running
+ *
  * @fast_unmount: do not run journal commit before un-mounting
  * @big_lpt: flag that LPT is too big to write whole during commit
- * @check_lpt_free: flag that indicates LPT GC may be needed
- * @nospace: non-zero if the file-system does not have flash space (used as
- *           optimization)
- * @nospace_rp: the same as @nospace, but additionally means that even reserved
- *              pool is full
+ * @no_chk_data_crc: do not check CRCs when reading data nodes (except during
+ *                   recovery)
+ * @bulk_read: enable bulk-reads
  *
  * @tnc_mutex: protects the Tree Node Cache (TNC), @zroot, @cnext, @enext, and
  *             @calc_idx_sz
@@ -935,6 +969,7 @@ struct ubifs_mount_opts {
  * @mst_node: master node
  * @mst_offs: offset of valid master node
  * @mst_mutex: protects the master node area, @mst_node, and @mst_offs
+ * @bulk_read_buf_size: buffer size for bulk-reads
  *
  * @log_lebs: number of logical eraseblocks in the log
  * @log_bytes: log size in bytes
@@ -977,12 +1012,17 @@ struct ubifs_mount_opts {
  *                        but which still have to be taken into account because
  *                        the index has not been committed so far
  * @space_lock: protects @budg_idx_growth, @budg_data_growth, @budg_dd_growth,
- *              @budg_uncommited_idx, @min_idx_lebs, @old_idx_sz, and @lst;
+ *              @budg_uncommited_idx, @min_idx_lebs, @old_idx_sz, @lst,
+ *              @nospace, and @nospace_rp;
  * @min_idx_lebs: minimum number of LEBs required for the index
  * @old_idx_sz: size of index on flash
  * @calc_idx_sz: temporary variable which is used to calculate new index size
  *               (contains accurate new index size at end of TNC commit start)
  * @lst: lprops statistics
+ * @nospace: non-zero if the file-system does not have flash space (used as
+ *           optimization)
+ * @nospace_rp: the same as @nospace, but additionally means that even reserved
+ *              pool is full
  *
  * @page_budget: budget for a page
  * @inode_budget: budget for an inode
@@ -1061,6 +1101,7 @@ struct ubifs_mount_opts {
  * @lpt_drty_flgs: dirty flags for LPT special nodes e.g. ltab
  * @dirty_nn_cnt: number of dirty nnodes
  * @dirty_pn_cnt: number of dirty pnodes
+ * @check_lpt_free: flag that indicates LPT GC may be needed
  * @lpt_sz: LPT size
  * @lpt_nod_buf: buffer for an on-flash nnode or pnode
  * @lpt_buf: buffer of LEB size used by LPT
@@ -1102,6 +1143,7 @@ struct ubifs_mount_opts {
  * @rcvrd_mst_node: recovered master node to write when mounting ro to rw
  * @size_tree: inode size information for recovery
  * @remounting_rw: set while remounting from ro to rw (sb flags have MS_RDONLY)
+ * @always_chk_crc: always check CRCs (while mounting and remounting rw)
  * @mount_opts: UBIFS-specific mount options
  *
  * @dbg_buf: a buffer of LEB size used for debugging purposes
@@ -1146,11 +1188,11 @@ struct ubifs_info {
        int cmt_state;
        spinlock_t cs_lock;
        wait_queue_head_t cmt_wq;
+
        unsigned int fast_unmount:1;
        unsigned int big_lpt:1;
-       unsigned int check_lpt_free:1;
-       unsigned int nospace:1;
-       unsigned int nospace_rp:1;
+       unsigned int no_chk_data_crc:1;
+       unsigned int bulk_read:1;
 
        struct mutex tnc_mutex;
        struct ubifs_zbranch zroot;
@@ -1175,6 +1217,7 @@ struct ubifs_info {
        struct ubifs_mst_node *mst_node;
        int mst_offs;
        struct mutex mst_mutex;
+       int bulk_read_buf_size;
 
        int log_lebs;
        long long log_bytes;
@@ -1218,6 +1261,8 @@ struct ubifs_info {
        unsigned long long old_idx_sz;
        unsigned long long calc_idx_sz;
        struct ubifs_lp_stats lst;
+       unsigned int nospace:1;
+       unsigned int nospace_rp:1;
 
        int page_budget;
        int inode_budget;
@@ -1294,6 +1339,7 @@ struct ubifs_info {
        int lpt_drty_flgs;
        int dirty_nn_cnt;
        int dirty_pn_cnt;
+       int check_lpt_free;
        long long lpt_sz;
        void *lpt_nod_buf;
        void *lpt_buf;
@@ -1335,6 +1381,7 @@ struct ubifs_info {
        struct ubifs_mst_node *rcvrd_mst_node;
        struct rb_root size_tree;
        int remounting_rw;
+       int always_chk_crc;
        struct ubifs_mount_opts mount_opts;
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
@@ -1347,6 +1394,12 @@ struct ubifs_info {
        unsigned long fail_timeout;
        unsigned int fail_cnt;
        unsigned int fail_cnt_max;
+       long long chk_lpt_sz;
+       long long chk_lpt_sz2;
+       long long chk_lpt_wastage;
+       int chk_lpt_lebs;
+       int new_nhead_lnum;
+       int new_nhead_offs;
 #endif
 };
 
@@ -1377,7 +1430,7 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
 int ubifs_write_node(struct ubifs_info *c, void *node, int len, int lnum,
                     int offs, int dtype);
 int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,
-                    int offs, int quiet);
+                    int offs, int quiet, int chk_crc);
 void ubifs_prepare_node(struct ubifs_info *c, void *buf, int len, int pad);
 void ubifs_prep_grp_node(struct ubifs_info *c, void *node, int len, int last);
 int ubifs_io_init(struct ubifs_info *c);
@@ -1490,6 +1543,8 @@ void destroy_old_idx(struct ubifs_info *c);
 int is_idx_node_in_tnc(struct ubifs_info *c, union ubifs_key *key, int level,
                       int lnum, int offs);
 int insert_old_idx_znode(struct ubifs_info *c, struct ubifs_znode *znode);
+int ubifs_tnc_get_bu_keys(struct ubifs_info *c, struct bu_info *bu);
+int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu);
 
 /* tnc_misc.c */
 struct ubifs_znode *ubifs_tnc_levelorder_next(struct ubifs_znode *zr,
@@ -1586,12 +1641,10 @@ int ubifs_lpt_post_commit(struct ubifs_info *c);
 void ubifs_lpt_free(struct ubifs_info *c, int wr_only);
 
 /* lprops.c */
-void ubifs_get_lprops(struct ubifs_info *c);
 const struct ubifs_lprops *ubifs_change_lp(struct ubifs_info *c,
                                           const struct ubifs_lprops *lp,
                                           int free, int dirty, int flags,
                                           int idx_gc_cnt);
-void ubifs_release_lprops(struct ubifs_info *c);
 void ubifs_get_lp_stats(struct ubifs_info *c, struct ubifs_lp_stats *stats);
 void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
                      int cat);
index 649bec78b6455819eb8c216f12a9877063a53880..cfd31e229c89d48e3315edd8f96613a262c16979 100644 (file)
@@ -446,7 +446,7 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
                int type;
 
                xent = ubifs_tnc_next_ent(c, &key, &nm);
-               if (unlikely(IS_ERR(xent))) {
+               if (IS_ERR(xent)) {
                        err = PTR_ERR(xent);
                        break;
                }
index 7efe1000f99d23e18b0825d7b8f4c7ebc52df53d..cee97f14af3bf4896bedcbc48aec2dfee97c89f2 100644 (file)
@@ -88,6 +88,7 @@ struct thread_info {
 #define TIF_RESTORE_SIGMASK    9       /* restore signal mask in do_signal() */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE             17
+#define TIF_FREEZE             18      /* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
@@ -95,6 +96,7 @@ struct thread_info {
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
index 71ef3f0b9685f8adbfcc74a7717b8f7baf2cd496..89061c1a67d473f42c039780e0dcfa1506bec640 100644 (file)
@@ -84,12 +84,12 @@ static inline unsigned int get_rtc_time(struct rtc_time *time)
 
        if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
        {
-               BCD_TO_BIN(time->tm_sec);
-               BCD_TO_BIN(time->tm_min);
-               BCD_TO_BIN(time->tm_hour);
-               BCD_TO_BIN(time->tm_mday);
-               BCD_TO_BIN(time->tm_mon);
-               BCD_TO_BIN(time->tm_year);
+               time->tm_sec = bcd2bin(time->tm_sec);
+               time->tm_min = bcd2bin(time->tm_min);
+               time->tm_hour = bcd2bin(time->tm_hour);
+               time->tm_mday = bcd2bin(time->tm_mday);
+               time->tm_mon = bcd2bin(time->tm_mon);
+               time->tm_year = bcd2bin(time->tm_year);
        }
 
 #ifdef CONFIG_MACH_DECSTATION
@@ -159,12 +159,12 @@ static inline int set_rtc_time(struct rtc_time *time)
 
        if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
            || RTC_ALWAYS_BCD) {
-               BIN_TO_BCD(sec);
-               BIN_TO_BCD(min);
-               BIN_TO_BCD(hrs);
-               BIN_TO_BCD(day);
-               BIN_TO_BCD(mon);
-               BIN_TO_BCD(yrs);
+               sec = bin2bcd(sec);
+               min = bin2bcd(min);
+               hrs = bin2bcd(hrs);
+               day = bin2bcd(day);
+               mon = bin2bcd(mon);
+               yrs = bin2bcd(yrs);
        }
 
        save_control = CMOS_READ(RTC_CONTROL);
index abc002798a2b07a9fcb502ab0f93c1c7f502ef50..af0fda46e94bc969978a9572221ac2843f23bae2 100644 (file)
@@ -52,5 +52,6 @@ struct thread_info {
 #define TIF_DELAYED_TRACE      14      /* single step a syscall */
 #define TIF_SYSCALL_TRACE      15      /* syscall trace active */
 #define TIF_MEMDIE             16
+#define TIF_FREEZE             17      /* thread is freezing for suspend */
 
 #endif /* _ASM_M68K_THREAD_INFO_H */
index 9f812741c3553d41a45e8dada845c7bb57fef86a..0407959da489d54a72b4ccab371cc21e996e79a3 100644 (file)
@@ -58,6 +58,7 @@ struct thread_info {
 #define TIF_32BIT               4       /* 32 bit binary */
 #define TIF_MEMDIE             5
 #define TIF_RESTORE_SIGMASK    6       /* restore saved signal mask */
+#define TIF_FREEZE             7       /* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
@@ -65,6 +66,7 @@ struct thread_info {
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT             (1 << TIF_32BIT)
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE            (1 << TIF_FREEZE)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | \
                                  _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
index e07e72846c7a339544e859d4295eba4452891197..62274ab9471fe6f8eb0de14368acf05b65e17691 100644 (file)
@@ -69,6 +69,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_MEMDIE             5
 #define TIF_SYSCALL_AUDIT      6
 #define TIF_RESTORE_SIGMASK    7
+#define TIF_FREEZE             16      /* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
@@ -77,5 +78,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_MEMDIE            (1 << TIF_MEMDIE)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE            (1 << TIF_FREEZE)
 
 #endif
index 7e4131dd546c5d62655b12fc89460a5e44b31a82..0f4fe1faf9ba46fed7f9c689f2bb2652fe25923b 100644 (file)
@@ -134,6 +134,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_MEMDIE             5
 #define TIF_RESTORE_SIGMASK    6       /* restore signal mask in do_signal() */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_FREEZE             17      /* is freezing for suspend */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
@@ -142,6 +143,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_IRET              (1<<TIF_IRET)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
+#define _TIF_FREEZE            (1<<TIF_FREEZE)
 
 #define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
 #define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
index bf9aca548f14a931f33e35bfed8a8efb4036e8e8..e531783e5d78db542fb4e86c602698bf5824d72b 100644 (file)
@@ -183,6 +183,7 @@ unifdef-y += auto_fs.h
 unifdef-y += auxvec.h
 unifdef-y += binfmts.h
 unifdef-y += blktrace_api.h
+unifdef-y += byteorder.h
 unifdef-y += capability.h
 unifdef-y += capi.h
 unifdef-y += cciss_ioctl.h
@@ -340,6 +341,7 @@ unifdef-y += soundcard.h
 unifdef-y += stat.h
 unifdef-y += stddef.h
 unifdef-y += string.h
+unifdef-y += swab.h
 unifdef-y += synclink.h
 unifdef-y += sysctl.h
 unifdef-y += tcp.h
index 0a24d5550eb3a082725a150856af3055b77f4ae2..bee52abb8a4dbfd46e53f650d7d7dbca881a9169 100644 (file)
@@ -175,6 +175,8 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
  * BDI_CAP_READ_MAP:       Can be mapped for reading
  * BDI_CAP_WRITE_MAP:      Can be mapped for writing
  * BDI_CAP_EXEC_MAP:       Can be mapped for execution
+ *
+ * BDI_CAP_SWAP_BACKED:    Count shmem/tmpfs objects as swap-backed.
  */
 #define BDI_CAP_NO_ACCT_DIRTY  0x00000001
 #define BDI_CAP_NO_WRITEBACK   0x00000002
@@ -184,6 +186,7 @@ int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned int max_ratio);
 #define BDI_CAP_WRITE_MAP      0x00000020
 #define BDI_CAP_EXEC_MAP       0x00000040
 #define BDI_CAP_NO_ACCT_WB     0x00000080
+#define BDI_CAP_SWAP_BACKED    0x00000100
 
 #define BDI_CAP_VMFLAGS \
        (BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP)
@@ -248,6 +251,11 @@ static inline bool bdi_cap_account_writeback(struct backing_dev_info *bdi)
                                      BDI_CAP_NO_WRITEBACK));
 }
 
+static inline bool bdi_cap_swap_backed(struct backing_dev_info *bdi)
+{
+       return bdi->capabilities & BDI_CAP_SWAP_BACKED;
+}
+
 static inline bool mapping_cap_writeback_dirty(struct address_space *mapping)
 {
        return bdi_cap_writeback_dirty(mapping->backing_dev_info);
@@ -258,4 +266,9 @@ static inline bool mapping_cap_account_dirty(struct address_space *mapping)
        return bdi_cap_account_dirty(mapping->backing_dev_info);
 }
 
+static inline bool mapping_cap_swap_backed(struct address_space *mapping)
+{
+       return bdi_cap_swap_backed(mapping->backing_dev_info);
+}
+
 #endif         /* _LINUX_BACKING_DEV_H */
index 7ac518e3c152d9da46f53ed097adb3019245dd5f..22ea563ba3eb169f9e04aac1233b404923c42d6e 100644 (file)
@@ -1,12 +1,3 @@
-/* Permission is hereby granted to copy, modify and redistribute this code
- * in terms of the GNU Library General Public License, Version 2 or later,
- * at your option.
- */
-
-/* macros to translate to/from binary and binary-coded decimal (frequently
- * found in RTC chips).
- */
-
 #ifndef _BCD_H
 #define _BCD_H
 
@@ -15,11 +6,4 @@
 unsigned bcd2bin(unsigned char val) __attribute_const__;
 unsigned char bin2bcd(unsigned val) __attribute_const__;
 
-#define BCD2BIN(val)   bcd2bin(val)
-#define BIN2BCD(val)   bin2bcd(val)
-
-/* backwards compat */
-#define BCD_TO_BIN(val) ((val)=BCD2BIN(val))
-#define BIN_TO_BCD(val) ((val)=BIN2BCD(val))
-
 #endif /* _BCD_H */
index 89781fd48859bb957bbaafabce4c87ad0affd2a0..1abfe664c4446a9a64ea182ce680e6c08d1a3086 100644 (file)
@@ -110,7 +110,6 @@ extern int __bitmap_weight(const unsigned long *bitmap, int bits);
 
 extern int bitmap_scnprintf(char *buf, unsigned int len,
                        const unsigned long *src, int nbits);
-extern int bitmap_scnprintf_len(unsigned int nr_bits);
 extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user,
                        unsigned long *dst, int nbits);
 extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen,
index eadaab44015f62e4fa04ab003828945d6c6bf503..3ce64b90118c20346a704d1c727ec9450d7ccb95 100644 (file)
@@ -322,7 +322,7 @@ static inline void wait_on_buffer(struct buffer_head *bh)
 
 static inline int trylock_buffer(struct buffer_head *bh)
 {
-       return likely(!test_and_set_bit(BH_Lock, &bh->b_state));
+       return likely(!test_and_set_bit_lock(BH_Lock, &bh->b_state));
 }
 
 static inline void lock_buffer(struct buffer_head *bh)
index 1133d5f9d8181c4811362c6992b29b157a0dbb4e..fbaa7f9cee32253c38212318561bd9754a6674d1 100644 (file)
@@ -1,3 +1,4 @@
 unifdef-y += big_endian.h
 unifdef-y += little_endian.h
 unifdef-y += swab.h
+unifdef-y += swabb.h
index 44f95b92393b89b19186166232efa4a797f7314a..1cba3f3efe5f7aaa2ee0ef66afaffbdf3b5fab64 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/byteorder/swab.h>
+#include <linux/byteorder/swabb.h>
 
 #define __constant_htonl(x) ((__force __be32)(__u32)(x))
 #define __constant_ntohl(x) ((__force __u32)(__be32)(x))
index 4cc170a3176219b69ab73bec0035c0868a0362a2..cedc1b5a289c63a4c3102d34db02260b37c1223b 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/byteorder/swab.h>
+#include <linux/byteorder/swabb.h>
 
 #define __constant_htonl(x) ((__force __be32)___constant_swab32((x)))
 #define __constant_ntohl(x) ___constant_swab32((__force __be32)(x))
index 30934e4bfaab7b9e3197e0d7410579c0737bf2c7..8b00f6643e934444f323c7aa3aeac0aff4b2af43 100644 (file)
@@ -9,12 +9,12 @@
  */
 
 #include <linux/sched.h>
-#include <linux/kref.h>
 #include <linux/cpumask.h>
 #include <linux/nodemask.h>
 #include <linux/rcupdate.h>
 #include <linux/cgroupstats.h>
 #include <linux/prio_heap.h>
+#include <linux/rwsem.h>
 
 #ifdef CONFIG_CGROUPS
 
@@ -137,6 +137,15 @@ struct cgroup {
         * release_list_lock
         */
        struct list_head release_list;
+
+       /* pids_mutex protects the fields below */
+       struct rw_semaphore pids_mutex;
+       /* Array of process ids in the cgroup */
+       pid_t *tasks_pids;
+       /* How many files are using the current tasks_pids array */
+       int pids_use_count;
+       /* Length of the current tasks_pids array */
+       int pids_length;
 };
 
 /* A css_set is a structure holding pointers to a set of
@@ -149,7 +158,7 @@ struct cgroup {
 struct css_set {
 
        /* Reference count */
-       struct kref ref;
+       atomic_t refcount;
 
        /*
         * List running through all cgroup groups in the same hash
@@ -394,6 +403,9 @@ void cgroup_iter_end(struct cgroup *cgrp, struct cgroup_iter *it);
 int cgroup_scan_tasks(struct cgroup_scanner *scan);
 int cgroup_attach_task(struct cgroup *, struct task_struct *);
 
+void cgroup_mm_owner_callbacks(struct task_struct *old,
+                              struct task_struct *new);
+
 #else /* !CONFIG_CGROUPS */
 
 static inline int cgroup_init_early(void) { return 0; }
@@ -412,15 +424,9 @@ static inline int cgroupstats_build(struct cgroupstats *stats,
        return -EINVAL;
 }
 
+static inline void cgroup_mm_owner_callbacks(struct task_struct *old,
+                                            struct task_struct *new) {}
+
 #endif /* !CONFIG_CGROUPS */
 
-#ifdef CONFIG_MM_OWNER
-extern void
-cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new);
-#else /* !CONFIG_MM_OWNER */
-static inline void
-cgroup_mm_owner_callbacks(struct task_struct *old, struct task_struct *new)
-{
-}
-#endif /* CONFIG_MM_OWNER */
 #endif /* _LINUX_CGROUP_H */
index e2877454ec82df3205c0251f9c9759db9334dedb..9c22396e8b50355e3058e93807f293112622079f 100644 (file)
@@ -48,3 +48,9 @@ SUBSYS(devices)
 #endif
 
 /* */
+
+#ifdef CONFIG_CGROUP_FREEZER
+SUBSYS(freezer)
+#endif
+
+/* */
index 025e4f5751034ac15139a704a63941a0f1d6dbce..0acf3b737e2ea179c30d9c9fa69076fbdf488a1c 100644 (file)
@@ -8,12 +8,9 @@
 #include <linux/proc_fs.h>
 
 #define ELFCORE_ADDR_MAX       (-1ULL)
+#define ELFCORE_ADDR_ERR       (-2ULL)
 
-#ifdef CONFIG_PROC_VMCORE
 extern unsigned long long elfcorehdr_addr;
-#else
-static const unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-#endif
 
 extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
                                                unsigned long, int);
@@ -28,10 +25,43 @@ extern struct proc_dir_entry *proc_vmcore;
 
 #define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
 
+/*
+ * is_kdump_kernel() checks whether this kernel is booting after a panic of
+ * previous kernel or not. This is determined by checking if previous kernel
+ * has passed the elf core header address on command line.
+ *
+ * This is not just a test if CONFIG_CRASH_DUMP is enabled or not. It will
+ * return 1 if CONFIG_CRASH_DUMP=y and if kernel is booting after a panic of
+ * previous kernel.
+ */
+
 static inline int is_kdump_kernel(void)
 {
        return (elfcorehdr_addr != ELFCORE_ADDR_MAX) ? 1 : 0;
 }
+
+/* is_vmcore_usable() checks if the kernel is booting after a panic and
+ * the vmcore region is usable.
+ *
+ * This makes use of the fact that due to alignment -2ULL is not
+ * a valid pointer, much in the vain of IS_ERR(), except
+ * dealing directly with an unsigned long long rather than a pointer.
+ */
+
+static inline int is_vmcore_usable(void)
+{
+       return is_kdump_kernel() && elfcorehdr_addr != ELFCORE_ADDR_ERR ? 1 : 0;
+}
+
+/* vmcore_unusable() marks the vmcore as unusable,
+ * without disturbing the logic of is_kdump_kernel()
+ */
+
+static inline void vmcore_unusable(void)
+{
+       if (is_kdump_kernel())
+               elfcorehdr_addr = ELFCORE_ADDR_ERR;
+}
 #else /* !CONFIG_CRASH_DUMP */
 static inline int is_kdump_kernel(void) { return 0; }
 #endif /* CONFIG_CRASH_DUMP */
index 159d9b476cd7f404c0ae33facd7189e7efe477ad..d14f029184832bd300ad7856c7cacbe467101c5d 100644 (file)
@@ -380,6 +380,8 @@ struct ext3_inode {
 #define EXT3_MOUNT_QUOTA               0x80000 /* Some quota option set */
 #define EXT3_MOUNT_USRQUOTA            0x100000 /* "old" user quota */
 #define EXT3_MOUNT_GRPQUOTA            0x200000 /* "old" group quota */
+#define EXT3_MOUNT_DATA_ERR_ABORT      0x400000 /* Abort on file data write
+                                                 * error in ordered mode */
 
 /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
 #ifndef _LINUX_EXT2_FS_H
index 531ccd5f5960b0fe5818fdb768d3beb6bd3f3ea7..75a81eaf34309c43ba4da319babecd5e3bd00ca0 100644 (file)
@@ -808,6 +808,7 @@ struct fb_tile_ops {
 struct fb_info {
        int node;
        int flags;
+       struct mutex lock;              /* Lock for open/release/ioctl funcs */
        struct fb_var_screeninfo var;   /* Current var */
        struct fb_fix_screeninfo fix;   /* Current fix */
        struct fb_monspecs monspecs;    /* Current Monitor specs */
index deddeedf32571f12015de116f729ae666f74ede4..8f225339eee9e49329b842803d89c2b4c90f9d38 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/sched.h>
 #include <linux/wait.h>
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FREEZER
 /*
  * Check if a process has been frozen
  */
@@ -39,28 +39,18 @@ static inline void clear_freeze_flag(struct task_struct *p)
        clear_tsk_thread_flag(p, TIF_FREEZE);
 }
 
+static inline bool should_send_signal(struct task_struct *p)
+{
+       return !(p->flags & PF_FREEZER_NOSIG);
+}
+
 /*
  * Wake up a frozen process
- *
- * task_lock() is taken to prevent the race with refrigerator() which may
- * occur if the freezing of tasks fails.  Namely, without the lock, if the
- * freezing of tasks failed, thaw_tasks() might have run before a task in
- * refrigerator() could call frozen_process(), in which case the task would be
- * frozen and no one would thaw it.
  */
-static inline int thaw_process(struct task_struct *p)
-{
-       task_lock(p);
-       if (frozen(p)) {
-               p->flags &= ~PF_FROZEN;
-               task_unlock(p);
-               wake_up_process(p);
-               return 1;
-       }
-       clear_freeze_flag(p);
-       task_unlock(p);
-       return 0;
-}
+extern int __thaw_process(struct task_struct *p);
+
+/* Takes and releases task alloc lock using task_lock() */
+extern int thaw_process(struct task_struct *p);
 
 extern void refrigerator(void);
 extern int freeze_processes(void);
@@ -75,6 +65,15 @@ static inline int try_to_freeze(void)
                return 0;
 }
 
+extern bool freeze_task(struct task_struct *p, bool sig_only);
+extern void cancel_freezing(struct task_struct *p);
+
+#ifdef CONFIG_CGROUP_FREEZER
+extern int cgroup_frozen(struct task_struct *task);
+#else /* !CONFIG_CGROUP_FREEZER */
+static inline int cgroup_frozen(struct task_struct *task) { return 0; }
+#endif /* !CONFIG_CGROUP_FREEZER */
+
 /*
  * The PF_FREEZER_SKIP flag should be set by a vfork parent right before it
  * calls wait_for_completion(&vfork) and reset right after it returns from this
@@ -166,7 +165,7 @@ static inline void set_freezable_with_signal(void)
        } while (try_to_freeze());                                      \
        __retval;                                                       \
 })
-#else /* !CONFIG_PM_SLEEP */
+#else /* !CONFIG_FREEZER */
 static inline int frozen(struct task_struct *p) { return 0; }
 static inline int freezing(struct task_struct *p) { return 0; }
 static inline void set_freeze_flag(struct task_struct *p) {}
@@ -191,6 +190,6 @@ static inline void set_freezable_with_signal(void) {}
 #define wait_event_freezable_timeout(wq, condition, timeout)           \
                wait_event_interruptible_timeout(wq, condition, timeout)
 
-#endif /* !CONFIG_PM_SLEEP */
+#endif /* !CONFIG_FREEZER */
 
 #endif /* FREEZER_H_INCLUDED */
index 7ebbcb1c9ba4e5d6a5a72290c002f37c09617fce..35d4f6342fac82f3158b88e23790aa03a2140c79 100644 (file)
@@ -816,6 +816,9 @@ struct journal_s
 #define JFS_FLUSHED    0x008   /* The journal superblock has been flushed */
 #define JFS_LOADED     0x010   /* The journal superblock has been loaded */
 #define JFS_BARRIER    0x020   /* Use IDE barriers */
+#define JFS_ABORT_ON_SYNCDATA_ERR      0x040  /* Abort the journal on file
+                                               * data write error in ordered
+                                               * mode */
 
 /*
  * Function declarations for the journaling transaction and buffer
index fdf3967e13975a4dc24ec7c37026295ea4fa8f0e..1fbe14d39521d728dd877d263b278210bd9d3ed5 100644 (file)
@@ -27,16 +27,13 @@ struct mm_struct;
 
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 
-#define page_reset_bad_cgroup(page)    ((page)->page_cgroup = 0)
-
-extern struct page_cgroup *page_get_page_cgroup(struct page *page);
 extern int mem_cgroup_charge(struct page *page, struct mm_struct *mm,
                                gfp_t gfp_mask);
 extern int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
                                        gfp_t gfp_mask);
+extern void mem_cgroup_move_lists(struct page *page, enum lru_list lru);
 extern void mem_cgroup_uncharge_page(struct page *page);
 extern void mem_cgroup_uncharge_cache_page(struct page *page);
-extern void mem_cgroup_move_lists(struct page *page, bool active);
 extern int mem_cgroup_shrink_usage(struct mm_struct *mm, gfp_t gfp_mask);
 
 extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
@@ -44,7 +41,7 @@ extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
                                        unsigned long *scanned, int order,
                                        int mode, struct zone *z,
                                        struct mem_cgroup *mem_cont,
-                                       int active);
+                                       int active, int file);
 extern void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask);
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
@@ -69,21 +66,11 @@ extern void mem_cgroup_note_reclaim_priority(struct mem_cgroup *mem,
 extern void mem_cgroup_record_reclaim_priority(struct mem_cgroup *mem,
                                                        int priority);
 
-extern long mem_cgroup_calc_reclaim_active(struct mem_cgroup *mem,
-                               struct zone *zone, int priority);
-extern long mem_cgroup_calc_reclaim_inactive(struct mem_cgroup *mem,
-                               struct zone *zone, int priority);
-
-#else /* CONFIG_CGROUP_MEM_RES_CTLR */
-static inline void page_reset_bad_cgroup(struct page *page)
-{
-}
+extern long mem_cgroup_calc_reclaim(struct mem_cgroup *mem, struct zone *zone,
+                                       int priority, enum lru_list lru);
 
-static inline struct page_cgroup *page_get_page_cgroup(struct page *page)
-{
-       return NULL;
-}
 
+#else /* CONFIG_CGROUP_MEM_RES_CTLR */
 static inline int mem_cgroup_charge(struct page *page,
                                        struct mm_struct *mm, gfp_t gfp_mask)
 {
@@ -159,14 +146,9 @@ static inline void mem_cgroup_record_reclaim_priority(struct mem_cgroup *mem,
 {
 }
 
-static inline long mem_cgroup_calc_reclaim_active(struct mem_cgroup *mem,
-                                       struct zone *zone, int priority)
-{
-       return 0;
-}
-
-static inline long mem_cgroup_calc_reclaim_inactive(struct mem_cgroup *mem,
-                                       struct zone *zone, int priority)
+static inline long mem_cgroup_calc_reclaim(struct mem_cgroup *mem,
+                                       struct zone *zone, int priority,
+                                       enum lru_list lru)
 {
        return 0;
 }
index 03aea612d28450f24f96274c922a8da987bb918b..3f34005068d420b2b1766afdec804529dc2772d9 100644 (file)
@@ -7,7 +7,6 @@
 typedef struct page *new_page_t(struct page *, unsigned long private, int **);
 
 #ifdef CONFIG_MIGRATION
-extern int isolate_lru_page(struct page *p, struct list_head *pagelist);
 extern int putback_lru_pages(struct list_head *l);
 extern int migrate_page(struct address_space *,
                        struct page *, struct page *);
@@ -21,8 +20,6 @@ extern int migrate_vmas(struct mm_struct *mm,
                const nodemask_t *from, const nodemask_t *to,
                unsigned long flags);
 #else
-static inline int isolate_lru_page(struct page *p, struct list_head *list)
-                                       { return -ENOSYS; }
 static inline int putback_lru_pages(struct list_head *l) { return 0; }
 static inline int migrate_pages(struct list_head *l, new_page_t x,
                unsigned long private) { return -ENOSYS; }
index c61ba10768ea48d6691cd58678476f35c1c878f1..ffee2f74341856275ead62f71c6093c8de457199 100644 (file)
@@ -131,6 +131,11 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_SequentialReadHint(v)       ((v)->vm_flags & VM_SEQ_READ)
 #define VM_RandomReadHint(v)           ((v)->vm_flags & VM_RAND_READ)
 
+/*
+ * special vmas that are non-mergable, non-mlock()able
+ */
+#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
+
 /*
  * mapping from the currently active vm_flags protection bits (the
  * low four bits) to a page protection mask..
@@ -700,10 +705,10 @@ static inline int page_mapped(struct page *page)
 extern void show_free_areas(void);
 
 #ifdef CONFIG_SHMEM
-int shmem_lock(struct file *file, int lock, struct user_struct *user);
+extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
 #else
 static inline int shmem_lock(struct file *file, int lock,
-                            struct user_struct *user)
+                           struct user_struct *user)
 {
        return 0;
 }
index 895bc4e93039cdba7f6585b484abed3b9eb4a920..c948350c378e93cb9144e9c17c52f3445e8f4a80 100644 (file)
-static inline void
-add_page_to_active_list(struct zone *zone, struct page *page)
-{
-       list_add(&page->lru, &zone->active_list);
-       __inc_zone_state(zone, NR_ACTIVE);
-}
+#ifndef LINUX_MM_INLINE_H
+#define LINUX_MM_INLINE_H
 
-static inline void
-add_page_to_inactive_list(struct zone *zone, struct page *page)
+/**
+ * page_is_file_cache - should the page be on a file LRU or anon LRU?
+ * @page: the page to test
+ *
+ * Returns LRU_FILE if @page is page cache page backed by a regular filesystem,
+ * or 0 if @page is anonymous, tmpfs or otherwise ram or swap backed.
+ * Used by functions that manipulate the LRU lists, to sort a page
+ * onto the right LRU list.
+ *
+ * We would like to get this info without a page flag, but the state
+ * needs to survive until the page is last deleted from the LRU, which
+ * could be as far down as __page_cache_release.
+ */
+static inline int page_is_file_cache(struct page *page)
 {
-       list_add(&page->lru, &zone->inactive_list);
-       __inc_zone_state(zone, NR_INACTIVE);
+       if (PageSwapBacked(page))
+               return 0;
+
+       /* The page is page cache backed by a normal filesystem. */
+       return LRU_FILE;
 }
 
 static inline void
-del_page_from_active_list(struct zone *zone, struct page *page)
+add_page_to_lru_list(struct zone *zone, struct page *page, enum lru_list l)
 {
-       list_del(&page->lru);
-       __dec_zone_state(zone, NR_ACTIVE);
+       list_add(&page->lru, &zone->lru[l].list);
+       __inc_zone_state(zone, NR_LRU_BASE + l);
 }
 
 static inline void
-del_page_from_inactive_list(struct zone *zone, struct page *page)
+del_page_from_lru_list(struct zone *zone, struct page *page, enum lru_list l)
 {
        list_del(&page->lru);
-       __dec_zone_state(zone, NR_INACTIVE);
+       __dec_zone_state(zone, NR_LRU_BASE + l);
 }
 
 static inline void
 del_page_from_lru(struct zone *zone, struct page *page)
 {
+       enum lru_list l = LRU_BASE;
+
        list_del(&page->lru);
-       if (PageActive(page)) {
-               __ClearPageActive(page);
-               __dec_zone_state(zone, NR_ACTIVE);
+       if (PageUnevictable(page)) {
+               __ClearPageUnevictable(page);
+               l = LRU_UNEVICTABLE;
        } else {
-               __dec_zone_state(zone, NR_INACTIVE);
+               if (PageActive(page)) {
+                       __ClearPageActive(page);
+                       l += LRU_ACTIVE;
+               }
+               l += page_is_file_cache(page);
+       }
+       __dec_zone_state(zone, NR_LRU_BASE + l);
+}
+
+/**
+ * page_lru - which LRU list should a page be on?
+ * @page: the page to test
+ *
+ * Returns the LRU list a page should be on, as an index
+ * into the array of LRU lists.
+ */
+static inline enum lru_list page_lru(struct page *page)
+{
+       enum lru_list lru = LRU_BASE;
+
+       if (PageUnevictable(page))
+               lru = LRU_UNEVICTABLE;
+       else {
+               if (PageActive(page))
+                       lru += LRU_ACTIVE;
+               lru += page_is_file_cache(page);
        }
+
+       return lru;
 }
 
+/**
+ * inactive_anon_is_low - check if anonymous pages need to be deactivated
+ * @zone: zone to check
+ *
+ * Returns true if the zone does not have enough inactive anon pages,
+ * meaning some active anon pages need to be deactivated.
+ */
+static inline int inactive_anon_is_low(struct zone *zone)
+{
+       unsigned long active, inactive;
+
+       active = zone_page_state(zone, NR_ACTIVE_ANON);
+       inactive = zone_page_state(zone, NR_INACTIVE_ANON);
+
+       if (inactive * zone->inactive_ratio < active)
+               return 1;
+
+       return 0;
+}
+#endif
index 9d49fa36bbeff3237e2e0f4925a0ed3ac1ec1b29..fe825471d5aaf9d59440a7f322989004736ea71f 100644 (file)
@@ -94,9 +94,6 @@ struct page {
        void *virtual;                  /* Kernel virtual address (NULL if
                                           not kmapped, ie. highmem) */
 #endif /* WANT_PAGE_VIRTUAL */
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR
-       unsigned long page_cgroup;
-#endif
 };
 
 /*
index 428328a05fa123779a832b4b51731bee45984ea6..35a7b5e19465fc89154dd2097f0bd4913e7b2e21 100644 (file)
@@ -81,21 +81,31 @@ struct zone_padding {
 enum zone_stat_item {
        /* First 128 byte cacheline (assuming 64 bit words) */
        NR_FREE_PAGES,
-       NR_INACTIVE,
-       NR_ACTIVE,
+       NR_LRU_BASE,
+       NR_INACTIVE_ANON = NR_LRU_BASE, /* must match order of LRU_[IN]ACTIVE */
+       NR_ACTIVE_ANON,         /*  "     "     "   "       "         */
+       NR_INACTIVE_FILE,       /*  "     "     "   "       "         */
+       NR_ACTIVE_FILE,         /*  "     "     "   "       "         */
+#ifdef CONFIG_UNEVICTABLE_LRU
+       NR_UNEVICTABLE,         /*  "     "     "   "       "         */
+       NR_MLOCK,               /* mlock()ed pages found and moved off LRU */
+#else
+       NR_UNEVICTABLE = NR_ACTIVE_FILE, /* avoid compiler errors in dead code */
+       NR_MLOCK = NR_ACTIVE_FILE,
+#endif
        NR_ANON_PAGES,  /* Mapped anonymous pages */
        NR_FILE_MAPPED, /* pagecache pages mapped into pagetables.
                           only modified from process context */
        NR_FILE_PAGES,
        NR_FILE_DIRTY,
        NR_WRITEBACK,
-       /* Second 128 byte cacheline */
        NR_SLAB_RECLAIMABLE,
        NR_SLAB_UNRECLAIMABLE,
        NR_PAGETABLE,           /* used for pagetables */
        NR_UNSTABLE_NFS,        /* NFS unstable pages */
        NR_BOUNCE,
        NR_VMSCAN_WRITE,
+       /* Second 128 byte cacheline */
        NR_WRITEBACK_TEMP,      /* Writeback using temporary buffers */
 #ifdef CONFIG_NUMA
        NUMA_HIT,               /* allocated in intended node */
@@ -107,6 +117,55 @@ enum zone_stat_item {
 #endif
        NR_VM_ZONE_STAT_ITEMS };
 
+/*
+ * We do arithmetic on the LRU lists in various places in the code,
+ * so it is important to keep the active lists LRU_ACTIVE higher in
+ * the array than the corresponding inactive lists, and to keep
+ * the *_FILE lists LRU_FILE higher than the corresponding _ANON lists.
+ *
+ * This has to be kept in sync with the statistics in zone_stat_item
+ * above and the descriptions in vmstat_text in mm/vmstat.c
+ */
+#define LRU_BASE 0
+#define LRU_ACTIVE 1
+#define LRU_FILE 2
+
+enum lru_list {
+       LRU_INACTIVE_ANON = LRU_BASE,
+       LRU_ACTIVE_ANON = LRU_BASE + LRU_ACTIVE,
+       LRU_INACTIVE_FILE = LRU_BASE + LRU_FILE,
+       LRU_ACTIVE_FILE = LRU_BASE + LRU_FILE + LRU_ACTIVE,
+#ifdef CONFIG_UNEVICTABLE_LRU
+       LRU_UNEVICTABLE,
+#else
+       LRU_UNEVICTABLE = LRU_ACTIVE_FILE, /* avoid compiler errors in dead code */
+#endif
+       NR_LRU_LISTS
+};
+
+#define for_each_lru(l) for (l = 0; l < NR_LRU_LISTS; l++)
+
+#define for_each_evictable_lru(l) for (l = 0; l <= LRU_ACTIVE_FILE; l++)
+
+static inline int is_file_lru(enum lru_list l)
+{
+       return (l == LRU_INACTIVE_FILE || l == LRU_ACTIVE_FILE);
+}
+
+static inline int is_active_lru(enum lru_list l)
+{
+       return (l == LRU_ACTIVE_ANON || l == LRU_ACTIVE_FILE);
+}
+
+static inline int is_unevictable_lru(enum lru_list l)
+{
+#ifdef CONFIG_UNEVICTABLE_LRU
+       return (l == LRU_UNEVICTABLE);
+#else
+       return 0;
+#endif
+}
+
 struct per_cpu_pages {
        int count;              /* number of pages in the list */
        int high;               /* high watermark, emptying needed */
@@ -251,10 +310,22 @@ struct zone {
 
        /* Fields commonly accessed by the page reclaim scanner */
        spinlock_t              lru_lock;       
-       struct list_head        active_list;
-       struct list_head        inactive_list;
-       unsigned long           nr_scan_active;
-       unsigned long           nr_scan_inactive;
+       struct {
+               struct list_head list;
+               unsigned long nr_scan;
+       } lru[NR_LRU_LISTS];
+
+       /*
+        * The pageout code in vmscan.c keeps track of how many of the
+        * mem/swap backed and file backed pages are refeferenced.
+        * The higher the rotated/scanned ratio, the more valuable
+        * that cache is.
+        *
+        * The anon LRU stats live in [0], file LRU stats in [1]
+        */
+       unsigned long           recent_rotated[2];
+       unsigned long           recent_scanned[2];
+
        unsigned long           pages_scanned;     /* since last reclaim */
        unsigned long           flags;             /* zone flags, see below */
 
@@ -276,6 +347,12 @@ struct zone {
         */
        int prev_priority;
 
+       /*
+        * The target ratio of ACTIVE_ANON to INACTIVE_ANON pages on
+        * this zone's LRU.  Maintained by the pageout code.
+        */
+       unsigned int inactive_ratio;
+
 
        ZONE_PADDING(_pad2_)
        /* Rarely used or read-mostly fields */
@@ -524,8 +601,11 @@ typedef struct pglist_data {
        struct zone node_zones[MAX_NR_ZONES];
        struct zonelist node_zonelists[MAX_ZONELISTS];
        int nr_zones;
-#ifdef CONFIG_FLAT_NODE_MEM_MAP
+#ifdef CONFIG_FLAT_NODE_MEM_MAP        /* means !SPARSEMEM */
        struct page *node_mem_map;
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+       struct page_cgroup *node_page_cgroup;
+#endif
 #endif
        struct bootmem_data *bdata;
 #ifdef CONFIG_MEMORY_HOTPLUG
@@ -854,6 +934,7 @@ static inline unsigned long early_pfn_to_nid(unsigned long pfn)
 #endif
 
 struct page;
+struct page_cgroup;
 struct mem_section {
        /*
         * This is, logically, a pointer to an array of struct
@@ -871,6 +952,14 @@ struct mem_section {
 
        /* See declaration of similar field in struct zone */
        unsigned long *pageblock_flags;
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+       /*
+        * If !SPARSEMEM, pgdat doesn't have page_cgroup pointer. We use
+        * section. (see memcontrol.h/page_cgroup.h about this.)
+        */
+       struct page_cgroup *page_cgroup;
+       unsigned long pad;
+#endif
 };
 
 #ifdef CONFIG_SPARSEMEM_EXTREME
index d6fb115f5a0714794c077ea6ff98ea18243d537e..ee5124ec319e4e036f1f139dff39c428c6732190 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/mtd/flashchip.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/cfi_endian.h>
+#include <linux/mtd/xip.h>
 
 #ifdef CONFIG_MTD_CFI_I1
 #define cfi_interleave(cfi) 1
@@ -430,7 +431,6 @@ static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t
 {
        map_word val;
        uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type);
-
        val = cfi_build_cmd(cmd, map, cfi);
 
        if (prev_val)
@@ -483,6 +483,13 @@ static inline void cfi_udelay(int us)
        }
 }
 
+int __xipram cfi_qry_present(struct map_info *map, __u32 base,
+                            struct cfi_private *cfi);
+int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
+                            struct cfi_private *cfi);
+void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
+                              struct cfi_private *cfi);
+
 struct cfi_extquery *cfi_read_pri(struct map_info *map, uint16_t adr, uint16_t size,
                             const char* name);
 struct cfi_fixup {
index 08dd131301c1fe98e87d900f9173cc054f953a84..d4f38c5fd44ec1d1affcc5876e23dfaadc727fd8 100644 (file)
@@ -73,6 +73,10 @@ struct flchip {
        int buffer_write_time;
        int erase_time;
 
+       int word_write_time_max;
+       int buffer_write_time_max;
+       int erase_time_max;
+
        void *priv;
 };
 
index 922636548558943d7af9007074cb8d2e7e91fcb0..eae26bb6430ae0e8db2c70385d1b1c72c3e32d5b 100644 (file)
 #define MTD_ERASE_DONE          0x08
 #define MTD_ERASE_FAILED        0x10
 
+#define MTD_FAIL_ADDR_UNKNOWN 0xffffffff
+
 /* If the erase fails, fail_addr might indicate exactly which block failed.  If
-   fail_addr = 0xffffffff, the failure was not at the device level or was not
+   fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level or was not
    specific to any particular block. */
 struct erase_info {
        struct mtd_info *mtd;
diff --git a/include/linux/mtd/nand-gpio.h b/include/linux/mtd/nand-gpio.h
new file mode 100644 (file)
index 0000000..51534e5
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __LINUX_MTD_NAND_GPIO_H
+#define __LINUX_MTD_NAND_GPIO_H
+
+#include <linux/mtd/nand.h>
+
+struct gpio_nand_platdata {
+       int     gpio_nce;
+       int     gpio_nwp;
+       int     gpio_cle;
+       int     gpio_ale;
+       int     gpio_rdy;
+       void    (*adjust_parts)(struct gpio_nand_platdata *, size_t);
+       struct mtd_partition *parts;
+       unsigned int num_parts;
+       unsigned int options;
+       int     chip_delay;
+};
+
+#endif
index 81774e5facf4e74a2d5dd742bae6bb81a1922b17..733d3f3b4eb8bbda4101a6a1a37eba84d424b9f0 100644 (file)
@@ -248,6 +248,7 @@ struct nand_hw_control {
  * @read_page_raw:     function to read a raw page without ECC
  * @write_page_raw:    function to write a raw page without ECC
  * @read_page: function to read a page according to the ecc generator requirements
+ * @read_subpage:      function to read parts of the page covered by ECC.
  * @write_page:        function to write a page according to the ecc generator requirements
  * @read_oob:  function to read chip OOB data
  * @write_oob: function to write chip OOB data
index d1b310c92eb45a9272c8ba2ac30c26becb856a5e..0c6bbe28f38ce91e01151faa517c75688300488b 100644 (file)
 #define ONENAND_SYS_CFG1_INT           (1 << 6)
 #define ONENAND_SYS_CFG1_IOBE          (1 << 5)
 #define ONENAND_SYS_CFG1_RDY_CONF      (1 << 4)
+#define ONENAND_SYS_CFG1_HF            (1 << 2)
+#define ONENAND_SYS_CFG1_SYNC_WRITE    (1 << 1)
 
 /*
  * Controller Status Register F240h (R)
index 5014f7a9f5dfe57a8df546d4cee4edb2e6a065df..c92b4d439609feec0640b953fedc502fd9a8890d 100644 (file)
@@ -73,7 +73,6 @@ struct device;
 struct device_node;
 
 int __devinit of_mtd_parse_partitions(struct device *dev,
-                                      struct mtd_info *mtd,
                                       struct device_node *node,
                                       struct mtd_partition **pparts);
 
diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h
new file mode 100644 (file)
index 0000000..e77c1ce
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * SuperH FLCTL nand controller
+ *
+ * Copyright Â© 2008 Renesas Solutions 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifndef __SH_FLCTL_H__
+#define __SH_FLCTL_H__
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+
+/* FLCTL registers */
+#define FLCMNCR(f)             (f->reg + 0x0)
+#define FLCMDCR(f)             (f->reg + 0x4)
+#define FLCMCDR(f)             (f->reg + 0x8)
+#define FLADR(f)               (f->reg + 0xC)
+#define FLADR2(f)              (f->reg + 0x3C)
+#define FLDATAR(f)             (f->reg + 0x10)
+#define FLDTCNTR(f)            (f->reg + 0x14)
+#define FLINTDMACR(f)          (f->reg + 0x18)
+#define FLBSYTMR(f)            (f->reg + 0x1C)
+#define FLBSYCNT(f)            (f->reg + 0x20)
+#define FLDTFIFO(f)            (f->reg + 0x24)
+#define FLECFIFO(f)            (f->reg + 0x28)
+#define FLTRCR(f)              (f->reg + 0x2C)
+#define        FL4ECCRESULT0(f)        (f->reg + 0x80)
+#define        FL4ECCRESULT1(f)        (f->reg + 0x84)
+#define        FL4ECCRESULT2(f)        (f->reg + 0x88)
+#define        FL4ECCRESULT3(f)        (f->reg + 0x8C)
+#define        FL4ECCCR(f)             (f->reg + 0x90)
+#define        FL4ECCCNT(f)            (f->reg + 0x94)
+#define        FLERRADR(f)             (f->reg + 0x98)
+
+/* FLCMNCR control bits */
+#define ECCPOS2                (0x1 << 25)
+#define _4ECCCNTEN     (0x1 << 24)
+#define _4ECCEN                (0x1 << 23)
+#define _4ECCCORRECT   (0x1 << 22)
+#define SNAND_E                (0x1 << 18)     /* SNAND (0=512 1=2048)*/
+#define QTSEL_E                (0x1 << 17)
+#define ENDIAN         (0x1 << 16)     /* 1 = little endian */
+#define FCKSEL_E       (0x1 << 15)
+#define ECCPOS_00      (0x00 << 12)
+#define ECCPOS_01      (0x01 << 12)
+#define ECCPOS_02      (0x02 << 12)
+#define ACM_SACCES_MODE        (0x01 << 10)
+#define NANWF_E                (0x1 << 9)
+#define SE_D           (0x1 << 8)      /* Spare area disable */
+#define        CE1_ENABLE      (0x1 << 4)      /* Chip Enable 1 */
+#define        CE0_ENABLE      (0x1 << 3)      /* Chip Enable 0 */
+#define        TYPESEL_SET     (0x1 << 0)
+
+/* FLCMDCR control bits */
+#define ADRCNT2_E      (0x1 << 31)     /* 5byte address enable */
+#define ADRMD_E                (0x1 << 26)     /* Sector address access */
+#define CDSRC_E                (0x1 << 25)     /* Data buffer selection */
+#define DOSR_E         (0x1 << 24)     /* Status read check */
+#define SELRW          (0x1 << 21)     /*  0:read 1:write */
+#define DOADR_E                (0x1 << 20)     /* Address stage execute */
+#define ADRCNT_1       (0x00 << 18)    /* Address data bytes: 1byte */
+#define ADRCNT_2       (0x01 << 18)    /* Address data bytes: 2byte */
+#define ADRCNT_3       (0x02 << 18)    /* Address data bytes: 3byte */
+#define ADRCNT_4       (0x03 << 18)    /* Address data bytes: 4byte */
+#define DOCMD2_E       (0x1 << 17)     /* 2nd cmd stage execute */
+#define DOCMD1_E       (0x1 << 16)     /* 1st cmd stage execute */
+
+/* FLTRCR control bits */
+#define TRSTRT         (0x1 << 0)      /* translation start */
+#define TREND          (0x1 << 1)      /* translation end */
+
+/* FL4ECCCR control bits */
+#define        _4ECCFA         (0x1 << 2)      /* 4 symbols correct fault */
+#define        _4ECCEND        (0x1 << 1)      /* 4 symbols end */
+#define        _4ECCEXST       (0x1 << 0)      /* 4 symbols exist */
+
+#define INIT_FL4ECCRESULT_VAL  0x03FF03FF
+#define LOOP_TIMEOUT_MAX       0x00010000
+
+#define mtd_to_flctl(mtd)      container_of(mtd, struct sh_flctl, mtd)
+
+struct sh_flctl {
+       struct mtd_info         mtd;
+       struct nand_chip        chip;
+       void __iomem            *reg;
+
+       uint8_t done_buff[2048 + 64];   /* max size 2048 + 64 */
+       int     read_bytes;
+       int     index;
+       int     seqin_column;           /* column in SEQIN cmd */
+       int     seqin_page_addr;        /* page_addr in SEQIN cmd */
+       uint32_t seqin_read_cmd;                /* read cmd in SEQIN cmd */
+       int     erase1_page_addr;       /* page_addr in ERASE1 cmd */
+       uint32_t erase_ADRCNT;          /* bits of FLCMDCR in ERASE1 cmd */
+       uint32_t rw_ADRCNT;     /* bits of FLCMDCR in READ WRITE cmd */
+
+       int     hwecc_cant_correct[4];
+
+       unsigned page_size:1;   /* NAND page size (0 = 512, 1 = 2048) */
+       unsigned hwecc:1;       /* Hardware ECC (0 = disabled, 1 = enabled) */
+};
+
+struct sh_flctl_platform_data {
+       struct mtd_partition    *parts;
+       int                     nr_parts;
+       unsigned long           flcmncr_val;
+
+       unsigned has_hwecc:1;
+};
+
+#endif /* __SH_FLCTL_H__ */
index c74d3e87531420faf4e6a65b075ae078ff6277c3..b12f93a3c345f781b3edd26716f193efb1fdf0d4 100644 (file)
@@ -93,6 +93,11 @@ enum pageflags {
        PG_mappedtodisk,        /* Has blocks allocated on-disk */
        PG_reclaim,             /* To be reclaimed asap */
        PG_buddy,               /* Page is free, on buddy lists */
+       PG_swapbacked,          /* Page is backed by RAM/swap */
+#ifdef CONFIG_UNEVICTABLE_LRU
+       PG_unevictable,         /* Page is "unevictable"  */
+       PG_mlocked,             /* Page is vma mlocked */
+#endif
 #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
        PG_uncached,            /* Page has been mapped as uncached */
 #endif
@@ -161,6 +166,18 @@ static inline int Page##uname(struct page *page)                   \
 #define TESTSCFLAG(uname, lname)                                       \
        TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname)
 
+#define SETPAGEFLAG_NOOP(uname)                                                \
+static inline void SetPage##uname(struct page *page) {  }
+
+#define CLEARPAGEFLAG_NOOP(uname)                                      \
+static inline void ClearPage##uname(struct page *page) {  }
+
+#define __CLEARPAGEFLAG_NOOP(uname)                                    \
+static inline void __ClearPage##uname(struct page *page) {  }
+
+#define TESTCLEARFLAG_FALSE(uname)                                     \
+static inline int TestClearPage##uname(struct page *page) { return 0; }
+
 struct page;   /* forward declaration */
 
 TESTPAGEFLAG(Locked, locked)
@@ -169,6 +186,7 @@ PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced)
 PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
 PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru)
 PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
+       TESTCLEARFLAG(Active, active)
 __PAGEFLAG(Slab, slab)
 PAGEFLAG(Checked, checked)             /* Used by some filesystems */
 PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned)    /* Xen */
@@ -176,6 +194,7 @@ PAGEFLAG(SavePinned, savepinned);                   /* Xen */
 PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
 PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private)
        __SETPAGEFLAG(Private, private)
+PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)
 
 __PAGEFLAG(SlobPage, slob_page)
 __PAGEFLAG(SlobFree, slob_free)
@@ -211,6 +230,25 @@ PAGEFLAG(SwapCache, swapcache)
 PAGEFLAG_FALSE(SwapCache)
 #endif
 
+#ifdef CONFIG_UNEVICTABLE_LRU
+PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable)
+       TESTCLEARFLAG(Unevictable, unevictable)
+
+#define MLOCK_PAGES 1
+PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked)
+       TESTSCFLAG(Mlocked, mlocked)
+
+#else
+
+#define MLOCK_PAGES 0
+PAGEFLAG_FALSE(Mlocked)
+       SETPAGEFLAG_NOOP(Mlocked) TESTCLEARFLAG_FALSE(Mlocked)
+
+PAGEFLAG_FALSE(Unevictable) TESTCLEARFLAG_FALSE(Unevictable)
+       SETPAGEFLAG_NOOP(Unevictable) CLEARPAGEFLAG_NOOP(Unevictable)
+       __CLEARPAGEFLAG_NOOP(Unevictable)
+#endif
+
 #ifdef CONFIG_IA64_UNCACHED_ALLOCATOR
 PAGEFLAG(Uncached, uncached)
 #else
@@ -326,15 +364,25 @@ static inline void __ClearPageTail(struct page *page)
 
 #endif /* !PAGEFLAGS_EXTENDED */
 
+#ifdef CONFIG_UNEVICTABLE_LRU
+#define __PG_UNEVICTABLE       (1 << PG_unevictable)
+#define __PG_MLOCKED           (1 << PG_mlocked)
+#else
+#define __PG_UNEVICTABLE       0
+#define __PG_MLOCKED           0
+#endif
+
 #define PAGE_FLAGS     (1 << PG_lru   | 1 << PG_private   | 1 << PG_locked | \
                         1 << PG_buddy | 1 << PG_writeback | \
-                        1 << PG_slab  | 1 << PG_swapcache | 1 << PG_active)
+                        1 << PG_slab  | 1 << PG_swapcache | 1 << PG_active | \
+                        __PG_UNEVICTABLE | __PG_MLOCKED)
 
 /*
  * Flags checked in bad_page().  Pages on the free list should not have
  * these flags set.  It they are, there is a problem.
  */
-#define PAGE_FLAGS_CLEAR_WHEN_BAD (PAGE_FLAGS | 1 << PG_reclaim | 1 << PG_dirty)
+#define PAGE_FLAGS_CLEAR_WHEN_BAD (PAGE_FLAGS | \
+               1 << PG_reclaim | 1 << PG_dirty | 1 << PG_swapbacked)
 
 /*
  * Flags checked when a page is freed.  Pages being freed should not have
@@ -347,7 +395,8 @@ static inline void __ClearPageTail(struct page *page)
  * Pages being prepped should not have these flags set.  It they are, there
  * is a problem.
  */
-#define PAGE_FLAGS_CHECK_AT_PREP (PAGE_FLAGS | 1 << PG_reserved | 1 << PG_dirty)
+#define PAGE_FLAGS_CHECK_AT_PREP (PAGE_FLAGS | \
+               1 << PG_reserved | 1 << PG_dirty | 1 << PG_swapbacked)
 
 #endif /* !__GENERATING_BOUNDS_H */
 #endif /* PAGE_FLAGS_H */
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h
new file mode 100644 (file)
index 0000000..0fd39f2
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef __LINUX_PAGE_CGROUP_H
+#define __LINUX_PAGE_CGROUP_H
+
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+#include <linux/bit_spinlock.h>
+/*
+ * Page Cgroup can be considered as an extended mem_map.
+ * A page_cgroup page is associated with every page descriptor. The
+ * page_cgroup helps us identify information about the cgroup
+ * All page cgroups are allocated at boot or memory hotplug event,
+ * then the page cgroup for pfn always exists.
+ */
+struct page_cgroup {
+       unsigned long flags;
+       struct mem_cgroup *mem_cgroup;
+       struct page *page;
+       struct list_head lru;           /* per cgroup LRU list */
+};
+
+void __init pgdat_page_cgroup_init(struct pglist_data *pgdat);
+void __init page_cgroup_init(void);
+struct page_cgroup *lookup_page_cgroup(struct page *page);
+
+enum {
+       /* flags for mem_cgroup */
+       PCG_LOCK,  /* page cgroup is locked */
+       PCG_CACHE, /* charged as cache */
+       PCG_USED, /* this object is in use. */
+       /* flags for LRU placement */
+       PCG_ACTIVE, /* page is active in this cgroup */
+       PCG_FILE, /* page is file system backed */
+       PCG_UNEVICTABLE, /* page is unevictableable */
+};
+
+#define TESTPCGFLAG(uname, lname)                      \
+static inline int PageCgroup##uname(struct page_cgroup *pc)    \
+       { return test_bit(PCG_##lname, &pc->flags); }
+
+#define SETPCGFLAG(uname, lname)                       \
+static inline void SetPageCgroup##uname(struct page_cgroup *pc)\
+       { set_bit(PCG_##lname, &pc->flags);  }
+
+#define CLEARPCGFLAG(uname, lname)                     \
+static inline void ClearPageCgroup##uname(struct page_cgroup *pc)      \
+       { clear_bit(PCG_##lname, &pc->flags);  }
+
+/* Cache flag is set only once (at allocation) */
+TESTPCGFLAG(Cache, CACHE)
+
+TESTPCGFLAG(Used, USED)
+CLEARPCGFLAG(Used, USED)
+
+/* LRU management flags (from global-lru definition) */
+TESTPCGFLAG(File, FILE)
+SETPCGFLAG(File, FILE)
+CLEARPCGFLAG(File, FILE)
+
+TESTPCGFLAG(Active, ACTIVE)
+SETPCGFLAG(Active, ACTIVE)
+CLEARPCGFLAG(Active, ACTIVE)
+
+TESTPCGFLAG(Unevictable, UNEVICTABLE)
+SETPCGFLAG(Unevictable, UNEVICTABLE)
+CLEARPCGFLAG(Unevictable, UNEVICTABLE)
+
+static inline int page_cgroup_nid(struct page_cgroup *pc)
+{
+       return page_to_nid(pc->page);
+}
+
+static inline enum zone_type page_cgroup_zid(struct page_cgroup *pc)
+{
+       return page_zonenum(pc->page);
+}
+
+static inline void lock_page_cgroup(struct page_cgroup *pc)
+{
+       bit_spin_lock(PCG_LOCK, &pc->flags);
+}
+
+static inline int trylock_page_cgroup(struct page_cgroup *pc)
+{
+       return bit_spin_trylock(PCG_LOCK, &pc->flags);
+}
+
+static inline void unlock_page_cgroup(struct page_cgroup *pc)
+{
+       bit_spin_unlock(PCG_LOCK, &pc->flags);
+}
+
+#else /* CONFIG_CGROUP_MEM_RES_CTLR */
+struct page_cgroup;
+
+static inline void pgdat_page_cgroup_init(struct pglist_data *pgdat)
+{
+}
+
+static inline struct page_cgroup *lookup_page_cgroup(struct page *page)
+{
+       return NULL;
+}
+#endif
+#endif
index 5da31c12101c2e459524f0073a0af4f2f5dd7357..709742be02f0a1bac5336d5e38b172a2b7d9f2b7 100644 (file)
@@ -32,6 +32,34 @@ static inline void mapping_set_error(struct address_space *mapping, int error)
        }
 }
 
+#ifdef CONFIG_UNEVICTABLE_LRU
+#define AS_UNEVICTABLE (__GFP_BITS_SHIFT + 2)  /* e.g., ramdisk, SHM_LOCK */
+
+static inline void mapping_set_unevictable(struct address_space *mapping)
+{
+       set_bit(AS_UNEVICTABLE, &mapping->flags);
+}
+
+static inline void mapping_clear_unevictable(struct address_space *mapping)
+{
+       clear_bit(AS_UNEVICTABLE, &mapping->flags);
+}
+
+static inline int mapping_unevictable(struct address_space *mapping)
+{
+       if (likely(mapping))
+               return test_bit(AS_UNEVICTABLE, &mapping->flags);
+       return !!mapping;
+}
+#else
+static inline void mapping_set_unevictable(struct address_space *mapping) { }
+static inline void mapping_clear_unevictable(struct address_space *mapping) { }
+static inline int mapping_unevictable(struct address_space *mapping)
+{
+       return 0;
+}
+#endif
+
 static inline gfp_t mapping_gfp_mask(struct address_space * mapping)
 {
        return (__force gfp_t)mapping->flags & __GFP_BITS_MASK;
@@ -271,19 +299,19 @@ extern int __lock_page_killable(struct page *page);
 extern void __lock_page_nosync(struct page *page);
 extern void unlock_page(struct page *page);
 
-static inline void set_page_locked(struct page *page)
+static inline void __set_page_locked(struct page *page)
 {
-       set_bit(PG_locked, &page->flags);
+       __set_bit(PG_locked, &page->flags);
 }
 
-static inline void clear_page_locked(struct page *page)
+static inline void __clear_page_locked(struct page *page)
 {
-       clear_bit(PG_locked, &page->flags);
+       __clear_bit(PG_locked, &page->flags);
 }
 
 static inline int trylock_page(struct page *page)
 {
-       return !test_and_set_bit(PG_locked, &page->flags);
+       return (likely(!test_and_set_bit_lock(PG_locked, &page->flags)));
 }
 
 /*
@@ -410,17 +438,17 @@ extern void __remove_from_page_cache(struct page *page);
 
 /*
  * Like add_to_page_cache_locked, but used to add newly allocated pages:
- * the page is new, so we can just run set_page_locked() against it.
+ * the page is new, so we can just run __set_page_locked() against it.
  */
 static inline int add_to_page_cache(struct page *page,
                struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
 {
        int error;
 
-       set_page_locked(page);
+       __set_page_locked(page);
        error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
        if (unlikely(error))
-               clear_page_locked(page);
+               __clear_page_locked(page);
        return error;
 }
 
index 8eb7fa76c1d025055683c6428388213e9ae2af2c..e90a2cb0291530db1e80ad64bc553da45855d984 100644 (file)
@@ -23,9 +23,9 @@ struct pagevec {
 void __pagevec_release(struct pagevec *pvec);
 void __pagevec_release_nonlru(struct pagevec *pvec);
 void __pagevec_free(struct pagevec *pvec);
-void __pagevec_lru_add(struct pagevec *pvec);
-void __pagevec_lru_add_active(struct pagevec *pvec);
+void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru);
 void pagevec_strip(struct pagevec *pvec);
+void pagevec_swap_free(struct pagevec *pvec);
 unsigned pagevec_lookup(struct pagevec *pvec, struct address_space *mapping,
                pgoff_t start, unsigned nr_pages);
 unsigned pagevec_lookup_tag(struct pagevec *pvec,
@@ -81,10 +81,36 @@ static inline void pagevec_free(struct pagevec *pvec)
                __pagevec_free(pvec);
 }
 
-static inline void pagevec_lru_add(struct pagevec *pvec)
+static inline void __pagevec_lru_add_anon(struct pagevec *pvec)
+{
+       ____pagevec_lru_add(pvec, LRU_INACTIVE_ANON);
+}
+
+static inline void __pagevec_lru_add_active_anon(struct pagevec *pvec)
+{
+       ____pagevec_lru_add(pvec, LRU_ACTIVE_ANON);
+}
+
+static inline void __pagevec_lru_add_file(struct pagevec *pvec)
+{
+       ____pagevec_lru_add(pvec, LRU_INACTIVE_FILE);
+}
+
+static inline void __pagevec_lru_add_active_file(struct pagevec *pvec)
+{
+       ____pagevec_lru_add(pvec, LRU_ACTIVE_FILE);
+}
+
+static inline void pagevec_lru_add_file(struct pagevec *pvec)
+{
+       if (pagevec_count(pvec))
+               __pagevec_lru_add_file(pvec);
+}
+
+static inline void pagevec_lru_add_anon(struct pagevec *pvec)
 {
        if (pagevec_count(pvec))
-               __pagevec_lru_add(pvec);
+               __pagevec_lru_add_anon(pvec);
 }
 
 #endif /* _LINUX_PAGEVEC_H */
index 98dc6243a706424ae099853320ef34edab5a8bc8..acf8f24037cd0cd261772e23cbf8d86386318f2d 100644 (file)
@@ -631,6 +631,8 @@ int __must_check pci_assign_resource(struct pci_dev *dev, int i);
 int pci_select_bars(struct pci_dev *dev, unsigned long flags);
 
 /* ROM control related routines */
+int pci_enable_rom(struct pci_dev *pdev);
+void pci_disable_rom(struct pci_dev *pdev);
 void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 size_t pci_get_rom_size(void __iomem *rom, size_t size);
index ea7416c901d1ef8923adb2417b236cf8633a09f0..22641d5d45df7d29d43bde4b60b4f19b825e30a6 100644 (file)
@@ -94,7 +94,6 @@ extern void ptrace_notify(int exit_code);
 extern void __ptrace_link(struct task_struct *child,
                          struct task_struct *new_parent);
 extern void __ptrace_unlink(struct task_struct *child);
-extern void ptrace_untrace(struct task_struct *child);
 #define PTRACE_MODE_READ   1
 #define PTRACE_MODE_ATTACH 2
 /* Returns 0 on success, -errno on denial. */
index fed6f5e0b41139070dd9c99b84ee324e7254f63f..89f0564b10c8f7c81951b571e98dbd5ef88a40a4 100644 (file)
@@ -39,18 +39,6 @@ struct anon_vma {
 
 #ifdef CONFIG_MMU
 
-extern struct kmem_cache *anon_vma_cachep;
-
-static inline struct anon_vma *anon_vma_alloc(void)
-{
-       return kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
-}
-
-static inline void anon_vma_free(struct anon_vma *anon_vma)
-{
-       kmem_cache_free(anon_vma_cachep, anon_vma);
-}
-
 static inline void anon_vma_lock(struct vm_area_struct *vma)
 {
        struct anon_vma *anon_vma = vma->anon_vma;
@@ -75,6 +63,9 @@ void anon_vma_unlink(struct vm_area_struct *);
 void anon_vma_link(struct vm_area_struct *);
 void __anon_vma_link(struct vm_area_struct *);
 
+extern struct anon_vma *page_lock_anon_vma(struct page *page);
+extern void page_unlock_anon_vma(struct anon_vma *anon_vma);
+
 /*
  * rmap interfaces called when adding or removing pte of page
  */
@@ -117,6 +108,19 @@ unsigned long page_address_in_vma(struct page *, struct vm_area_struct *);
  */
 int page_mkclean(struct page *);
 
+#ifdef CONFIG_UNEVICTABLE_LRU
+/*
+ * called in munlock()/munmap() path to check for other vmas holding
+ * the page mlocked.
+ */
+int try_to_munlock(struct page *);
+#else
+static inline int try_to_munlock(struct page *page)
+{
+       return 0;       /* a.k.a. SWAP_SUCCESS */
+}
+#endif
+
 #else  /* !CONFIG_MMU */
 
 #define anon_vma_init()                do {} while (0)
@@ -140,5 +144,6 @@ static inline int page_mkclean(struct page *page)
 #define SWAP_SUCCESS   0
 #define SWAP_AGAIN     1
 #define SWAP_FAIL      2
+#define SWAP_MLOCK     3
 
 #endif /* _LINUX_RMAP_H */
index c226c7b82946ce1d830853c4fd3b9bad3d92fa0d..f52dbd3587a78c4c031759f6934b5d03685b666a 100644 (file)
@@ -403,12 +403,21 @@ extern int get_dumpable(struct mm_struct *mm);
 #define MMF_DUMP_MAPPED_PRIVATE        4
 #define MMF_DUMP_MAPPED_SHARED 5
 #define MMF_DUMP_ELF_HEADERS   6
+#define MMF_DUMP_HUGETLB_PRIVATE 7
+#define MMF_DUMP_HUGETLB_SHARED  8
 #define MMF_DUMP_FILTER_SHIFT  MMF_DUMPABLE_BITS
-#define MMF_DUMP_FILTER_BITS   5
+#define MMF_DUMP_FILTER_BITS   7
 #define MMF_DUMP_FILTER_MASK \
        (((1 << MMF_DUMP_FILTER_BITS) - 1) << MMF_DUMP_FILTER_SHIFT)
 #define MMF_DUMP_FILTER_DEFAULT \
-       ((1 << MMF_DUMP_ANON_PRIVATE) | (1 << MMF_DUMP_ANON_SHARED))
+       ((1 << MMF_DUMP_ANON_PRIVATE) | (1 << MMF_DUMP_ANON_SHARED) |\
+        (1 << MMF_DUMP_HUGETLB_PRIVATE) | MMF_DUMP_MASK_DEFAULT_ELF)
+
+#ifdef CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS
+# define MMF_DUMP_MASK_DEFAULT_ELF     (1 << MMF_DUMP_ELF_HEADERS)
+#else
+# define MMF_DUMP_MASK_DEFAULT_ELF     0
+#endif
 
 struct sighand_struct {
        atomic_t                count;
index a1783b229ef4c219081fc7200fcdc5dd63c267e4..dc50bcc282a888ba1611a5485c53467d4a2ab953 100644 (file)
@@ -60,6 +60,19 @@ static inline int seq_nodemask(struct seq_file *m, nodemask_t *mask)
        return seq_bitmap(m, mask->bits, MAX_NUMNODES);
 }
 
+int seq_bitmap_list(struct seq_file *m, unsigned long *bits,
+               unsigned int nr_bits);
+
+static inline int seq_cpumask_list(struct seq_file *m, cpumask_t *mask)
+{
+       return seq_bitmap_list(m, mask->bits, NR_CPUS);
+}
+
+static inline int seq_nodemask_list(struct seq_file *m, nodemask_t *mask)
+{
+       return seq_bitmap_list(m, mask->bits, MAX_NUMNODES);
+}
+
 int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
 int single_release(struct inode *, struct file *);
 void *__seq_open_private(struct file *, const struct seq_operations *, int);
diff --git a/include/linux/sh_intc.h b/include/linux/sh_intc.h
new file mode 100644 (file)
index 0000000..68e212f
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __SH_INTC_H
+#define __SH_INTC_H
+
+typedef unsigned char intc_enum;
+
+struct intc_vect {
+       intc_enum enum_id;
+       unsigned short vect;
+};
+
+#define INTC_VECT(enum_id, vect) { enum_id, vect }
+#define INTC_IRQ(enum_id, irq) INTC_VECT(enum_id, irq2evt(irq))
+
+struct intc_group {
+       intc_enum enum_id;
+       intc_enum enum_ids[32];
+};
+
+#define INTC_GROUP(enum_id, ids...) { enum_id, { ids } }
+
+struct intc_mask_reg {
+       unsigned long set_reg, clr_reg, reg_width;
+       intc_enum enum_ids[32];
+#ifdef CONFIG_SMP
+       unsigned long smp;
+#endif
+};
+
+struct intc_prio_reg {
+       unsigned long set_reg, clr_reg, reg_width, field_width;
+       intc_enum enum_ids[16];
+#ifdef CONFIG_SMP
+       unsigned long smp;
+#endif
+};
+
+struct intc_sense_reg {
+       unsigned long reg, reg_width, field_width;
+       intc_enum enum_ids[16];
+};
+
+#ifdef CONFIG_SMP
+#define INTC_SMP(stride, nr) .smp = (stride) | ((nr) << 8)
+#else
+#define INTC_SMP(stride, nr)
+#endif
+
+struct intc_desc {
+       struct intc_vect *vectors;
+       unsigned int nr_vectors;
+       struct intc_group *groups;
+       unsigned int nr_groups;
+       struct intc_mask_reg *mask_regs;
+       unsigned int nr_mask_regs;
+       struct intc_prio_reg *prio_regs;
+       unsigned int nr_prio_regs;
+       struct intc_sense_reg *sense_regs;
+       unsigned int nr_sense_regs;
+       char *name;
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+       struct intc_mask_reg *ack_regs;
+       unsigned int nr_ack_regs;
+#endif
+};
+
+#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
+#define DECLARE_INTC_DESC(symbol, chipname, vectors, groups,           \
+       mask_regs, prio_regs, sense_regs)                               \
+struct intc_desc symbol __initdata = {                                 \
+       _INTC_ARRAY(vectors), _INTC_ARRAY(groups),                      \
+       _INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),                 \
+       _INTC_ARRAY(sense_regs),                                        \
+       chipname,                                                       \
+}
+
+#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
+#define DECLARE_INTC_DESC_ACK(symbol, chipname, vectors, groups,       \
+       mask_regs, prio_regs, sense_regs, ack_regs)                     \
+struct intc_desc symbol __initdata = {                                 \
+       _INTC_ARRAY(vectors), _INTC_ARRAY(groups),                      \
+       _INTC_ARRAY(mask_regs), _INTC_ARRAY(prio_regs),                 \
+       _INTC_ARRAY(sense_regs),                                        \
+       chipname,                                                       \
+       _INTC_ARRAY(ack_regs),                                          \
+}
+#endif
+
+void __init register_intc_controller(struct intc_desc *desc);
+int intc_set_priority(unsigned int irq, unsigned int prio);
+
+#endif /* __SH_INTC_H */
index 270d5c208a899aaeee19148a8a39109d59e384a8..bbed279f3b32b53ff90dde829a8380fa0f8f768f 100644 (file)
@@ -47,8 +47,6 @@ static inline __attribute_const__ __u16 ___swab16(__u16 val)
 {
 #ifdef __arch_swab16
        return __arch_swab16(val);
-#elif defined(__arch_swab16p)
-       return __arch_swab16p(&val);
 #else
        return __const_swab16(val);
 #endif
@@ -58,8 +56,6 @@ static inline __attribute_const__ __u32 ___swab32(__u32 val)
 {
 #ifdef __arch_swab32
        return __arch_swab32(val);
-#elif defined(__arch_swab32p)
-       return __arch_swab32p(&val);
 #else
        return __const_swab32(val);
 #endif
@@ -69,8 +65,6 @@ static inline __attribute_const__ __u64 ___swab64(__u64 val)
 {
 #ifdef __arch_swab64
        return __arch_swab64(val);
-#elif defined(__arch_swab64p)
-       return __arch_swab64p(&val);
 #elif defined(__SWAB_64_THRU_32__)
        __u32 h = val >> 32;
        __u32 l = val & ((1ULL << 32) - 1);
@@ -84,8 +78,6 @@ static inline __attribute_const__ __u32 ___swahw32(__u32 val)
 {
 #ifdef __arch_swahw32
        return __arch_swahw32(val);
-#elif defined(__arch_swahw32p)
-       return __arch_swahw32p(&val);
 #else
        return __const_swahw32(val);
 #endif
@@ -95,8 +87,6 @@ static inline __attribute_const__ __u32 ___swahb32(__u32 val)
 {
 #ifdef __arch_swahb32
        return __arch_swahb32(val);
-#elif defined(__arch_swahb32p)
-       return __arch_swahb32p(&val);
 #else
        return __const_swahb32(val);
 #endif
index de40f169a4e4134fa79c2ab0c360d057d2a1f62d..a3af95b2cb6dfcf24f5d278e43a29e62f23f452e 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/list.h>
 #include <linux/memcontrol.h>
 #include <linux/sched.h>
+#include <linux/node.h>
 
 #include <asm/atomic.h>
 #include <asm/page.h>
@@ -171,8 +172,10 @@ extern unsigned int nr_free_pagecache_pages(void);
 
 
 /* linux/mm/swap.c */
-extern void lru_cache_add(struct page *);
-extern void lru_cache_add_active(struct page *);
+extern void __lru_cache_add(struct page *, enum lru_list lru);
+extern void lru_cache_add_lru(struct page *, enum lru_list lru);
+extern void lru_cache_add_active_or_unevictable(struct page *,
+                                       struct vm_area_struct *);
 extern void activate_page(struct page *);
 extern void mark_page_accessed(struct page *);
 extern void lru_add_drain(void);
@@ -180,12 +183,38 @@ extern int lru_add_drain_all(void);
 extern void rotate_reclaimable_page(struct page *page);
 extern void swap_setup(void);
 
+extern void add_page_to_unevictable_list(struct page *page);
+
+/**
+ * lru_cache_add: add a page to the page lists
+ * @page: the page to add
+ */
+static inline void lru_cache_add_anon(struct page *page)
+{
+       __lru_cache_add(page, LRU_INACTIVE_ANON);
+}
+
+static inline void lru_cache_add_active_anon(struct page *page)
+{
+       __lru_cache_add(page, LRU_ACTIVE_ANON);
+}
+
+static inline void lru_cache_add_file(struct page *page)
+{
+       __lru_cache_add(page, LRU_INACTIVE_FILE);
+}
+
+static inline void lru_cache_add_active_file(struct page *page)
+{
+       __lru_cache_add(page, LRU_ACTIVE_FILE);
+}
+
 /* linux/mm/vmscan.c */
 extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
                                        gfp_t gfp_mask);
 extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem,
                                                        gfp_t gfp_mask);
-extern int __isolate_lru_page(struct page *page, int mode);
+extern int __isolate_lru_page(struct page *page, int mode, int file);
 extern unsigned long shrink_all_memory(unsigned long nr_pages);
 extern int vm_swappiness;
 extern int remove_mapping(struct address_space *mapping, struct page *page);
@@ -204,6 +233,34 @@ static inline int zone_reclaim(struct zone *z, gfp_t mask, unsigned int order)
 }
 #endif
 
+#ifdef CONFIG_UNEVICTABLE_LRU
+extern int page_evictable(struct page *page, struct vm_area_struct *vma);
+extern void scan_mapping_unevictable_pages(struct address_space *);
+
+extern unsigned long scan_unevictable_pages;
+extern int scan_unevictable_handler(struct ctl_table *, int, struct file *,
+                                       void __user *, size_t *, loff_t *);
+extern int scan_unevictable_register_node(struct node *node);
+extern void scan_unevictable_unregister_node(struct node *node);
+#else
+static inline int page_evictable(struct page *page,
+                                               struct vm_area_struct *vma)
+{
+       return 1;
+}
+
+static inline void scan_mapping_unevictable_pages(struct address_space *mapping)
+{
+}
+
+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);
 
 #ifdef CONFIG_MMU
@@ -251,6 +308,7 @@ extern sector_t swapdev_block(int, pgoff_t);
 extern struct swap_info_struct *get_swap_info_struct(unsigned);
 extern int can_share_swap_page(struct page *);
 extern int remove_exclusive_swap_page(struct page *);
+extern int remove_exclusive_swap_page_ref(struct page *);
 struct backing_dev_info;
 
 /* linux/mm/thrash.c */
@@ -339,6 +397,11 @@ static inline int remove_exclusive_swap_page(struct page *p)
        return 0;
 }
 
+static inline int remove_exclusive_swap_page_ref(struct page *page)
+{
+       return 0;
+}
+
 static inline swp_entry_t get_swap_page(void)
 {
        swp_entry_t entry;
index b330e289d71f280f7bb6ca3af431a733039ac420..9d68fed50f119423904db7d7f608fd4baede5a82 100644 (file)
@@ -21,8 +21,9 @@ struct kobject;
 struct module;
 
 /* FIXME
- * The *owner field is no longer used, but leave around
- * until the tree gets cleaned up fully.
+ * The *owner field is no longer used.
+ * x86 tree has been cleaned up. The owner
+ * attribute is still left for other arches.
  */
 struct attribute {
        const char              *name;
index 328eb40227277967c8a6179efb56ad14e03fc233..4c28c4d564e2da1e5e6112e0e5081d4f08ebd942 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_VMALLOC_H
 
 #include <linux/spinlock.h>
+#include <linux/init.h>
 #include <asm/page.h>          /* pgprot_t */
 
 struct vm_area_struct;         /* vma defining user mapping in mm_types.h */
@@ -23,7 +24,6 @@ struct vm_area_struct;                /* vma defining user mapping in mm_types.h */
 #endif
 
 struct vm_struct {
-       /* keep next,addr,size together to speedup lookups */
        struct vm_struct        *next;
        void                    *addr;
        unsigned long           size;
@@ -37,6 +37,19 @@ struct vm_struct {
 /*
  *     Highlevel APIs for driver use
  */
+extern void vm_unmap_ram(const void *mem, unsigned int count);
+extern void *vm_map_ram(struct page **pages, unsigned int count,
+                               int node, pgprot_t prot);
+extern void vm_unmap_aliases(void);
+
+#ifdef CONFIG_MMU
+extern void __init vmalloc_init(void);
+#else
+static inline void vmalloc_init(void)
+{
+}
+#endif
+
 extern void *vmalloc(unsigned long size);
 extern void *vmalloc_user(unsigned long size);
 extern void *vmalloc_node(unsigned long size, int node);
index 58334d4395167b9f3105cba86b0b68b60bca39d0..9cd3ab0f554d301224f518391b47fdd1752fc33d 100644 (file)
@@ -40,6 +40,16 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                PAGEOUTRUN, ALLOCSTALL, PGROTATED,
 #ifdef CONFIG_HUGETLB_PAGE
                HTLB_BUDDY_PGALLOC, HTLB_BUDDY_PGALLOC_FAIL,
+#endif
+#ifdef CONFIG_UNEVICTABLE_LRU
+               UNEVICTABLE_PGCULLED,   /* culled to noreclaim list */
+               UNEVICTABLE_PGSCANNED,  /* scanned for reclaimability */
+               UNEVICTABLE_PGRESCUED,  /* rescued from noreclaim list */
+               UNEVICTABLE_PGMLOCKED,
+               UNEVICTABLE_PGMUNLOCKED,
+               UNEVICTABLE_PGCLEARED,  /* on COW, page truncate */
+               UNEVICTABLE_PGSTRANDED, /* unable to isolate on unlock */
+               UNEVICTABLE_MLOCKFREED,
 #endif
                NR_VM_EVENT_ITEMS
 };
@@ -159,6 +169,16 @@ static inline unsigned long zone_page_state(struct zone *zone,
        return x;
 }
 
+extern unsigned long global_lru_pages(void);
+
+static inline unsigned long zone_lru_pages(struct zone *zone)
+{
+       return (zone_page_state(zone, NR_ACTIVE_ANON)
+               + zone_page_state(zone, NR_ACTIVE_FILE)
+               + zone_page_state(zone, NR_INACTIVE_ANON)
+               + zone_page_state(zone, NR_INACTIVE_FILE));
+}
+
 #ifdef CONFIG_NUMA
 /*
  * Determine the per node value of a stat item. This function
index 0cb63ed2c1fc268843af16f911db33e571e24b38..b8093971ccb476e5288037a8c653cb06a8addf49 100644 (file)
@@ -2,9 +2,9 @@
 #define __NETNS_X_TABLES_H
 
 #include <linux/list.h>
-#include <linux/net.h>
+#include <linux/netfilter.h>
 
 struct netns_xt {
-       struct list_head tables[NPROTO];
+       struct list_head tables[NFPROTO_NUMPROTO];
 };
 #endif
similarity index 82%
rename from arch/sh/include/asm/sh_mobile_lcdc.h
rename to include/video/sh_mobile_lcdc.h
index 130102f663f593eaceff1b884a4db798edad6731..1a4bc6ada6068300fb2cb23dd1df161ac230051e 100644 (file)
@@ -28,6 +28,12 @@ enum { LCDC_CHAN_DISABLED = 0,
 
 enum { LCDC_CLK_BUS, LCDC_CLK_PERIPHERAL, LCDC_CLK_EXTERNAL };
 
+#define LCDC_FLAGS_DWPOL (1 << 0) /* Rising edge dot clock data latch */
+#define LCDC_FLAGS_DIPOL (1 << 1) /* Active low display enable polarity */
+#define LCDC_FLAGS_DAPOL (1 << 2) /* Active low display data polarity */
+#define LCDC_FLAGS_HSCNT (1 << 3) /* Disable HSYNC during VBLANK */
+#define LCDC_FLAGS_DWCNT (1 << 4) /* Disable dotclock during blanking */
+
 struct sh_mobile_lcdc_sys_bus_cfg {
        unsigned long ldmt2r;
        unsigned long ldmt3r;
@@ -57,6 +63,7 @@ struct sh_mobile_lcdc_chan_cfg {
        int bpp;
        int interface_type; /* selects RGBn or SYSn I/F, see above */
        int clock_divider;
+       unsigned long flags; /* LCDC_FLAGS_... */
        struct fb_videomode lcd_cfg;
        struct sh_mobile_lcdc_lcd_size_cfg lcd_size_cfg;
        struct sh_mobile_lcdc_board_cfg board_cfg;
@@ -64,7 +71,6 @@ struct sh_mobile_lcdc_chan_cfg {
 };
 
 struct sh_mobile_lcdc_info {
-       unsigned long lddckr;
        int clock_source;
        struct sh_mobile_lcdc_chan_cfg ch[2];
 };
index 5ceff3249a2d84cd23110b99fb3f8a076e8cf56c..8828ed0b2051f16df1d3a491419d3e868ac8d014 100644 (file)
@@ -299,6 +299,13 @@ config CGROUP_NS
           for instance virtual servers and checkpoint/restart
           jobs.
 
+config CGROUP_FREEZER
+        bool "control group freezer subsystem"
+        depends on CGROUPS
+        help
+          Provides a way to freeze and unfreeze all tasks in a
+         cgroup.
+
 config CGROUP_DEVICE
        bool "Device controller for cgroups"
        depends on CGROUPS && EXPERIMENTAL
index 27f6bf6108e96908b10df5b20e0011aaebb3266c..4371d11721f618f45ccfc65b799fbbdfebbf8140 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/gfp.h>
 #include <linux/percpu.h>
 #include <linux/kmod.h>
+#include <linux/vmalloc.h>
 #include <linux/kernel_stat.h>
 #include <linux/start_kernel.h>
 #include <linux/security.h>
@@ -642,6 +643,7 @@ asmlinkage void __init start_kernel(void)
                initrd_start = 0;
        }
 #endif
+       vmalloc_init();
        vfs_caches_init_early();
        cpuset_init_early();
        mem_init();
index 96fb36cd9874cb26b242933178426244d1ed7e13..68eb857cfdea2a1961760320a7e956608b8b432c 100644 (file)
 #define HARD_MSGMAX    (131072/sizeof(void*))
 #define DFLT_MSGSIZEMAX 8192   /* max message size */
 
+/*
+ * Define the ranges various user-specified maximum values can
+ * be set to.
+ */
+#define MIN_MSGMAX     1               /* min value for msg_max */
+#define MAX_MSGMAX     HARD_MSGMAX     /* max value for msg_max */
+#define MIN_MSGSIZEMAX 128             /* min value for msgsize_max */
+#define MAX_MSGSIZEMAX (8192*128)      /* max value for msgsize_max */
 
 struct ext_wait_queue {                /* queue of sleeping tasks */
        struct task_struct *task;
@@ -134,8 +142,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
                        info->qsize = 0;
                        info->user = NULL;      /* set when all is ok */
                        memset(&info->attr, 0, sizeof(info->attr));
-                       info->attr.mq_maxmsg = DFLT_MSGMAX;
-                       info->attr.mq_msgsize = DFLT_MSGSIZEMAX;
+                       info->attr.mq_maxmsg = msg_max;
+                       info->attr.mq_msgsize = msgsize_max;
                        if (attr) {
                                info->attr.mq_maxmsg = attr->mq_maxmsg;
                                info->attr.mq_msgsize = attr->mq_msgsize;
@@ -1191,11 +1199,11 @@ static struct file_system_type mqueue_fs_type = {
        .kill_sb = kill_litter_super,
 };
 
-static int msg_max_limit_min = DFLT_MSGMAX;
-static int msg_max_limit_max = HARD_MSGMAX;
+static int msg_max_limit_min = MIN_MSGMAX;
+static int msg_max_limit_max = MAX_MSGMAX;
 
-static int msg_maxsize_limit_min = DFLT_MSGSIZEMAX;
-static int msg_maxsize_limit_max = INT_MAX;
+static int msg_maxsize_limit_min = MIN_MSGSIZEMAX;
+static int msg_maxsize_limit_max = MAX_MSGSIZEMAX;
 
 static ctl_table mq_sysctls[] = {
        {
index e77ec698cf408c2344d302ac693814d44d411180..0add3fa5f54774d15eb81330a3f52ea9a5ddb084 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -737,6 +737,10 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
        case SHM_LOCK:
        case SHM_UNLOCK:
        {
+               struct file *uninitialized_var(shm_file);
+
+               lru_add_drain_all();  /* drain pagevecs to lru lists */
+
                shp = shm_lock_check(ns, shmid);
                if (IS_ERR(shp)) {
                        err = PTR_ERR(shp);
diff --git a/kernel/Kconfig.freezer b/kernel/Kconfig.freezer
new file mode 100644 (file)
index 0000000..a3bb4cb
--- /dev/null
@@ -0,0 +1,2 @@
+config FREEZER
+       def_bool PM_SLEEP || CGROUP_FREEZER
index 4e1d7df7c3e279af83ae70f2f70c9196044514f2..066550aa61c5018a32dff60fcd75e6ffdebbdedd 100644 (file)
@@ -24,6 +24,7 @@ CFLAGS_REMOVE_sched_clock.o = -pg
 CFLAGS_REMOVE_sched.o = -mno-spe -pg
 endif
 
+obj-$(CONFIG_FREEZER) += freezer.o
 obj-$(CONFIG_PROFILING) += profile.o
 obj-$(CONFIG_SYSCTL_SYSCALL_CHECK) += sysctl_check.o
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
@@ -55,6 +56,7 @@ obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
 obj-$(CONFIG_COMPAT) += compat.o
 obj-$(CONFIG_CGROUPS) += cgroup.o
 obj-$(CONFIG_CGROUP_DEBUG) += cgroup_debug.o
+obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o
 obj-$(CONFIG_CPUSETS) += cpuset.o
 obj-$(CONFIG_CGROUP_NS) += ns_cgroup.o
 obj-$(CONFIG_UTS_NS) += utsname.o
index 8c6e1c17e6d37faae0870c2d9ff5635c1e192037..046c1609606bc627059aa6cd5df687fa86f15d3b 100644 (file)
@@ -241,7 +241,6 @@ static void unlink_css_set(struct css_set *cg)
        struct cg_cgroup_link *link;
        struct cg_cgroup_link *saved_link;
 
-       write_lock(&css_set_lock);
        hlist_del(&cg->hlist);
        css_set_count--;
 
@@ -251,16 +250,25 @@ static void unlink_css_set(struct css_set *cg)
                list_del(&link->cgrp_link_list);
                kfree(link);
        }
-
-       write_unlock(&css_set_lock);
 }
 
-static void __release_css_set(struct kref *k, int taskexit)
+static void __put_css_set(struct css_set *cg, int taskexit)
 {
        int i;
-       struct css_set *cg = container_of(k, struct css_set, ref);
-
+       /*
+        * Ensure that the refcount doesn't hit zero while any readers
+        * can see it. Similar to atomic_dec_and_lock(), but for an
+        * rwlock
+        */
+       if (atomic_add_unless(&cg->refcount, -1, 1))
+               return;
+       write_lock(&css_set_lock);
+       if (!atomic_dec_and_test(&cg->refcount)) {
+               write_unlock(&css_set_lock);
+               return;
+       }
        unlink_css_set(cg);
+       write_unlock(&css_set_lock);
 
        rcu_read_lock();
        for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
@@ -276,32 +284,22 @@ static void __release_css_set(struct kref *k, int taskexit)
        kfree(cg);
 }
 
-static void release_css_set(struct kref *k)
-{
-       __release_css_set(k, 0);
-}
-
-static void release_css_set_taskexit(struct kref *k)
-{
-       __release_css_set(k, 1);
-}
-
 /*
  * refcounted get/put for css_set objects
  */
 static inline void get_css_set(struct css_set *cg)
 {
-       kref_get(&cg->ref);
+       atomic_inc(&cg->refcount);
 }
 
 static inline void put_css_set(struct css_set *cg)
 {
-       kref_put(&cg->ref, release_css_set);
+       __put_css_set(cg, 0);
 }
 
 static inline void put_css_set_taskexit(struct css_set *cg)
 {
-       kref_put(&cg->ref, release_css_set_taskexit);
+       __put_css_set(cg, 1);
 }
 
 /*
@@ -427,7 +425,7 @@ static struct css_set *find_css_set(
                return NULL;
        }
 
-       kref_init(&res->ref);
+       atomic_set(&res->refcount, 1);
        INIT_LIST_HEAD(&res->cg_links);
        INIT_LIST_HEAD(&res->tasks);
        INIT_HLIST_NODE(&res->hlist);
@@ -870,6 +868,14 @@ static struct super_operations cgroup_ops = {
        .remount_fs = cgroup_remount,
 };
 
+static void init_cgroup_housekeeping(struct cgroup *cgrp)
+{
+       INIT_LIST_HEAD(&cgrp->sibling);
+       INIT_LIST_HEAD(&cgrp->children);
+       INIT_LIST_HEAD(&cgrp->css_sets);
+       INIT_LIST_HEAD(&cgrp->release_list);
+       init_rwsem(&cgrp->pids_mutex);
+}
 static void init_cgroup_root(struct cgroupfs_root *root)
 {
        struct cgroup *cgrp = &root->top_cgroup;
@@ -878,10 +884,7 @@ static void init_cgroup_root(struct cgroupfs_root *root)
        root->number_of_cgroups = 1;
        cgrp->root = root;
        cgrp->top_cgroup = cgrp;
-       INIT_LIST_HEAD(&cgrp->sibling);
-       INIT_LIST_HEAD(&cgrp->children);
-       INIT_LIST_HEAD(&cgrp->css_sets);
-       INIT_LIST_HEAD(&cgrp->release_list);
+       init_cgroup_housekeeping(cgrp);
 }
 
 static int cgroup_test_super(struct super_block *sb, void *data)
@@ -1728,7 +1731,7 @@ int cgroup_task_count(const struct cgroup *cgrp)
 
        read_lock(&css_set_lock);
        list_for_each_entry(link, &cgrp->css_sets, cgrp_link_list) {
-               count += atomic_read(&link->cg->ref.refcount);
+               count += atomic_read(&link->cg->refcount);
        }
        read_unlock(&css_set_lock);
        return count;
@@ -1997,16 +2000,7 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan)
  * but we cannot guarantee that the information we produce is correct
  * unless we produce it entirely atomically.
  *
- * Upon tasks file open(), a struct ctr_struct is allocated, that
- * will have a pointer to an array (also allocated here).  The struct
- * ctr_struct * is stored in file->private_data.  Its resources will
- * be freed by release() when the file is closed.  The array is used
- * to sprintf the PIDs and then used by read().
  */
-struct ctr_struct {
-       char *buf;
-       int bufsz;
-};
 
 /*
  * Load into 'pidarray' up to 'npids' of the tasks using cgroup
@@ -2088,42 +2082,132 @@ static int cmppid(const void *a, const void *b)
        return *(pid_t *)a - *(pid_t *)b;
 }
 
+
 /*
- * Convert array 'a' of 'npids' pid_t's to a string of newline separated
- * decimal pids in 'buf'.  Don't write more than 'sz' chars, but return
- * count 'cnt' of how many chars would be written if buf were large enough.
+ * seq_file methods for the "tasks" file. The seq_file position is the
+ * next pid to display; the seq_file iterator is a pointer to the pid
+ * in the cgroup->tasks_pids array.
  */
-static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
+
+static void *cgroup_tasks_start(struct seq_file *s, loff_t *pos)
 {
-       int cnt = 0;
-       int i;
+       /*
+        * Initially we receive a position value that corresponds to
+        * one more than the last pid shown (or 0 on the first call or
+        * after a seek to the start). Use a binary-search to find the
+        * next pid to display, if any
+        */
+       struct cgroup *cgrp = s->private;
+       int index = 0, pid = *pos;
+       int *iter;
 
-       for (i = 0; i < npids; i++)
-               cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
-       return cnt;
+       down_read(&cgrp->pids_mutex);
+       if (pid) {
+               int end = cgrp->pids_length;
+               int i;
+               while (index < end) {
+                       int mid = (index + end) / 2;
+                       if (cgrp->tasks_pids[mid] == pid) {
+                               index = mid;
+                               break;
+                       } else if (cgrp->tasks_pids[mid] <= pid)
+                               index = mid + 1;
+                       else
+                               end = mid;
+               }
+       }
+       /* If we're off the end of the array, we're done */
+       if (index >= cgrp->pids_length)
+               return NULL;
+       /* Update the abstract position to be the actual pid that we found */
+       iter = cgrp->tasks_pids + index;
+       *pos = *iter;
+       return iter;
+}
+
+static void cgroup_tasks_stop(struct seq_file *s, void *v)
+{
+       struct cgroup *cgrp = s->private;
+       up_read(&cgrp->pids_mutex);
 }
 
+static void *cgroup_tasks_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       struct cgroup *cgrp = s->private;
+       int *p = v;
+       int *end = cgrp->tasks_pids + cgrp->pids_length;
+
+       /*
+        * Advance to the next pid in the array. If this goes off the
+        * end, we're done
+        */
+       p++;
+       if (p >= end) {
+               return NULL;
+       } else {
+               *pos = *p;
+               return p;
+       }
+}
+
+static int cgroup_tasks_show(struct seq_file *s, void *v)
+{
+       return seq_printf(s, "%d\n", *(int *)v);
+}
+
+static struct seq_operations cgroup_tasks_seq_operations = {
+       .start = cgroup_tasks_start,
+       .stop = cgroup_tasks_stop,
+       .next = cgroup_tasks_next,
+       .show = cgroup_tasks_show,
+};
+
+static void release_cgroup_pid_array(struct cgroup *cgrp)
+{
+       down_write(&cgrp->pids_mutex);
+       BUG_ON(!cgrp->pids_use_count);
+       if (!--cgrp->pids_use_count) {
+               kfree(cgrp->tasks_pids);
+               cgrp->tasks_pids = NULL;
+               cgrp->pids_length = 0;
+       }
+       up_write(&cgrp->pids_mutex);
+}
+
+static int cgroup_tasks_release(struct inode *inode, struct file *file)
+{
+       struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
+
+       if (!(file->f_mode & FMODE_READ))
+               return 0;
+
+       release_cgroup_pid_array(cgrp);
+       return seq_release(inode, file);
+}
+
+static struct file_operations cgroup_tasks_operations = {
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .write = cgroup_file_write,
+       .release = cgroup_tasks_release,
+};
+
 /*
- * Handle an open on 'tasks' file.  Prepare a buffer listing the
+ * Handle an open on 'tasks' file.  Prepare an array containing the
  * process id's of tasks currently attached to the cgroup being opened.
- *
- * Does not require any specific cgroup mutexes, and does not take any.
  */
+
 static int cgroup_tasks_open(struct inode *unused, struct file *file)
 {
        struct cgroup *cgrp = __d_cgrp(file->f_dentry->d_parent);
-       struct ctr_struct *ctr;
        pid_t *pidarray;
        int npids;
-       char c;
+       int retval;
 
+       /* Nothing to do for write-only files */
        if (!(file->f_mode & FMODE_READ))
                return 0;
 
-       ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
-       if (!ctr)
-               goto err0;
-
        /*
         * If cgroup gets more users after we read count, we won't have
         * enough space - tough.  This race is indistinguishable to the
@@ -2131,57 +2215,31 @@ static int cgroup_tasks_open(struct inode *unused, struct file *file)
         * show up until sometime later on.
         */
        npids = cgroup_task_count(cgrp);
-       if (npids) {
-               pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
-               if (!pidarray)
-                       goto err1;
-
-               npids = pid_array_load(pidarray, npids, cgrp);
-               sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
-
-               /* Call pid_array_to_buf() twice, first just to get bufsz */
-               ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
-               ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
-               if (!ctr->buf)
-                       goto err2;
-               ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
-
-               kfree(pidarray);
-       } else {
-               ctr->buf = NULL;
-               ctr->bufsz = 0;
-       }
-       file->private_data = ctr;
-       return 0;
-
-err2:
-       kfree(pidarray);
-err1:
-       kfree(ctr);
-err0:
-       return -ENOMEM;
-}
+       pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
+       if (!pidarray)
+               return -ENOMEM;
+       npids = pid_array_load(pidarray, npids, cgrp);
+       sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
 
-static ssize_t cgroup_tasks_read(struct cgroup *cgrp,
-                                   struct cftype *cft,
-                                   struct file *file, char __user *buf,
-                                   size_t nbytes, loff_t *ppos)
-{
-       struct ctr_struct *ctr = file->private_data;
+       /*
+        * Store the array in the cgroup, freeing the old
+        * array if necessary
+        */
+       down_write(&cgrp->pids_mutex);
+       kfree(cgrp->tasks_pids);
+       cgrp->tasks_pids = pidarray;
+       cgrp->pids_length = npids;
+       cgrp->pids_use_count++;
+       up_write(&cgrp->pids_mutex);
 
-       return simple_read_from_buffer(buf, nbytes, ppos, ctr->buf, ctr->bufsz);
-}
+       file->f_op = &cgroup_tasks_operations;
 
-static int cgroup_tasks_release(struct inode *unused_inode,
-                                       struct file *file)
-{
-       struct ctr_struct *ctr;
-
-       if (file->f_mode & FMODE_READ) {
-               ctr = file->private_data;
-               kfree(ctr->buf);
-               kfree(ctr);
+       retval = seq_open(file, &cgroup_tasks_seq_operations);
+       if (retval) {
+               release_cgroup_pid_array(cgrp);
+               return retval;
        }
+       ((struct seq_file *)file->private_data)->private = cgrp;
        return 0;
 }
 
@@ -2210,7 +2268,6 @@ static struct cftype files[] = {
        {
                .name = "tasks",
                .open = cgroup_tasks_open,
-               .read = cgroup_tasks_read,
                .write_u64 = cgroup_tasks_write,
                .release = cgroup_tasks_release,
                .private = FILE_TASKLIST,
@@ -2300,10 +2357,7 @@ static long cgroup_create(struct cgroup *parent, struct dentry *dentry,
 
        mutex_lock(&cgroup_mutex);
 
-       INIT_LIST_HEAD(&cgrp->sibling);
-       INIT_LIST_HEAD(&cgrp->children);
-       INIT_LIST_HEAD(&cgrp->css_sets);
-       INIT_LIST_HEAD(&cgrp->release_list);
+       init_cgroup_housekeeping(cgrp);
 
        cgrp->parent = parent;
        cgrp->root = parent->root;
@@ -2495,8 +2549,7 @@ static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
 int __init cgroup_init_early(void)
 {
        int i;
-       kref_init(&init_css_set.ref);
-       kref_get(&init_css_set.ref);
+       atomic_set(&init_css_set.refcount, 1);
        INIT_LIST_HEAD(&init_css_set.cg_links);
        INIT_LIST_HEAD(&init_css_set.tasks);
        INIT_HLIST_NODE(&init_css_set.hlist);
index c3dc3aba4c02a5b243b25b1ed7be971c5ec1ef17..daca6209202df4a84df7e0fc41025e33c7642131 100644 (file)
@@ -57,7 +57,7 @@ static u64 current_css_set_refcount_read(struct cgroup *cont,
        u64 count;
 
        rcu_read_lock();
-       count = atomic_read(&current->cgroups->ref.refcount);
+       count = atomic_read(&current->cgroups->refcount);
        rcu_read_unlock();
        return count;
 }
@@ -90,7 +90,7 @@ static struct cftype files[] =  {
        {
                .name = "releasable",
                .read_u64 = releasable_read,
-       }
+       },
 };
 
 static int debug_populate(struct cgroup_subsys *ss, struct cgroup *cont)
diff --git a/kernel/cgroup_freezer.c b/kernel/cgroup_freezer.c
new file mode 100644 (file)
index 0000000..e950569
--- /dev/null
@@ -0,0 +1,379 @@
+/*
+ * cgroup_freezer.c -  control group freezer subsystem
+ *
+ * Copyright IBM Corporation, 2007
+ *
+ * Author : Cedric Le Goater <clg@fr.ibm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2.1 of the GNU Lesser General Public License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <linux/module.h>
+#include <linux/cgroup.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/freezer.h>
+#include <linux/seq_file.h>
+
+enum freezer_state {
+       CGROUP_THAWED = 0,
+       CGROUP_FREEZING,
+       CGROUP_FROZEN,
+};
+
+struct freezer {
+       struct cgroup_subsys_state css;
+       enum freezer_state state;
+       spinlock_t lock; /* protects _writes_ to state */
+};
+
+static inline struct freezer *cgroup_freezer(
+               struct cgroup *cgroup)
+{
+       return container_of(
+               cgroup_subsys_state(cgroup, freezer_subsys_id),
+               struct freezer, css);
+}
+
+static inline struct freezer *task_freezer(struct task_struct *task)
+{
+       return container_of(task_subsys_state(task, freezer_subsys_id),
+                           struct freezer, css);
+}
+
+int cgroup_frozen(struct task_struct *task)
+{
+       struct freezer *freezer;
+       enum freezer_state state;
+
+       task_lock(task);
+       freezer = task_freezer(task);
+       state = freezer->state;
+       task_unlock(task);
+
+       return state == CGROUP_FROZEN;
+}
+
+/*
+ * cgroups_write_string() limits the size of freezer state strings to
+ * CGROUP_LOCAL_BUFFER_SIZE
+ */
+static const char *freezer_state_strs[] = {
+       "THAWED",
+       "FREEZING",
+       "FROZEN",
+};
+
+/*
+ * State diagram
+ * Transitions are caused by userspace writes to the freezer.state file.
+ * The values in parenthesis are state labels. The rest are edge labels.
+ *
+ * (THAWED) --FROZEN--> (FREEZING) --FROZEN--> (FROZEN)
+ *    ^ ^                    |                     |
+ *    | \_______THAWED_______/                     |
+ *    \__________________________THAWED____________/
+ */
+
+struct cgroup_subsys freezer_subsys;
+
+/* Locks taken and their ordering
+ * ------------------------------
+ * css_set_lock
+ * cgroup_mutex (AKA cgroup_lock)
+ * task->alloc_lock (AKA task_lock)
+ * freezer->lock
+ * task->sighand->siglock
+ *
+ * cgroup code forces css_set_lock to be taken before task->alloc_lock
+ *
+ * freezer_create(), freezer_destroy():
+ * cgroup_mutex [ by cgroup core ]
+ *
+ * can_attach():
+ * cgroup_mutex
+ *
+ * cgroup_frozen():
+ * task->alloc_lock (to get task's cgroup)
+ *
+ * freezer_fork() (preserving fork() performance means can't take cgroup_mutex):
+ * task->alloc_lock (to get task's cgroup)
+ * freezer->lock
+ *  sighand->siglock (if the cgroup is freezing)
+ *
+ * freezer_read():
+ * cgroup_mutex
+ *  freezer->lock
+ *   read_lock css_set_lock (cgroup iterator start)
+ *
+ * freezer_write() (freeze):
+ * cgroup_mutex
+ *  freezer->lock
+ *   read_lock css_set_lock (cgroup iterator start)
+ *    sighand->siglock
+ *
+ * freezer_write() (unfreeze):
+ * cgroup_mutex
+ *  freezer->lock
+ *   read_lock css_set_lock (cgroup iterator start)
+ *    task->alloc_lock (to prevent races with freeze_task())
+ *     sighand->siglock
+ */
+static struct cgroup_subsys_state *freezer_create(struct cgroup_subsys *ss,
+                                                 struct cgroup *cgroup)
+{
+       struct freezer *freezer;
+
+       freezer = kzalloc(sizeof(struct freezer), GFP_KERNEL);
+       if (!freezer)
+               return ERR_PTR(-ENOMEM);
+
+       spin_lock_init(&freezer->lock);
+       freezer->state = CGROUP_THAWED;
+       return &freezer->css;
+}
+
+static void freezer_destroy(struct cgroup_subsys *ss,
+                           struct cgroup *cgroup)
+{
+       kfree(cgroup_freezer(cgroup));
+}
+
+/* Task is frozen or will freeze immediately when next it gets woken */
+static bool is_task_frozen_enough(struct task_struct *task)
+{
+       return frozen(task) ||
+               (task_is_stopped_or_traced(task) && freezing(task));
+}
+
+/*
+ * The call to cgroup_lock() in the freezer.state write method prevents
+ * a write to that file racing against an attach, and hence the
+ * can_attach() result will remain valid until the attach completes.
+ */
+static int freezer_can_attach(struct cgroup_subsys *ss,
+                             struct cgroup *new_cgroup,
+                             struct task_struct *task)
+{
+       struct freezer *freezer;
+       int retval;
+
+       /* Anything frozen can't move or be moved to/from */
+
+       if (is_task_frozen_enough(task))
+               return -EBUSY;
+
+       freezer = cgroup_freezer(new_cgroup);
+       if (freezer->state == CGROUP_FROZEN)
+               return -EBUSY;
+
+       retval = 0;
+       task_lock(task);
+       freezer = task_freezer(task);
+       if (freezer->state == CGROUP_FROZEN)
+               retval = -EBUSY;
+       task_unlock(task);
+       return retval;
+}
+
+static void freezer_fork(struct cgroup_subsys *ss, struct task_struct *task)
+{
+       struct freezer *freezer;
+
+       task_lock(task);
+       freezer = task_freezer(task);
+       task_unlock(task);
+
+       BUG_ON(freezer->state == CGROUP_FROZEN);
+       spin_lock_irq(&freezer->lock);
+       /* Locking avoids race with FREEZING -> THAWED transitions. */
+       if (freezer->state == CGROUP_FREEZING)
+               freeze_task(task, true);
+       spin_unlock_irq(&freezer->lock);
+}
+
+/*
+ * caller must hold freezer->lock
+ */
+static void update_freezer_state(struct cgroup *cgroup,
+                                struct freezer *freezer)
+{
+       struct cgroup_iter it;
+       struct task_struct *task;
+       unsigned int nfrozen = 0, ntotal = 0;
+
+       cgroup_iter_start(cgroup, &it);
+       while ((task = cgroup_iter_next(cgroup, &it))) {
+               ntotal++;
+               if (is_task_frozen_enough(task))
+                       nfrozen++;
+       }
+
+       /*
+        * Transition to FROZEN when no new tasks can be added ensures
+        * that we never exist in the FROZEN state while there are unfrozen
+        * tasks.
+        */
+       if (nfrozen == ntotal)
+               freezer->state = CGROUP_FROZEN;
+       else if (nfrozen > 0)
+               freezer->state = CGROUP_FREEZING;
+       else
+               freezer->state = CGROUP_THAWED;
+       cgroup_iter_end(cgroup, &it);
+}
+
+static int freezer_read(struct cgroup *cgroup, struct cftype *cft,
+                       struct seq_file *m)
+{
+       struct freezer *freezer;
+       enum freezer_state state;
+
+       if (!cgroup_lock_live_group(cgroup))
+               return -ENODEV;
+
+       freezer = cgroup_freezer(cgroup);
+       spin_lock_irq(&freezer->lock);
+       state = freezer->state;
+       if (state == CGROUP_FREEZING) {
+               /* We change from FREEZING to FROZEN lazily if the cgroup was
+                * only partially frozen when we exitted write. */
+               update_freezer_state(cgroup, freezer);
+               state = freezer->state;
+       }
+       spin_unlock_irq(&freezer->lock);
+       cgroup_unlock();
+
+       seq_puts(m, freezer_state_strs[state]);
+       seq_putc(m, '\n');
+       return 0;
+}
+
+static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
+{
+       struct cgroup_iter it;
+       struct task_struct *task;
+       unsigned int num_cant_freeze_now = 0;
+
+       freezer->state = CGROUP_FREEZING;
+       cgroup_iter_start(cgroup, &it);
+       while ((task = cgroup_iter_next(cgroup, &it))) {
+               if (!freeze_task(task, true))
+                       continue;
+               if (is_task_frozen_enough(task))
+                       continue;
+               if (!freezing(task) && !freezer_should_skip(task))
+                       num_cant_freeze_now++;
+       }
+       cgroup_iter_end(cgroup, &it);
+
+       return num_cant_freeze_now ? -EBUSY : 0;
+}
+
+static int unfreeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
+{
+       struct cgroup_iter it;
+       struct task_struct *task;
+
+       cgroup_iter_start(cgroup, &it);
+       while ((task = cgroup_iter_next(cgroup, &it))) {
+               int do_wake;
+
+               task_lock(task);
+               do_wake = __thaw_process(task);
+               task_unlock(task);
+               if (do_wake)
+                       wake_up_process(task);
+       }
+       cgroup_iter_end(cgroup, &it);
+       freezer->state = CGROUP_THAWED;
+
+       return 0;
+}
+
+static int freezer_change_state(struct cgroup *cgroup,
+                               enum freezer_state goal_state)
+{
+       struct freezer *freezer;
+       int retval = 0;
+
+       freezer = cgroup_freezer(cgroup);
+       spin_lock_irq(&freezer->lock);
+       update_freezer_state(cgroup, freezer);
+       if (goal_state == freezer->state)
+               goto out;
+       switch (freezer->state) {
+       case CGROUP_THAWED:
+               retval = try_to_freeze_cgroup(cgroup, freezer);
+               break;
+       case CGROUP_FREEZING:
+               if (goal_state == CGROUP_FROZEN) {
+                       /* Userspace is retrying after
+                        * "/bin/echo FROZEN > freezer.state" returned -EBUSY */
+                       retval = try_to_freeze_cgroup(cgroup, freezer);
+                       break;
+               }
+               /* state == FREEZING and goal_state == THAWED, so unfreeze */
+       case CGROUP_FROZEN:
+               retval = unfreeze_cgroup(cgroup, freezer);
+               break;
+       default:
+               break;
+       }
+out:
+       spin_unlock_irq(&freezer->lock);
+
+       return retval;
+}
+
+static int freezer_write(struct cgroup *cgroup,
+                        struct cftype *cft,
+                        const char *buffer)
+{
+       int retval;
+       enum freezer_state goal_state;
+
+       if (strcmp(buffer, freezer_state_strs[CGROUP_THAWED]) == 0)
+               goal_state = CGROUP_THAWED;
+       else if (strcmp(buffer, freezer_state_strs[CGROUP_FROZEN]) == 0)
+               goal_state = CGROUP_FROZEN;
+       else
+               return -EIO;
+
+       if (!cgroup_lock_live_group(cgroup))
+               return -ENODEV;
+       retval = freezer_change_state(cgroup, goal_state);
+       cgroup_unlock();
+       return retval;
+}
+
+static struct cftype files[] = {
+       {
+               .name = "state",
+               .read_seq_string = freezer_read,
+               .write_string = freezer_write,
+       },
+};
+
+static int freezer_populate(struct cgroup_subsys *ss, struct cgroup *cgroup)
+{
+       return cgroup_add_files(cgroup, ss, files, ARRAY_SIZE(files));
+}
+
+struct cgroup_subsys freezer_subsys = {
+       .name           = "freezer",
+       .create         = freezer_create,
+       .destroy        = freezer_destroy,
+       .populate       = freezer_populate,
+       .subsys_id      = freezer_subsys_id,
+       .can_attach     = freezer_can_attach,
+       .attach         = NULL,
+       .fork           = freezer_fork,
+       .exit           = NULL,
+};
index 4c345210ed8cca3ffb1c64a9e4aef92cf97eedf8..abaee684ecbf95fe1d47426d7b47b77e6ed91fab 100644 (file)
@@ -54,9 +54,6 @@
 
 #ifdef CONFIG_IKCONFIG_PROC
 
-/**************************************************/
-/* globals and useful constants                   */
-
 static ssize_t
 ikconfig_read_current(struct file *file, char __user *buf,
                      size_t len, loff_t * offset)
@@ -71,9 +68,6 @@ static const struct file_operations ikconfig_file_ops = {
        .read = ikconfig_read_current,
 };
 
-/***************************************************/
-/* ikconfig_init: start up everything we need to */
-
 static int __init ikconfig_init(void)
 {
        struct proc_dir_entry *entry;
@@ -89,9 +83,6 @@ static int __init ikconfig_init(void)
        return 0;
 }
 
-/***************************************************/
-/* ikconfig_cleanup: clean up our mess           */
-
 static void __exit ikconfig_cleanup(void)
 {
        remove_proc_entry("config.gz", NULL);
index eab7bd6628e0ad48ef5f1d4fcea2af05f173bae5..3e00526f52ec14d56eb89ee1ab5c1a40fbed1331 100644 (file)
@@ -1172,7 +1172,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
 {
        struct cpuset trialcs;
        int err;
-       int cpus_nonempty, balance_flag_changed;
+       int balance_flag_changed;
 
        trialcs = *cs;
        if (turning_on)
@@ -1184,7 +1184,6 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
        if (err < 0)
                return err;
 
-       cpus_nonempty = !cpus_empty(trialcs.cpus_allowed);
        balance_flag_changed = (is_sched_load_balance(cs) !=
                                        is_sched_load_balance(&trialcs));
 
@@ -1192,7 +1191,7 @@ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
        cs->flags = trialcs.flags;
        mutex_unlock(&callback_mutex);
 
-       if (cpus_nonempty && balance_flag_changed)
+       if (!cpus_empty(trialcs.cpus_allowed) && balance_flag_changed)
                async_rebuild_sched_domains();
 
        return 0;
@@ -2437,19 +2436,15 @@ const struct file_operations proc_cpuset_operations = {
 void cpuset_task_status_allowed(struct seq_file *m, struct task_struct *task)
 {
        seq_printf(m, "Cpus_allowed:\t");
-       m->count += cpumask_scnprintf(m->buf + m->count, m->size - m->count,
-                                       task->cpus_allowed);
+       seq_cpumask(m, &task->cpus_allowed);
        seq_printf(m, "\n");
        seq_printf(m, "Cpus_allowed_list:\t");
-       m->count += cpulist_scnprintf(m->buf + m->count, m->size - m->count,
-                                       task->cpus_allowed);
+       seq_cpumask_list(m, &task->cpus_allowed);
        seq_printf(m, "\n");
        seq_printf(m, "Mems_allowed:\t");
-       m->count += nodemask_scnprintf(m->buf + m->count, m->size - m->count,
-                                       task->mems_allowed);
+       seq_nodemask(m, &task->mems_allowed);
        seq_printf(m, "\n");
        seq_printf(m, "Mems_allowed_list:\t");
-       m->count += nodelist_scnprintf(m->buf + m->count, m->size - m->count,
-                                       task->mems_allowed);
+       seq_nodemask_list(m, &task->mems_allowed);
        seq_printf(m, "\n");
 }
diff --git a/kernel/freezer.c b/kernel/freezer.c
new file mode 100644 (file)
index 0000000..ba6248b
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * kernel/freezer.c - Function to freeze a process
+ *
+ * Originally from kernel/power/process.c
+ */
+
+#include <linux/interrupt.h>
+#include <linux/suspend.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/freezer.h>
+
+/*
+ * freezing is complete, mark current process as frozen
+ */
+static inline void frozen_process(void)
+{
+       if (!unlikely(current->flags & PF_NOFREEZE)) {
+               current->flags |= PF_FROZEN;
+               wmb();
+       }
+       clear_freeze_flag(current);
+}
+
+/* Refrigerator is place where frozen processes are stored :-). */
+void refrigerator(void)
+{
+       /* Hmm, should we be allowed to suspend when there are realtime
+          processes around? */
+       long save;
+
+       task_lock(current);
+       if (freezing(current)) {
+               frozen_process();
+               task_unlock(current);
+       } else {
+               task_unlock(current);
+               return;
+       }
+       save = current->state;
+       pr_debug("%s entered refrigerator\n", current->comm);
+
+       spin_lock_irq(&current->sighand->siglock);
+       recalc_sigpending(); /* We sent fake signal, clean it up */
+       spin_unlock_irq(&current->sighand->siglock);
+
+       for (;;) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               if (!frozen(current))
+                       break;
+               schedule();
+       }
+       pr_debug("%s left refrigerator\n", current->comm);
+       __set_current_state(save);
+}
+EXPORT_SYMBOL(refrigerator);
+
+static void fake_signal_wake_up(struct task_struct *p)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&p->sighand->siglock, flags);
+       signal_wake_up(p, 0);
+       spin_unlock_irqrestore(&p->sighand->siglock, flags);
+}
+
+/**
+ *     freeze_task - send a freeze request to given task
+ *     @p: task to send the request to
+ *     @sig_only: if set, the request will only be sent if the task has the
+ *             PF_FREEZER_NOSIG flag unset
+ *     Return value: 'false', if @sig_only is set and the task has
+ *             PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise
+ *
+ *     The freeze request is sent by setting the tasks's TIF_FREEZE flag and
+ *     either sending a fake signal to it or waking it up, depending on whether
+ *     or not it has PF_FREEZER_NOSIG set.  If @sig_only is set and the task
+ *     has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its
+ *     TIF_FREEZE flag will not be set.
+ */
+bool freeze_task(struct task_struct *p, bool sig_only)
+{
+       /*
+        * We first check if the task is freezing and next if it has already
+        * been frozen to avoid the race with frozen_process() which first marks
+        * the task as frozen and next clears its TIF_FREEZE.
+        */
+       if (!freezing(p)) {
+               rmb();
+               if (frozen(p))
+                       return false;
+
+               if (!sig_only || should_send_signal(p))
+                       set_freeze_flag(p);
+               else
+                       return false;
+       }
+
+       if (should_send_signal(p)) {
+               if (!signal_pending(p))
+                       fake_signal_wake_up(p);
+       } else if (sig_only) {
+               return false;
+       } else {
+               wake_up_state(p, TASK_INTERRUPTIBLE);
+       }
+
+       return true;
+}
+
+void cancel_freezing(struct task_struct *p)
+{
+       unsigned long flags;
+
+       if (freezing(p)) {
+               pr_debug("  clean up: %s\n", p->comm);
+               clear_freeze_flag(p);
+               spin_lock_irqsave(&p->sighand->siglock, flags);
+               recalc_sigpending_and_wake(p);
+               spin_unlock_irqrestore(&p->sighand->siglock, flags);
+       }
+}
+
+/*
+ * Wake up a frozen process
+ *
+ * task_lock() is needed to prevent the race with refrigerator() which may
+ * occur if the freezing of tasks fails.  Namely, without the lock, if the
+ * freezing of tasks failed, thaw_tasks() might have run before a task in
+ * refrigerator() could call frozen_process(), in which case the task would be
+ * frozen and no one would thaw it.
+ */
+int __thaw_process(struct task_struct *p)
+{
+       if (frozen(p)) {
+               p->flags &= ~PF_FROZEN;
+               return 1;
+       }
+       clear_freeze_flag(p);
+       return 0;
+}
+
+int thaw_process(struct task_struct *p)
+{
+       task_lock(p);
+       if (__thaw_process(p) == 1) {
+               task_unlock(p);
+               wake_up_process(p);
+               return 1;
+       }
+       task_unlock(p);
+       return 0;
+}
+EXPORT_SYMBOL(thaw_process);
index aef265325cd3596db981ed2515efec42f255804e..777ac458ac993b8195a3c3cb7042a941ba611339 100644 (file)
@@ -1371,6 +1371,7 @@ static int __init crash_save_vmcoreinfo_init(void)
        VMCOREINFO_SYMBOL(node_online_map);
        VMCOREINFO_SYMBOL(swapper_pg_dir);
        VMCOREINFO_SYMBOL(_stext);
+       VMCOREINFO_SYMBOL(vmlist);
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
        VMCOREINFO_SYMBOL(mem_map);
@@ -1406,6 +1407,7 @@ static int __init crash_save_vmcoreinfo_init(void)
        VMCOREINFO_OFFSET(free_area, free_list);
        VMCOREINFO_OFFSET(list_head, next);
        VMCOREINFO_OFFSET(list_head, prev);
+       VMCOREINFO_OFFSET(vm_struct, addr);
        VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
        VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
        VMCOREINFO_NUMBER(NR_FREE_PAGES);
index 96cff2f8710baac71e7ce91ec96202665142b5e8..14ec64fe175ad5a742aac30718362a1f6875e9af 100644 (file)
@@ -171,12 +171,11 @@ EXPORT_SYMBOL(kthread_create);
  */
 void kthread_bind(struct task_struct *k, unsigned int cpu)
 {
-       if (k->state != TASK_UNINTERRUPTIBLE) {
+       /* Must have done schedule() in kthread() before we set_task_cpu */
+       if (!wait_task_inactive(k, TASK_UNINTERRUPTIBLE)) {
                WARN_ON(1);
                return;
        }
-       /* Must have done schedule() in kthread() before we set_task_cpu */
-       wait_task_inactive(k, 0);
        set_task_cpu(k, cpu);
        k->cpus_allowed = cpumask_of_cpu(cpu);
        k->rt.nr_cpus_allowed = 1;
index 278946aecaf0d24b46b0736506de8ca3aafdc873..ca634019497a5cf8b035872bdaf8edcfaefd8b88 100644 (file)
@@ -28,121 +28,6 @@ static inline int freezeable(struct task_struct * p)
        return 1;
 }
 
-/*
- * freezing is complete, mark current process as frozen
- */
-static inline void frozen_process(void)
-{
-       if (!unlikely(current->flags & PF_NOFREEZE)) {
-               current->flags |= PF_FROZEN;
-               wmb();
-       }
-       clear_freeze_flag(current);
-}
-
-/* Refrigerator is place where frozen processes are stored :-). */
-void refrigerator(void)
-{
-       /* Hmm, should we be allowed to suspend when there are realtime
-          processes around? */
-       long save;
-
-       task_lock(current);
-       if (freezing(current)) {
-               frozen_process();
-               task_unlock(current);
-       } else {
-               task_unlock(current);
-               return;
-       }
-       save = current->state;
-       pr_debug("%s entered refrigerator\n", current->comm);
-
-       spin_lock_irq(&current->sighand->siglock);
-       recalc_sigpending(); /* We sent fake signal, clean it up */
-       spin_unlock_irq(&current->sighand->siglock);
-
-       for (;;) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
-               if (!frozen(current))
-                       break;
-               schedule();
-       }
-       pr_debug("%s left refrigerator\n", current->comm);
-       __set_current_state(save);
-}
-
-static void fake_signal_wake_up(struct task_struct *p)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&p->sighand->siglock, flags);
-       signal_wake_up(p, 0);
-       spin_unlock_irqrestore(&p->sighand->siglock, flags);
-}
-
-static inline bool should_send_signal(struct task_struct *p)
-{
-       return !(p->flags & PF_FREEZER_NOSIG);
-}
-
-/**
- *     freeze_task - send a freeze request to given task
- *     @p: task to send the request to
- *     @sig_only: if set, the request will only be sent if the task has the
- *             PF_FREEZER_NOSIG flag unset
- *     Return value: 'false', if @sig_only is set and the task has
- *             PF_FREEZER_NOSIG set or the task is frozen, 'true', otherwise
- *
- *     The freeze request is sent by setting the tasks's TIF_FREEZE flag and
- *     either sending a fake signal to it or waking it up, depending on whether
- *     or not it has PF_FREEZER_NOSIG set.  If @sig_only is set and the task
- *     has PF_FREEZER_NOSIG set (ie. it is a typical kernel thread), its
- *     TIF_FREEZE flag will not be set.
- */
-static bool freeze_task(struct task_struct *p, bool sig_only)
-{
-       /*
-        * We first check if the task is freezing and next if it has already
-        * been frozen to avoid the race with frozen_process() which first marks
-        * the task as frozen and next clears its TIF_FREEZE.
-        */
-       if (!freezing(p)) {
-               rmb();
-               if (frozen(p))
-                       return false;
-
-               if (!sig_only || should_send_signal(p))
-                       set_freeze_flag(p);
-               else
-                       return false;
-       }
-
-       if (should_send_signal(p)) {
-               if (!signal_pending(p))
-                       fake_signal_wake_up(p);
-       } else if (sig_only) {
-               return false;
-       } else {
-               wake_up_state(p, TASK_INTERRUPTIBLE);
-       }
-
-       return true;
-}
-
-static void cancel_freezing(struct task_struct *p)
-{
-       unsigned long flags;
-
-       if (freezing(p)) {
-               pr_debug("  clean up: %s\n", p->comm);
-               clear_freeze_flag(p);
-               spin_lock_irqsave(&p->sighand->siglock, flags);
-               recalc_sigpending_and_wake(p);
-               spin_unlock_irqrestore(&p->sighand->siglock, flags);
-       }
-}
-
 static int try_to_freeze_tasks(bool sig_only)
 {
        struct task_struct *g, *p;
@@ -250,6 +135,9 @@ static void thaw_tasks(bool nosig_only)
                if (nosig_only && should_send_signal(p))
                        continue;
 
+               if (cgroup_frozen(p))
+                       continue;
+
                thaw_process(p);
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
@@ -264,4 +152,3 @@ void thaw_processes(void)
        printk("done.\n");
 }
 
-EXPORT_SYMBOL(refrigerator);
index 356699a96d565faa2e034253f9178c7d0aa2829d..1e68e4c39e2c05306dbfd9d111ef018aa0f8d9ca 100644 (file)
@@ -45,7 +45,7 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
  * TASK_TRACED, resume it now.
  * Requires that irqs be disabled.
  */
-void ptrace_untrace(struct task_struct *child)
+static void ptrace_untrace(struct task_struct *child)
 {
        spin_lock(&child->sighand->siglock);
        if (task_is_traced(child)) {
index ca4bbbe04aa4db9d150a503c9025dbe83e0d62a3..59236e8b9daa38e1e92a709e769fa75d857bb41e 100644 (file)
@@ -54,9 +54,9 @@
 #include <linux/cpu.h>
 #include <linux/random.h>
 #include <linux/delay.h>
-#include <linux/byteorder/swabb.h>
 #include <linux/cpumask.h>
 #include <linux/rcupreempt_trace.h>
+#include <asm/byteorder.h>
 
 /*
  * PREEMPT_RCU data structures.
index 617d41e4d6a08eae69152515e1ac47a9c8a3fc85..b3cc73931d1f6411c6e99faf205124987d4a887e 100644 (file)
@@ -833,6 +833,16 @@ static struct ctl_table kern_table[] = {
                .proc_handler   = &proc_dointvec,
        },
 #endif
+#ifdef CONFIG_UNEVICTABLE_LRU
+       {
+               .ctl_name       = CTL_UNNUMBERED,
+               .procname       = "scan_unevictable_pages",
+               .data           = &scan_unevictable_pages,
+               .maxlen         = sizeof(scan_unevictable_pages),
+               .mode           = 0644,
+               .proc_handler   = &scan_unevictable_handler,
+       },
+#endif
 /*
  * NOTE: do not add new entries to this table unless you have read
  * Documentation/sysctl/ctl_unnumbered.txt
index 06fb57c86de07007dad10f4bbeb3b1adcc0742c4..482df94ea21eb3e9ab7b2ef4efe88643147c3d80 100644 (file)
@@ -315,17 +315,6 @@ int bitmap_scnprintf(char *buf, unsigned int buflen,
 }
 EXPORT_SYMBOL(bitmap_scnprintf);
 
-/**
- * bitmap_scnprintf_len - return buffer length needed to convert
- * bitmap to an ASCII hex string
- * @nr_bits: number of bits to be converted
- */
-int bitmap_scnprintf_len(unsigned int nr_bits)
-{
-       unsigned int nr_nibbles = ALIGN(nr_bits, 4) / 4;
-       return nr_nibbles + ALIGN(nr_nibbles, CHUNKSZ / 4) / (CHUNKSZ / 4) - 1;
-}
-
 /**
  * __bitmap_parse - convert an ASCII hex string into a bitmap.
  * @buf: pointer to buffer containing string.
index cceecb6a963d1638bd420a82f7a3b85014cea379..a013bbc237178c1bc86c522b0e3ee4a66f47a2c9 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/kallsyms.h>
 #include <linux/uaccess.h>
+#include <linux/ioport.h>
 
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/div64.h>
@@ -550,18 +551,51 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int
 #endif
 }
 
+static char *resource_string(char *buf, char *end, struct resource *res, int field_width, int precision, int flags)
+{
+#ifndef IO_RSRC_PRINTK_SIZE
+#define IO_RSRC_PRINTK_SIZE    4
+#endif
+
+#ifndef MEM_RSRC_PRINTK_SIZE
+#define MEM_RSRC_PRINTK_SIZE   8
+#endif
+
+       /* room for the actual numbers, the two "0x", -, [, ] and the final zero */
+       char sym[4*sizeof(resource_size_t) + 8];
+       char *p = sym, *pend = sym + sizeof(sym);
+       int size = -1;
+
+       if (res->flags & IORESOURCE_IO)
+               size = IO_RSRC_PRINTK_SIZE;
+       else if (res->flags & IORESOURCE_MEM)
+               size = MEM_RSRC_PRINTK_SIZE;
+
+       *p++ = '[';
+       p = number(p, pend, res->start, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
+       *p++ = '-';
+       p = number(p, pend, res->end, 16, size, -1, SPECIAL | SMALL | ZEROPAD);
+       *p++ = ']';
+       *p = 0;
+
+       return string(buf, end, sym, field_width, precision, flags);
+}
+
 /*
  * Show a '%p' thing.  A kernel extension is that the '%p' is followed
  * by an extra set of alphanumeric characters that are extended format
  * specifiers.
  *
- * Right now we just handle 'F' (for symbolic Function descriptor pointers)
- * and 'S' (for Symbolic direct pointers), but this can easily be
- * extended in the future (network address types etc).
+ * Right now we handle:
+ *
+ * - 'F' For symbolic function descriptor pointers
+ * - 'S' For symbolic direct pointers
+ * - 'R' For a struct resource pointer, it prints the range of
+ *       addresses (not the name nor the flags)
  *
- * The difference between 'S' and 'F' is that on ia64 and ppc64 function
- * pointers are really function descriptors, which contain a pointer the
- * real address. 
+ * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
+ * function pointers are really function descriptors, which contain a
+ * pointer to the real address.
  */
 static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field_width, int precision, int flags)
 {
@@ -571,6 +605,8 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
                /* Fallthrough */
        case 'S':
                return symbol_string(buf, end, ptr, field_width, precision, flags);
+       case 'R':
+               return resource_string(buf, end, ptr, field_width, precision, flags);
        }
        flags |= SMALL;
        if (field_width == -1) {
@@ -590,6 +626,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
  * This function follows C99 vsnprintf, but has some extensions:
  * %pS output the name of a text symbol
  * %pF output the name of a function pointer
+ * %pR output the address range in a struct resource
  *
  * The return value is the number of characters which would
  * be generated for the given input, excluding the trailing
index 1a501a4de95cba98543bf706d8c8078ce598d3cd..5b5790f8a81686644a2d27beee9aa1f1a7f006c3 100644 (file)
@@ -209,5 +209,16 @@ config VIRT_TO_BUS
        def_bool y
        depends on !ARCH_NO_VIRT_TO_BUS
 
+config UNEVICTABLE_LRU
+       bool "Add LRU list to track non-evictable pages"
+       default y
+       depends on MMU
+       help
+         Keeps unevictable pages off of the active and inactive pageout
+         lists, so kswapd will not waste CPU time or have its balancing
+         algorithms thrown off by scanning these pages.  Selecting this
+         will use one page flag and increase the code size a little,
+         say Y unless you know what you are doing.
+
 config MMU_NOTIFIER
        bool
index da4ccf015aea72ba4d18dc69cf47e7ac97481129..c06b45a1ff5f64cf2e007258bfdaf9af5c280d98 100644 (file)
@@ -33,5 +33,4 @@ obj-$(CONFIG_FS_XIP) += filemap_xip.o
 obj-$(CONFIG_MIGRATION) += migrate.o
 obj-$(CONFIG_SMP) += allocpercpu.o
 obj-$(CONFIG_QUICKLIST) += quicklist.o
-obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o
-
+obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
index 903bf316912a68882dadfb0144aef035a6bd5fda..ab8553658af3fb2fcfac7b0c80bc2ed8d1343721 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/cpuset.h>
 #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
 #include <linux/memcontrol.h>
+#include <linux/mm_inline.h> /* for page_is_file_cache() */
 #include "internal.h"
 
 /*
@@ -115,12 +116,12 @@ void __remove_from_page_cache(struct page *page)
 {
        struct address_space *mapping = page->mapping;
 
-       mem_cgroup_uncharge_cache_page(page);
        radix_tree_delete(&mapping->page_tree, page->index);
        page->mapping = NULL;
        mapping->nrpages--;
        __dec_zone_page_state(page, NR_FILE_PAGES);
        BUG_ON(page_mapped(page));
+       mem_cgroup_uncharge_cache_page(page);
 
        /*
         * Some filesystems seem to re-dirty the page even after
@@ -492,9 +493,24 @@ EXPORT_SYMBOL(add_to_page_cache_locked);
 int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
                                pgoff_t offset, gfp_t gfp_mask)
 {
-       int ret = add_to_page_cache(page, mapping, offset, gfp_mask);
-       if (ret == 0)
-               lru_cache_add(page);
+       int ret;
+
+       /*
+        * Splice_read and readahead add shmem/tmpfs pages into the page cache
+        * before shmem_readpage has a chance to mark them as SwapBacked: they
+        * need to go on the active_anon lru below, and mem_cgroup_cache_charge
+        * (called in add_to_page_cache) needs to know where they're going too.
+        */
+       if (mapping_cap_swap_backed(mapping))
+               SetPageSwapBacked(page);
+
+       ret = add_to_page_cache(page, mapping, offset, gfp_mask);
+       if (ret == 0) {
+               if (page_is_file_cache(page))
+                       lru_cache_add_file(page);
+               else
+                       lru_cache_add_active_anon(page);
+       }
        return ret;
 }
 
@@ -557,17 +573,14 @@ EXPORT_SYMBOL(wait_on_page_bit);
  * mechananism between PageLocked pages and PageWriteback pages is shared.
  * But that's OK - sleepers in wait_on_page_writeback() just go back to sleep.
  *
- * The first mb is necessary to safely close the critical section opened by the
- * test_and_set_bit() to lock the page; the second mb is necessary to enforce
- * ordering between the clear_bit and the read of the waitqueue (to avoid SMP
- * races with a parallel wait_on_page_locked()).
+ * The mb is necessary to enforce ordering between the clear_bit and the read
+ * of the waitqueue (to avoid SMP races with a parallel wait_on_page_locked()).
  */
 void unlock_page(struct page *page)
 {
-       smp_mb__before_clear_bit();
-       if (!test_and_clear_bit(PG_locked, &page->flags))
-               BUG();
-       smp_mb__after_clear_bit(); 
+       VM_BUG_ON(!PageLocked(page));
+       clear_bit_unlock(PG_locked, &page->flags);
+       smp_mb__after_clear_bit();
        wake_up_page(page, PG_locked);
 }
 EXPORT_SYMBOL(unlock_page);
index 7881638e4a12bd8c5489c8d08b5779b5ae5a0080..7d12ca70ef7bf22c7e1efcdee186adad87a6c8c8 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
+#include "internal.h"
+
 static void zap_pte(struct mm_struct *mm, struct vm_area_struct *vma,
                        unsigned long addr, pte_t *ptep)
 {
@@ -215,15 +217,31 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
                spin_unlock(&mapping->i_mmap_lock);
        }
 
+       if (vma->vm_flags & VM_LOCKED) {
+               /*
+                * drop PG_Mlocked flag for over-mapped range
+                */
+               unsigned int saved_flags = vma->vm_flags;
+               munlock_vma_pages_range(vma, start, start + size);
+               vma->vm_flags = saved_flags;
+       }
+
        mmu_notifier_invalidate_range_start(mm, start, start + size);
        err = populate_range(mm, vma, start, size, pgoff);
        mmu_notifier_invalidate_range_end(mm, start, start + size);
        if (!err && !(flags & MAP_NONBLOCK)) {
-               if (unlikely(has_write_lock)) {
-                       downgrade_write(&mm->mmap_sem);
-                       has_write_lock = 0;
+               if (vma->vm_flags & VM_LOCKED) {
+                       /*
+                        * might be mapping previously unmapped range of file
+                        */
+                       mlock_vma_pages_range(vma, start, start + size);
+               } else {
+                       if (unlikely(has_write_lock)) {
+                               downgrade_write(&mm->mmap_sem);
+                               has_write_lock = 0;
+                       }
+                       make_pages_present(start, start+size);
                }
-               make_pages_present(start, start+size);
        }
 
        /*
@@ -240,4 +258,3 @@ out:
 
        return err;
 }
-
index 38633864a93e874009d9e6aa00619cf7471b0d9e..ce8cbb29860bd1b867454014195fe497332e2f61 100644 (file)
@@ -262,7 +262,7 @@ struct resv_map {
        struct list_head regions;
 };
 
-struct resv_map *resv_map_alloc(void)
+static struct resv_map *resv_map_alloc(void)
 {
        struct resv_map *resv_map = kmalloc(sizeof(*resv_map), GFP_KERNEL);
        if (!resv_map)
@@ -274,7 +274,7 @@ struct resv_map *resv_map_alloc(void)
        return resv_map;
 }
 
-void resv_map_release(struct kref *ref)
+static void resv_map_release(struct kref *ref)
 {
        struct resv_map *resv_map = container_of(ref, struct resv_map, refs);
 
@@ -289,7 +289,7 @@ static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
        if (!(vma->vm_flags & VM_SHARED))
                return (struct resv_map *)(get_vma_private_data(vma) &
                                                        ~HPAGE_RESV_MASK);
-       return 0;
+       return NULL;
 }
 
 static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
@@ -1459,11 +1459,11 @@ int hugetlb_report_meminfo(char *buf)
 {
        struct hstate *h = &default_hstate;
        return sprintf(buf,
-                       "HugePages_Total: %5lu\n"
-                       "HugePages_Free:  %5lu\n"
-                       "HugePages_Rsvd:  %5lu\n"
-                       "HugePages_Surp:  %5lu\n"
-                       "Hugepagesize:    %5lu kB\n",
+                       "HugePages_Total:   %5lu\n"
+                       "HugePages_Free:    %5lu\n"
+                       "HugePages_Rsvd:    %5lu\n"
+                       "HugePages_Surp:    %5lu\n"
+                       "Hugepagesize:   %8lu kB\n",
                        h->nr_huge_pages,
                        h->free_huge_pages,
                        h->resv_huge_pages,
@@ -1747,10 +1747,8 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start,
  * from other VMAs and let the children be SIGKILLed if they are faulting the
  * same region.
  */
-int unmap_ref_private(struct mm_struct *mm,
-                                       struct vm_area_struct *vma,
-                                       struct page *page,
-                                       unsigned long address)
+static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma,
+                               struct page *page, unsigned long address)
 {
        struct vm_area_struct *iter_vma;
        struct address_space *mapping;
@@ -2073,6 +2071,14 @@ follow_huge_pud(struct mm_struct *mm, unsigned long address,
        return NULL;
 }
 
+static int huge_zeropage_ok(pte_t *ptep, int write, int shared)
+{
+       if (!ptep || write || shared)
+               return 0;
+       else
+               return huge_pte_none(huge_ptep_get(ptep));
+}
+
 int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        struct page **pages, struct vm_area_struct **vmas,
                        unsigned long *position, int *length, int i,
@@ -2082,6 +2088,8 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
        unsigned long vaddr = *position;
        int remainder = *length;
        struct hstate *h = hstate_vma(vma);
+       int zeropage_ok = 0;
+       int shared = vma->vm_flags & VM_SHARED;
 
        spin_lock(&mm->page_table_lock);
        while (vaddr < vma->vm_end && remainder) {
@@ -2094,8 +2102,11 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                 * first, for the page indexing below to work.
                 */
                pte = huge_pte_offset(mm, vaddr & huge_page_mask(h));
+               if (huge_zeropage_ok(pte, write, shared))
+                       zeropage_ok = 1;
 
-               if (!pte || huge_pte_none(huge_ptep_get(pte)) ||
+               if (!pte ||
+                   (huge_pte_none(huge_ptep_get(pte)) && !zeropage_ok) ||
                    (write && !pte_write(huge_ptep_get(pte)))) {
                        int ret;
 
@@ -2115,8 +2126,11 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                page = pte_page(huge_ptep_get(pte));
 same_page:
                if (pages) {
-                       get_page(page);
-                       pages[i] = page + pfn_offset;
+                       if (zeropage_ok)
+                               pages[i] = ZERO_PAGE(0);
+                       else
+                               pages[i] = page + pfn_offset;
+                       get_page(pages[i]);
                }
 
                if (vmas)
index 1f43f7416972d3c4f1b07ab04898008a8ec76a81..e4e728bdf324fc62a24ba0c951869989ab081ea1 100644 (file)
@@ -39,6 +39,15 @@ static inline void __put_page(struct page *page)
        atomic_dec(&page->_count);
 }
 
+/*
+ * in mm/vmscan.c:
+ */
+extern int isolate_lru_page(struct page *page);
+extern void putback_lru_page(struct page *page);
+
+/*
+ * in mm/page_alloc.c
+ */
 extern void __free_pages_bootmem(struct page *page, unsigned int order);
 
 /*
@@ -52,6 +61,120 @@ static inline unsigned long page_order(struct page *page)
        return page_private(page);
 }
 
+extern long mlock_vma_pages_range(struct vm_area_struct *vma,
+                       unsigned long start, unsigned long end);
+extern void munlock_vma_pages_range(struct vm_area_struct *vma,
+                       unsigned long start, unsigned long end);
+static inline void munlock_vma_pages_all(struct vm_area_struct *vma)
+{
+       munlock_vma_pages_range(vma, vma->vm_start, vma->vm_end);
+}
+
+#ifdef CONFIG_UNEVICTABLE_LRU
+/*
+ * unevictable_migrate_page() called only from migrate_page_copy() to
+ * migrate unevictable flag to new page.
+ * Note that the old page has been isolated from the LRU lists at this
+ * point so we don't need to worry about LRU statistics.
+ */
+static inline void unevictable_migrate_page(struct page *new, struct page *old)
+{
+       if (TestClearPageUnevictable(old))
+               SetPageUnevictable(new);
+}
+#else
+static inline void unevictable_migrate_page(struct page *new, struct page *old)
+{
+}
+#endif
+
+#ifdef CONFIG_UNEVICTABLE_LRU
+/*
+ * Called only in fault path via page_evictable() for a new page
+ * to determine if it's being mapped into a LOCKED vma.
+ * If so, mark page as mlocked.
+ */
+static inline int is_mlocked_vma(struct vm_area_struct *vma, struct page *page)
+{
+       VM_BUG_ON(PageLRU(page));
+
+       if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED))
+               return 0;
+
+       if (!TestSetPageMlocked(page)) {
+               inc_zone_page_state(page, NR_MLOCK);
+               count_vm_event(UNEVICTABLE_PGMLOCKED);
+       }
+       return 1;
+}
+
+/*
+ * must be called with vma's mmap_sem held for read, and page locked.
+ */
+extern void mlock_vma_page(struct page *page);
+
+/*
+ * Clear the page's PageMlocked().  This can be useful in a situation where
+ * we want to unconditionally remove a page from the pagecache -- e.g.,
+ * on truncation or freeing.
+ *
+ * It is legal to call this function for any page, mlocked or not.
+ * If called for a page that is still mapped by mlocked vmas, all we do
+ * is revert to lazy LRU behaviour -- semantics are not broken.
+ */
+extern void __clear_page_mlock(struct page *page);
+static inline void clear_page_mlock(struct page *page)
+{
+       if (unlikely(TestClearPageMlocked(page)))
+               __clear_page_mlock(page);
+}
+
+/*
+ * mlock_migrate_page - called only from migrate_page_copy() to
+ * migrate the Mlocked page flag; update statistics.
+ */
+static inline void mlock_migrate_page(struct page *newpage, struct page *page)
+{
+       if (TestClearPageMlocked(page)) {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               __dec_zone_page_state(page, NR_MLOCK);
+               SetPageMlocked(newpage);
+               __inc_zone_page_state(newpage, NR_MLOCK);
+               local_irq_restore(flags);
+       }
+}
+
+/*
+ * free_page_mlock() -- clean up attempts to free and mlocked() page.
+ * Page should not be on lru, so no need to fix that up.
+ * free_pages_check() will verify...
+ */
+static inline void free_page_mlock(struct page *page)
+{
+       if (unlikely(TestClearPageMlocked(page))) {
+               unsigned long flags;
+
+               local_irq_save(flags);
+               __dec_zone_page_state(page, NR_MLOCK);
+               __count_vm_event(UNEVICTABLE_MLOCKFREED);
+               local_irq_restore(flags);
+       }
+}
+
+#else /* CONFIG_UNEVICTABLE_LRU */
+static inline int is_mlocked_vma(struct vm_area_struct *v, struct page *p)
+{
+       return 0;
+}
+static inline void clear_page_mlock(struct page *page) { }
+static inline void mlock_vma_page(struct page *page) { }
+static inline void mlock_migrate_page(struct page *new, struct page *old) { }
+static inline void free_page_mlock(struct page *page) { }
+
+#endif /* CONFIG_UNEVICTABLE_LRU */
+
 /*
  * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node,
  * so all functions starting at paging_init should be marked __init
@@ -120,4 +243,12 @@ static inline void mminit_validate_memmodel_limits(unsigned long *start_pfn,
 }
 #endif /* CONFIG_SPARSEMEM */
 
+#define GUP_FLAGS_WRITE                  0x1
+#define GUP_FLAGS_FORCE                  0x2
+#define GUP_FLAGS_IGNORE_VMA_PERMISSIONS 0x4
+
+int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+                    unsigned long start, int len, int flags,
+                    struct page **pages, struct vm_area_struct **vmas);
+
 #endif
index 36896f3eb7f5e5c2e4c3803cc8125fe461a71669..d4a92b63e98e1da2fa619a7272cd0db3d15f18f1 100644 (file)
 #include <linux/fs.h>
 #include <linux/seq_file.h>
 #include <linux/vmalloc.h>
+#include <linux/mm_inline.h>
+#include <linux/page_cgroup.h>
 
 #include <asm/uaccess.h>
 
 struct cgroup_subsys mem_cgroup_subsys __read_mostly;
-static struct kmem_cache *page_cgroup_cache __read_mostly;
 #define MEM_CGROUP_RECLAIM_RETRIES     5
 
 /*
@@ -65,11 +66,10 @@ struct mem_cgroup_stat {
 /*
  * For accounting under irq disable, no need for increment preempt count.
  */
-static void __mem_cgroup_stat_add_safe(struct mem_cgroup_stat *stat,
+static inline void __mem_cgroup_stat_add_safe(struct mem_cgroup_stat_cpu *stat,
                enum mem_cgroup_stat_index idx, int val)
 {
-       int cpu = smp_processor_id();
-       stat->cpustat[cpu].count[idx] += val;
+       stat->count[idx] += val;
 }
 
 static s64 mem_cgroup_read_stat(struct mem_cgroup_stat *stat,
@@ -85,22 +85,13 @@ static s64 mem_cgroup_read_stat(struct mem_cgroup_stat *stat,
 /*
  * per-zone information in memory controller.
  */
-
-enum mem_cgroup_zstat_index {
-       MEM_CGROUP_ZSTAT_ACTIVE,
-       MEM_CGROUP_ZSTAT_INACTIVE,
-
-       NR_MEM_CGROUP_ZSTAT,
-};
-
 struct mem_cgroup_per_zone {
        /*
         * spin_lock to protect the per cgroup LRU
         */
        spinlock_t              lru_lock;
-       struct list_head        active_list;
-       struct list_head        inactive_list;
-       unsigned long count[NR_MEM_CGROUP_ZSTAT];
+       struct list_head        lists[NR_LRU_LISTS];
+       unsigned long           count[NR_LRU_LISTS];
 };
 /* Macro for accessing counter */
 #define MEM_CGROUP_ZSTAT(mz, idx)      ((mz)->count[(idx)])
@@ -144,69 +135,52 @@ struct mem_cgroup {
 };
 static struct mem_cgroup init_mem_cgroup;
 
-/*
- * We use the lower bit of the page->page_cgroup pointer as a bit spin
- * lock.  We need to ensure that page->page_cgroup is at least two
- * byte aligned (based on comments from Nick Piggin).  But since
- * bit_spin_lock doesn't actually set that lock bit in a non-debug
- * uniprocessor kernel, we should avoid setting it here too.
- */
-#define PAGE_CGROUP_LOCK_BIT   0x0
-#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
-#define PAGE_CGROUP_LOCK       (1 << PAGE_CGROUP_LOCK_BIT)
-#else
-#define PAGE_CGROUP_LOCK       0x0
-#endif
-
-/*
- * A page_cgroup page is associated with every page descriptor. The
- * page_cgroup helps us identify information about the cgroup
- */
-struct page_cgroup {
-       struct list_head lru;           /* per cgroup LRU list */
-       struct page *page;
-       struct mem_cgroup *mem_cgroup;
-       int flags;
-};
-#define PAGE_CGROUP_FLAG_CACHE (0x1)   /* charged as cache */
-#define PAGE_CGROUP_FLAG_ACTIVE (0x2)  /* page is active in this cgroup */
-
-static int page_cgroup_nid(struct page_cgroup *pc)
-{
-       return page_to_nid(pc->page);
-}
-
-static enum zone_type page_cgroup_zid(struct page_cgroup *pc)
-{
-       return page_zonenum(pc->page);
-}
-
 enum charge_type {
        MEM_CGROUP_CHARGE_TYPE_CACHE = 0,
        MEM_CGROUP_CHARGE_TYPE_MAPPED,
+       MEM_CGROUP_CHARGE_TYPE_SHMEM,   /* used by page migration of shmem */
        MEM_CGROUP_CHARGE_TYPE_FORCE,   /* used by force_empty */
+       NR_CHARGE_TYPE,
+};
+
+/* only for here (for easy reading.) */
+#define PCGF_CACHE     (1UL << PCG_CACHE)
+#define PCGF_USED      (1UL << PCG_USED)
+#define PCGF_ACTIVE    (1UL << PCG_ACTIVE)
+#define PCGF_LOCK      (1UL << PCG_LOCK)
+#define PCGF_FILE      (1UL << PCG_FILE)
+static const unsigned long
+pcg_default_flags[NR_CHARGE_TYPE] = {
+       PCGF_CACHE | PCGF_FILE | PCGF_USED | PCGF_LOCK, /* File Cache */
+       PCGF_ACTIVE | PCGF_USED | PCGF_LOCK, /* Anon */
+       PCGF_ACTIVE | PCGF_CACHE | PCGF_USED | PCGF_LOCK, /* Shmem */
+       0, /* FORCE */
 };
 
 /*
  * Always modified under lru lock. Then, not necessary to preempt_disable()
  */
-static void mem_cgroup_charge_statistics(struct mem_cgroup *mem, int flags,
-                                       bool charge)
+static void mem_cgroup_charge_statistics(struct mem_cgroup *mem,
+                                        struct page_cgroup *pc,
+                                        bool charge)
 {
        int val = (charge)? 1 : -1;
        struct mem_cgroup_stat *stat = &mem->stat;
+       struct mem_cgroup_stat_cpu *cpustat;
 
        VM_BUG_ON(!irqs_disabled());
-       if (flags & PAGE_CGROUP_FLAG_CACHE)
-               __mem_cgroup_stat_add_safe(stat, MEM_CGROUP_STAT_CACHE, val);
+
+       cpustat = &stat->cpustat[smp_processor_id()];
+       if (PageCgroupCache(pc))
+               __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_CACHE, val);
        else
-               __mem_cgroup_stat_add_safe(stat, MEM_CGROUP_STAT_RSS, val);
+               __mem_cgroup_stat_add_safe(cpustat, MEM_CGROUP_STAT_RSS, val);
 
        if (charge)
-               __mem_cgroup_stat_add_safe(stat,
+               __mem_cgroup_stat_add_safe(cpustat,
                                MEM_CGROUP_STAT_PGPGIN_COUNT, 1);
        else
-               __mem_cgroup_stat_add_safe(stat,
+               __mem_cgroup_stat_add_safe(cpustat,
                                MEM_CGROUP_STAT_PGPGOUT_COUNT, 1);
 }
 
@@ -227,7 +201,7 @@ page_cgroup_zoneinfo(struct page_cgroup *pc)
 }
 
 static unsigned long mem_cgroup_get_all_zonestat(struct mem_cgroup *mem,
-                                       enum mem_cgroup_zstat_index idx)
+                                       enum lru_list idx)
 {
        int nid, zid;
        struct mem_cgroup_per_zone *mz;
@@ -262,85 +236,77 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
                                struct mem_cgroup, css);
 }
 
-static inline int page_cgroup_locked(struct page *page)
-{
-       return bit_spin_is_locked(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
-}
-
-static void page_assign_page_cgroup(struct page *page, struct page_cgroup *pc)
-{
-       VM_BUG_ON(!page_cgroup_locked(page));
-       page->page_cgroup = ((unsigned long)pc | PAGE_CGROUP_LOCK);
-}
-
-struct page_cgroup *page_get_page_cgroup(struct page *page)
-{
-       return (struct page_cgroup *) (page->page_cgroup & ~PAGE_CGROUP_LOCK);
-}
-
-static void lock_page_cgroup(struct page *page)
-{
-       bit_spin_lock(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
-}
-
-static int try_lock_page_cgroup(struct page *page)
-{
-       return bit_spin_trylock(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
-}
-
-static void unlock_page_cgroup(struct page *page)
-{
-       bit_spin_unlock(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup);
-}
-
 static void __mem_cgroup_remove_list(struct mem_cgroup_per_zone *mz,
                        struct page_cgroup *pc)
 {
-       int from = pc->flags & PAGE_CGROUP_FLAG_ACTIVE;
+       int lru = LRU_BASE;
+
+       if (PageCgroupUnevictable(pc))
+               lru = LRU_UNEVICTABLE;
+       else {
+               if (PageCgroupActive(pc))
+                       lru += LRU_ACTIVE;
+               if (PageCgroupFile(pc))
+                       lru += LRU_FILE;
+       }
 
-       if (from)
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) -= 1;
-       else
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) -= 1;
+       MEM_CGROUP_ZSTAT(mz, lru) -= 1;
 
-       mem_cgroup_charge_statistics(pc->mem_cgroup, pc->flags, false);
+       mem_cgroup_charge_statistics(pc->mem_cgroup, pc, false);
        list_del(&pc->lru);
 }
 
 static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz,
                                struct page_cgroup *pc)
 {
-       int to = pc->flags & PAGE_CGROUP_FLAG_ACTIVE;
-
-       if (!to) {
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) += 1;
-               list_add(&pc->lru, &mz->inactive_list);
-       } else {
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) += 1;
-               list_add(&pc->lru, &mz->active_list);
+       int lru = LRU_BASE;
+
+       if (PageCgroupUnevictable(pc))
+               lru = LRU_UNEVICTABLE;
+       else {
+               if (PageCgroupActive(pc))
+                       lru += LRU_ACTIVE;
+               if (PageCgroupFile(pc))
+                       lru += LRU_FILE;
        }
-       mem_cgroup_charge_statistics(pc->mem_cgroup, pc->flags, true);
+
+       MEM_CGROUP_ZSTAT(mz, lru) += 1;
+       list_add(&pc->lru, &mz->lists[lru]);
+
+       mem_cgroup_charge_statistics(pc->mem_cgroup, pc, true);
 }
 
-static void __mem_cgroup_move_lists(struct page_cgroup *pc, bool active)
+static void __mem_cgroup_move_lists(struct page_cgroup *pc, enum lru_list lru)
 {
-       int from = pc->flags & PAGE_CGROUP_FLAG_ACTIVE;
        struct mem_cgroup_per_zone *mz = page_cgroup_zoneinfo(pc);
+       int active    = PageCgroupActive(pc);
+       int file      = PageCgroupFile(pc);
+       int unevictable = PageCgroupUnevictable(pc);
+       enum lru_list from = unevictable ? LRU_UNEVICTABLE :
+                               (LRU_FILE * !!file + !!active);
 
-       if (from)
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) -= 1;
-       else
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) -= 1;
+       if (lru == from)
+               return;
 
-       if (active) {
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) += 1;
-               pc->flags |= PAGE_CGROUP_FLAG_ACTIVE;
-               list_move(&pc->lru, &mz->active_list);
+       MEM_CGROUP_ZSTAT(mz, from) -= 1;
+       /*
+        * However this is done under mz->lru_lock, another flags, which
+        * are not related to LRU, will be modified from out-of-lock.
+        * We have to use atomic set/clear flags.
+        */
+       if (is_unevictable_lru(lru)) {
+               ClearPageCgroupActive(pc);
+               SetPageCgroupUnevictable(pc);
        } else {
-               MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) += 1;
-               pc->flags &= ~PAGE_CGROUP_FLAG_ACTIVE;
-               list_move(&pc->lru, &mz->inactive_list);
+               if (is_active_lru(lru))
+                       SetPageCgroupActive(pc);
+               else
+                       ClearPageCgroupActive(pc);
+               ClearPageCgroupUnevictable(pc);
        }
+
+       MEM_CGROUP_ZSTAT(mz, lru) += 1;
+       list_move(&pc->lru, &mz->lists[lru]);
 }
 
 int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
@@ -356,7 +322,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem)
 /*
  * This routine assumes that the appropriate zone's lru lock is already held
  */
-void mem_cgroup_move_lists(struct page *page, bool active)
+void mem_cgroup_move_lists(struct page *page, enum lru_list lru)
 {
        struct page_cgroup *pc;
        struct mem_cgroup_per_zone *mz;
@@ -372,17 +338,16 @@ void mem_cgroup_move_lists(struct page *page, bool active)
         * safely get to page_cgroup without it, so just try_lock it:
         * mem_cgroup_isolate_pages allows for page left on wrong list.
         */
-       if (!try_lock_page_cgroup(page))
+       pc = lookup_page_cgroup(page);
+       if (!trylock_page_cgroup(pc))
                return;
-
-       pc = page_get_page_cgroup(page);
-       if (pc) {
+       if (pc && PageCgroupUsed(pc)) {
                mz = page_cgroup_zoneinfo(pc);
                spin_lock_irqsave(&mz->lru_lock, flags);
-               __mem_cgroup_move_lists(pc, active);
+               __mem_cgroup_move_lists(pc, lru);
                spin_unlock_irqrestore(&mz->lru_lock, flags);
        }
-       unlock_page_cgroup(page);
+       unlock_page_cgroup(pc);
 }
 
 /*
@@ -402,21 +367,6 @@ int mem_cgroup_calc_mapped_ratio(struct mem_cgroup *mem)
        return (int)((rss * 100L) / total);
 }
 
-/*
- * This function is called from vmscan.c. In page reclaiming loop. balance
- * between active and inactive list is calculated. For memory controller
- * page reclaiming, we should use using mem_cgroup's imbalance rather than
- * zone's global lru imbalance.
- */
-long mem_cgroup_reclaim_imbalance(struct mem_cgroup *mem)
-{
-       unsigned long active, inactive;
-       /* active and inactive are the number of pages. 'long' is ok.*/
-       active = mem_cgroup_get_all_zonestat(mem, MEM_CGROUP_ZSTAT_ACTIVE);
-       inactive = mem_cgroup_get_all_zonestat(mem, MEM_CGROUP_ZSTAT_INACTIVE);
-       return (long) (active / (inactive + 1));
-}
-
 /*
  * prev_priority control...this will be used in memory reclaim path.
  */
@@ -444,28 +394,17 @@ void mem_cgroup_record_reclaim_priority(struct mem_cgroup *mem, int priority)
  * (see include/linux/mmzone.h)
  */
 
-long mem_cgroup_calc_reclaim_active(struct mem_cgroup *mem,
-                                  struct zone *zone, int priority)
+long mem_cgroup_calc_reclaim(struct mem_cgroup *mem, struct zone *zone,
+                                       int priority, enum lru_list lru)
 {
-       long nr_active;
+       long nr_pages;
        int nid = zone->zone_pgdat->node_id;
        int zid = zone_idx(zone);
        struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(mem, nid, zid);
 
-       nr_active = MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE);
-       return (nr_active >> priority);
-}
+       nr_pages = MEM_CGROUP_ZSTAT(mz, lru);
 
-long mem_cgroup_calc_reclaim_inactive(struct mem_cgroup *mem,
-                                       struct zone *zone, int priority)
-{
-       long nr_inactive;
-       int nid = zone->zone_pgdat->node_id;
-       int zid = zone_idx(zone);
-       struct mem_cgroup_per_zone *mz = mem_cgroup_zoneinfo(mem, nid, zid);
-
-       nr_inactive = MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE);
-       return (nr_inactive >> priority);
+       return (nr_pages >> priority);
 }
 
 unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
@@ -473,7 +412,7 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
                                        unsigned long *scanned, int order,
                                        int mode, struct zone *z,
                                        struct mem_cgroup *mem_cont,
-                                       int active)
+                                       int active, int file)
 {
        unsigned long nr_taken = 0;
        struct page *page;
@@ -484,38 +423,38 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
        int nid = z->zone_pgdat->node_id;
        int zid = zone_idx(z);
        struct mem_cgroup_per_zone *mz;
+       int lru = LRU_FILE * !!file + !!active;
 
        BUG_ON(!mem_cont);
        mz = mem_cgroup_zoneinfo(mem_cont, nid, zid);
-       if (active)
-               src = &mz->active_list;
-       else
-               src = &mz->inactive_list;
-
+       src = &mz->lists[lru];
 
        spin_lock(&mz->lru_lock);
        scan = 0;
        list_for_each_entry_safe_reverse(pc, tmp, src, lru) {
                if (scan >= nr_to_scan)
                        break;
+               if (unlikely(!PageCgroupUsed(pc)))
+                       continue;
                page = pc->page;
 
                if (unlikely(!PageLRU(page)))
                        continue;
 
-               if (PageActive(page) && !active) {
-                       __mem_cgroup_move_lists(pc, true);
-                       continue;
-               }
-               if (!PageActive(page) && active) {
-                       __mem_cgroup_move_lists(pc, false);
+               /*
+                * TODO: play better with lumpy reclaim, grabbing anything.
+                */
+               if (PageUnevictable(page) ||
+                   (PageActive(page) && !active) ||
+                   (!PageActive(page) && active)) {
+                       __mem_cgroup_move_lists(pc, page_lru(page));
                        continue;
                }
 
                scan++;
                list_move(&pc->lru, &pc_list);
 
-               if (__isolate_lru_page(page, mode) == 0) {
+               if (__isolate_lru_page(page, mode, file) == 0) {
                        list_move(&page->lru, dst);
                        nr_taken++;
                }
@@ -540,26 +479,27 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
 {
        struct mem_cgroup *mem;
        struct page_cgroup *pc;
-       unsigned long flags;
        unsigned long nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
        struct mem_cgroup_per_zone *mz;
+       unsigned long flags;
 
-       pc = kmem_cache_alloc(page_cgroup_cache, gfp_mask);
-       if (unlikely(pc == NULL))
-               goto err;
-
+       pc = lookup_page_cgroup(page);
+       /* can happen at boot */
+       if (unlikely(!pc))
+               return 0;
+       prefetchw(pc);
        /*
         * We always charge the cgroup the mm_struct belongs to.
         * The mm_struct's mem_cgroup changes on task migration if the
         * thread group leader migrates. It's possible that mm is not
         * set, if so charge the init_mm (happens for pagecache usage).
         */
+
        if (likely(!memcg)) {
                rcu_read_lock();
                mem = mem_cgroup_from_task(rcu_dereference(mm->owner));
                if (unlikely(!mem)) {
                        rcu_read_unlock();
-                       kmem_cache_free(page_cgroup_cache, pc);
                        return 0;
                }
                /*
@@ -572,7 +512,7 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
                css_get(&memcg->css);
        }
 
-       while (res_counter_charge(&mem->res, PAGE_SIZE)) {
+       while (unlikely(res_counter_charge(&mem->res, PAGE_SIZE))) {
                if (!(gfp_mask & __GFP_WAIT))
                        goto out;
 
@@ -595,39 +535,33 @@ static int mem_cgroup_charge_common(struct page *page, struct mm_struct *mm,
                }
        }
 
-       pc->mem_cgroup = mem;
-       pc->page = page;
-       /*
-        * If a page is accounted as a page cache, insert to inactive list.
-        * If anon, insert to active list.
-        */
-       if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE)
-               pc->flags = PAGE_CGROUP_FLAG_CACHE;
-       else
-               pc->flags = PAGE_CGROUP_FLAG_ACTIVE;
 
-       lock_page_cgroup(page);
-       if (unlikely(page_get_page_cgroup(page))) {
-               unlock_page_cgroup(page);
+       lock_page_cgroup(pc);
+       if (unlikely(PageCgroupUsed(pc))) {
+               unlock_page_cgroup(pc);
                res_counter_uncharge(&mem->res, PAGE_SIZE);
                css_put(&mem->css);
-               kmem_cache_free(page_cgroup_cache, pc);
+
                goto done;
        }
-       page_assign_page_cgroup(page, pc);
+       pc->mem_cgroup = mem;
+       /*
+        * If a page is accounted as a page cache, insert to inactive list.
+        * If anon, insert to active list.
+        */
+       pc->flags = pcg_default_flags[ctype];
 
        mz = page_cgroup_zoneinfo(pc);
+
        spin_lock_irqsave(&mz->lru_lock, flags);
        __mem_cgroup_add_list(mz, pc);
        spin_unlock_irqrestore(&mz->lru_lock, flags);
+       unlock_page_cgroup(pc);
 
-       unlock_page_cgroup(page);
 done:
        return 0;
 out:
        css_put(&mem->css);
-       kmem_cache_free(page_cgroup_cache, pc);
-err:
        return -ENOMEM;
 }
 
@@ -635,7 +569,8 @@ int mem_cgroup_charge(struct page *page, struct mm_struct *mm, gfp_t gfp_mask)
 {
        if (mem_cgroup_subsys.disabled)
                return 0;
-
+       if (PageCompound(page))
+               return 0;
        /*
         * If already mapped, we don't have to account.
         * If page cache, page->mapping has address_space.
@@ -656,7 +591,8 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
 {
        if (mem_cgroup_subsys.disabled)
                return 0;
-
+       if (PageCompound(page))
+               return 0;
        /*
         * Corner case handling. This is called from add_to_page_cache()
         * in usual. But some FS (shmem) precharges this page before calling it
@@ -669,22 +605,27 @@ int mem_cgroup_cache_charge(struct page *page, struct mm_struct *mm,
        if (!(gfp_mask & __GFP_WAIT)) {
                struct page_cgroup *pc;
 
-               lock_page_cgroup(page);
-               pc = page_get_page_cgroup(page);
-               if (pc) {
-                       VM_BUG_ON(pc->page != page);
-                       VM_BUG_ON(!pc->mem_cgroup);
-                       unlock_page_cgroup(page);
+
+               pc = lookup_page_cgroup(page);
+               if (!pc)
+                       return 0;
+               lock_page_cgroup(pc);
+               if (PageCgroupUsed(pc)) {
+                       unlock_page_cgroup(pc);
                        return 0;
                }
-               unlock_page_cgroup(page);
+               unlock_page_cgroup(pc);
        }
 
        if (unlikely(!mm))
                mm = &init_mm;
 
-       return mem_cgroup_charge_common(page, mm, gfp_mask,
+       if (page_is_file_cache(page))
+               return mem_cgroup_charge_common(page, mm, gfp_mask,
                                MEM_CGROUP_CHARGE_TYPE_CACHE, NULL);
+       else
+               return mem_cgroup_charge_common(page, mm, gfp_mask,
+                               MEM_CGROUP_CHARGE_TYPE_SHMEM, NULL);
 }
 
 /*
@@ -704,44 +645,46 @@ __mem_cgroup_uncharge_common(struct page *page, enum charge_type ctype)
        /*
         * Check if our page_cgroup is valid
         */
-       lock_page_cgroup(page);
-       pc = page_get_page_cgroup(page);
-       if (unlikely(!pc))
-               goto unlock;
-
-       VM_BUG_ON(pc->page != page);
+       pc = lookup_page_cgroup(page);
+       if (unlikely(!pc || !PageCgroupUsed(pc)))
+               return;
 
-       if ((ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED)
-           && ((pc->flags & PAGE_CGROUP_FLAG_CACHE)
-               || page_mapped(page)))
-               goto unlock;
+       lock_page_cgroup(pc);
+       if ((ctype == MEM_CGROUP_CHARGE_TYPE_MAPPED && page_mapped(page))
+            || !PageCgroupUsed(pc)) {
+               /* This happens at race in zap_pte_range() and do_swap_page()*/
+               unlock_page_cgroup(pc);
+               return;
+       }
+       ClearPageCgroupUsed(pc);
+       mem = pc->mem_cgroup;
 
        mz = page_cgroup_zoneinfo(pc);
        spin_lock_irqsave(&mz->lru_lock, flags);
        __mem_cgroup_remove_list(mz, pc);
        spin_unlock_irqrestore(&mz->lru_lock, flags);
+       unlock_page_cgroup(pc);
 
-       page_assign_page_cgroup(page, NULL);
-       unlock_page_cgroup(page);
-
-       mem = pc->mem_cgroup;
        res_counter_uncharge(&mem->res, PAGE_SIZE);
        css_put(&mem->css);
 
-       kmem_cache_free(page_cgroup_cache, pc);
        return;
-unlock:
-       unlock_page_cgroup(page);
 }
 
 void mem_cgroup_uncharge_page(struct page *page)
 {
+       /* early check. */
+       if (page_mapped(page))
+               return;
+       if (page->mapping && !PageAnon(page))
+               return;
        __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_MAPPED);
 }
 
 void mem_cgroup_uncharge_cache_page(struct page *page)
 {
        VM_BUG_ON(page_mapped(page));
+       VM_BUG_ON(page->mapping);
        __mem_cgroup_uncharge_common(page, MEM_CGROUP_CHARGE_TYPE_CACHE);
 }
 
@@ -758,15 +701,19 @@ int mem_cgroup_prepare_migration(struct page *page, struct page *newpage)
        if (mem_cgroup_subsys.disabled)
                return 0;
 
-       lock_page_cgroup(page);
-       pc = page_get_page_cgroup(page);
-       if (pc) {
+       pc = lookup_page_cgroup(page);
+       lock_page_cgroup(pc);
+       if (PageCgroupUsed(pc)) {
                mem = pc->mem_cgroup;
                css_get(&mem->css);
-               if (pc->flags & PAGE_CGROUP_FLAG_CACHE)
-                       ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
+               if (PageCgroupCache(pc)) {
+                       if (page_is_file_cache(page))
+                               ctype = MEM_CGROUP_CHARGE_TYPE_CACHE;
+                       else
+                               ctype = MEM_CGROUP_CHARGE_TYPE_SHMEM;
+               }
        }
-       unlock_page_cgroup(page);
+       unlock_page_cgroup(pc);
        if (mem) {
                ret = mem_cgroup_charge_common(newpage, NULL, GFP_KERNEL,
                        ctype, mem);
@@ -791,7 +738,7 @@ void mem_cgroup_end_migration(struct page *newpage)
         */
        if (!newpage->mapping)
                __mem_cgroup_uncharge_common(newpage,
-                                        MEM_CGROUP_CHARGE_TYPE_FORCE);
+                               MEM_CGROUP_CHARGE_TYPE_FORCE);
        else if (PageAnon(newpage))
                mem_cgroup_uncharge_page(newpage);
 }
@@ -863,7 +810,7 @@ int mem_cgroup_resize_limit(struct mem_cgroup *memcg, unsigned long long val)
 #define FORCE_UNCHARGE_BATCH   (128)
 static void mem_cgroup_force_empty_list(struct mem_cgroup *mem,
                            struct mem_cgroup_per_zone *mz,
-                           int active)
+                           enum lru_list lru)
 {
        struct page_cgroup *pc;
        struct page *page;
@@ -871,15 +818,14 @@ static void mem_cgroup_force_empty_list(struct mem_cgroup *mem,
        unsigned long flags;
        struct list_head *list;
 
-       if (active)
-               list = &mz->active_list;
-       else
-               list = &mz->inactive_list;
+       list = &mz->lists[lru];
 
        spin_lock_irqsave(&mz->lru_lock, flags);
        while (!list_empty(list)) {
                pc = list_entry(list->prev, struct page_cgroup, lru);
                page = pc->page;
+               if (!PageCgroupUsed(pc))
+                       break;
                get_page(page);
                spin_unlock_irqrestore(&mz->lru_lock, flags);
                /*
@@ -894,8 +840,10 @@ static void mem_cgroup_force_empty_list(struct mem_cgroup *mem,
                                count = FORCE_UNCHARGE_BATCH;
                                cond_resched();
                        }
-               } else
-                       cond_resched();
+               } else {
+                       spin_lock_irqsave(&mz->lru_lock, flags);
+                       break;
+               }
                spin_lock_irqsave(&mz->lru_lock, flags);
        }
        spin_unlock_irqrestore(&mz->lru_lock, flags);
@@ -919,15 +867,17 @@ static int mem_cgroup_force_empty(struct mem_cgroup *mem)
        while (mem->res.usage > 0) {
                if (atomic_read(&mem->css.cgroup->count) > 0)
                        goto out;
+               /* This is for making all *used* pages to be on LRU. */
+               lru_add_drain_all();
                for_each_node_state(node, N_POSSIBLE)
                        for (zid = 0; zid < MAX_NR_ZONES; zid++) {
                                struct mem_cgroup_per_zone *mz;
+                               enum lru_list l;
                                mz = mem_cgroup_zoneinfo(mem, node, zid);
-                               /* drop all page_cgroup in active_list */
-                               mem_cgroup_force_empty_list(mem, mz, 1);
-                               /* drop all page_cgroup in inactive_list */
-                               mem_cgroup_force_empty_list(mem, mz, 0);
+                               for_each_lru(l)
+                                       mem_cgroup_force_empty_list(mem, mz, l);
                        }
+               cond_resched();
        }
        ret = 0;
 out:
@@ -1012,14 +962,27 @@ static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft,
        }
        /* showing # of active pages */
        {
-               unsigned long active, inactive;
-
-               inactive = mem_cgroup_get_all_zonestat(mem_cont,
-                                               MEM_CGROUP_ZSTAT_INACTIVE);
-               active = mem_cgroup_get_all_zonestat(mem_cont,
-                                               MEM_CGROUP_ZSTAT_ACTIVE);
-               cb->fill(cb, "active", (active) * PAGE_SIZE);
-               cb->fill(cb, "inactive", (inactive) * PAGE_SIZE);
+               unsigned long active_anon, inactive_anon;
+               unsigned long active_file, inactive_file;
+               unsigned long unevictable;
+
+               inactive_anon = mem_cgroup_get_all_zonestat(mem_cont,
+                                               LRU_INACTIVE_ANON);
+               active_anon = mem_cgroup_get_all_zonestat(mem_cont,
+                                               LRU_ACTIVE_ANON);
+               inactive_file = mem_cgroup_get_all_zonestat(mem_cont,
+                                               LRU_INACTIVE_FILE);
+               active_file = mem_cgroup_get_all_zonestat(mem_cont,
+                                               LRU_ACTIVE_FILE);
+               unevictable = mem_cgroup_get_all_zonestat(mem_cont,
+                                                       LRU_UNEVICTABLE);
+
+               cb->fill(cb, "active_anon", (active_anon) * PAGE_SIZE);
+               cb->fill(cb, "inactive_anon", (inactive_anon) * PAGE_SIZE);
+               cb->fill(cb, "active_file", (active_file) * PAGE_SIZE);
+               cb->fill(cb, "inactive_file", (inactive_file) * PAGE_SIZE);
+               cb->fill(cb, "unevictable", unevictable * PAGE_SIZE);
+
        }
        return 0;
 }
@@ -1062,6 +1025,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
 {
        struct mem_cgroup_per_node *pn;
        struct mem_cgroup_per_zone *mz;
+       enum lru_list l;
        int zone, tmp = node;
        /*
         * This routine is called against possible nodes.
@@ -1082,9 +1046,9 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node)
 
        for (zone = 0; zone < MAX_NR_ZONES; zone++) {
                mz = &pn->zoneinfo[zone];
-               INIT_LIST_HEAD(&mz->active_list);
-               INIT_LIST_HEAD(&mz->inactive_list);
                spin_lock_init(&mz->lru_lock);
+               for_each_lru(l)
+                       INIT_LIST_HEAD(&mz->lists[l]);
        }
        return 0;
 }
@@ -1124,8 +1088,8 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont)
        int node;
 
        if (unlikely((cont->parent) == NULL)) {
+               page_cgroup_init();
                mem = &init_mem_cgroup;
-               page_cgroup_cache = KMEM_CACHE(page_cgroup, SLAB_PANIC);
        } else {
                mem = mem_cgroup_alloc();
                if (!mem)
index 1002f473f497c37f34c5c33d4dfa7d2bd49faed0..3a6c4a6583256584303c4ac7c8813938abc49ed0 100644 (file)
@@ -64,6 +64,8 @@
 
 #include "internal.h"
 
+#include "internal.h"
+
 #ifndef CONFIG_NEED_MULTIPLE_NODES
 /* use the per-pgdat data instead for discontigmem - mbligh */
 unsigned long max_mapnr;
@@ -1129,12 +1131,17 @@ static inline int use_zero_page(struct vm_area_struct *vma)
        return !vma->vm_ops || !vma->vm_ops->fault;
 }
 
-int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-               unsigned long start, int len, int write, int force,
+
+
+int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+                    unsigned long start, int len, int flags,
                struct page **pages, struct vm_area_struct **vmas)
 {
        int i;
-       unsigned int vm_flags;
+       unsigned int vm_flags = 0;
+       int write = !!(flags & GUP_FLAGS_WRITE);
+       int force = !!(flags & GUP_FLAGS_FORCE);
+       int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS);
 
        if (len <= 0)
                return 0;
@@ -1158,7 +1165,9 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        pud_t *pud;
                        pmd_t *pmd;
                        pte_t *pte;
-                       if (write) /* user gate pages are read-only */
+
+                       /* user gate pages are read-only */
+                       if (!ignore && write)
                                return i ? : -EFAULT;
                        if (pg > TASK_SIZE)
                                pgd = pgd_offset_k(pg);
@@ -1190,8 +1199,9 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        continue;
                }
 
-               if (!vma || (vma->vm_flags & (VM_IO | VM_PFNMAP))
-                               || !(vm_flags & vma->vm_flags))
+               if (!vma ||
+                   (vma->vm_flags & (VM_IO | VM_PFNMAP)) ||
+                   (!ignore && !(vm_flags & vma->vm_flags)))
                        return i ? : -EFAULT;
 
                if (is_vm_hugetlb_page(vma)) {
@@ -1266,6 +1276,23 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
        } while (len);
        return i;
 }
+
+int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+               unsigned long start, int len, int write, int force,
+               struct page **pages, struct vm_area_struct **vmas)
+{
+       int flags = 0;
+
+       if (write)
+               flags |= GUP_FLAGS_WRITE;
+       if (force)
+               flags |= GUP_FLAGS_FORCE;
+
+       return __get_user_pages(tsk, mm,
+                               start, len, flags,
+                               pages, vmas);
+}
+
 EXPORT_SYMBOL(get_user_pages);
 
 pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr,
@@ -1296,18 +1323,14 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
        pte_t *pte;
        spinlock_t *ptl;
 
-       retval = mem_cgroup_charge(page, mm, GFP_KERNEL);
-       if (retval)
-               goto out;
-
        retval = -EINVAL;
        if (PageAnon(page))
-               goto out_uncharge;
+               goto out;
        retval = -ENOMEM;
        flush_dcache_page(page);
        pte = get_locked_pte(mm, addr, &ptl);
        if (!pte)
-               goto out_uncharge;
+               goto out;
        retval = -EBUSY;
        if (!pte_none(*pte))
                goto out_unlock;
@@ -1323,8 +1346,6 @@ static int insert_page(struct vm_area_struct *vma, unsigned long addr,
        return retval;
 out_unlock:
        pte_unmap_unlock(pte, ptl);
-out_uncharge:
-       mem_cgroup_uncharge_page(page);
 out:
        return retval;
 }
@@ -1858,6 +1879,15 @@ gotten:
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address);
        if (!new_page)
                goto oom;
+       /*
+        * Don't let another task, with possibly unlocked vma,
+        * keep the mlocked page.
+        */
+       if (vma->vm_flags & VM_LOCKED) {
+               lock_page(old_page);    /* for LRU manipulation */
+               clear_page_mlock(old_page);
+               unlock_page(old_page);
+       }
        cow_user_page(new_page, old_page, address, vma);
        __SetPageUptodate(new_page);
 
@@ -1886,11 +1916,13 @@ gotten:
                 * thread doing COW.
                 */
                ptep_clear_flush_notify(vma, address, page_table);
-               set_pte_at(mm, address, page_table, entry);
-               update_mmu_cache(vma, address, entry);
-               lru_cache_add_active(new_page);
+               SetPageSwapBacked(new_page);
+               lru_cache_add_active_or_unevictable(new_page, vma);
                page_add_new_anon_rmap(new_page, vma, address);
 
+//TODO:  is this safe?  do_anonymous_page() does it this way.
+               set_pte_at(mm, address, page_table, entry);
+               update_mmu_cache(vma, address, entry);
                if (old_page) {
                        /*
                         * Only after switching the pte to the new page may
@@ -2288,16 +2320,17 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
                count_vm_event(PGMAJFAULT);
        }
 
+       mark_page_accessed(page);
+
+       lock_page(page);
+       delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
+
        if (mem_cgroup_charge(page, mm, GFP_KERNEL)) {
-               delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
                ret = VM_FAULT_OOM;
+               unlock_page(page);
                goto out;
        }
 
-       mark_page_accessed(page);
-       lock_page(page);
-       delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
-
        /*
         * Back out if somebody else already faulted in this pte.
         */
@@ -2324,7 +2357,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma,
        page_add_anon_rmap(page, vma, address);
 
        swap_free(entry);
-       if (vm_swap_full())
+       if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
                remove_exclusive_swap_page(page);
        unlock_page(page);
 
@@ -2382,7 +2415,8 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
        if (!pte_none(*page_table))
                goto release;
        inc_mm_counter(mm, anon_rss);
-       lru_cache_add_active(page);
+       SetPageSwapBacked(page);
+       lru_cache_add_active_or_unevictable(page, vma);
        page_add_new_anon_rmap(page, vma, address);
        set_pte_at(mm, address, page_table, entry);
 
@@ -2423,6 +2457,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
        struct page *page;
        pte_t entry;
        int anon = 0;
+       int charged = 0;
        struct page *dirty_page = NULL;
        struct vm_fault vmf;
        int ret;
@@ -2463,6 +2498,18 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                                ret = VM_FAULT_OOM;
                                goto out;
                        }
+                       if (mem_cgroup_charge(page, mm, GFP_KERNEL)) {
+                               ret = VM_FAULT_OOM;
+                               page_cache_release(page);
+                               goto out;
+                       }
+                       charged = 1;
+                       /*
+                        * Don't let another task, with possibly unlocked vma,
+                        * keep the mlocked page.
+                        */
+                       if (vma->vm_flags & VM_LOCKED)
+                               clear_page_mlock(vmf.page);
                        copy_user_highpage(page, vmf.page, address, vma);
                        __SetPageUptodate(page);
                } else {
@@ -2497,11 +2544,6 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
        }
 
-       if (mem_cgroup_charge(page, mm, GFP_KERNEL)) {
-               ret = VM_FAULT_OOM;
-               goto out;
-       }
-
        page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
 
        /*
@@ -2520,11 +2562,11 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                entry = mk_pte(page, vma->vm_page_prot);
                if (flags & FAULT_FLAG_WRITE)
                        entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-               set_pte_at(mm, address, page_table, entry);
                if (anon) {
-                        inc_mm_counter(mm, anon_rss);
-                        lru_cache_add_active(page);
-                        page_add_new_anon_rmap(page, vma, address);
+                       inc_mm_counter(mm, anon_rss);
+                       SetPageSwapBacked(page);
+                       lru_cache_add_active_or_unevictable(page, vma);
+                       page_add_new_anon_rmap(page, vma, address);
                } else {
                        inc_mm_counter(mm, file_rss);
                        page_add_file_rmap(page);
@@ -2533,11 +2575,14 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                                get_page(dirty_page);
                        }
                }
+//TODO:  is this safe?  do_anonymous_page() does it this way.
+               set_pte_at(mm, address, page_table, entry);
 
                /* no need to invalidate: a not-present page won't be cached */
                update_mmu_cache(vma, address, entry);
        } else {
-               mem_cgroup_uncharge_page(page);
+               if (charged)
+                       mem_cgroup_uncharge_page(page);
                if (anon)
                        page_cache_release(page);
                else
@@ -2772,19 +2817,9 @@ int make_pages_present(unsigned long addr, unsigned long end)
        len = DIV_ROUND_UP(end, PAGE_SIZE) - addr/PAGE_SIZE;
        ret = get_user_pages(current, current->mm, addr,
                        len, write, 0, NULL, NULL);
-       if (ret < 0) {
-               /*
-                  SUS require strange return value to mlock
-                   - invalid addr generate to ENOMEM.
-                   - out of memory should generate EAGAIN.
-               */
-               if (ret == -EFAULT)
-                       ret = -ENOMEM;
-               else if (ret == -ENOMEM)
-                       ret = -EAGAIN;
+       if (ret < 0)
                return ret;
-       }
-       return ret == len ? 0 : -ENOMEM;
+       return ret == len ? 0 : -EFAULT;
 }
 
 #if !defined(__HAVE_ARCH_GATE_AREA)
index 89fee2dcb03928594ca2da67e9b75e7c8507394b..6837a1014372556c7dd78d66d9ba9ea9cb931832 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/delay.h>
 #include <linux/migrate.h>
 #include <linux/page-isolation.h>
+#include <linux/pfn.h>
 
 #include <asm/tlbflush.h>
 
@@ -323,11 +324,11 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn,
        BUG_ON(phys_start_pfn & ~PAGE_SECTION_MASK);
        BUG_ON(nr_pages % PAGES_PER_SECTION);
 
-       release_mem_region(phys_start_pfn << PAGE_SHIFT, nr_pages * PAGE_SIZE);
-
        sections_to_remove = nr_pages / PAGES_PER_SECTION;
        for (i = 0; i < sections_to_remove; i++) {
                unsigned long pfn = phys_start_pfn + i*PAGES_PER_SECTION;
+               release_mem_region(pfn << PAGE_SHIFT,
+                                  PAGES_PER_SECTION << PAGE_SHIFT);
                ret = __remove_section(zone, __pfn_to_section(pfn));
                if (ret)
                        break;
@@ -657,8 +658,9 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                 * We can skip free pages. And we can only deal with pages on
                 * LRU.
                 */
-               ret = isolate_lru_page(page, &source);
+               ret = isolate_lru_page(page);
                if (!ret) { /* Success */
+                       list_add_tail(&page->lru, &source);
                        move_pages--;
                } else {
                        /* Becasue we don't have big zone->lock. we should
@@ -849,10 +851,19 @@ failed_removal:
 
        return ret;
 }
+
+int remove_memory(u64 start, u64 size)
+{
+       unsigned long start_pfn, end_pfn;
+
+       start_pfn = PFN_DOWN(start);
+       end_pfn = start_pfn + PFN_DOWN(size);
+       return offline_pages(start_pfn, end_pfn, 120 * HZ);
+}
 #else
 int remove_memory(u64 start, u64 size)
 {
        return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(remove_memory);
 #endif /* CONFIG_MEMORY_HOTREMOVE */
+EXPORT_SYMBOL_GPL(remove_memory);
index 83369058ec133b380a482ca86792087134b944f6..36f42573a3352fa6ba452eea2d76ed2021c8605c 100644 (file)
@@ -93,6 +93,8 @@
 #include <asm/tlbflush.h>
 #include <asm/uaccess.h>
 
+#include "internal.h"
+
 /* Internal flags */
 #define MPOL_MF_DISCONTIG_OK (MPOL_MF_INTERNAL << 0)   /* Skip checks for continuous vmas */
 #define MPOL_MF_INVERT (MPOL_MF_INTERNAL << 1)         /* Invert check for nodemask */
@@ -762,8 +764,11 @@ static void migrate_page_add(struct page *page, struct list_head *pagelist,
        /*
         * Avoid migrating a page that is shared with others.
         */
-       if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1)
-               isolate_lru_page(page, pagelist);
+       if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) == 1) {
+               if (!isolate_lru_page(page)) {
+                       list_add_tail(&page->lru, pagelist);
+               }
+       }
 }
 
 static struct page *new_node_page(struct page *page, unsigned long node, int **x)
@@ -2197,7 +2202,7 @@ static void gather_stats(struct page *page, void *private, int pte_dirty)
        if (PageSwapCache(page))
                md->swapcache++;
 
-       if (PageActive(page))
+       if (PageActive(page) || PageUnevictable(page))
                md->active++;
 
        if (PageWriteback(page))
index 2a80136b23bbc16fb9d2ec2fad932b29e30dda50..6602941bfab0b03607f9bce6dd8e3f9ce1046bfe 100644 (file)
 
 #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
 
-/*
- * Isolate one page from the LRU lists. If successful put it onto
- * the indicated list with elevated page count.
- *
- * Result:
- *  -EBUSY: page not on LRU list
- *  0: page removed from LRU list and added to the specified list.
- */
-int isolate_lru_page(struct page *page, struct list_head *pagelist)
-{
-       int ret = -EBUSY;
-
-       if (PageLRU(page)) {
-               struct zone *zone = page_zone(page);
-
-               spin_lock_irq(&zone->lru_lock);
-               if (PageLRU(page) && get_page_unless_zero(page)) {
-                       ret = 0;
-                       ClearPageLRU(page);
-                       if (PageActive(page))
-                               del_page_from_active_list(zone, page);
-                       else
-                               del_page_from_inactive_list(zone, page);
-                       list_add_tail(&page->lru, pagelist);
-               }
-               spin_unlock_irq(&zone->lru_lock);
-       }
-       return ret;
-}
-
 /*
  * migrate_prep() needs to be called before we start compiling a list of pages
  * to be migrated using isolate_lru_page().
@@ -83,23 +53,9 @@ int migrate_prep(void)
        return 0;
 }
 
-static inline void move_to_lru(struct page *page)
-{
-       if (PageActive(page)) {
-               /*
-                * lru_cache_add_active checks that
-                * the PG_active bit is off.
-                */
-               ClearPageActive(page);
-               lru_cache_add_active(page);
-       } else {
-               lru_cache_add(page);
-       }
-       put_page(page);
-}
-
 /*
- * Add isolated pages on the list back to the LRU.
+ * Add isolated pages on the list back to the LRU under page lock
+ * to avoid leaking evictable pages back onto unevictable list.
  *
  * returns the number of pages put back.
  */
@@ -111,7 +67,7 @@ int putback_lru_pages(struct list_head *l)
 
        list_for_each_entry_safe(page, page2, l, lru) {
                list_del(&page->lru);
-               move_to_lru(page);
+               putback_lru_page(page);
                count++;
        }
        return count;
@@ -374,8 +330,6 @@ static int migrate_page_move_mapping(struct address_space *mapping,
        __inc_zone_page_state(newpage, NR_FILE_PAGES);
 
        spin_unlock_irq(&mapping->tree_lock);
-       if (!PageSwapCache(newpage))
-               mem_cgroup_uncharge_cache_page(page);
 
        return 0;
 }
@@ -385,6 +339,8 @@ static int migrate_page_move_mapping(struct address_space *mapping,
  */
 static void migrate_page_copy(struct page *newpage, struct page *page)
 {
+       int anon;
+
        copy_highpage(newpage, page);
 
        if (PageError(page))
@@ -393,8 +349,11 @@ static void migrate_page_copy(struct page *newpage, struct page *page)
                SetPageReferenced(newpage);
        if (PageUptodate(page))
                SetPageUptodate(newpage);
-       if (PageActive(page))
+       if (TestClearPageActive(page)) {
+               VM_BUG_ON(PageUnevictable(page));
                SetPageActive(newpage);
+       } else
+               unevictable_migrate_page(newpage, page);
        if (PageChecked(page))
                SetPageChecked(newpage);
        if (PageMappedToDisk(page))
@@ -412,14 +371,20 @@ static void migrate_page_copy(struct page *newpage, struct page *page)
                __set_page_dirty_nobuffers(newpage);
        }
 
+       mlock_migrate_page(newpage, page);
+
 #ifdef CONFIG_SWAP
        ClearPageSwapCache(page);
 #endif
-       ClearPageActive(page);
        ClearPagePrivate(page);
        set_page_private(page, 0);
+       /* page->mapping contains a flag for PageAnon() */
+       anon = PageAnon(page);
        page->mapping = NULL;
 
+       if (!anon) /* This page was removed from radix-tree. */
+               mem_cgroup_uncharge_cache_page(page);
+
        /*
         * If any waiters have accumulated on the new page then
         * wake them up.
@@ -594,6 +559,10 @@ static int fallback_migrate_page(struct address_space *mapping,
  *
  * The new page will have replaced the old page if this function
  * is successful.
+ *
+ * Return value:
+ *   < 0 - error code
+ *  == 0 - success
  */
 static int move_to_new_page(struct page *newpage, struct page *page)
 {
@@ -611,6 +580,8 @@ static int move_to_new_page(struct page *newpage, struct page *page)
        /* Prepare mapping for the new page.*/
        newpage->index = page->index;
        newpage->mapping = page->mapping;
+       if (PageSwapBacked(page))
+               SetPageSwapBacked(newpage);
 
        mapping = page_mapping(page);
        if (!mapping)
@@ -654,9 +625,10 @@ static int unmap_and_move(new_page_t get_new_page, unsigned long private,
        if (!newpage)
                return -ENOMEM;
 
-       if (page_count(page) == 1)
+       if (page_count(page) == 1) {
                /* page was freed from under us. So we are done. */
                goto move_newpage;
+       }
 
        charge = mem_cgroup_prepare_migration(page, newpage);
        if (charge == -ENOMEM) {
@@ -730,7 +702,6 @@ rcu_unlock:
                rcu_read_unlock();
 
 unlock:
-
        unlock_page(page);
 
        if (rc != -EAGAIN) {
@@ -741,17 +712,19 @@ unlock:
                 * restored.
                 */
                list_del(&page->lru);
-               move_to_lru(page);
+               putback_lru_page(page);
        }
 
 move_newpage:
        if (!charge)
                mem_cgroup_end_migration(newpage);
+
        /*
         * Move the new page to the LRU. If migration was not successful
         * then this will free the page.
         */
-       move_to_lru(newpage);
+       putback_lru_page(newpage);
+
        if (result) {
                if (rc)
                        *result = rc;
@@ -858,9 +831,11 @@ static struct page *new_page_node(struct page *p, unsigned long private,
  * Move a set of pages as indicated in the pm array. The addr
  * field must be set to the virtual address of the page to be moved
  * and the node number must contain a valid target node.
+ * The pm array ends with node = MAX_NUMNODES.
  */
-static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm,
-                               int migrate_all)
+static int do_move_page_to_node_array(struct mm_struct *mm,
+                                     struct page_to_node *pm,
+                                     int migrate_all)
 {
        int err;
        struct page_to_node *pp;
@@ -914,7 +889,9 @@ static int do_move_pages(struct mm_struct *mm, struct page_to_node *pm,
                                !migrate_all)
                        goto put_and_set;
 
-               err = isolate_lru_page(page, &pagelist);
+               err = isolate_lru_page(page);
+               if (!err)
+                       list_add_tail(&page->lru, &pagelist);
 put_and_set:
                /*
                 * Either remove the duplicate refcount from
@@ -926,36 +903,118 @@ set_status:
                pp->status = err;
        }
 
+       err = 0;
        if (!list_empty(&pagelist))
                err = migrate_pages(&pagelist, new_page_node,
                                (unsigned long)pm);
-       else
-               err = -ENOENT;
 
        up_read(&mm->mmap_sem);
        return err;
 }
 
 /*
- * Determine the nodes of a list of pages. The addr in the pm array
- * must have been set to the virtual address of which we want to determine
- * the node number.
+ * Migrate an array of page address onto an array of nodes and fill
+ * the corresponding array of status.
  */
-static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm)
+static int do_pages_move(struct mm_struct *mm, struct task_struct *task,
+                        unsigned long nr_pages,
+                        const void __user * __user *pages,
+                        const int __user *nodes,
+                        int __user *status, int flags)
 {
+       struct page_to_node *pm = NULL;
+       nodemask_t task_nodes;
+       int err = 0;
+       int i;
+
+       task_nodes = cpuset_mems_allowed(task);
+
+       /* Limit nr_pages so that the multiplication may not overflow */
+       if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) {
+               err = -E2BIG;
+               goto out;
+       }
+
+       pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node));
+       if (!pm) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /*
+        * Get parameters from user space and initialize the pm
+        * array. Return various errors if the user did something wrong.
+        */
+       for (i = 0; i < nr_pages; i++) {
+               const void __user *p;
+
+               err = -EFAULT;
+               if (get_user(p, pages + i))
+                       goto out_pm;
+
+               pm[i].addr = (unsigned long)p;
+               if (nodes) {
+                       int node;
+
+                       if (get_user(node, nodes + i))
+                               goto out_pm;
+
+                       err = -ENODEV;
+                       if (!node_state(node, N_HIGH_MEMORY))
+                               goto out_pm;
+
+                       err = -EACCES;
+                       if (!node_isset(node, task_nodes))
+                               goto out_pm;
+
+                       pm[i].node = node;
+               } else
+                       pm[i].node = 0; /* anything to not match MAX_NUMNODES */
+       }
+       /* End marker */
+       pm[nr_pages].node = MAX_NUMNODES;
+
+       err = do_move_page_to_node_array(mm, pm, flags & MPOL_MF_MOVE_ALL);
+       if (err >= 0)
+               /* Return status information */
+               for (i = 0; i < nr_pages; i++)
+                       if (put_user(pm[i].status, status + i))
+                               err = -EFAULT;
+
+out_pm:
+       vfree(pm);
+out:
+       return err;
+}
+
+/*
+ * Determine the nodes of an array of pages and store it in an array of status.
+ */
+static int do_pages_stat(struct mm_struct *mm, unsigned long nr_pages,
+                        const void __user * __user *pages,
+                        int __user *status)
+{
+       unsigned long i;
+       int err;
+
        down_read(&mm->mmap_sem);
 
-       for ( ; pm->node != MAX_NUMNODES; pm++) {
+       for (i = 0; i < nr_pages; i++) {
+               const void __user *p;
+               unsigned long addr;
                struct vm_area_struct *vma;
                struct page *page;
-               int err;
 
                err = -EFAULT;
-               vma = find_vma(mm, pm->addr);
+               if (get_user(p, pages+i))
+                       goto out;
+               addr = (unsigned long) p;
+
+               vma = find_vma(mm, addr);
                if (!vma)
                        goto set_status;
 
-               page = follow_page(vma, pm->addr, 0);
+               page = follow_page(vma, addr, 0);
 
                err = PTR_ERR(page);
                if (IS_ERR(page))
@@ -968,11 +1027,13 @@ static int do_pages_stat(struct mm_struct *mm, struct page_to_node *pm)
 
                err = page_to_nid(page);
 set_status:
-               pm->status = err;
+               put_user(err, status+i);
        }
+       err = 0;
 
+out:
        up_read(&mm->mmap_sem);
-       return 0;
+       return err;
 }
 
 /*
@@ -984,12 +1045,9 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
                        const int __user *nodes,
                        int __user *status, int flags)
 {
-       int err = 0;
-       int i;
        struct task_struct *task;
-       nodemask_t task_nodes;
        struct mm_struct *mm;
-       struct page_to_node *pm = NULL;
+       int err;
 
        /* Check flags */
        if (flags & ~(MPOL_MF_MOVE|MPOL_MF_MOVE_ALL))
@@ -1021,75 +1079,21 @@ asmlinkage long sys_move_pages(pid_t pid, unsigned long nr_pages,
            (current->uid != task->suid) && (current->uid != task->uid) &&
            !capable(CAP_SYS_NICE)) {
                err = -EPERM;
-               goto out2;
+               goto out;
        }
 
        err = security_task_movememory(task);
        if (err)
-               goto out2;
-
-
-       task_nodes = cpuset_mems_allowed(task);
-
-       /* Limit nr_pages so that the multiplication may not overflow */
-       if (nr_pages >= ULONG_MAX / sizeof(struct page_to_node) - 1) {
-               err = -E2BIG;
-               goto out2;
-       }
-
-       pm = vmalloc((nr_pages + 1) * sizeof(struct page_to_node));
-       if (!pm) {
-               err = -ENOMEM;
-               goto out2;
-       }
-
-       /*
-        * Get parameters from user space and initialize the pm
-        * array. Return various errors if the user did something wrong.
-        */
-       for (i = 0; i < nr_pages; i++) {
-               const void __user *p;
-
-               err = -EFAULT;
-               if (get_user(p, pages + i))
-                       goto out;
-
-               pm[i].addr = (unsigned long)p;
-               if (nodes) {
-                       int node;
-
-                       if (get_user(node, nodes + i))
-                               goto out;
-
-                       err = -ENODEV;
-                       if (!node_state(node, N_HIGH_MEMORY))
-                               goto out;
-
-                       err = -EACCES;
-                       if (!node_isset(node, task_nodes))
-                               goto out;
+               goto out;
 
-                       pm[i].node = node;
-               } else
-                       pm[i].node = 0; /* anything to not match MAX_NUMNODES */
+       if (nodes) {
+               err = do_pages_move(mm, task, nr_pages, pages, nodes, status,
+                                   flags);
+       } else {
+               err = do_pages_stat(mm, nr_pages, pages, status);
        }
-       /* End marker */
-       pm[nr_pages].node = MAX_NUMNODES;
-
-       if (nodes)
-               err = do_move_pages(mm, pm, flags & MPOL_MF_MOVE_ALL);
-       else
-               err = do_pages_stat(mm, pm);
-
-       if (err >= 0)
-               /* Return status information */
-               for (i = 0; i < nr_pages; i++)
-                       if (put_user(pm[i].status, status + i))
-                               err = -EFAULT;
 
 out:
-       vfree(pm);
-out2:
        mmput(mm);
        return err;
 }
index 01fbe93eff5ca25f1143b1295da6ce7115e00bde..008ea70b7afa9a2baed56cdc9b6b43ef0b05a6ff 100644 (file)
@@ -8,10 +8,18 @@
 #include <linux/capability.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
+#include <linux/pagemap.h>
 #include <linux/mempolicy.h>
 #include <linux/syscalls.h>
 #include <linux/sched.h>
 #include <linux/module.h>
+#include <linux/rmap.h>
+#include <linux/mmzone.h>
+#include <linux/hugetlb.h>
+
+#include "internal.h"
 
 int can_do_mlock(void)
 {
@@ -23,17 +31,381 @@ int can_do_mlock(void)
 }
 EXPORT_SYMBOL(can_do_mlock);
 
+#ifdef CONFIG_UNEVICTABLE_LRU
+/*
+ * Mlocked pages are marked with PageMlocked() flag for efficient testing
+ * in vmscan and, possibly, the fault path; and to support semi-accurate
+ * statistics.
+ *
+ * An mlocked page [PageMlocked(page)] is unevictable.  As such, it will
+ * be placed on the LRU "unevictable" list, rather than the [in]active lists.
+ * The unevictable list is an LRU sibling list to the [in]active lists.
+ * PageUnevictable is set to indicate the unevictable state.
+ *
+ * When lazy mlocking via vmscan, it is important to ensure that the
+ * vma's VM_LOCKED status is not concurrently being modified, otherwise we
+ * may have mlocked a page that is being munlocked. So lazy mlock must take
+ * the mmap_sem for read, and verify that the vma really is locked
+ * (see mm/rmap.c).
+ */
+
+/*
+ *  LRU accounting for clear_page_mlock()
+ */
+void __clear_page_mlock(struct page *page)
+{
+       VM_BUG_ON(!PageLocked(page));
+
+       if (!page->mapping) {   /* truncated ? */
+               return;
+       }
+
+       dec_zone_page_state(page, NR_MLOCK);
+       count_vm_event(UNEVICTABLE_PGCLEARED);
+       if (!isolate_lru_page(page)) {
+               putback_lru_page(page);
+       } else {
+               /*
+                * Page not on the LRU yet.  Flush all pagevecs and retry.
+                */
+               lru_add_drain_all();
+               if (!isolate_lru_page(page))
+                       putback_lru_page(page);
+               else if (PageUnevictable(page))
+                       count_vm_event(UNEVICTABLE_PGSTRANDED);
+
+       }
+}
+
+/*
+ * Mark page as mlocked if not already.
+ * If page on LRU, isolate and putback to move to unevictable list.
+ */
+void mlock_vma_page(struct page *page)
+{
+       BUG_ON(!PageLocked(page));
+
+       if (!TestSetPageMlocked(page)) {
+               inc_zone_page_state(page, NR_MLOCK);
+               count_vm_event(UNEVICTABLE_PGMLOCKED);
+               if (!isolate_lru_page(page))
+                       putback_lru_page(page);
+       }
+}
+
+/*
+ * called from munlock()/munmap() path with page supposedly on the LRU.
+ *
+ * Note:  unlike mlock_vma_page(), we can't just clear the PageMlocked
+ * [in try_to_munlock()] and then attempt to isolate the page.  We must
+ * isolate the page to keep others from messing with its unevictable
+ * and mlocked state while trying to munlock.  However, we pre-clear the
+ * mlocked state anyway as we might lose the isolation race and we might
+ * not get another chance to clear PageMlocked.  If we successfully
+ * isolate the page and try_to_munlock() detects other VM_LOCKED vmas
+ * mapping the page, it will restore the PageMlocked state, unless the page
+ * is mapped in a non-linear vma.  So, we go ahead and SetPageMlocked(),
+ * perhaps redundantly.
+ * If we lose the isolation race, and the page is mapped by other VM_LOCKED
+ * vmas, we'll detect this in vmscan--via try_to_munlock() or try_to_unmap()
+ * either of which will restore the PageMlocked state by calling
+ * mlock_vma_page() above, if it can grab the vma's mmap sem.
+ */
+static void munlock_vma_page(struct page *page)
+{
+       BUG_ON(!PageLocked(page));
+
+       if (TestClearPageMlocked(page)) {
+               dec_zone_page_state(page, NR_MLOCK);
+               if (!isolate_lru_page(page)) {
+                       int ret = try_to_munlock(page);
+                       /*
+                        * did try_to_unlock() succeed or punt?
+                        */
+                       if (ret == SWAP_SUCCESS || ret == SWAP_AGAIN)
+                               count_vm_event(UNEVICTABLE_PGMUNLOCKED);
+
+                       putback_lru_page(page);
+               } else {
+                       /*
+                        * We lost the race.  let try_to_unmap() deal
+                        * with it.  At least we get the page state and
+                        * mlock stats right.  However, page is still on
+                        * the noreclaim list.  We'll fix that up when
+                        * the page is eventually freed or we scan the
+                        * noreclaim list.
+                        */
+                       if (PageUnevictable(page))
+                               count_vm_event(UNEVICTABLE_PGSTRANDED);
+                       else
+                               count_vm_event(UNEVICTABLE_PGMUNLOCKED);
+               }
+       }
+}
+
+/**
+ * __mlock_vma_pages_range() -  mlock/munlock a range of pages in the vma.
+ * @vma:   target vma
+ * @start: start address
+ * @end:   end address
+ * @mlock: 0 indicate munlock, otherwise mlock.
+ *
+ * If @mlock == 0, unlock an mlocked range;
+ * else mlock the range of pages.  This takes care of making the pages present ,
+ * too.
+ *
+ * return 0 on success, negative error code on error.
+ *
+ * vma->vm_mm->mmap_sem must be held for at least read.
+ */
+static long __mlock_vma_pages_range(struct vm_area_struct *vma,
+                                  unsigned long start, unsigned long end,
+                                  int mlock)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       unsigned long addr = start;
+       struct page *pages[16]; /* 16 gives a reasonable batch */
+       int nr_pages = (end - start) / PAGE_SIZE;
+       int ret;
+       int gup_flags = 0;
+
+       VM_BUG_ON(start & ~PAGE_MASK);
+       VM_BUG_ON(end   & ~PAGE_MASK);
+       VM_BUG_ON(start < vma->vm_start);
+       VM_BUG_ON(end   > vma->vm_end);
+       VM_BUG_ON((!rwsem_is_locked(&mm->mmap_sem)) &&
+                 (atomic_read(&mm->mm_users) != 0));
+
+       /*
+        * mlock:   don't page populate if page has PROT_NONE permission.
+        * munlock: the pages always do munlock althrough
+        *          its has PROT_NONE permission.
+        */
+       if (!mlock)
+               gup_flags |= GUP_FLAGS_IGNORE_VMA_PERMISSIONS;
+
+       if (vma->vm_flags & VM_WRITE)
+               gup_flags |= GUP_FLAGS_WRITE;
+
+       lru_add_drain_all();    /* push cached pages to LRU */
+
+       while (nr_pages > 0) {
+               int i;
+
+               cond_resched();
+
+               /*
+                * get_user_pages makes pages present if we are
+                * setting mlock. and this extra reference count will
+                * disable migration of this page.  However, page may
+                * still be truncated out from under us.
+                */
+               ret = __get_user_pages(current, mm, addr,
+                               min_t(int, nr_pages, ARRAY_SIZE(pages)),
+                               gup_flags, pages, NULL);
+               /*
+                * This can happen for, e.g., VM_NONLINEAR regions before
+                * a page has been allocated and mapped at a given offset,
+                * or for addresses that map beyond end of a file.
+                * We'll mlock the the pages if/when they get faulted in.
+                */
+               if (ret < 0)
+                       break;
+               if (ret == 0) {
+                       /*
+                        * We know the vma is there, so the only time
+                        * we cannot get a single page should be an
+                        * error (ret < 0) case.
+                        */
+                       WARN_ON(1);
+                       break;
+               }
+
+               lru_add_drain();        /* push cached pages to LRU */
+
+               for (i = 0; i < ret; i++) {
+                       struct page *page = pages[i];
+
+                       lock_page(page);
+                       /*
+                        * Because we lock page here and migration is blocked
+                        * by the elevated reference, we need only check for
+                        * page truncation (file-cache only).
+                        */
+                       if (page->mapping) {
+                               if (mlock)
+                                       mlock_vma_page(page);
+                               else
+                                       munlock_vma_page(page);
+                       }
+                       unlock_page(page);
+                       put_page(page);         /* ref from get_user_pages() */
+
+                       /*
+                        * here we assume that get_user_pages() has given us
+                        * a list of virtually contiguous pages.
+                        */
+                       addr += PAGE_SIZE;      /* for next get_user_pages() */
+                       nr_pages--;
+               }
+               ret = 0;
+       }
+
+       lru_add_drain_all();    /* to update stats */
+
+       return ret;     /* count entire vma as locked_vm */
+}
+
+/*
+ * convert get_user_pages() return value to posix mlock() error
+ */
+static int __mlock_posix_error_return(long retval)
+{
+       if (retval == -EFAULT)
+               retval = -ENOMEM;
+       else if (retval == -ENOMEM)
+               retval = -EAGAIN;
+       return retval;
+}
+
+#else /* CONFIG_UNEVICTABLE_LRU */
+
+/*
+ * Just make pages present if VM_LOCKED.  No-op if unlocking.
+ */
+static long __mlock_vma_pages_range(struct vm_area_struct *vma,
+                                  unsigned long start, unsigned long end,
+                                  int mlock)
+{
+       if (mlock && (vma->vm_flags & VM_LOCKED))
+               return make_pages_present(start, end);
+       return 0;
+}
+
+static inline int __mlock_posix_error_return(long retval)
+{
+       return 0;
+}
+
+#endif /* CONFIG_UNEVICTABLE_LRU */
+
+/**
+ * mlock_vma_pages_range() - mlock pages in specified vma range.
+ * @vma - the vma containing the specfied address range
+ * @start - starting address in @vma to mlock
+ * @end   - end address [+1] in @vma to mlock
+ *
+ * For mmap()/mremap()/expansion of mlocked vma.
+ *
+ * return 0 on success for "normal" vmas.
+ *
+ * return number of pages [> 0] to be removed from locked_vm on success
+ * of "special" vmas.
+ *
+ * return negative error if vma spanning @start-@range disappears while
+ * mmap semaphore is dropped.  Unlikely?
+ */
+long mlock_vma_pages_range(struct vm_area_struct *vma,
+                       unsigned long start, unsigned long end)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       int nr_pages = (end - start) / PAGE_SIZE;
+       BUG_ON(!(vma->vm_flags & VM_LOCKED));
+
+       /*
+        * filter unlockable vmas
+        */
+       if (vma->vm_flags & (VM_IO | VM_PFNMAP))
+               goto no_mlock;
+
+       if (!((vma->vm_flags & (VM_DONTEXPAND | VM_RESERVED)) ||
+                       is_vm_hugetlb_page(vma) ||
+                       vma == get_gate_vma(current))) {
+               long error;
+               downgrade_write(&mm->mmap_sem);
+
+               error = __mlock_vma_pages_range(vma, start, end, 1);
+
+               up_read(&mm->mmap_sem);
+               /* vma can change or disappear */
+               down_write(&mm->mmap_sem);
+               vma = find_vma(mm, start);
+               /* non-NULL vma must contain @start, but need to check @end */
+               if (!vma ||  end > vma->vm_end)
+                       return -ENOMEM;
+
+               return 0;       /* hide other errors from mmap(), et al */
+       }
+
+       /*
+        * User mapped kernel pages or huge pages:
+        * make these pages present to populate the ptes, but
+        * fall thru' to reset VM_LOCKED--no need to unlock, and
+        * return nr_pages so these don't get counted against task's
+        * locked limit.  huge pages are already counted against
+        * locked vm limit.
+        */
+       make_pages_present(start, end);
+
+no_mlock:
+       vma->vm_flags &= ~VM_LOCKED;    /* and don't come back! */
+       return nr_pages;                /* error or pages NOT mlocked */
+}
+
+
+/*
+ * munlock_vma_pages_range() - munlock all pages in the vma range.'
+ * @vma - vma containing range to be munlock()ed.
+ * @start - start address in @vma of the range
+ * @end - end of range in @vma.
+ *
+ *  For mremap(), munmap() and exit().
+ *
+ * Called with @vma VM_LOCKED.
+ *
+ * Returns with VM_LOCKED cleared.  Callers must be prepared to
+ * deal with this.
+ *
+ * We don't save and restore VM_LOCKED here because pages are
+ * still on lru.  In unmap path, pages might be scanned by reclaim
+ * and re-mlocked by try_to_{munlock|unmap} before we unmap and
+ * free them.  This will result in freeing mlocked pages.
+ */
+void munlock_vma_pages_range(struct vm_area_struct *vma,
+                          unsigned long start, unsigned long end)
+{
+       vma->vm_flags &= ~VM_LOCKED;
+       __mlock_vma_pages_range(vma, start, end, 0);
+}
+
+/*
+ * mlock_fixup  - handle mlock[all]/munlock[all] requests.
+ *
+ * Filters out "special" vmas -- VM_LOCKED never gets set for these, and
+ * munlock is a no-op.  However, for some special vmas, we go ahead and
+ * populate the ptes via make_pages_present().
+ *
+ * For vmas that pass the filters, merge/split as appropriate.
+ */
 static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
        unsigned long start, unsigned long end, unsigned int newflags)
 {
-       struct mm_struct * mm = vma->vm_mm;
+       struct mm_struct *mm = vma->vm_mm;
        pgoff_t pgoff;
-       int pages;
+       int nr_pages;
        int ret = 0;
-
-       if (newflags == vma->vm_flags) {
-               *prev = vma;
-               goto out;
+       int lock = newflags & VM_LOCKED;
+
+       if (newflags == vma->vm_flags ||
+                       (vma->vm_flags & (VM_IO | VM_PFNMAP)))
+               goto out;       /* don't set VM_LOCKED,  don't count */
+
+       if ((vma->vm_flags & (VM_DONTEXPAND | VM_RESERVED)) ||
+                       is_vm_hugetlb_page(vma) ||
+                       vma == get_gate_vma(current)) {
+               if (lock)
+                       make_pages_present(start, end);
+               goto out;       /* don't set VM_LOCKED,  don't count */
        }
 
        pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT);
@@ -44,8 +416,6 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
                goto success;
        }
 
-       *prev = vma;
-
        if (start != vma->vm_start) {
                ret = split_vma(mm, vma, start, 1);
                if (ret)
@@ -59,25 +429,62 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
        }
 
 success:
+       /*
+        * Keep track of amount of locked VM.
+        */
+       nr_pages = (end - start) >> PAGE_SHIFT;
+       if (!lock)
+               nr_pages = -nr_pages;
+       mm->locked_vm += nr_pages;
+
        /*
         * vm_flags is protected by the mmap_sem held in write mode.
         * It's okay if try_to_unmap_one unmaps a page just after we
-        * set VM_LOCKED, make_pages_present below will bring it back.
+        * set VM_LOCKED, __mlock_vma_pages_range will bring it back.
         */
        vma->vm_flags = newflags;
 
-       /*
-        * Keep track of amount of locked VM.
-        */
-       pages = (end - start) >> PAGE_SHIFT;
-       if (newflags & VM_LOCKED) {
-               pages = -pages;
-               if (!(newflags & VM_IO))
-                       ret = make_pages_present(start, end);
+       if (lock) {
+               /*
+                * mmap_sem is currently held for write.  Downgrade the write
+                * lock to a read lock so that other faults, mmap scans, ...
+                * while we fault in all pages.
+                */
+               downgrade_write(&mm->mmap_sem);
+
+               ret = __mlock_vma_pages_range(vma, start, end, 1);
+
+               /*
+                * Need to reacquire mmap sem in write mode, as our callers
+                * expect this.  We have no support for atomically upgrading
+                * a sem to write, so we need to check for ranges while sem
+                * is unlocked.
+                */
+               up_read(&mm->mmap_sem);
+               /* vma can change or disappear */
+               down_write(&mm->mmap_sem);
+               *prev = find_vma(mm, start);
+               /* non-NULL *prev must contain @start, but need to check @end */
+               if (!(*prev) || end > (*prev)->vm_end)
+                       ret = -ENOMEM;
+               else if (ret > 0) {
+                       mm->locked_vm -= ret;
+                       ret = 0;
+               } else
+                       ret = __mlock_posix_error_return(ret); /* translate if needed */
+       } else {
+               /*
+                * TODO:  for unlocking, pages will already be resident, so
+                * we don't need to wait for allocations/reclaim/pagein, ...
+                * However, unlocking a very large region can still take a
+                * while.  Should we downgrade the semaphore for both lock
+                * AND unlock ?
+                */
+               __mlock_vma_pages_range(vma, start, end, 0);
        }
 
-       mm->locked_vm -= pages;
 out:
+       *prev = vma;
        return ret;
 }
 
index e7a5a68a9c2e4ef0b477aba5850a7299bc410aab..74f4d158022ec00ae1d405596fdbb5bb465c88b5 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -410,7 +410,7 @@ void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma,
        rb_insert_color(&vma->vm_rb, &mm->mm_rb);
 }
 
-static inline void __vma_link_file(struct vm_area_struct *vma)
+static void __vma_link_file(struct vm_area_struct *vma)
 {
        struct file * file;
 
@@ -662,8 +662,6 @@ again:                      remove_next = 1 + (end > next->vm_end);
  * If the vma has a ->close operation then the driver probably needs to release
  * per-vma resources, so we don't attempt to merge those.
  */
-#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
-
 static inline int is_mergeable_vma(struct vm_area_struct *vma,
                        struct file *file, unsigned long vm_flags)
 {
@@ -972,6 +970,7 @@ unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
                        return -EPERM;
                vm_flags |= VM_LOCKED;
        }
+
        /* mlock MCL_FUTURE? */
        if (vm_flags & VM_LOCKED) {
                unsigned long locked, lock_limit;
@@ -1139,10 +1138,12 @@ munmap_back:
         * The VM_SHARED test is necessary because shmem_zero_setup
         * will create the file object for a shared anonymous map below.
         */
-       if (!file && !(vm_flags & VM_SHARED) &&
-           vma_merge(mm, prev, addr, addr + len, vm_flags,
-                                       NULL, NULL, pgoff, NULL))
-               goto out;
+       if (!file && !(vm_flags & VM_SHARED)) {
+               vma = vma_merge(mm, prev, addr, addr + len, vm_flags,
+                                       NULL, NULL, pgoff, NULL);
+               if (vma)
+                       goto out;
+       }
 
        /*
         * Determine the object being mapped and call the appropriate
@@ -1224,10 +1225,14 @@ out:
        mm->total_vm += len >> PAGE_SHIFT;
        vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
        if (vm_flags & VM_LOCKED) {
-               mm->locked_vm += len >> PAGE_SHIFT;
-               make_pages_present(addr, addr + len);
-       }
-       if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
+               /*
+                * makes pages present; downgrades, drops, reacquires mmap_sem
+                */
+               long nr_pages = mlock_vma_pages_range(vma, addr, addr + len);
+               if (nr_pages < 0)
+                       return nr_pages;        /* vma gone! */
+               mm->locked_vm += (len >> PAGE_SHIFT) - nr_pages;
+       } else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
                make_pages_present(addr, addr + len);
        return addr;
 
@@ -1586,7 +1591,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
  * vma is the last one with address > vma->vm_end.  Have to extend vma.
  */
 #ifndef CONFIG_IA64
-static inline
+static
 #endif
 int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 {
@@ -1636,7 +1641,7 @@ int expand_upwards(struct vm_area_struct *vma, unsigned long address)
 /*
  * vma is the first one with address < vma->vm_start.  Have to extend vma.
  */
-static inline int expand_downwards(struct vm_area_struct *vma,
+static int expand_downwards(struct vm_area_struct *vma,
                                   unsigned long address)
 {
        int error;
@@ -1698,10 +1703,12 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr)
        vma = find_vma_prev(mm, addr, &prev);
        if (vma && (vma->vm_start <= addr))
                return vma;
-       if (!prev || expand_stack(prev, addr))
+       if (expand_stack(prev, addr))
                return NULL;
-       if (prev->vm_flags & VM_LOCKED)
-               make_pages_present(addr, prev->vm_end);
+       if (prev->vm_flags & VM_LOCKED) {
+               if (mlock_vma_pages_range(prev, addr, prev->vm_end) < 0)
+                       return NULL;    /* vma gone! */
+       }
        return prev;
 }
 #else
@@ -1727,8 +1734,10 @@ find_extend_vma(struct mm_struct * mm, unsigned long addr)
        start = vma->vm_start;
        if (expand_stack(vma, addr))
                return NULL;
-       if (vma->vm_flags & VM_LOCKED)
-               make_pages_present(addr, start);
+       if (vma->vm_flags & VM_LOCKED) {
+               if (mlock_vma_pages_range(vma, addr, start) < 0)
+                       return NULL;    /* vma gone! */
+       }
        return vma;
 }
 #endif
@@ -1747,8 +1756,6 @@ static void remove_vma_list(struct mm_struct *mm, struct vm_area_struct *vma)
                long nrpages = vma_pages(vma);
 
                mm->total_vm -= nrpages;
-               if (vma->vm_flags & VM_LOCKED)
-                       mm->locked_vm -= nrpages;
                vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages);
                vma = remove_vma(vma);
        } while (vma);
@@ -1913,6 +1920,20 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
        }
        vma = prev? prev->vm_next: mm->mmap;
 
+       /*
+        * unlock any mlock()ed ranges before detaching vmas
+        */
+       if (mm->locked_vm) {
+               struct vm_area_struct *tmp = vma;
+               while (tmp && tmp->vm_start < end) {
+                       if (tmp->vm_flags & VM_LOCKED) {
+                               mm->locked_vm -= vma_pages(tmp);
+                               munlock_vma_pages_all(tmp);
+                       }
+                       tmp = tmp->vm_next;
+               }
+       }
+
        /*
         * Remove the vma's, and unmap the actual pages
         */
@@ -2025,8 +2046,9 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
                return -ENOMEM;
 
        /* Can we just expand an old private anonymous mapping? */
-       if (vma_merge(mm, prev, addr, addr + len, flags,
-                                       NULL, NULL, pgoff, NULL))
+       vma = vma_merge(mm, prev, addr, addr + len, flags,
+                                       NULL, NULL, pgoff, NULL);
+       if (vma)
                goto out;
 
        /*
@@ -2048,8 +2070,8 @@ unsigned long do_brk(unsigned long addr, unsigned long len)
 out:
        mm->total_vm += len >> PAGE_SHIFT;
        if (flags & VM_LOCKED) {
-               mm->locked_vm += len >> PAGE_SHIFT;
-               make_pages_present(addr, addr + len);
+               if (!mlock_vma_pages_range(vma, addr, addr + len))
+                       mm->locked_vm += (len >> PAGE_SHIFT);
        }
        return addr;
 }
@@ -2060,7 +2082,7 @@ EXPORT_SYMBOL(do_brk);
 void exit_mmap(struct mm_struct *mm)
 {
        struct mmu_gather *tlb;
-       struct vm_area_struct *vma = mm->mmap;
+       struct vm_area_struct *vma;
        unsigned long nr_accounted = 0;
        unsigned long end;
 
@@ -2068,6 +2090,15 @@ void exit_mmap(struct mm_struct *mm)
        arch_exit_mmap(mm);
        mmu_notifier_release(mm);
 
+       if (mm->locked_vm) {
+               vma = mm->mmap;
+               while (vma) {
+                       if (vma->vm_flags & VM_LOCKED)
+                               munlock_vma_pages_all(vma);
+                       vma = vma->vm_next;
+               }
+       }
+       vma = mm->mmap;
        lru_add_drain();
        flush_cache_mm(mm);
        tlb = tlb_gather_mmu(mm, 1);
index 1a7743923c8c42c536d79ecb64f45457b2a3f994..58a2908f42f500002e49adc218adbca0e8602c26 100644 (file)
@@ -24,6 +24,8 @@
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
+#include "internal.h"
+
 static pmd_t *get_old_pmd(struct mm_struct *mm, unsigned long addr)
 {
        pgd_t *pgd;
@@ -238,8 +240,8 @@ static unsigned long move_vma(struct vm_area_struct *vma,
        if (vm_flags & VM_LOCKED) {
                mm->locked_vm += new_len >> PAGE_SHIFT;
                if (new_len > old_len)
-                       make_pages_present(new_addr + old_len,
-                                          new_addr + new_len);
+                       mlock_vma_pages_range(new_vma, new_addr + old_len,
+                                                      new_addr + new_len);
        }
 
        return new_addr;
@@ -379,7 +381,7 @@ unsigned long do_mremap(unsigned long addr,
                        vm_stat_account(mm, vma->vm_flags, vma->vm_file, pages);
                        if (vma->vm_flags & VM_LOCKED) {
                                mm->locked_vm += pages;
-                               make_pages_present(addr + old_len,
+                               mlock_vma_pages_range(vma, addr + old_len,
                                                   addr + new_len);
                        }
                        ret = addr;
index ed75bc962fbe913f8a5835c0a9bc43170582dd7f..2696b24f2bb37c427168655b8f690c46c931dcf6 100644 (file)
@@ -34,6 +34,8 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
+#include "internal.h"
+
 void *high_memory;
 struct page *mem_map;
 unsigned long max_mapnr;
@@ -128,20 +130,16 @@ unsigned int kobjsize(const void *objp)
        return PAGE_SIZE << compound_order(page);
 }
 
-/*
- * get a list of pages in an address range belonging to the specified process
- * and indicate the VMA that covers each page
- * - this is potentially dodgy as we may end incrementing the page count of a
- *   slab page or a secondary page from a compound page
- * - don't permit access to VMAs that don't support it, such as I/O mappings
- */
-int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
-       unsigned long start, int len, int write, int force,
-       struct page **pages, struct vm_area_struct **vmas)
+int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+                    unsigned long start, int len, int flags,
+               struct page **pages, struct vm_area_struct **vmas)
 {
        struct vm_area_struct *vma;
        unsigned long vm_flags;
        int i;
+       int write = !!(flags & GUP_FLAGS_WRITE);
+       int force = !!(flags & GUP_FLAGS_FORCE);
+       int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS);
 
        /* calculate required read or write permissions.
         * - if 'force' is set, we only require the "MAY" flags.
@@ -156,7 +154,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 
                /* protect what we can, including chardevs */
                if (vma->vm_flags & (VM_IO | VM_PFNMAP) ||
-                   !(vm_flags & vma->vm_flags))
+                   (!ignore && !(vm_flags & vma->vm_flags)))
                        goto finish_or_fault;
 
                if (pages) {
@@ -174,6 +172,30 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
 finish_or_fault:
        return i ? : -EFAULT;
 }
+
+
+/*
+ * get a list of pages in an address range belonging to the specified process
+ * and indicate the VMA that covers each page
+ * - this is potentially dodgy as we may end incrementing the page count of a
+ *   slab page or a secondary page from a compound page
+ * - don't permit access to VMAs that don't support it, such as I/O mappings
+ */
+int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
+       unsigned long start, int len, int write, int force,
+       struct page **pages, struct vm_area_struct **vmas)
+{
+       int flags = 0;
+
+       if (write)
+               flags |= GUP_FLAGS_WRITE;
+       if (force)
+               flags |= GUP_FLAGS_FORCE;
+
+       return __get_user_pages(tsk, mm,
+                               start, len, flags,
+                               pages, vmas);
+}
 EXPORT_SYMBOL(get_user_pages);
 
 DEFINE_RWLOCK(vmlist_lock);
index b40f6d5f8fe9bc24750fb829742ef655f0f4c42c..2970e35fd03f0fb6c3f178eca78b30166eeb6450 100644 (file)
@@ -329,9 +329,7 @@ static unsigned long highmem_dirtyable_memory(unsigned long total)
                struct zone *z =
                        &NODE_DATA(node)->node_zones[ZONE_HIGHMEM];
 
-               x += zone_page_state(z, NR_FREE_PAGES)
-                       + zone_page_state(z, NR_INACTIVE)
-                       + zone_page_state(z, NR_ACTIVE);
+               x += zone_page_state(z, NR_FREE_PAGES) + zone_lru_pages(z);
        }
        /*
         * Make sure that the number of highmem pages is never larger
@@ -355,9 +353,7 @@ unsigned long determine_dirtyable_memory(void)
 {
        unsigned long x;
 
-       x = global_page_state(NR_FREE_PAGES)
-               + global_page_state(NR_INACTIVE)
-               + global_page_state(NR_ACTIVE);
+       x = global_page_state(NR_FREE_PAGES) + global_lru_pages();
 
        if (!vm_highmem_is_dirtyable)
                x -= highmem_dirtyable_memory(x);
index 9eb9eb92828510efbc7100addea5fa766c8f48ea..d0a240fbb8bfc34f5304ee896af7964442230d4d 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/backing-dev.h>
 #include <linux/fault-inject.h>
 #include <linux/page-isolation.h>
-#include <linux/memcontrol.h>
+#include <linux/page_cgroup.h>
 #include <linux/debugobjects.h>
 
 #include <asm/tlbflush.h>
@@ -223,17 +223,12 @@ static inline int bad_range(struct zone *zone, struct page *page)
 
 static void bad_page(struct page *page)
 {
-       void *pc = page_get_page_cgroup(page);
-
        printk(KERN_EMERG "Bad page state in process '%s'\n" KERN_EMERG
                "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n",
                current->comm, page, (int)(2*sizeof(unsigned long)),
                (unsigned long)page->flags, page->mapping,
                page_mapcount(page), page_count(page));
-       if (pc) {
-               printk(KERN_EMERG "cgroup:%p\n", pc);
-               page_reset_bad_cgroup(page);
-       }
+
        printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n"
                KERN_EMERG "Backtrace:\n");
        dump_stack();
@@ -454,14 +449,16 @@ static inline void __free_one_page(struct page *page,
 
 static inline int free_pages_check(struct page *page)
 {
+       free_page_mlock(page);
        if (unlikely(page_mapcount(page) |
                (page->mapping != NULL)  |
-               (page_get_page_cgroup(page) != NULL) |
                (page_count(page) != 0)  |
                (page->flags & PAGE_FLAGS_CHECK_AT_FREE)))
                bad_page(page);
        if (PageDirty(page))
                __ClearPageDirty(page);
+       if (PageSwapBacked(page))
+               __ClearPageSwapBacked(page);
        /*
         * For now, we report if PG_reserved was found set, but do not
         * clear it, and do not free the page.  But we shall soon need
@@ -600,7 +597,6 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
 {
        if (unlikely(page_mapcount(page) |
                (page->mapping != NULL)  |
-               (page_get_page_cgroup(page) != NULL) |
                (page_count(page) != 0)  |
                (page->flags & PAGE_FLAGS_CHECK_AT_PREP)))
                bad_page(page);
@@ -614,7 +610,11 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
 
        page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_reclaim |
                        1 << PG_referenced | 1 << PG_arch_1 |
-                       1 << PG_owner_priv_1 | 1 << PG_mappedtodisk);
+                       1 << PG_owner_priv_1 | 1 << PG_mappedtodisk
+#ifdef CONFIG_UNEVICTABLE_LRU
+                       | 1 << PG_mlocked
+#endif
+                       );
        set_page_private(page, 0);
        set_page_refcounted(page);
 
@@ -1862,10 +1862,21 @@ void show_free_areas(void)
                }
        }
 
-       printk("Active:%lu inactive:%lu dirty:%lu writeback:%lu unstable:%lu\n"
+       printk("Active_anon:%lu active_file:%lu inactive_anon:%lu\n"
+               " inactive_file:%lu"
+//TODO:  check/adjust line lengths
+#ifdef CONFIG_UNEVICTABLE_LRU
+               " unevictable:%lu"
+#endif
+               " dirty:%lu writeback:%lu unstable:%lu\n"
                " free:%lu slab:%lu mapped:%lu pagetables:%lu bounce:%lu\n",
-               global_page_state(NR_ACTIVE),
-               global_page_state(NR_INACTIVE),
+               global_page_state(NR_ACTIVE_ANON),
+               global_page_state(NR_ACTIVE_FILE),
+               global_page_state(NR_INACTIVE_ANON),
+               global_page_state(NR_INACTIVE_FILE),
+#ifdef CONFIG_UNEVICTABLE_LRU
+               global_page_state(NR_UNEVICTABLE),
+#endif
                global_page_state(NR_FILE_DIRTY),
                global_page_state(NR_WRITEBACK),
                global_page_state(NR_UNSTABLE_NFS),
@@ -1888,8 +1899,13 @@ void show_free_areas(void)
                        " min:%lukB"
                        " low:%lukB"
                        " high:%lukB"
-                       " active:%lukB"
-                       " inactive:%lukB"
+                       " active_anon:%lukB"
+                       " inactive_anon:%lukB"
+                       " active_file:%lukB"
+                       " inactive_file:%lukB"
+#ifdef CONFIG_UNEVICTABLE_LRU
+                       " unevictable:%lukB"
+#endif
                        " present:%lukB"
                        " pages_scanned:%lu"
                        " all_unreclaimable? %s"
@@ -1899,8 +1915,13 @@ void show_free_areas(void)
                        K(zone->pages_min),
                        K(zone->pages_low),
                        K(zone->pages_high),
-                       K(zone_page_state(zone, NR_ACTIVE)),
-                       K(zone_page_state(zone, NR_INACTIVE)),
+                       K(zone_page_state(zone, NR_ACTIVE_ANON)),
+                       K(zone_page_state(zone, NR_INACTIVE_ANON)),
+                       K(zone_page_state(zone, NR_ACTIVE_FILE)),
+                       K(zone_page_state(zone, NR_INACTIVE_FILE)),
+#ifdef CONFIG_UNEVICTABLE_LRU
+                       K(zone_page_state(zone, NR_UNEVICTABLE)),
+#endif
                        K(zone->present_pages),
                        zone->pages_scanned,
                        (zone_is_all_unreclaimable(zone) ? "yes" : "no")
@@ -3410,10 +3431,12 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
        pgdat->nr_zones = 0;
        init_waitqueue_head(&pgdat->kswapd_wait);
        pgdat->kswapd_max_order = 0;
+       pgdat_page_cgroup_init(pgdat);
        
        for (j = 0; j < MAX_NR_ZONES; j++) {
                struct zone *zone = pgdat->node_zones + j;
                unsigned long size, realsize, memmap_pages;
+               enum lru_list l;
 
                size = zone_spanned_pages_in_node(nid, j, zones_size);
                realsize = size - zone_absent_pages_in_node(nid, j,
@@ -3428,8 +3451,8 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                        PAGE_ALIGN(size * sizeof(struct page)) >> PAGE_SHIFT;
                if (realsize >= memmap_pages) {
                        realsize -= memmap_pages;
-                       mminit_dprintk(MMINIT_TRACE, "memmap_init",
-                               "%s zone: %lu pages used for memmap\n",
+                       printk(KERN_DEBUG
+                               "  %s zone: %lu pages used for memmap\n",
                                zone_names[j], memmap_pages);
                } else
                        printk(KERN_WARNING
@@ -3439,8 +3462,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                /* Account for reserved pages */
                if (j == 0 && realsize > dma_reserve) {
                        realsize -= dma_reserve;
-                       mminit_dprintk(MMINIT_TRACE, "memmap_init",
-                                       "%s zone: %lu pages reserved\n",
+                       printk(KERN_DEBUG "  %s zone: %lu pages reserved\n",
                                        zone_names[0], dma_reserve);
                }
 
@@ -3465,10 +3487,14 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                zone->prev_priority = DEF_PRIORITY;
 
                zone_pcp_init(zone);
-               INIT_LIST_HEAD(&zone->active_list);
-               INIT_LIST_HEAD(&zone->inactive_list);
-               zone->nr_scan_active = 0;
-               zone->nr_scan_inactive = 0;
+               for_each_lru(l) {
+                       INIT_LIST_HEAD(&zone->lru[l].list);
+                       zone->lru[l].nr_scan = 0;
+               }
+               zone->recent_rotated[0] = 0;
+               zone->recent_rotated[1] = 0;
+               zone->recent_scanned[0] = 0;
+               zone->recent_scanned[1] = 0;
                zap_zone_vm_stats(zone);
                zone->flags = 0;
                if (!size)
@@ -4210,7 +4236,7 @@ void setup_per_zone_pages_min(void)
        for_each_zone(zone) {
                u64 tmp;
 
-               spin_lock_irqsave(&zone->lru_lock, flags);
+               spin_lock_irqsave(&zone->lock, flags);
                tmp = (u64)pages_min * zone->present_pages;
                do_div(tmp, lowmem_pages);
                if (is_highmem(zone)) {
@@ -4242,13 +4268,53 @@ void setup_per_zone_pages_min(void)
                zone->pages_low   = zone->pages_min + (tmp >> 2);
                zone->pages_high  = zone->pages_min + (tmp >> 1);
                setup_zone_migrate_reserve(zone);
-               spin_unlock_irqrestore(&zone->lru_lock, flags);
+               spin_unlock_irqrestore(&zone->lock, flags);
        }
 
        /* update totalreserve_pages */
        calculate_totalreserve_pages();
 }
 
+/**
+ * setup_per_zone_inactive_ratio - called when min_free_kbytes changes.
+ *
+ * The inactive anon list should be small enough that the VM never has to
+ * do too much work, but large enough that each inactive page has a chance
+ * to be referenced again before it is swapped out.
+ *
+ * The inactive_anon ratio is the target ratio of ACTIVE_ANON to
+ * INACTIVE_ANON pages on this zone's LRU, maintained by the
+ * pageout code. A zone->inactive_ratio of 3 means 3:1 or 25% of
+ * the anonymous pages are kept on the inactive list.
+ *
+ * total     target    max
+ * memory    ratio     inactive anon
+ * -------------------------------------
+ *   10MB       1         5MB
+ *  100MB       1        50MB
+ *    1GB       3       250MB
+ *   10GB      10       0.9GB
+ *  100GB      31         3GB
+ *    1TB     101        10GB
+ *   10TB     320        32GB
+ */
+void setup_per_zone_inactive_ratio(void)
+{
+       struct zone *zone;
+
+       for_each_zone(zone) {
+               unsigned int gb, ratio;
+
+               /* Zone size in gigabytes */
+               gb = zone->present_pages >> (30 - PAGE_SHIFT);
+               ratio = int_sqrt(10 * gb);
+               if (!ratio)
+                       ratio = 1;
+
+               zone->inactive_ratio = ratio;
+       }
+}
+
 /*
  * Initialise min_free_kbytes.
  *
@@ -4286,6 +4352,7 @@ static int __init init_per_zone_pages_min(void)
                min_free_kbytes = 65536;
        setup_per_zone_pages_min();
        setup_per_zone_lowmem_reserve();
+       setup_per_zone_inactive_ratio();
        return 0;
 }
 module_init(init_per_zone_pages_min)
diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c
new file mode 100644 (file)
index 0000000..5d86550
--- /dev/null
@@ -0,0 +1,237 @@
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <linux/bootmem.h>
+#include <linux/bit_spinlock.h>
+#include <linux/page_cgroup.h>
+#include <linux/hash.h>
+#include <linux/memory.h>
+
+static void __meminit
+__init_page_cgroup(struct page_cgroup *pc, unsigned long pfn)
+{
+       pc->flags = 0;
+       pc->mem_cgroup = NULL;
+       pc->page = pfn_to_page(pfn);
+}
+static unsigned long total_usage;
+
+#if !defined(CONFIG_SPARSEMEM)
+
+
+void __init pgdat_page_cgroup_init(struct pglist_data *pgdat)
+{
+       pgdat->node_page_cgroup = NULL;
+}
+
+struct page_cgroup *lookup_page_cgroup(struct page *page)
+{
+       unsigned long pfn = page_to_pfn(page);
+       unsigned long offset;
+       struct page_cgroup *base;
+
+       base = NODE_DATA(page_to_nid(page))->node_page_cgroup;
+       if (unlikely(!base))
+               return NULL;
+
+       offset = pfn - NODE_DATA(page_to_nid(page))->node_start_pfn;
+       return base + offset;
+}
+
+static int __init alloc_node_page_cgroup(int nid)
+{
+       struct page_cgroup *base, *pc;
+       unsigned long table_size;
+       unsigned long start_pfn, nr_pages, index;
+
+       start_pfn = NODE_DATA(nid)->node_start_pfn;
+       nr_pages = NODE_DATA(nid)->node_spanned_pages;
+
+       table_size = sizeof(struct page_cgroup) * nr_pages;
+
+       base = __alloc_bootmem_node_nopanic(NODE_DATA(nid),
+                       table_size, PAGE_SIZE, __pa(MAX_DMA_ADDRESS));
+       if (!base)
+               return -ENOMEM;
+       for (index = 0; index < nr_pages; index++) {
+               pc = base + index;
+               __init_page_cgroup(pc, start_pfn + index);
+       }
+       NODE_DATA(nid)->node_page_cgroup = base;
+       total_usage += table_size;
+       return 0;
+}
+
+void __init page_cgroup_init(void)
+{
+
+       int nid, fail;
+
+       for_each_online_node(nid)  {
+               fail = alloc_node_page_cgroup(nid);
+               if (fail)
+                       goto fail;
+       }
+       printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage);
+       printk(KERN_INFO "please try cgroup_disable=memory option if you"
+       " don't want\n");
+       return;
+fail:
+       printk(KERN_CRIT "allocation of page_cgroup was failed.\n");
+       printk(KERN_CRIT "please try cgroup_disable=memory boot option\n");
+       panic("Out of memory");
+}
+
+#else /* CONFIG_FLAT_NODE_MEM_MAP */
+
+struct page_cgroup *lookup_page_cgroup(struct page *page)
+{
+       unsigned long pfn = page_to_pfn(page);
+       struct mem_section *section = __pfn_to_section(pfn);
+
+       return section->page_cgroup + pfn;
+}
+
+int __meminit init_section_page_cgroup(unsigned long pfn)
+{
+       struct mem_section *section;
+       struct page_cgroup *base, *pc;
+       unsigned long table_size;
+       int nid, index;
+
+       section = __pfn_to_section(pfn);
+
+       if (section->page_cgroup)
+               return 0;
+
+       nid = page_to_nid(pfn_to_page(pfn));
+
+       table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
+       base = kmalloc_node(table_size, GFP_KERNEL, nid);
+       if (!base)
+               base = vmalloc_node(table_size, nid);
+
+       if (!base) {
+               printk(KERN_ERR "page cgroup allocation failure\n");
+               return -ENOMEM;
+       }
+
+       for (index = 0; index < PAGES_PER_SECTION; index++) {
+               pc = base + index;
+               __init_page_cgroup(pc, pfn + index);
+       }
+
+       section = __pfn_to_section(pfn);
+       section->page_cgroup = base - pfn;
+       total_usage += table_size;
+       return 0;
+}
+#ifdef CONFIG_MEMORY_HOTPLUG
+void __free_page_cgroup(unsigned long pfn)
+{
+       struct mem_section *ms;
+       struct page_cgroup *base;
+
+       ms = __pfn_to_section(pfn);
+       if (!ms || !ms->page_cgroup)
+               return;
+       base = ms->page_cgroup + pfn;
+       ms->page_cgroup = NULL;
+       if (is_vmalloc_addr(base))
+               vfree(base);
+       else
+               kfree(base);
+}
+
+int online_page_cgroup(unsigned long start_pfn,
+                       unsigned long nr_pages,
+                       int nid)
+{
+       unsigned long start, end, pfn;
+       int fail = 0;
+
+       start = start_pfn & (PAGES_PER_SECTION - 1);
+       end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
+
+       for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) {
+               if (!pfn_present(pfn))
+                       continue;
+               fail = init_section_page_cgroup(pfn);
+       }
+       if (!fail)
+               return 0;
+
+       /* rollback */
+       for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION)
+               __free_page_cgroup(pfn);
+
+       return -ENOMEM;
+}
+
+int offline_page_cgroup(unsigned long start_pfn,
+               unsigned long nr_pages, int nid)
+{
+       unsigned long start, end, pfn;
+
+       start = start_pfn & (PAGES_PER_SECTION - 1);
+       end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
+
+       for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION)
+               __free_page_cgroup(pfn);
+       return 0;
+
+}
+
+static int page_cgroup_callback(struct notifier_block *self,
+                              unsigned long action, void *arg)
+{
+       struct memory_notify *mn = arg;
+       int ret = 0;
+       switch (action) {
+       case MEM_GOING_ONLINE:
+               ret = online_page_cgroup(mn->start_pfn,
+                                  mn->nr_pages, mn->status_change_nid);
+               break;
+       case MEM_CANCEL_ONLINE:
+       case MEM_OFFLINE:
+               offline_page_cgroup(mn->start_pfn,
+                               mn->nr_pages, mn->status_change_nid);
+               break;
+       case MEM_GOING_OFFLINE:
+               break;
+       case MEM_ONLINE:
+       case MEM_CANCEL_OFFLINE:
+               break;
+       }
+       ret = notifier_from_errno(ret);
+       return ret;
+}
+
+#endif
+
+void __init page_cgroup_init(void)
+{
+       unsigned long pfn;
+       int fail = 0;
+
+       for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) {
+               if (!pfn_present(pfn))
+                       continue;
+               fail = init_section_page_cgroup(pfn);
+       }
+       if (fail) {
+               printk(KERN_CRIT "try cgroup_disable=memory boot option\n");
+               panic("Out of memory");
+       } else {
+               hotplug_memory_notifier(page_cgroup_callback, 0);
+       }
+       printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage);
+       printk(KERN_INFO "please try cgroup_disable=memory option if you don't"
+       " want\n");
+}
+
+void __init pgdat_page_cgroup_init(struct pglist_data *pgdat)
+{
+       return;
+}
+
+#endif
index 6cbd9a72fde2c8c1e20bd1c3da9144fa0d13d65c..bec83c15a78f61b58a1dfbb74a336b9848b5d876 100644 (file)
@@ -229,7 +229,7 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp,
  */
 unsigned long max_sane_readahead(unsigned long nr)
 {
-       return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE)
+       return min(nr, (node_page_state(numa_node_id(), NR_INACTIVE_FILE)
                + node_page_state(numa_node_id(), NR_FREE_PAGES)) / 2);
 }
 
index 0383acfcb0681a877f15f59d4d712980c37e1811..10993942d6c989314477291520c6bb6980a0439d 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
 
 #include <asm/tlbflush.h>
 
-struct kmem_cache *anon_vma_cachep;
+#include "internal.h"
 
-/* This must be called under the mmap_sem. */
+static struct kmem_cache *anon_vma_cachep;
+
+static inline struct anon_vma *anon_vma_alloc(void)
+{
+       return kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
+}
+
+static inline void anon_vma_free(struct anon_vma *anon_vma)
+{
+       kmem_cache_free(anon_vma_cachep, anon_vma);
+}
+
+/**
+ * anon_vma_prepare - attach an anon_vma to a memory region
+ * @vma: the memory region in question
+ *
+ * This makes sure the memory mapping described by 'vma' has
+ * an 'anon_vma' attached to it, so that we can associate the
+ * anonymous pages mapped into it with that anon_vma.
+ *
+ * The common case will be that we already have one, but if
+ * if not we either need to find an adjacent mapping that we
+ * can re-use the anon_vma from (very common when the only
+ * reason for splitting a vma has been mprotect()), or we
+ * allocate a new one.
+ *
+ * Anon-vma allocations are very subtle, because we may have
+ * optimistically looked up an anon_vma in page_lock_anon_vma()
+ * and that may actually touch the spinlock even in the newly
+ * allocated vma (it depends on RCU to make sure that the
+ * anon_vma isn't actually destroyed).
+ *
+ * As a result, we need to do proper anon_vma locking even
+ * for the new allocation. At the same time, we do not want
+ * to do any locking for the common case of already having
+ * an anon_vma.
+ *
+ * This must be called with the mmap_sem held for reading.
+ */
 int anon_vma_prepare(struct vm_area_struct *vma)
 {
        struct anon_vma *anon_vma = vma->anon_vma;
@@ -63,20 +101,17 @@ int anon_vma_prepare(struct vm_area_struct *vma)
        might_sleep();
        if (unlikely(!anon_vma)) {
                struct mm_struct *mm = vma->vm_mm;
-               struct anon_vma *allocated, *locked;
+               struct anon_vma *allocated;
 
                anon_vma = find_mergeable_anon_vma(vma);
-               if (anon_vma) {
-                       allocated = NULL;
-                       locked = anon_vma;
-                       spin_lock(&locked->lock);
-               } else {
+               allocated = NULL;
+               if (!anon_vma) {
                        anon_vma = anon_vma_alloc();
                        if (unlikely(!anon_vma))
                                return -ENOMEM;
                        allocated = anon_vma;
-                       locked = NULL;
                }
+               spin_lock(&anon_vma->lock);
 
                /* page_table_lock to protect against threads */
                spin_lock(&mm->page_table_lock);
@@ -87,8 +122,7 @@ int anon_vma_prepare(struct vm_area_struct *vma)
                }
                spin_unlock(&mm->page_table_lock);
 
-               if (locked)
-                       spin_unlock(&locked->lock);
+               spin_unlock(&anon_vma->lock);
                if (unlikely(allocated))
                        anon_vma_free(allocated);
        }
@@ -157,7 +191,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.
  */
-static 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;
        unsigned long anon_mapping;
@@ -177,7 +211,7 @@ out:
        return NULL;
 }
 
-static void page_unlock_anon_vma(struct anon_vma *anon_vma)
+void page_unlock_anon_vma(struct anon_vma *anon_vma)
 {
        spin_unlock(&anon_vma->lock);
        rcu_read_unlock();
@@ -268,6 +302,32 @@ pte_t *page_check_address(struct page *page, struct mm_struct *mm,
        return NULL;
 }
 
+/**
+ * page_mapped_in_vma - check whether a page is really mapped in a VMA
+ * @page: the page to test
+ * @vma: the VMA to test
+ *
+ * Returns 1 if the page is mapped into the page tables of the VMA, 0
+ * if the page is not mapped into the page tables of this VMA.  Only
+ * valid for normal file or anonymous VMAs.
+ */
+static int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma)
+{
+       unsigned long address;
+       pte_t *pte;
+       spinlock_t *ptl;
+
+       address = vma_address(page, vma);
+       if (address == -EFAULT)         /* out of vma range */
+               return 0;
+       pte = page_check_address(page, vma->vm_mm, address, &ptl, 1);
+       if (!pte)                       /* the page is not in this mm */
+               return 0;
+       pte_unmap_unlock(pte, ptl);
+
+       return 1;
+}
+
 /*
  * Subfunctions of page_referenced: page_referenced_one called
  * repeatedly from either page_referenced_anon or page_referenced_file.
@@ -289,10 +349,17 @@ static int page_referenced_one(struct page *page,
        if (!pte)
                goto out;
 
+       /*
+        * Don't want to elevate referenced for mlocked page that gets this far,
+        * in order that it progresses to try_to_unmap and is moved to the
+        * unevictable list.
+        */
        if (vma->vm_flags & VM_LOCKED) {
-               referenced++;
                *mapcount = 1;  /* break early from loop */
-       } else if (ptep_clear_flush_young_notify(vma, address, pte))
+               goto out_unmap;
+       }
+
+       if (ptep_clear_flush_young_notify(vma, address, pte))
                referenced++;
 
        /* Pretend the page is referenced if the task has the
@@ -301,6 +368,7 @@ static int page_referenced_one(struct page *page,
                        rwsem_is_locked(&mm->mmap_sem))
                referenced++;
 
+out_unmap:
        (*mapcount)--;
        pte_unmap_unlock(pte, ptl);
 out:
@@ -390,11 +458,6 @@ static int page_referenced_file(struct page *page,
                 */
                if (mem_cont && !mm_match_cgroup(vma->vm_mm, mem_cont))
                        continue;
-               if ((vma->vm_flags & (VM_LOCKED|VM_MAYSHARE))
-                                 == (VM_LOCKED|VM_MAYSHARE)) {
-                       referenced++;
-                       break;
-               }
                referenced += page_referenced_one(page, vma, &mapcount);
                if (!mapcount)
                        break;
@@ -674,8 +737,8 @@ void page_remove_rmap(struct page *page, struct vm_area_struct *vma)
                        page_clear_dirty(page);
                        set_page_dirty(page);
                }
-
-               mem_cgroup_uncharge_page(page);
+               if (PageAnon(page))
+                       mem_cgroup_uncharge_page(page);
                __dec_zone_page_state(page,
                        PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED);
                /*
@@ -717,11 +780,16 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * If it's recently referenced (perhaps page_referenced
         * skipped over this mm) then we should reactivate it.
         */
-       if (!migration && ((vma->vm_flags & VM_LOCKED) ||
-                       (ptep_clear_flush_young_notify(vma, address, pte)))) {
-               ret = SWAP_FAIL;
-               goto out_unmap;
-       }
+       if (!migration) {
+               if (vma->vm_flags & VM_LOCKED) {
+                       ret = SWAP_MLOCK;
+                       goto out_unmap;
+               }
+               if (ptep_clear_flush_young_notify(vma, address, pte)) {
+                       ret = SWAP_FAIL;
+                       goto out_unmap;
+               }
+       }
 
        /* Nuke the page table entry. */
        flush_cache_page(vma, address, page_to_pfn(page));
@@ -802,12 +870,17 @@ out:
  * For very sparsely populated VMAs this is a little inefficient - chances are
  * there there won't be many ptes located within the scan cluster.  In this case
  * maybe we could scan further - to the end of the pte page, perhaps.
+ *
+ * Mlocked pages:  check VM_LOCKED under mmap_sem held for read, if we can
+ * acquire it without blocking.  If vma locked, mlock the pages in the cluster,
+ * rather than unmapping them.  If we encounter the "check_page" that vmscan is
+ * trying to unmap, return SWAP_MLOCK, else default SWAP_AGAIN.
  */
 #define CLUSTER_SIZE   min(32*PAGE_SIZE, PMD_SIZE)
 #define CLUSTER_MASK   (~(CLUSTER_SIZE - 1))
 
-static void try_to_unmap_cluster(unsigned long cursor,
-       unsigned int *mapcount, struct vm_area_struct *vma)
+static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
+               struct vm_area_struct *vma, struct page *check_page)
 {
        struct mm_struct *mm = vma->vm_mm;
        pgd_t *pgd;
@@ -819,6 +892,8 @@ static void try_to_unmap_cluster(unsigned long cursor,
        struct page *page;
        unsigned long address;
        unsigned long end;
+       int ret = SWAP_AGAIN;
+       int locked_vma = 0;
 
        address = (vma->vm_start + cursor) & CLUSTER_MASK;
        end = address + CLUSTER_SIZE;
@@ -829,15 +904,26 @@ static void try_to_unmap_cluster(unsigned long cursor,
 
        pgd = pgd_offset(mm, address);
        if (!pgd_present(*pgd))
-               return;
+               return ret;
 
        pud = pud_offset(pgd, address);
        if (!pud_present(*pud))
-               return;
+               return ret;
 
        pmd = pmd_offset(pud, address);
        if (!pmd_present(*pmd))
-               return;
+               return ret;
+
+       /*
+        * MLOCK_PAGES => feature is configured.
+        * if we can acquire the mmap_sem for read, and vma is VM_LOCKED,
+        * keep the sem while scanning the cluster for mlocking pages.
+        */
+       if (MLOCK_PAGES && down_read_trylock(&vma->vm_mm->mmap_sem)) {
+               locked_vma = (vma->vm_flags & VM_LOCKED);
+               if (!locked_vma)
+                       up_read(&vma->vm_mm->mmap_sem); /* don't need it */
+       }
 
        pte = pte_offset_map_lock(mm, pmd, address, &ptl);
 
@@ -850,6 +936,13 @@ static void try_to_unmap_cluster(unsigned long cursor,
                page = vm_normal_page(vma, address, *pte);
                BUG_ON(!page || PageAnon(page));
 
+               if (locked_vma) {
+                       mlock_vma_page(page);   /* no-op if already mlocked */
+                       if (page == check_page)
+                               ret = SWAP_MLOCK;
+                       continue;       /* don't unmap */
+               }
+
                if (ptep_clear_flush_young_notify(vma, address, pte))
                        continue;
 
@@ -871,39 +964,104 @@ static void try_to_unmap_cluster(unsigned long cursor,
                (*mapcount)--;
        }
        pte_unmap_unlock(pte - 1, ptl);
+       if (locked_vma)
+               up_read(&vma->vm_mm->mmap_sem);
+       return ret;
 }
 
-static int try_to_unmap_anon(struct page *page, int migration)
+/*
+ * common handling for pages mapped in VM_LOCKED vmas
+ */
+static int try_to_mlock_page(struct page *page, struct vm_area_struct *vma)
+{
+       int mlocked = 0;
+
+       if (down_read_trylock(&vma->vm_mm->mmap_sem)) {
+               if (vma->vm_flags & VM_LOCKED) {
+                       mlock_vma_page(page);
+                       mlocked++;      /* really mlocked the page */
+               }
+               up_read(&vma->vm_mm->mmap_sem);
+       }
+       return mlocked;
+}
+
+/**
+ * try_to_unmap_anon - unmap or unlock anonymous page using the object-based
+ * rmap method
+ * @page: the page to unmap/unlock
+ * @unlock:  request for unlock rather than unmap [unlikely]
+ * @migration:  unmapping for migration - ignored if @unlock
+ *
+ * Find all the mappings of a page using the mapping pointer and the vma chains
+ * contained in the anon_vma struct it points to.
+ *
+ * This function is only called from try_to_unmap/try_to_munlock for
+ * anonymous pages.
+ * When called from try_to_munlock(), the mmap_sem of the mm containing the vma
+ * where the page was found will be held for write.  So, we won't recheck
+ * vm_flags for that VMA.  That should be OK, because that vma shouldn't be
+ * 'LOCKED.
+ */
+static int try_to_unmap_anon(struct page *page, int unlock, int migration)
 {
        struct anon_vma *anon_vma;
        struct vm_area_struct *vma;
+       unsigned int mlocked = 0;
        int ret = SWAP_AGAIN;
 
+       if (MLOCK_PAGES && unlikely(unlock))
+               ret = SWAP_SUCCESS;     /* default for try_to_munlock() */
+
        anon_vma = page_lock_anon_vma(page);
        if (!anon_vma)
                return ret;
 
        list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
-               ret = try_to_unmap_one(page, vma, migration);
-               if (ret == SWAP_FAIL || !page_mapped(page))
-                       break;
+               if (MLOCK_PAGES && unlikely(unlock)) {
+                       if (!((vma->vm_flags & VM_LOCKED) &&
+                             page_mapped_in_vma(page, vma)))
+                               continue;  /* must visit all unlocked vmas */
+                       ret = SWAP_MLOCK;  /* saw at least one mlocked vma */
+               } else {
+                       ret = try_to_unmap_one(page, vma, migration);
+                       if (ret == SWAP_FAIL || !page_mapped(page))
+                               break;
+               }
+               if (ret == SWAP_MLOCK) {
+                       mlocked = try_to_mlock_page(page, vma);
+                       if (mlocked)
+                               break;  /* stop if actually mlocked page */
+               }
        }
 
        page_unlock_anon_vma(anon_vma);
+
+       if (mlocked)
+               ret = SWAP_MLOCK;       /* actually mlocked the page */
+       else if (ret == SWAP_MLOCK)
+               ret = SWAP_AGAIN;       /* saw VM_LOCKED vma */
+
        return ret;
 }
 
 /**
- * try_to_unmap_file - unmap file page using the object-based rmap method
- * @page: the page to unmap
- * @migration: migration flag
+ * try_to_unmap_file - unmap/unlock file page using the object-based rmap method
+ * @page: the page to unmap/unlock
+ * @unlock:  request for unlock rather than unmap [unlikely]
+ * @migration:  unmapping for migration - ignored if @unlock
  *
  * Find all the mappings of a page using the mapping pointer and the vma chains
  * contained in the address_space struct it points to.
  *
- * This function is only called from try_to_unmap for object-based pages.
+ * This function is only called from try_to_unmap/try_to_munlock for
+ * object-based pages.
+ * When called from try_to_munlock(), the mmap_sem of the mm containing the vma
+ * where the page was found will be held for write.  So, we won't recheck
+ * vm_flags for that VMA.  That should be OK, because that vma shouldn't be
+ * 'LOCKED.
  */
-static int try_to_unmap_file(struct page *page, int migration)
+static int try_to_unmap_file(struct page *page, int unlock, int migration)
 {
        struct address_space *mapping = page->mapping;
        pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
@@ -914,20 +1072,44 @@ static int try_to_unmap_file(struct page *page, int migration)
        unsigned long max_nl_cursor = 0;
        unsigned long max_nl_size = 0;
        unsigned int mapcount;
+       unsigned int mlocked = 0;
+
+       if (MLOCK_PAGES && unlikely(unlock))
+               ret = SWAP_SUCCESS;     /* default for try_to_munlock() */
 
        spin_lock(&mapping->i_mmap_lock);
        vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
-               ret = try_to_unmap_one(page, vma, migration);
-               if (ret == SWAP_FAIL || !page_mapped(page))
-                       goto out;
+               if (MLOCK_PAGES && unlikely(unlock)) {
+                       if (!(vma->vm_flags & VM_LOCKED))
+                               continue;       /* must visit all vmas */
+                       ret = SWAP_MLOCK;
+               } else {
+                       ret = try_to_unmap_one(page, vma, migration);
+                       if (ret == SWAP_FAIL || !page_mapped(page))
+                               goto out;
+               }
+               if (ret == SWAP_MLOCK) {
+                       mlocked = try_to_mlock_page(page, vma);
+                       if (mlocked)
+                               break;  /* stop if actually mlocked page */
+               }
        }
 
+       if (mlocked)
+               goto out;
+
        if (list_empty(&mapping->i_mmap_nonlinear))
                goto out;
 
        list_for_each_entry(vma, &mapping->i_mmap_nonlinear,
                                                shared.vm_set.list) {
-               if ((vma->vm_flags & VM_LOCKED) && !migration)
+               if (MLOCK_PAGES && unlikely(unlock)) {
+                       if (!(vma->vm_flags & VM_LOCKED))
+                               continue;       /* must visit all vmas */
+                       ret = SWAP_MLOCK;       /* leave mlocked == 0 */
+                       goto out;               /* no need to look further */
+               }
+               if (!MLOCK_PAGES && !migration && (vma->vm_flags & VM_LOCKED))
                        continue;
                cursor = (unsigned long) vma->vm_private_data;
                if (cursor > max_nl_cursor)
@@ -937,7 +1119,7 @@ static int try_to_unmap_file(struct page *page, int migration)
                        max_nl_size = cursor;
        }
 
-       if (max_nl_size == 0) { /* any nonlinears locked or reserved */
+       if (max_nl_size == 0) { /* all nonlinears locked or reserved ? */
                ret = SWAP_FAIL;
                goto out;
        }
@@ -961,12 +1143,16 @@ static int try_to_unmap_file(struct page *page, int migration)
        do {
                list_for_each_entry(vma, &mapping->i_mmap_nonlinear,
                                                shared.vm_set.list) {
-                       if ((vma->vm_flags & VM_LOCKED) && !migration)
+                       if (!MLOCK_PAGES && !migration &&
+                           (vma->vm_flags & VM_LOCKED))
                                continue;
                        cursor = (unsigned long) vma->vm_private_data;
                        while ( cursor < max_nl_cursor &&
                                cursor < vma->vm_end - vma->vm_start) {
-                               try_to_unmap_cluster(cursor, &mapcount, vma);
+                               ret = try_to_unmap_cluster(cursor, &mapcount,
+                                                               vma, page);
+                               if (ret == SWAP_MLOCK)
+                                       mlocked = 2;    /* to return below */
                                cursor += CLUSTER_SIZE;
                                vma->vm_private_data = (void *) cursor;
                                if ((int)mapcount <= 0)
@@ -987,6 +1173,10 @@ static int try_to_unmap_file(struct page *page, int migration)
                vma->vm_private_data = NULL;
 out:
        spin_unlock(&mapping->i_mmap_lock);
+       if (mlocked)
+               ret = SWAP_MLOCK;       /* actually mlocked the page */
+       else if (ret == SWAP_MLOCK)
+               ret = SWAP_AGAIN;       /* saw VM_LOCKED vma */
        return ret;
 }
 
@@ -1002,6 +1192,7 @@ out:
  * SWAP_SUCCESS        - we succeeded in removing all mappings
  * SWAP_AGAIN  - we missed a mapping, try again later
  * SWAP_FAIL   - the page is unswappable
+ * SWAP_MLOCK  - page is mlocked.
  */
 int try_to_unmap(struct page *page, int migration)
 {
@@ -1010,12 +1201,36 @@ int try_to_unmap(struct page *page, int migration)
        BUG_ON(!PageLocked(page));
 
        if (PageAnon(page))
-               ret = try_to_unmap_anon(page, migration);
+               ret = try_to_unmap_anon(page, 0, migration);
        else
-               ret = try_to_unmap_file(page, migration);
-
-       if (!page_mapped(page))
+               ret = try_to_unmap_file(page, 0, migration);
+       if (ret != SWAP_MLOCK && !page_mapped(page))
                ret = SWAP_SUCCESS;
        return ret;
 }
 
+#ifdef CONFIG_UNEVICTABLE_LRU
+/**
+ * try_to_munlock - try to munlock a page
+ * @page: the page to be munlocked
+ *
+ * Called from munlock code.  Checks all of the VMAs mapping the page
+ * to make sure nobody else has this page mlocked. The page will be
+ * returned with PG_mlocked cleared if no other vmas have it mlocked.
+ *
+ * Return values are:
+ *
+ * SWAP_SUCCESS        - no vma's holding page mlocked.
+ * SWAP_AGAIN  - page mapped in mlocked vma -- couldn't acquire mmap sem
+ * SWAP_MLOCK  - page is now mlocked.
+ */
+int try_to_munlock(struct page *page)
+{
+       VM_BUG_ON(!PageLocked(page) || PageLRU(page));
+
+       if (PageAnon(page))
+               return try_to_unmap_anon(page, 1, 0);
+       else
+               return try_to_unmap_file(page, 1, 0);
+}
+#endif
index d87958a5f03e95b2cb851722fb91d2c6e5447f66..d38d7e61fcd0bed76af19f52ac9fc03d3a9eb262 100644 (file)
@@ -199,7 +199,7 @@ static struct vm_operations_struct shmem_vm_ops;
 
 static struct backing_dev_info shmem_backing_dev_info  __read_mostly = {
        .ra_pages       = 0,    /* No readahead */
-       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_SWAP_BACKED,
        .unplug_io_fn   = default_unplug_io_fn,
 };
 
@@ -1367,6 +1367,7 @@ repeat:
                                error = -ENOMEM;
                                goto failed;
                        }
+                       SetPageSwapBacked(filepage);
 
                        /* Precharge page while we can wait, compensate after */
                        error = mem_cgroup_cache_charge(filepage, current->mm,
@@ -1476,12 +1477,16 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
                if (!user_shm_lock(inode->i_size, user))
                        goto out_nomem;
                info->flags |= VM_LOCKED;
+               mapping_set_unevictable(file->f_mapping);
        }
        if (!lock && (info->flags & VM_LOCKED) && user) {
                user_shm_unlock(inode->i_size, user);
                info->flags &= ~VM_LOCKED;
+               mapping_clear_unevictable(file->f_mapping);
+               scan_mapping_unevictable_pages(file->f_mapping);
        }
        retval = 0;
+
 out_nomem:
        spin_unlock(&info->lock);
        return retval;
index 9e0cb3118079e6eae0cf27fed41b8f2ff59f8bc2..2152e48a7b8f0726f06a88c516d82a0becf3c19d 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
 #include <linux/backing-dev.h>
 #include <linux/memcontrol.h>
 
+#include "internal.h"
+
 /* How many pages do we try to swap or page in/out together? */
 int page_cluster;
 
-static DEFINE_PER_CPU(struct pagevec, lru_add_pvecs);
-static DEFINE_PER_CPU(struct pagevec, lru_add_active_pvecs);
+static DEFINE_PER_CPU(struct pagevec[NR_LRU_LISTS], lru_add_pvecs);
 static DEFINE_PER_CPU(struct pagevec, lru_rotate_pvecs);
 
 /*
@@ -116,8 +117,9 @@ static void pagevec_move_tail(struct pagevec *pvec)
                        zone = pagezone;
                        spin_lock(&zone->lru_lock);
                }
-               if (PageLRU(page) && !PageActive(page)) {
-                       list_move_tail(&page->lru, &zone->inactive_list);
+               if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
+                       int lru = page_is_file_cache(page);
+                       list_move_tail(&page->lru, &zone->lru[lru].list);
                        pgmoved++;
                }
        }
@@ -136,7 +138,7 @@ static void pagevec_move_tail(struct pagevec *pvec)
 void  rotate_reclaimable_page(struct page *page)
 {
        if (!PageLocked(page) && !PageDirty(page) && !PageActive(page) &&
-           PageLRU(page)) {
+           !PageUnevictable(page) && PageLRU(page)) {
                struct pagevec *pvec;
                unsigned long flags;
 
@@ -157,12 +159,19 @@ void activate_page(struct page *page)
        struct zone *zone = page_zone(page);
 
        spin_lock_irq(&zone->lru_lock);
-       if (PageLRU(page) && !PageActive(page)) {
-               del_page_from_inactive_list(zone, page);
+       if (PageLRU(page) && !PageActive(page) && !PageUnevictable(page)) {
+               int file = page_is_file_cache(page);
+               int lru = LRU_BASE + file;
+               del_page_from_lru_list(zone, page, lru);
+
                SetPageActive(page);
-               add_page_to_active_list(zone, page);
+               lru += LRU_ACTIVE;
+               add_page_to_lru_list(zone, page, lru);
                __count_vm_event(PGACTIVATE);
-               mem_cgroup_move_lists(page, true);
+               mem_cgroup_move_lists(page, lru);
+
+               zone->recent_rotated[!!file]++;
+               zone->recent_scanned[!!file]++;
        }
        spin_unlock_irq(&zone->lru_lock);
 }
@@ -176,7 +185,8 @@ void activate_page(struct page *page)
  */
 void mark_page_accessed(struct page *page)
 {
-       if (!PageActive(page) && PageReferenced(page) && PageLRU(page)) {
+       if (!PageActive(page) && !PageUnevictable(page) &&
+                       PageReferenced(page) && PageLRU(page)) {
                activate_page(page);
                ClearPageReferenced(page);
        } else if (!PageReferenced(page)) {
@@ -186,28 +196,73 @@ void mark_page_accessed(struct page *page)
 
 EXPORT_SYMBOL(mark_page_accessed);
 
-/**
- * lru_cache_add: add a page to the page lists
- * @page: the page to add
- */
-void lru_cache_add(struct page *page)
+void __lru_cache_add(struct page *page, enum lru_list lru)
 {
-       struct pagevec *pvec = &get_cpu_var(lru_add_pvecs);
+       struct pagevec *pvec = &get_cpu_var(lru_add_pvecs)[lru];
 
        page_cache_get(page);
        if (!pagevec_add(pvec, page))
-               __pagevec_lru_add(pvec);
+               ____pagevec_lru_add(pvec, lru);
        put_cpu_var(lru_add_pvecs);
 }
 
-void lru_cache_add_active(struct page *page)
+/**
+ * lru_cache_add_lru - add a page to a page list
+ * @page: the page to be added to the LRU.
+ * @lru: the LRU list to which the page is added.
+ */
+void lru_cache_add_lru(struct page *page, enum lru_list lru)
 {
-       struct pagevec *pvec = &get_cpu_var(lru_add_active_pvecs);
+       if (PageActive(page)) {
+               VM_BUG_ON(PageUnevictable(page));
+               ClearPageActive(page);
+       } else if (PageUnevictable(page)) {
+               VM_BUG_ON(PageActive(page));
+               ClearPageUnevictable(page);
+       }
 
-       page_cache_get(page);
-       if (!pagevec_add(pvec, page))
-               __pagevec_lru_add_active(pvec);
-       put_cpu_var(lru_add_active_pvecs);
+       VM_BUG_ON(PageLRU(page) || PageActive(page) || PageUnevictable(page));
+       __lru_cache_add(page, lru);
+}
+
+/**
+ * add_page_to_unevictable_list - add a page to the unevictable list
+ * @page:  the page to be added to the unevictable list
+ *
+ * Add page directly to its zone's unevictable list.  To avoid races with
+ * tasks that might be making the page evictable, through eg. munlock,
+ * munmap or exit, while it's not on the lru, we want to add the page
+ * while it's locked or otherwise "invisible" to other tasks.  This is
+ * difficult to do when using the pagevec cache, so bypass that.
+ */
+void add_page_to_unevictable_list(struct page *page)
+{
+       struct zone *zone = page_zone(page);
+
+       spin_lock_irq(&zone->lru_lock);
+       SetPageUnevictable(page);
+       SetPageLRU(page);
+       add_page_to_lru_list(zone, page, LRU_UNEVICTABLE);
+       spin_unlock_irq(&zone->lru_lock);
+}
+
+/**
+ * lru_cache_add_active_or_unevictable
+ * @page:  the page to be added to LRU
+ * @vma:   vma in which page is mapped for determining reclaimability
+ *
+ * place @page on active or unevictable LRU list, depending on
+ * page_evictable().  Note that if the page is not evictable,
+ * it goes directly back onto it's zone's unevictable list.  It does
+ * NOT use a per cpu pagevec.
+ */
+void lru_cache_add_active_or_unevictable(struct page *page,
+                                       struct vm_area_struct *vma)
+{
+       if (page_evictable(page, vma))
+               lru_cache_add_lru(page, LRU_ACTIVE + page_is_file_cache(page));
+       else
+               add_page_to_unevictable_list(page);
 }
 
 /*
@@ -217,15 +272,15 @@ void lru_cache_add_active(struct page *page)
  */
 static void drain_cpu_pagevecs(int cpu)
 {
+       struct pagevec *pvecs = per_cpu(lru_add_pvecs, cpu);
        struct pagevec *pvec;
+       int lru;
 
-       pvec = &per_cpu(lru_add_pvecs, cpu);
-       if (pagevec_count(pvec))
-               __pagevec_lru_add(pvec);
-
-       pvec = &per_cpu(lru_add_active_pvecs, cpu);
-       if (pagevec_count(pvec))
-               __pagevec_lru_add_active(pvec);
+       for_each_lru(lru) {
+               pvec = &pvecs[lru - LRU_BASE];
+               if (pagevec_count(pvec))
+                       ____pagevec_lru_add(pvec, lru);
+       }
 
        pvec = &per_cpu(lru_rotate_pvecs, cpu);
        if (pagevec_count(pvec)) {
@@ -244,7 +299,7 @@ void lru_add_drain(void)
        put_cpu();
 }
 
-#ifdef CONFIG_NUMA
+#if defined(CONFIG_NUMA) || defined(CONFIG_UNEVICTABLE_LRU)
 static void lru_add_drain_per_cpu(struct work_struct *dummy)
 {
        lru_add_drain();
@@ -308,6 +363,7 @@ void release_pages(struct page **pages, int nr, int cold)
 
                if (PageLRU(page)) {
                        struct zone *pagezone = page_zone(page);
+
                        if (pagezone != zone) {
                                if (zone)
                                        spin_unlock_irqrestore(&zone->lru_lock,
@@ -380,10 +436,11 @@ void __pagevec_release_nonlru(struct pagevec *pvec)
  * Add the passed pages to the LRU, then drop the caller's refcount
  * on them.  Reinitialises the caller's pagevec.
  */
-void __pagevec_lru_add(struct pagevec *pvec)
+void ____pagevec_lru_add(struct pagevec *pvec, enum lru_list lru)
 {
        int i;
        struct zone *zone = NULL;
+       VM_BUG_ON(is_unevictable_lru(lru));
 
        for (i = 0; i < pagevec_count(pvec); i++) {
                struct page *page = pvec->pages[i];
@@ -395,9 +452,13 @@ void __pagevec_lru_add(struct pagevec *pvec)
                        zone = pagezone;
                        spin_lock_irq(&zone->lru_lock);
                }
+               VM_BUG_ON(PageActive(page));
+               VM_BUG_ON(PageUnevictable(page));
                VM_BUG_ON(PageLRU(page));
                SetPageLRU(page);
-               add_page_to_inactive_list(zone, page);
+               if (is_active_lru(lru))
+                       SetPageActive(page);
+               add_page_to_lru_list(zone, page, lru);
        }
        if (zone)
                spin_unlock_irq(&zone->lru_lock);
@@ -405,48 +466,45 @@ void __pagevec_lru_add(struct pagevec *pvec)
        pagevec_reinit(pvec);
 }
 
-EXPORT_SYMBOL(__pagevec_lru_add);
+EXPORT_SYMBOL(____pagevec_lru_add);
 
-void __pagevec_lru_add_active(struct pagevec *pvec)
+/*
+ * Try to drop buffers from the pages in a pagevec
+ */
+void pagevec_strip(struct pagevec *pvec)
 {
        int i;
-       struct zone *zone = NULL;
 
        for (i = 0; i < pagevec_count(pvec); i++) {
                struct page *page = pvec->pages[i];
-               struct zone *pagezone = page_zone(page);
 
-               if (pagezone != zone) {
-                       if (zone)
-                               spin_unlock_irq(&zone->lru_lock);
-                       zone = pagezone;
-                       spin_lock_irq(&zone->lru_lock);
+               if (PagePrivate(page) && trylock_page(page)) {
+                       if (PagePrivate(page))
+                               try_to_release_page(page, 0);
+                       unlock_page(page);
                }
-               VM_BUG_ON(PageLRU(page));
-               SetPageLRU(page);
-               VM_BUG_ON(PageActive(page));
-               SetPageActive(page);
-               add_page_to_active_list(zone, page);
        }
-       if (zone)
-               spin_unlock_irq(&zone->lru_lock);
-       release_pages(pvec->pages, pvec->nr, pvec->cold);
-       pagevec_reinit(pvec);
 }
 
-/*
- * Try to drop buffers from the pages in a pagevec
+/**
+ * pagevec_swap_free - try to free swap space from the pages in a pagevec
+ * @pvec: pagevec with swapcache pages to free the swap space of
+ *
+ * The caller needs to hold an extra reference to each page and
+ * not hold the page lock on the pages.  This function uses a
+ * trylock on the page lock so it may not always free the swap
+ * space associated with a page.
  */
-void pagevec_strip(struct pagevec *pvec)
+void pagevec_swap_free(struct pagevec *pvec)
 {
        int i;
 
        for (i = 0; i < pagevec_count(pvec); i++) {
                struct page *page = pvec->pages[i];
 
-               if (PagePrivate(page) && trylock_page(page)) {
-                       if (PagePrivate(page))
-                               try_to_release_page(page, 0);
+               if (PageSwapCache(page) && trylock_page(page)) {
+                       if (PageSwapCache(page))
+                               remove_exclusive_swap_page_ref(page);
                        unlock_page(page);
                }
        }
index 797c3831cbec7401ccfecd3ecdc98c7667c8d6bb..3353c9029cef1cdf4b3f86231bc931b0d732f540 100644 (file)
@@ -33,7 +33,7 @@ static const struct address_space_operations swap_aops = {
 };
 
 static struct backing_dev_info swap_backing_dev_info = {
-       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK,
+       .capabilities   = BDI_CAP_NO_ACCT_AND_WRITEBACK | BDI_CAP_SWAP_BACKED,
        .unplug_io_fn   = swap_unplug_io_fn,
 };
 
@@ -75,6 +75,7 @@ int add_to_swap_cache(struct page *page, swp_entry_t entry, gfp_t gfp_mask)
        BUG_ON(!PageLocked(page));
        BUG_ON(PageSwapCache(page));
        BUG_ON(PagePrivate(page));
+       BUG_ON(!PageSwapBacked(page));
        error = radix_tree_preload(gfp_mask);
        if (!error) {
                page_cache_get(page);
@@ -302,17 +303,19 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
                 * re-using the just freed swap entry for an existing page.
                 * May fail (-ENOMEM) if radix-tree node allocation failed.
                 */
-               set_page_locked(new_page);
+               __set_page_locked(new_page);
+               SetPageSwapBacked(new_page);
                err = add_to_swap_cache(new_page, entry, gfp_mask & GFP_KERNEL);
                if (likely(!err)) {
                        /*
                         * Initiate read into locked page and return.
                         */
-                       lru_cache_add_active(new_page);
+                       lru_cache_add_anon(new_page);
                        swap_readpage(NULL, new_page);
                        return new_page;
                }
-               clear_page_locked(new_page);
+               ClearPageSwapBacked(new_page);
+               __clear_page_locked(new_page);
                swap_free(entry);
        } while (err != -ENOMEM);
 
index 1e330f2998fa259d2733f73f4c50ce0d649c5dc0..90cb67a5417cccea9f0352b6316f747bec4c608d 100644 (file)
@@ -344,7 +344,7 @@ int can_share_swap_page(struct page *page)
  * Work out if there are any other processes sharing this
  * swap cache page. Free it if you can. Return success.
  */
-int remove_exclusive_swap_page(struct page *page)
+static int remove_exclusive_swap_page_count(struct page *page, int count)
 {
        int retval;
        struct swap_info_struct * p;
@@ -357,7 +357,7 @@ int remove_exclusive_swap_page(struct page *page)
                return 0;
        if (PageWriteback(page))
                return 0;
-       if (page_count(page) != 2) /* 2: us + cache */
+       if (page_count(page) != count) /* us + cache + ptes */
                return 0;
 
        entry.val = page_private(page);
@@ -370,7 +370,7 @@ int remove_exclusive_swap_page(struct page *page)
        if (p->swap_map[swp_offset(entry)] == 1) {
                /* Recheck the page count with the swapcache lock held.. */
                spin_lock_irq(&swapper_space.tree_lock);
-               if ((page_count(page) == 2) && !PageWriteback(page)) {
+               if ((page_count(page) == count) && !PageWriteback(page)) {
                        __delete_from_swap_cache(page);
                        SetPageDirty(page);
                        retval = 1;
@@ -387,6 +387,25 @@ int remove_exclusive_swap_page(struct page *page)
        return retval;
 }
 
+/*
+ * Most of the time the page should have two references: one for the
+ * process and one for the swap cache.
+ */
+int remove_exclusive_swap_page(struct page *page)
+{
+       return remove_exclusive_swap_page_count(page, 2);
+}
+
+/*
+ * The pageout code holds an extra reference to the page.  That raises
+ * the reference count to test for to 2 for a page that is only in the
+ * swap cache plus 1 for each process that maps the page.
+ */
+int remove_exclusive_swap_page_ref(struct page *page)
+{
+       return remove_exclusive_swap_page_count(page, 2 + page_mapcount(page));
+}
+
 /*
  * Free the swap entry like above, but also try to
  * free the page cache entry if it is the last user.
@@ -403,7 +422,7 @@ void free_swap_and_cache(swp_entry_t entry)
        if (p) {
                if (swap_entry_free(p, swp_offset(entry)) == 1) {
                        page = find_get_page(&swapper_space, entry.val);
-                       if (page && unlikely(!trylock_page(page))) {
+                       if (page && !trylock_page(page)) {
                                page_cache_release(page);
                                page = NULL;
                        }
index e83e4b114ef12b78c74480cd0ddaa6b4369d3b4c..1229211104f84beb0e05e5df891f1780d392e418 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/task_io_accounting_ops.h>
 #include <linux/buffer_head.h> /* grr. try_to_release_page,
                                   do_invalidatepage */
+#include "internal.h"
 
 
 /**
@@ -103,6 +104,7 @@ truncate_complete_page(struct address_space *mapping, struct page *page)
 
        cancel_dirty_page(page, PAGE_CACHE_SIZE);
 
+       clear_page_mlock(page);
        remove_from_page_cache(page);
        ClearPageMappedToDisk(page);
        page_cache_release(page);       /* pagecache ref */
@@ -127,6 +129,7 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)
        if (PagePrivate(page) && !try_to_release_page(page, 0))
                return 0;
 
+       clear_page_mlock(page);
        ret = remove_mapping(mapping, page);
 
        return ret;
@@ -352,6 +355,7 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page)
        if (PageDirty(page))
                goto failed;
 
+       clear_page_mlock(page);
        BUG_ON(PagePrivate(page));
        __remove_from_page_cache(page);
        spin_unlock_irq(&mapping->tree_lock);
index bba06c41fc59ed10be118f7af24ecfa71d023c33..712ae47af0bf5f23a4b32ea0497dd2f6e8272085 100644 (file)
@@ -8,6 +8,7 @@
  *  Numa awareness, Christoph Lameter, SGI, June 2005
  */
 
+#include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/highmem.h>
 #include <linux/debugobjects.h>
 #include <linux/vmalloc.h>
 #include <linux/kallsyms.h>
+#include <linux/list.h>
+#include <linux/rbtree.h>
+#include <linux/radix-tree.h>
+#include <linux/rcupdate.h>
 
+#include <asm/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
 
 
-DEFINE_RWLOCK(vmlist_lock);
-struct vm_struct *vmlist;
-
-static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
-                           int node, void *caller);
+/*** Page table manipulation functions ***/
 
 static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
 {
@@ -40,8 +42,7 @@ static void vunmap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end)
        } while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
-static inline void vunmap_pmd_range(pud_t *pud, unsigned long addr,
-                                               unsigned long end)
+static void vunmap_pmd_range(pud_t *pud, unsigned long addr, unsigned long end)
 {
        pmd_t *pmd;
        unsigned long next;
@@ -55,8 +56,7 @@ static inline void vunmap_pmd_range(pud_t *pud, unsigned long addr,
        } while (pmd++, addr = next, addr != end);
 }
 
-static inline void vunmap_pud_range(pgd_t *pgd, unsigned long addr,
-                                               unsigned long end)
+static void vunmap_pud_range(pgd_t *pgd, unsigned long addr, unsigned long end)
 {
        pud_t *pud;
        unsigned long next;
@@ -70,12 +70,10 @@ static inline void vunmap_pud_range(pgd_t *pgd, unsigned long addr,
        } while (pud++, addr = next, addr != end);
 }
 
-void unmap_kernel_range(unsigned long addr, unsigned long size)
+static void vunmap_page_range(unsigned long addr, unsigned long end)
 {
        pgd_t *pgd;
        unsigned long next;
-       unsigned long start = addr;
-       unsigned long end = addr + size;
 
        BUG_ON(addr >= end);
        pgd = pgd_offset_k(addr);
@@ -86,35 +84,36 @@ void unmap_kernel_range(unsigned long addr, unsigned long size)
                        continue;
                vunmap_pud_range(pgd, addr, next);
        } while (pgd++, addr = next, addr != end);
-       flush_tlb_kernel_range(start, end);
-}
-
-static void unmap_vm_area(struct vm_struct *area)
-{
-       unmap_kernel_range((unsigned long)area->addr, area->size);
 }
 
 static int vmap_pte_range(pmd_t *pmd, unsigned long addr,
-                       unsigned long end, pgprot_t prot, struct page ***pages)
+               unsigned long end, pgprot_t prot, struct page **pages, int *nr)
 {
        pte_t *pte;
 
+       /*
+        * nr is a running index into the array which helps higher level
+        * callers keep track of where we're up to.
+        */
+
        pte = pte_alloc_kernel(pmd, addr);
        if (!pte)
                return -ENOMEM;
        do {
-               struct page *page = **pages;
-               WARN_ON(!pte_none(*pte));
-               if (!page)
+               struct page *page = pages[*nr];
+
+               if (WARN_ON(!pte_none(*pte)))
+                       return -EBUSY;
+               if (WARN_ON(!page))
                        return -ENOMEM;
                set_pte_at(&init_mm, addr, pte, mk_pte(page, prot));
-               (*pages)++;
+               (*nr)++;
        } while (pte++, addr += PAGE_SIZE, addr != end);
        return 0;
 }
 
-static inline int vmap_pmd_range(pud_t *pud, unsigned long addr,
-                       unsigned long end, pgprot_t prot, struct page ***pages)
+static int vmap_pmd_range(pud_t *pud, unsigned long addr,
+               unsigned long end, pgprot_t prot, struct page **pages, int *nr)
 {
        pmd_t *pmd;
        unsigned long next;
@@ -124,14 +123,14 @@ static inline int vmap_pmd_range(pud_t *pud, unsigned long addr,
                return -ENOMEM;
        do {
                next = pmd_addr_end(addr, end);
-               if (vmap_pte_range(pmd, addr, next, prot, pages))
+               if (vmap_pte_range(pmd, addr, next, prot, pages, nr))
                        return -ENOMEM;
        } while (pmd++, addr = next, addr != end);
        return 0;
 }
 
-static inline int vmap_pud_range(pgd_t *pgd, unsigned long addr,
-                       unsigned long end, pgprot_t prot, struct page ***pages)
+static int vmap_pud_range(pgd_t *pgd, unsigned long addr,
+               unsigned long end, pgprot_t prot, struct page **pages, int *nr)
 {
        pud_t *pud;
        unsigned long next;
@@ -141,44 +140,49 @@ static inline int vmap_pud_range(pgd_t *pgd, unsigned long addr,
                return -ENOMEM;
        do {
                next = pud_addr_end(addr, end);
-               if (vmap_pmd_range(pud, addr, next, prot, pages))
+               if (vmap_pmd_range(pud, addr, next, prot, pages, nr))
                        return -ENOMEM;
        } while (pud++, addr = next, addr != end);
        return 0;
 }
 
-int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
+/*
+ * Set up page tables in kva (addr, end). The ptes shall have prot "prot", and
+ * will have pfns corresponding to the "pages" array.
+ *
+ * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N]
+ */
+static int vmap_page_range(unsigned long addr, unsigned long end,
+                               pgprot_t prot, struct page **pages)
 {
        pgd_t *pgd;
        unsigned long next;
-       unsigned long addr = (unsigned long) area->addr;
-       unsigned long end = addr + area->size - PAGE_SIZE;
-       int err;
+       int err = 0;
+       int nr = 0;
 
        BUG_ON(addr >= end);
        pgd = pgd_offset_k(addr);
        do {
                next = pgd_addr_end(addr, end);
-               err = vmap_pud_range(pgd, addr, next, prot, pages);
+               err = vmap_pud_range(pgd, addr, next, prot, pages, &nr);
                if (err)
                        break;
        } while (pgd++, addr = next, addr != end);
-       flush_cache_vmap((unsigned long) area->addr, end);
-       return err;
+       flush_cache_vmap(addr, end);
+
+       if (unlikely(err))
+               return err;
+       return nr;
 }
-EXPORT_SYMBOL_GPL(map_vm_area);
 
 /*
- * Map a vmalloc()-space virtual address to the physical page.
+ * Walk a vmap address to the struct page it maps.
  */
 struct page *vmalloc_to_page(const void *vmalloc_addr)
 {
        unsigned long addr = (unsigned long) vmalloc_addr;
        struct page *page = NULL;
        pgd_t *pgd = pgd_offset_k(addr);
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *ptep, pte;
 
        /*
         * XXX we might need to change this if we add VIRTUAL_BUG_ON for
@@ -188,10 +192,12 @@ struct page *vmalloc_to_page(const void *vmalloc_addr)
                        !is_module_address(addr));
 
        if (!pgd_none(*pgd)) {
-               pud = pud_offset(pgd, addr);
+               pud_t *pud = pud_offset(pgd, addr);
                if (!pud_none(*pud)) {
-                       pmd = pmd_offset(pud, addr);
+                       pmd_t *pmd = pmd_offset(pud, addr);
                        if (!pmd_none(*pmd)) {
+                               pte_t *ptep, pte;
+
                                ptep = pte_offset_map(pmd, addr);
                                pte = *ptep;
                                if (pte_present(pte))
@@ -213,13 +219,751 @@ unsigned long vmalloc_to_pfn(const void *vmalloc_addr)
 }
 EXPORT_SYMBOL(vmalloc_to_pfn);
 
-static struct vm_struct *
-__get_vm_area_node(unsigned long size, unsigned long flags, unsigned long start,
-               unsigned long end, int node, gfp_t gfp_mask, void *caller)
+
+/*** Global kva allocator ***/
+
+#define VM_LAZY_FREE   0x01
+#define VM_LAZY_FREEING        0x02
+#define VM_VM_AREA     0x04
+
+struct vmap_area {
+       unsigned long va_start;
+       unsigned long va_end;
+       unsigned long flags;
+       struct rb_node rb_node;         /* address sorted rbtree */
+       struct list_head list;          /* address sorted list */
+       struct list_head purge_list;    /* "lazy purge" list */
+       void *private;
+       struct rcu_head rcu_head;
+};
+
+static DEFINE_SPINLOCK(vmap_area_lock);
+static struct rb_root vmap_area_root = RB_ROOT;
+static LIST_HEAD(vmap_area_list);
+
+static struct vmap_area *__find_vmap_area(unsigned long addr)
 {
-       struct vm_struct **p, *tmp, *area;
-       unsigned long align = 1;
+       struct rb_node *n = vmap_area_root.rb_node;
+
+       while (n) {
+               struct vmap_area *va;
+
+               va = rb_entry(n, struct vmap_area, rb_node);
+               if (addr < va->va_start)
+                       n = n->rb_left;
+               else if (addr > va->va_start)
+                       n = n->rb_right;
+               else
+                       return va;
+       }
+
+       return NULL;
+}
+
+static void __insert_vmap_area(struct vmap_area *va)
+{
+       struct rb_node **p = &vmap_area_root.rb_node;
+       struct rb_node *parent = NULL;
+       struct rb_node *tmp;
+
+       while (*p) {
+               struct vmap_area *tmp;
+
+               parent = *p;
+               tmp = rb_entry(parent, struct vmap_area, rb_node);
+               if (va->va_start < tmp->va_end)
+                       p = &(*p)->rb_left;
+               else if (va->va_end > tmp->va_start)
+                       p = &(*p)->rb_right;
+               else
+                       BUG();
+       }
+
+       rb_link_node(&va->rb_node, parent, p);
+       rb_insert_color(&va->rb_node, &vmap_area_root);
+
+       /* address-sort this list so it is usable like the vmlist */
+       tmp = rb_prev(&va->rb_node);
+       if (tmp) {
+               struct vmap_area *prev;
+               prev = rb_entry(tmp, struct vmap_area, rb_node);
+               list_add_rcu(&va->list, &prev->list);
+       } else
+               list_add_rcu(&va->list, &vmap_area_list);
+}
+
+static void purge_vmap_area_lazy(void);
+
+/*
+ * Allocate a region of KVA of the specified size and alignment, within the
+ * vstart and vend.
+ */
+static struct vmap_area *alloc_vmap_area(unsigned long size,
+                               unsigned long align,
+                               unsigned long vstart, unsigned long vend,
+                               int node, gfp_t gfp_mask)
+{
+       struct vmap_area *va;
+       struct rb_node *n;
+       unsigned long addr;
+       int purged = 0;
+
+       BUG_ON(size & ~PAGE_MASK);
+
+       addr = ALIGN(vstart, align);
+
+       va = kmalloc_node(sizeof(struct vmap_area),
+                       gfp_mask & GFP_RECLAIM_MASK, node);
+       if (unlikely(!va))
+               return ERR_PTR(-ENOMEM);
+
+retry:
+       spin_lock(&vmap_area_lock);
+       /* XXX: could have a last_hole cache */
+       n = vmap_area_root.rb_node;
+       if (n) {
+               struct vmap_area *first = NULL;
+
+               do {
+                       struct vmap_area *tmp;
+                       tmp = rb_entry(n, struct vmap_area, rb_node);
+                       if (tmp->va_end >= addr) {
+                               if (!first && tmp->va_start < addr + size)
+                                       first = tmp;
+                               n = n->rb_left;
+                       } else {
+                               first = tmp;
+                               n = n->rb_right;
+                       }
+               } while (n);
+
+               if (!first)
+                       goto found;
+
+               if (first->va_end < addr) {
+                       n = rb_next(&first->rb_node);
+                       if (n)
+                               first = rb_entry(n, struct vmap_area, rb_node);
+                       else
+                               goto found;
+               }
+
+               while (addr + size >= first->va_start && addr + size <= vend) {
+                       addr = ALIGN(first->va_end + PAGE_SIZE, align);
+
+                       n = rb_next(&first->rb_node);
+                       if (n)
+                               first = rb_entry(n, struct vmap_area, rb_node);
+                       else
+                               goto found;
+               }
+       }
+found:
+       if (addr + size > vend) {
+               spin_unlock(&vmap_area_lock);
+               if (!purged) {
+                       purge_vmap_area_lazy();
+                       purged = 1;
+                       goto retry;
+               }
+               if (printk_ratelimit())
+                       printk(KERN_WARNING "vmap allocation failed: "
+                                "use vmalloc=<size> to increase size.\n");
+               return ERR_PTR(-EBUSY);
+       }
+
+       BUG_ON(addr & (align-1));
+
+       va->va_start = addr;
+       va->va_end = addr + size;
+       va->flags = 0;
+       __insert_vmap_area(va);
+       spin_unlock(&vmap_area_lock);
+
+       return va;
+}
+
+static void rcu_free_va(struct rcu_head *head)
+{
+       struct vmap_area *va = container_of(head, struct vmap_area, rcu_head);
+
+       kfree(va);
+}
+
+static void __free_vmap_area(struct vmap_area *va)
+{
+       BUG_ON(RB_EMPTY_NODE(&va->rb_node));
+       rb_erase(&va->rb_node, &vmap_area_root);
+       RB_CLEAR_NODE(&va->rb_node);
+       list_del_rcu(&va->list);
+
+       call_rcu(&va->rcu_head, rcu_free_va);
+}
+
+/*
+ * Free a region of KVA allocated by alloc_vmap_area
+ */
+static void free_vmap_area(struct vmap_area *va)
+{
+       spin_lock(&vmap_area_lock);
+       __free_vmap_area(va);
+       spin_unlock(&vmap_area_lock);
+}
+
+/*
+ * Clear the pagetable entries of a given vmap_area
+ */
+static void unmap_vmap_area(struct vmap_area *va)
+{
+       vunmap_page_range(va->va_start, va->va_end);
+}
+
+/*
+ * lazy_max_pages is the maximum amount of virtual address space we gather up
+ * before attempting to purge with a TLB flush.
+ *
+ * There is a tradeoff here: a larger number will cover more kernel page tables
+ * and take slightly longer to purge, but it will linearly reduce the number of
+ * global TLB flushes that must be performed. It would seem natural to scale
+ * this number up linearly with the number of CPUs (because vmapping activity
+ * could also scale linearly with the number of CPUs), however it is likely
+ * that in practice, workloads might be constrained in other ways that mean
+ * vmap activity will not scale linearly with CPUs. Also, I want to be
+ * conservative and not introduce a big latency on huge systems, so go with
+ * a less aggressive log scale. It will still be an improvement over the old
+ * code, and it will be simple to change the scale factor if we find that it
+ * becomes a problem on bigger systems.
+ */
+static unsigned long lazy_max_pages(void)
+{
+       unsigned int log;
+
+       log = fls(num_online_cpus());
+
+       return log * (32UL * 1024 * 1024 / PAGE_SIZE);
+}
+
+static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
+
+/*
+ * Purges all lazily-freed vmap areas.
+ *
+ * If sync is 0 then don't purge if there is already a purge in progress.
+ * If force_flush is 1, then flush kernel TLBs between *start and *end even
+ * if we found no lazy vmap areas to unmap (callers can use this to optimise
+ * their own TLB flushing).
+ * Returns with *start = min(*start, lowest purged address)
+ *              *end = max(*end, highest purged address)
+ */
+static void __purge_vmap_area_lazy(unsigned long *start, unsigned long *end,
+                                       int sync, int force_flush)
+{
+       static DEFINE_SPINLOCK(purge_lock);
+       LIST_HEAD(valist);
+       struct vmap_area *va;
+       int nr = 0;
+
+       /*
+        * If sync is 0 but force_flush is 1, we'll go sync anyway but callers
+        * should not expect such behaviour. This just simplifies locking for
+        * the case that isn't actually used at the moment anyway.
+        */
+       if (!sync && !force_flush) {
+               if (!spin_trylock(&purge_lock))
+                       return;
+       } else
+               spin_lock(&purge_lock);
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(va, &vmap_area_list, list) {
+               if (va->flags & VM_LAZY_FREE) {
+                       if (va->va_start < *start)
+                               *start = va->va_start;
+                       if (va->va_end > *end)
+                               *end = va->va_end;
+                       nr += (va->va_end - va->va_start) >> PAGE_SHIFT;
+                       unmap_vmap_area(va);
+                       list_add_tail(&va->purge_list, &valist);
+                       va->flags |= VM_LAZY_FREEING;
+                       va->flags &= ~VM_LAZY_FREE;
+               }
+       }
+       rcu_read_unlock();
+
+       if (nr) {
+               BUG_ON(nr > atomic_read(&vmap_lazy_nr));
+               atomic_sub(nr, &vmap_lazy_nr);
+       }
+
+       if (nr || force_flush)
+               flush_tlb_kernel_range(*start, *end);
+
+       if (nr) {
+               spin_lock(&vmap_area_lock);
+               list_for_each_entry(va, &valist, purge_list)
+                       __free_vmap_area(va);
+               spin_unlock(&vmap_area_lock);
+       }
+       spin_unlock(&purge_lock);
+}
+
+/*
+ * Kick off a purge of the outstanding lazy areas.
+ */
+static void purge_vmap_area_lazy(void)
+{
+       unsigned long start = ULONG_MAX, end = 0;
+
+       __purge_vmap_area_lazy(&start, &end, 0, 0);
+}
+
+/*
+ * Free and unmap a vmap area
+ */
+static void free_unmap_vmap_area(struct vmap_area *va)
+{
+       va->flags |= VM_LAZY_FREE;
+       atomic_add((va->va_end - va->va_start) >> PAGE_SHIFT, &vmap_lazy_nr);
+       if (unlikely(atomic_read(&vmap_lazy_nr) > lazy_max_pages()))
+               purge_vmap_area_lazy();
+}
+
+static struct vmap_area *find_vmap_area(unsigned long addr)
+{
+       struct vmap_area *va;
+
+       spin_lock(&vmap_area_lock);
+       va = __find_vmap_area(addr);
+       spin_unlock(&vmap_area_lock);
+
+       return va;
+}
+
+static void free_unmap_vmap_area_addr(unsigned long addr)
+{
+       struct vmap_area *va;
+
+       va = find_vmap_area(addr);
+       BUG_ON(!va);
+       free_unmap_vmap_area(va);
+}
+
+
+/*** Per cpu kva allocator ***/
+
+/*
+ * vmap space is limited especially on 32 bit architectures. Ensure there is
+ * room for at least 16 percpu vmap blocks per CPU.
+ */
+/*
+ * If we had a constant VMALLOC_START and VMALLOC_END, we'd like to be able
+ * to #define VMALLOC_SPACE            (VMALLOC_END-VMALLOC_START). Guess
+ * instead (we just need a rough idea)
+ */
+#if BITS_PER_LONG == 32
+#define VMALLOC_SPACE          (128UL*1024*1024)
+#else
+#define VMALLOC_SPACE          (128UL*1024*1024*1024)
+#endif
+
+#define VMALLOC_PAGES          (VMALLOC_SPACE / PAGE_SIZE)
+#define VMAP_MAX_ALLOC         BITS_PER_LONG   /* 256K with 4K pages */
+#define VMAP_BBMAP_BITS_MAX    1024    /* 4MB with 4K pages */
+#define VMAP_BBMAP_BITS_MIN    (VMAP_MAX_ALLOC*2)
+#define VMAP_MIN(x, y)         ((x) < (y) ? (x) : (y)) /* can't use min() */
+#define VMAP_MAX(x, y)         ((x) > (y) ? (x) : (y)) /* can't use max() */
+#define VMAP_BBMAP_BITS                VMAP_MIN(VMAP_BBMAP_BITS_MAX,           \
+                                       VMAP_MAX(VMAP_BBMAP_BITS_MIN,   \
+                                               VMALLOC_PAGES / NR_CPUS / 16))
+
+#define VMAP_BLOCK_SIZE                (VMAP_BBMAP_BITS * PAGE_SIZE)
+
+struct vmap_block_queue {
+       spinlock_t lock;
+       struct list_head free;
+       struct list_head dirty;
+       unsigned int nr_dirty;
+};
+
+struct vmap_block {
+       spinlock_t lock;
+       struct vmap_area *va;
+       struct vmap_block_queue *vbq;
+       unsigned long free, dirty;
+       DECLARE_BITMAP(alloc_map, VMAP_BBMAP_BITS);
+       DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS);
+       union {
+               struct {
+                       struct list_head free_list;
+                       struct list_head dirty_list;
+               };
+               struct rcu_head rcu_head;
+       };
+};
+
+/* Queue of free and dirty vmap blocks, for allocation and flushing purposes */
+static DEFINE_PER_CPU(struct vmap_block_queue, vmap_block_queue);
+
+/*
+ * Radix tree of vmap blocks, indexed by address, to quickly find a vmap block
+ * in the free path. Could get rid of this if we change the API to return a
+ * "cookie" from alloc, to be passed to free. But no big deal yet.
+ */
+static DEFINE_SPINLOCK(vmap_block_tree_lock);
+static RADIX_TREE(vmap_block_tree, GFP_ATOMIC);
+
+/*
+ * We should probably have a fallback mechanism to allocate virtual memory
+ * out of partially filled vmap blocks. However vmap block sizing should be
+ * fairly reasonable according to the vmalloc size, so it shouldn't be a
+ * big problem.
+ */
+
+static unsigned long addr_to_vb_idx(unsigned long addr)
+{
+       addr -= VMALLOC_START & ~(VMAP_BLOCK_SIZE-1);
+       addr /= VMAP_BLOCK_SIZE;
+       return addr;
+}
+
+static struct vmap_block *new_vmap_block(gfp_t gfp_mask)
+{
+       struct vmap_block_queue *vbq;
+       struct vmap_block *vb;
+       struct vmap_area *va;
+       unsigned long vb_idx;
+       int node, err;
+
+       node = numa_node_id();
+
+       vb = kmalloc_node(sizeof(struct vmap_block),
+                       gfp_mask & GFP_RECLAIM_MASK, node);
+       if (unlikely(!vb))
+               return ERR_PTR(-ENOMEM);
+
+       va = alloc_vmap_area(VMAP_BLOCK_SIZE, VMAP_BLOCK_SIZE,
+                                       VMALLOC_START, VMALLOC_END,
+                                       node, gfp_mask);
+       if (unlikely(IS_ERR(va))) {
+               kfree(vb);
+               return ERR_PTR(PTR_ERR(va));
+       }
+
+       err = radix_tree_preload(gfp_mask);
+       if (unlikely(err)) {
+               kfree(vb);
+               free_vmap_area(va);
+               return ERR_PTR(err);
+       }
+
+       spin_lock_init(&vb->lock);
+       vb->va = va;
+       vb->free = VMAP_BBMAP_BITS;
+       vb->dirty = 0;
+       bitmap_zero(vb->alloc_map, VMAP_BBMAP_BITS);
+       bitmap_zero(vb->dirty_map, VMAP_BBMAP_BITS);
+       INIT_LIST_HEAD(&vb->free_list);
+       INIT_LIST_HEAD(&vb->dirty_list);
+
+       vb_idx = addr_to_vb_idx(va->va_start);
+       spin_lock(&vmap_block_tree_lock);
+       err = radix_tree_insert(&vmap_block_tree, vb_idx, vb);
+       spin_unlock(&vmap_block_tree_lock);
+       BUG_ON(err);
+       radix_tree_preload_end();
+
+       vbq = &get_cpu_var(vmap_block_queue);
+       vb->vbq = vbq;
+       spin_lock(&vbq->lock);
+       list_add(&vb->free_list, &vbq->free);
+       spin_unlock(&vbq->lock);
+       put_cpu_var(vmap_cpu_blocks);
+
+       return vb;
+}
+
+static void rcu_free_vb(struct rcu_head *head)
+{
+       struct vmap_block *vb = container_of(head, struct vmap_block, rcu_head);
+
+       kfree(vb);
+}
+
+static void free_vmap_block(struct vmap_block *vb)
+{
+       struct vmap_block *tmp;
+       unsigned long vb_idx;
+
+       spin_lock(&vb->vbq->lock);
+       if (!list_empty(&vb->free_list))
+               list_del(&vb->free_list);
+       if (!list_empty(&vb->dirty_list))
+               list_del(&vb->dirty_list);
+       spin_unlock(&vb->vbq->lock);
+
+       vb_idx = addr_to_vb_idx(vb->va->va_start);
+       spin_lock(&vmap_block_tree_lock);
+       tmp = radix_tree_delete(&vmap_block_tree, vb_idx);
+       spin_unlock(&vmap_block_tree_lock);
+       BUG_ON(tmp != vb);
+
+       free_unmap_vmap_area(vb->va);
+       call_rcu(&vb->rcu_head, rcu_free_vb);
+}
+
+static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
+{
+       struct vmap_block_queue *vbq;
+       struct vmap_block *vb;
+       unsigned long addr = 0;
+       unsigned int order;
+
+       BUG_ON(size & ~PAGE_MASK);
+       BUG_ON(size > PAGE_SIZE*VMAP_MAX_ALLOC);
+       order = get_order(size);
+
+again:
+       rcu_read_lock();
+       vbq = &get_cpu_var(vmap_block_queue);
+       list_for_each_entry_rcu(vb, &vbq->free, free_list) {
+               int i;
+
+               spin_lock(&vb->lock);
+               i = bitmap_find_free_region(vb->alloc_map,
+                                               VMAP_BBMAP_BITS, order);
+
+               if (i >= 0) {
+                       addr = vb->va->va_start + (i << PAGE_SHIFT);
+                       BUG_ON(addr_to_vb_idx(addr) !=
+                                       addr_to_vb_idx(vb->va->va_start));
+                       vb->free -= 1UL << order;
+                       if (vb->free == 0) {
+                               spin_lock(&vbq->lock);
+                               list_del_init(&vb->free_list);
+                               spin_unlock(&vbq->lock);
+                       }
+                       spin_unlock(&vb->lock);
+                       break;
+               }
+               spin_unlock(&vb->lock);
+       }
+       put_cpu_var(vmap_cpu_blocks);
+       rcu_read_unlock();
+
+       if (!addr) {
+               vb = new_vmap_block(gfp_mask);
+               if (IS_ERR(vb))
+                       return vb;
+               goto again;
+       }
+
+       return (void *)addr;
+}
+
+static void vb_free(const void *addr, unsigned long size)
+{
+       unsigned long offset;
+       unsigned long vb_idx;
+       unsigned int order;
+       struct vmap_block *vb;
+
+       BUG_ON(size & ~PAGE_MASK);
+       BUG_ON(size > PAGE_SIZE*VMAP_MAX_ALLOC);
+       order = get_order(size);
+
+       offset = (unsigned long)addr & (VMAP_BLOCK_SIZE - 1);
+
+       vb_idx = addr_to_vb_idx((unsigned long)addr);
+       rcu_read_lock();
+       vb = radix_tree_lookup(&vmap_block_tree, vb_idx);
+       rcu_read_unlock();
+       BUG_ON(!vb);
+
+       spin_lock(&vb->lock);
+       bitmap_allocate_region(vb->dirty_map, offset >> PAGE_SHIFT, order);
+       if (!vb->dirty) {
+               spin_lock(&vb->vbq->lock);
+               list_add(&vb->dirty_list, &vb->vbq->dirty);
+               spin_unlock(&vb->vbq->lock);
+       }
+       vb->dirty += 1UL << order;
+       if (vb->dirty == VMAP_BBMAP_BITS) {
+               BUG_ON(vb->free || !list_empty(&vb->free_list));
+               spin_unlock(&vb->lock);
+               free_vmap_block(vb);
+       } else
+               spin_unlock(&vb->lock);
+}
+
+/**
+ * vm_unmap_aliases - unmap outstanding lazy aliases in the vmap layer
+ *
+ * The vmap/vmalloc layer lazily flushes kernel virtual mappings primarily
+ * to amortize TLB flushing overheads. What this means is that any page you
+ * have now, may, in a former life, have been mapped into kernel virtual
+ * address by the vmap layer and so there might be some CPUs with TLB entries
+ * still referencing that page (additional to the regular 1:1 kernel mapping).
+ *
+ * vm_unmap_aliases flushes all such lazy mappings. After it returns, we can
+ * be sure that none of the pages we have control over will have any aliases
+ * from the vmap layer.
+ */
+void vm_unmap_aliases(void)
+{
+       unsigned long start = ULONG_MAX, end = 0;
+       int cpu;
+       int flush = 0;
+
+       for_each_possible_cpu(cpu) {
+               struct vmap_block_queue *vbq = &per_cpu(vmap_block_queue, cpu);
+               struct vmap_block *vb;
+
+               rcu_read_lock();
+               list_for_each_entry_rcu(vb, &vbq->free, free_list) {
+                       int i;
+
+                       spin_lock(&vb->lock);
+                       i = find_first_bit(vb->dirty_map, VMAP_BBMAP_BITS);
+                       while (i < VMAP_BBMAP_BITS) {
+                               unsigned long s, e;
+                               int j;
+                               j = find_next_zero_bit(vb->dirty_map,
+                                       VMAP_BBMAP_BITS, i);
+
+                               s = vb->va->va_start + (i << PAGE_SHIFT);
+                               e = vb->va->va_start + (j << PAGE_SHIFT);
+                               vunmap_page_range(s, e);
+                               flush = 1;
+
+                               if (s < start)
+                                       start = s;
+                               if (e > end)
+                                       end = e;
+
+                               i = j;
+                               i = find_next_bit(vb->dirty_map,
+                                                       VMAP_BBMAP_BITS, i);
+                       }
+                       spin_unlock(&vb->lock);
+               }
+               rcu_read_unlock();
+       }
+
+       __purge_vmap_area_lazy(&start, &end, 1, flush);
+}
+EXPORT_SYMBOL_GPL(vm_unmap_aliases);
+
+/**
+ * vm_unmap_ram - unmap linear kernel address space set up by vm_map_ram
+ * @mem: the pointer returned by vm_map_ram
+ * @count: the count passed to that vm_map_ram call (cannot unmap partial)
+ */
+void vm_unmap_ram(const void *mem, unsigned int count)
+{
+       unsigned long size = count << PAGE_SHIFT;
+       unsigned long addr = (unsigned long)mem;
+
+       BUG_ON(!addr);
+       BUG_ON(addr < VMALLOC_START);
+       BUG_ON(addr > VMALLOC_END);
+       BUG_ON(addr & (PAGE_SIZE-1));
+
+       debug_check_no_locks_freed(mem, size);
+
+       if (likely(count <= VMAP_MAX_ALLOC))
+               vb_free(mem, size);
+       else
+               free_unmap_vmap_area_addr(addr);
+}
+EXPORT_SYMBOL(vm_unmap_ram);
+
+/**
+ * vm_map_ram - map pages linearly into kernel virtual address (vmalloc space)
+ * @pages: an array of pointers to the pages to be mapped
+ * @count: number of pages
+ * @node: prefer to allocate data structures on this node
+ * @prot: memory protection to use. PAGE_KERNEL for regular RAM
+ * @returns: a pointer to the address that has been mapped, or NULL on failure
+ */
+void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t prot)
+{
+       unsigned long size = count << PAGE_SHIFT;
        unsigned long addr;
+       void *mem;
+
+       if (likely(count <= VMAP_MAX_ALLOC)) {
+               mem = vb_alloc(size, GFP_KERNEL);
+               if (IS_ERR(mem))
+                       return NULL;
+               addr = (unsigned long)mem;
+       } else {
+               struct vmap_area *va;
+               va = alloc_vmap_area(size, PAGE_SIZE,
+                               VMALLOC_START, VMALLOC_END, node, GFP_KERNEL);
+               if (IS_ERR(va))
+                       return NULL;
+
+               addr = va->va_start;
+               mem = (void *)addr;
+       }
+       if (vmap_page_range(addr, addr + size, prot, pages) < 0) {
+               vm_unmap_ram(mem, count);
+               return NULL;
+       }
+       return mem;
+}
+EXPORT_SYMBOL(vm_map_ram);
+
+void __init vmalloc_init(void)
+{
+       int i;
+
+       for_each_possible_cpu(i) {
+               struct vmap_block_queue *vbq;
+
+               vbq = &per_cpu(vmap_block_queue, i);
+               spin_lock_init(&vbq->lock);
+               INIT_LIST_HEAD(&vbq->free);
+               INIT_LIST_HEAD(&vbq->dirty);
+               vbq->nr_dirty = 0;
+       }
+}
+
+void unmap_kernel_range(unsigned long addr, unsigned long size)
+{
+       unsigned long end = addr + size;
+       vunmap_page_range(addr, end);
+       flush_tlb_kernel_range(addr, end);
+}
+
+int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages)
+{
+       unsigned long addr = (unsigned long)area->addr;
+       unsigned long end = addr + area->size - PAGE_SIZE;
+       int err;
+
+       err = vmap_page_range(addr, end, prot, *pages);
+       if (err > 0) {
+               *pages += err;
+               err = 0;
+       }
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(map_vm_area);
+
+/*** Old vmalloc interfaces ***/
+DEFINE_RWLOCK(vmlist_lock);
+struct vm_struct *vmlist;
+
+static struct vm_struct *__get_vm_area_node(unsigned long size,
+               unsigned long flags, unsigned long start, unsigned long end,
+               int node, gfp_t gfp_mask, void *caller)
+{
+       static struct vmap_area *va;
+       struct vm_struct *area;
+       struct vm_struct *tmp, **p;
+       unsigned long align = 1;
 
        BUG_ON(in_interrupt());
        if (flags & VM_IOREMAP) {
@@ -232,13 +976,12 @@ __get_vm_area_node(unsigned long size, unsigned long flags, unsigned long start,
 
                align = 1ul << bit;
        }
-       addr = ALIGN(start, align);
+
        size = PAGE_ALIGN(size);
        if (unlikely(!size))
                return NULL;
 
        area = kmalloc_node(sizeof(*area), gfp_mask & GFP_RECLAIM_MASK, node);
-
        if (unlikely(!area))
                return NULL;
 
@@ -247,48 +990,32 @@ __get_vm_area_node(unsigned long size, unsigned long flags, unsigned long start,
         */
        size += PAGE_SIZE;
 
-       write_lock(&vmlist_lock);
-       for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
-               if ((unsigned long)tmp->addr < addr) {
-                       if((unsigned long)tmp->addr + tmp->size >= addr)
-                               addr = ALIGN(tmp->size + 
-                                            (unsigned long)tmp->addr, align);
-                       continue;
-               }
-               if ((size + addr) < addr)
-                       goto out;
-               if (size + addr <= (unsigned long)tmp->addr)
-                       goto found;
-               addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
-               if (addr > end - size)
-                       goto out;
+       va = alloc_vmap_area(size, align, start, end, node, gfp_mask);
+       if (IS_ERR(va)) {
+               kfree(area);
+               return NULL;
        }
-       if ((size + addr) < addr)
-               goto out;
-       if (addr > end - size)
-               goto out;
-
-found:
-       area->next = *p;
-       *p = area;
 
        area->flags = flags;
-       area->addr = (void *)addr;
+       area->addr = (void *)va->va_start;
        area->size = size;
        area->pages = NULL;
        area->nr_pages = 0;
        area->phys_addr = 0;
        area->caller = caller;
+       va->private = area;
+       va->flags |= VM_VM_AREA;
+
+       write_lock(&vmlist_lock);
+       for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) {
+               if (tmp->addr >= area->addr)
+                       break;
+       }
+       area->next = *p;
+       *p = area;
        write_unlock(&vmlist_lock);
 
        return area;
-
-out:
-       write_unlock(&vmlist_lock);
-       kfree(area);
-       if (printk_ratelimit())
-               printk(KERN_WARNING "allocation failed: out of vmalloc space - use vmalloc=<size> to increase size.\n");
-       return NULL;
 }
 
 struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
@@ -328,39 +1055,15 @@ struct vm_struct *get_vm_area_node(unsigned long size, unsigned long flags,
                                  gfp_mask, __builtin_return_address(0));
 }
 
-/* Caller must hold vmlist_lock */
-static struct vm_struct *__find_vm_area(const void *addr)
+static struct vm_struct *find_vm_area(const void *addr)
 {
-       struct vm_struct *tmp;
+       struct vmap_area *va;
 
-       for (tmp = vmlist; tmp != NULL; tmp = tmp->next) {
-                if (tmp->addr == addr)
-                       break;
-       }
-
-       return tmp;
-}
-
-/* Caller must hold vmlist_lock */
-static struct vm_struct *__remove_vm_area(const void *addr)
-{
-       struct vm_struct **p, *tmp;
+       va = find_vmap_area((unsigned long)addr);
+       if (va && va->flags & VM_VM_AREA)
+               return va->private;
 
-       for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next) {
-                if (tmp->addr == addr)
-                        goto found;
-       }
        return NULL;
-
-found:
-       unmap_vm_area(tmp);
-       *p = tmp->next;
-
-       /*
-        * Remove the guard page.
-        */
-       tmp->size -= PAGE_SIZE;
-       return tmp;
 }
 
 /**
@@ -373,11 +1076,24 @@ found:
  */
 struct vm_struct *remove_vm_area(const void *addr)
 {
-       struct vm_struct *v;
-       write_lock(&vmlist_lock);
-       v = __remove_vm_area(addr);
-       write_unlock(&vmlist_lock);
-       return v;
+       struct vmap_area *va;
+
+       va = find_vmap_area((unsigned long)addr);
+       if (va && va->flags & VM_VM_AREA) {
+               struct vm_struct *vm = va->private;
+               struct vm_struct *tmp, **p;
+               free_unmap_vmap_area(va);
+               vm->size -= PAGE_SIZE;
+
+               write_lock(&vmlist_lock);
+               for (p = &vmlist; (tmp = *p) != vm; p = &tmp->next)
+                       ;
+               *p = tmp->next;
+               write_unlock(&vmlist_lock);
+
+               return vm;
+       }
+       return NULL;
 }
 
 static void __vunmap(const void *addr, int deallocate_pages)
@@ -487,6 +1203,8 @@ void *vmap(struct page **pages, unsigned int count,
 }
 EXPORT_SYMBOL(vmap);
 
+static void *__vmalloc_node(unsigned long size, gfp_t gfp_mask, pgprot_t prot,
+                           int node, void *caller);
 static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
                                 pgprot_t prot, int node, void *caller)
 {
@@ -613,10 +1331,8 @@ void *vmalloc_user(unsigned long size)
 
        ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
        if (ret) {
-               write_lock(&vmlist_lock);
-               area = __find_vm_area(ret);
+               area = find_vm_area(ret);
                area->flags |= VM_USERMAP;
-               write_unlock(&vmlist_lock);
        }
        return ret;
 }
@@ -696,10 +1412,8 @@ void *vmalloc_32_user(unsigned long size)
 
        ret = __vmalloc(size, GFP_VMALLOC32 | __GFP_ZERO, PAGE_KERNEL);
        if (ret) {
-               write_lock(&vmlist_lock);
-               area = __find_vm_area(ret);
+               area = find_vm_area(ret);
                area->flags |= VM_USERMAP;
-               write_unlock(&vmlist_lock);
        }
        return ret;
 }
@@ -800,26 +1514,25 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
        struct vm_struct *area;
        unsigned long uaddr = vma->vm_start;
        unsigned long usize = vma->vm_end - vma->vm_start;
-       int ret;
 
        if ((PAGE_SIZE-1) & (unsigned long)addr)
                return -EINVAL;
 
-       read_lock(&vmlist_lock);
-       area = __find_vm_area(addr);
+       area = find_vm_area(addr);
        if (!area)
-               goto out_einval_locked;
+               return -EINVAL;
 
        if (!(area->flags & VM_USERMAP))
-               goto out_einval_locked;
+               return -EINVAL;
 
        if (usize + (pgoff << PAGE_SHIFT) > area->size - PAGE_SIZE)
-               goto out_einval_locked;
-       read_unlock(&vmlist_lock);
+               return -EINVAL;
 
        addr += pgoff << PAGE_SHIFT;
        do {
                struct page *page = vmalloc_to_page(addr);
+               int ret;
+
                ret = vm_insert_page(vma, uaddr, page);
                if (ret)
                        return ret;
@@ -832,11 +1545,7 @@ int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
        /* Prevent "things" like memory migration? VM_flags need a cleanup... */
        vma->vm_flags |= VM_RESERVED;
 
-       return ret;
-
-out_einval_locked:
-       read_unlock(&vmlist_lock);
-       return -EINVAL;
+       return 0;
 }
 EXPORT_SYMBOL(remap_vmalloc_range);
 
index 1ff1a58e7c1075fffecda7eb9ce5c360e8369a17..3b5860294bb6654a7b6765a327cef83a9952a29d 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/freezer.h>
 #include <linux/memcontrol.h>
 #include <linux/delayacct.h>
+#include <linux/sysctl.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -78,7 +79,7 @@ struct scan_control {
        unsigned long (*isolate_pages)(unsigned long nr, struct list_head *dst,
                        unsigned long *scanned, int order, int mode,
                        struct zone *z, struct mem_cgroup *mem_cont,
-                       int active);
+                       int active, int file);
 };
 
 #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
@@ -470,6 +471,85 @@ int remove_mapping(struct address_space *mapping, struct page *page)
        return 0;
 }
 
+/**
+ * putback_lru_page - put previously isolated page onto appropriate LRU list
+ * @page: page to be put back to appropriate lru list
+ *
+ * Add previously isolated @page to appropriate LRU list.
+ * Page may still be unevictable for other reasons.
+ *
+ * lru_lock must not be held, interrupts must be enabled.
+ */
+#ifdef CONFIG_UNEVICTABLE_LRU
+void putback_lru_page(struct page *page)
+{
+       int lru;
+       int active = !!TestClearPageActive(page);
+       int was_unevictable = PageUnevictable(page);
+
+       VM_BUG_ON(PageLRU(page));
+
+redo:
+       ClearPageUnevictable(page);
+
+       if (page_evictable(page, NULL)) {
+               /*
+                * For evictable pages, we can use the cache.
+                * In event of a race, worst case is we end up with an
+                * unevictable page on [in]active list.
+                * We know how to handle that.
+                */
+               lru = active + page_is_file_cache(page);
+               lru_cache_add_lru(page, lru);
+       } else {
+               /*
+                * Put unevictable pages directly on zone's unevictable
+                * list.
+                */
+               lru = LRU_UNEVICTABLE;
+               add_page_to_unevictable_list(page);
+       }
+       mem_cgroup_move_lists(page, lru);
+
+       /*
+        * page's status can change while we move it among lru. If an evictable
+        * page is on unevictable list, it never be freed. To avoid that,
+        * check after we added it to the list, again.
+        */
+       if (lru == LRU_UNEVICTABLE && page_evictable(page, NULL)) {
+               if (!isolate_lru_page(page)) {
+                       put_page(page);
+                       goto redo;
+               }
+               /* This means someone else dropped this page from LRU
+                * So, it will be freed or putback to LRU again. There is
+                * nothing to do here.
+                */
+       }
+
+       if (was_unevictable && lru != LRU_UNEVICTABLE)
+               count_vm_event(UNEVICTABLE_PGRESCUED);
+       else if (!was_unevictable && lru == LRU_UNEVICTABLE)
+               count_vm_event(UNEVICTABLE_PGCULLED);
+
+       put_page(page);         /* drop ref from isolate */
+}
+
+#else /* CONFIG_UNEVICTABLE_LRU */
+
+void putback_lru_page(struct page *page)
+{
+       int lru;
+       VM_BUG_ON(PageLRU(page));
+
+       lru = !!TestClearPageActive(page) + page_is_file_cache(page);
+       lru_cache_add_lru(page, lru);
+       mem_cgroup_move_lists(page, lru);
+       put_page(page);
+}
+#endif /* CONFIG_UNEVICTABLE_LRU */
+
+
 /*
  * shrink_page_list() returns the number of reclaimed pages
  */
@@ -503,6 +583,9 @@ static unsigned long shrink_page_list(struct list_head *page_list,
 
                sc->nr_scanned++;
 
+               if (unlikely(!page_evictable(page, NULL)))
+                       goto cull_mlocked;
+
                if (!sc->may_swap && page_mapped(page))
                        goto keep_locked;
 
@@ -539,9 +622,19 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                 * Anonymous process memory has backing store?
                 * Try to allocate it some swap space here.
                 */
-               if (PageAnon(page) && !PageSwapCache(page))
+               if (PageAnon(page) && !PageSwapCache(page)) {
+                       switch (try_to_munlock(page)) {
+                       case SWAP_FAIL:         /* shouldn't happen */
+                       case SWAP_AGAIN:
+                               goto keep_locked;
+                       case SWAP_MLOCK:
+                               goto cull_mlocked;
+                       case SWAP_SUCCESS:
+                               ; /* fall thru'; add to swap cache */
+                       }
                        if (!add_to_swap(page, GFP_ATOMIC))
                                goto activate_locked;
+               }
 #endif /* CONFIG_SWAP */
 
                mapping = page_mapping(page);
@@ -556,6 +649,8 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                                goto activate_locked;
                        case SWAP_AGAIN:
                                goto keep_locked;
+                       case SWAP_MLOCK:
+                               goto cull_mlocked;
                        case SWAP_SUCCESS:
                                ; /* try to free the page below */
                        }
@@ -602,7 +697,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                 * possible for a page to have PageDirty set, but it is actually
                 * clean (all its buffers are clean).  This happens if the
                 * buffers were written out directly, with submit_bh(). ext3
-                * will do this, as well as the blockdev mapping. 
+                * will do this, as well as the blockdev mapping.
                 * try_to_release_page() will discover that cleanness and will
                 * drop the buffers and mark the page clean - it can be freed.
                 *
@@ -637,7 +732,14 @@ static unsigned long shrink_page_list(struct list_head *page_list,
                if (!mapping || !__remove_mapping(mapping, page))
                        goto keep_locked;
 
-               unlock_page(page);
+               /*
+                * At this point, we have no other references and there is
+                * no way to pick any more up (removed from LRU, removed
+                * from pagecache). Can use non-atomic bitops now (and
+                * we obviously don't have to worry about waking up a process
+                * waiting on the page lock, because there are no references.
+                */
+               __clear_page_locked(page);
 free_it:
                nr_reclaimed++;
                if (!pagevec_add(&freed_pvec, page)) {
@@ -646,14 +748,23 @@ free_it:
                }
                continue;
 
+cull_mlocked:
+               unlock_page(page);
+               putback_lru_page(page);
+               continue;
+
 activate_locked:
+               /* Not a candidate for swapping, so reclaim swap space. */
+               if (PageSwapCache(page) && vm_swap_full())
+                       remove_exclusive_swap_page_ref(page);
+               VM_BUG_ON(PageActive(page));
                SetPageActive(page);
                pgactivate++;
 keep_locked:
                unlock_page(page);
 keep:
                list_add(&page->lru, &ret_pages);
-               VM_BUG_ON(PageLRU(page));
+               VM_BUG_ON(PageLRU(page) || PageUnevictable(page));
        }
        list_splice(&ret_pages, page_list);
        if (pagevec_count(&freed_pvec))
@@ -677,7 +788,7 @@ keep:
  *
  * returns 0 on success, -ve errno on failure.
  */
-int __isolate_lru_page(struct page *page, int mode)
+int __isolate_lru_page(struct page *page, int mode, int file)
 {
        int ret = -EINVAL;
 
@@ -693,6 +804,17 @@ int __isolate_lru_page(struct page *page, int mode)
        if (mode != ISOLATE_BOTH && (!PageActive(page) != !mode))
                return ret;
 
+       if (mode != ISOLATE_BOTH && (!page_is_file_cache(page) != !file))
+               return ret;
+
+       /*
+        * When this function is being called for lumpy reclaim, we
+        * initially look into all LRU pages, active, inactive and
+        * unevictable; only give shrink_page_list evictable pages.
+        */
+       if (PageUnevictable(page))
+               return ret;
+
        ret = -EBUSY;
        if (likely(get_page_unless_zero(page))) {
                /*
@@ -723,12 +845,13 @@ int __isolate_lru_page(struct page *page, int mode)
  * @scanned:   The number of pages that were scanned.
  * @order:     The caller's attempted allocation order
  * @mode:      One of the LRU isolation modes
+ * @file:      True [1] if isolating file [!anon] pages
  *
  * returns how many pages were moved onto *@dst.
  */
 static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                struct list_head *src, struct list_head *dst,
-               unsigned long *scanned, int order, int mode)
+               unsigned long *scanned, int order, int mode, int file)
 {
        unsigned long nr_taken = 0;
        unsigned long scan;
@@ -745,7 +868,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
 
                VM_BUG_ON(!PageLRU(page));
 
-               switch (__isolate_lru_page(page, mode)) {
+               switch (__isolate_lru_page(page, mode, file)) {
                case 0:
                        list_move(&page->lru, dst);
                        nr_taken++;
@@ -788,10 +911,11 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                                break;
 
                        cursor_page = pfn_to_page(pfn);
+
                        /* Check that we have not crossed a zone boundary. */
                        if (unlikely(page_zone_id(cursor_page) != zone_id))
                                continue;
-                       switch (__isolate_lru_page(cursor_page, mode)) {
+                       switch (__isolate_lru_page(cursor_page, mode, file)) {
                        case 0:
                                list_move(&cursor_page->lru, dst);
                                nr_taken++;
@@ -802,7 +926,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                                /* else it is being freed elsewhere */
                                list_move(&cursor_page->lru, src);
                        default:
-                               break;
+                               break;  /* ! on LRU or wrong list */
                        }
                }
        }
@@ -816,40 +940,93 @@ static unsigned long isolate_pages_global(unsigned long nr,
                                        unsigned long *scanned, int order,
                                        int mode, struct zone *z,
                                        struct mem_cgroup *mem_cont,
-                                       int active)
+                                       int active, int file)
 {
+       int lru = LRU_BASE;
        if (active)
-               return isolate_lru_pages(nr, &z->active_list, dst,
-                                               scanned, order, mode);
-       else
-               return isolate_lru_pages(nr, &z->inactive_list, dst,
-                                               scanned, order, mode);
+               lru += LRU_ACTIVE;
+       if (file)
+               lru += LRU_FILE;
+       return isolate_lru_pages(nr, &z->lru[lru].list, dst, scanned, order,
+                                                               mode, !!file);
 }
 
 /*
  * clear_active_flags() is a helper for shrink_active_list(), clearing
  * any active bits from the pages in the list.
  */
-static unsigned long clear_active_flags(struct list_head *page_list)
+static unsigned long clear_active_flags(struct list_head *page_list,
+                                       unsigned int *count)
 {
        int nr_active = 0;
+       int lru;
        struct page *page;
 
-       list_for_each_entry(page, page_list, lru)
+       list_for_each_entry(page, page_list, lru) {
+               lru = page_is_file_cache(page);
                if (PageActive(page)) {
+                       lru += LRU_ACTIVE;
                        ClearPageActive(page);
                        nr_active++;
                }
+               count[lru]++;
+       }
 
        return nr_active;
 }
 
+/**
+ * isolate_lru_page - tries to isolate a page from its LRU list
+ * @page: page to isolate from its LRU list
+ *
+ * Isolates a @page from an LRU list, clears PageLRU and adjusts the
+ * vmstat statistic corresponding to whatever LRU list the page was on.
+ *
+ * Returns 0 if the page was removed from an LRU list.
+ * Returns -EBUSY if the page was not on an LRU list.
+ *
+ * The returned page will have PageLRU() cleared.  If it was found on
+ * the active list, it will have PageActive set.  If it was found on
+ * the unevictable list, it will have the PageUnevictable bit set. That flag
+ * may need to be cleared by the caller before letting the page go.
+ *
+ * The vmstat statistic corresponding to the list on which the page was
+ * found will be decremented.
+ *
+ * Restrictions:
+ * (1) Must be called with an elevated refcount on the page. This is a
+ *     fundamentnal difference from isolate_lru_pages (which is called
+ *     without a stable reference).
+ * (2) the lru_lock must not be held.
+ * (3) interrupts must be enabled.
+ */
+int isolate_lru_page(struct page *page)
+{
+       int ret = -EBUSY;
+
+       if (PageLRU(page)) {
+               struct zone *zone = page_zone(page);
+
+               spin_lock_irq(&zone->lru_lock);
+               if (PageLRU(page) && get_page_unless_zero(page)) {
+                       int lru = page_lru(page);
+                       ret = 0;
+                       ClearPageLRU(page);
+
+                       del_page_from_lru_list(zone, page, lru);
+               }
+               spin_unlock_irq(&zone->lru_lock);
+       }
+       return ret;
+}
+
 /*
  * shrink_inactive_list() is a helper for shrink_zone().  It returns the number
  * of reclaimed pages
  */
 static unsigned long shrink_inactive_list(unsigned long max_scan,
-                               struct zone *zone, struct scan_control *sc)
+                       struct zone *zone, struct scan_control *sc,
+                       int priority, int file)
 {
        LIST_HEAD(page_list);
        struct pagevec pvec;
@@ -866,20 +1043,43 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
                unsigned long nr_scan;
                unsigned long nr_freed;
                unsigned long nr_active;
+               unsigned int count[NR_LRU_LISTS] = { 0, };
+               int mode = ISOLATE_INACTIVE;
+
+               /*
+                * 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.
+                *
+                * We use the same threshold as pageout congestion_wait below.
+                */
+               if (sc->order > PAGE_ALLOC_COSTLY_ORDER)
+                       mode = ISOLATE_BOTH;
+               else if (sc->order && priority < DEF_PRIORITY - 2)
+                       mode = ISOLATE_BOTH;
 
                nr_taken = sc->isolate_pages(sc->swap_cluster_max,
-                            &page_list, &nr_scan, sc->order,
-                            (sc->order > PAGE_ALLOC_COSTLY_ORDER)?
-                                            ISOLATE_BOTH : ISOLATE_INACTIVE,
-                               zone, sc->mem_cgroup, 0);
-               nr_active = clear_active_flags(&page_list);
+                            &page_list, &nr_scan, sc->order, mode,
+                               zone, sc->mem_cgroup, 0, file);
+               nr_active = clear_active_flags(&page_list, count);
                __count_vm_events(PGDEACTIVATE, nr_active);
 
-               __mod_zone_page_state(zone, NR_ACTIVE, -nr_active);
-               __mod_zone_page_state(zone, NR_INACTIVE,
-                                               -(nr_taken - nr_active));
-               if (scan_global_lru(sc))
+               __mod_zone_page_state(zone, NR_ACTIVE_FILE,
+                                               -count[LRU_ACTIVE_FILE]);
+               __mod_zone_page_state(zone, NR_INACTIVE_FILE,
+                                               -count[LRU_INACTIVE_FILE]);
+               __mod_zone_page_state(zone, NR_ACTIVE_ANON,
+                                               -count[LRU_ACTIVE_ANON]);
+               __mod_zone_page_state(zone, NR_INACTIVE_ANON,
+                                               -count[LRU_INACTIVE_ANON]);
+
+               if (scan_global_lru(sc)) {
                        zone->pages_scanned += nr_scan;
+                       zone->recent_scanned[0] += count[LRU_INACTIVE_ANON];
+                       zone->recent_scanned[0] += count[LRU_ACTIVE_ANON];
+                       zone->recent_scanned[1] += count[LRU_INACTIVE_FILE];
+                       zone->recent_scanned[1] += count[LRU_ACTIVE_FILE];
+               }
                spin_unlock_irq(&zone->lru_lock);
 
                nr_scanned += nr_scan;
@@ -899,7 +1099,7 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
                         * The attempt at page out may have made some
                         * of the pages active, mark them inactive again.
                         */
-                       nr_active = clear_active_flags(&page_list);
+                       nr_active = clear_active_flags(&page_list, count);
                        count_vm_events(PGDEACTIVATE, nr_active);
 
                        nr_freed += shrink_page_list(&page_list, sc,
@@ -924,14 +1124,24 @@ static unsigned long shrink_inactive_list(unsigned long max_scan,
                 * Put back any unfreeable pages.
                 */
                while (!list_empty(&page_list)) {
+                       int lru;
                        page = lru_to_page(&page_list);
                        VM_BUG_ON(PageLRU(page));
-                       SetPageLRU(page);
                        list_del(&page->lru);
-                       if (PageActive(page))
-                               add_page_to_active_list(zone, page);
-                       else
-                               add_page_to_inactive_list(zone, page);
+                       if (unlikely(!page_evictable(page, NULL))) {
+                               spin_unlock_irq(&zone->lru_lock);
+                               putback_lru_page(page);
+                               spin_lock_irq(&zone->lru_lock);
+                               continue;
+                       }
+                       SetPageLRU(page);
+                       lru = page_lru(page);
+                       add_page_to_lru_list(zone, page, lru);
+                       mem_cgroup_move_lists(page, lru);
+                       if (PageActive(page) && scan_global_lru(sc)) {
+                               int file = !!page_is_file_cache(page);
+                               zone->recent_rotated[file]++;
+                       }
                        if (!pagevec_add(&pvec, page)) {
                                spin_unlock_irq(&zone->lru_lock);
                                __pagevec_release(&pvec);
@@ -962,115 +1172,7 @@ static inline void note_zone_scanning_priority(struct zone *zone, int priority)
 
 static inline int zone_is_near_oom(struct zone *zone)
 {
-       return zone->pages_scanned >= (zone_page_state(zone, NR_ACTIVE)
-                               + zone_page_state(zone, NR_INACTIVE))*3;
-}
-
-/*
- * Determine we should try to reclaim mapped pages.
- * This is called only when sc->mem_cgroup is NULL.
- */
-static int calc_reclaim_mapped(struct scan_control *sc, struct zone *zone,
-                               int priority)
-{
-       long mapped_ratio;
-       long distress;
-       long swap_tendency;
-       long imbalance;
-       int reclaim_mapped = 0;
-       int prev_priority;
-
-       if (scan_global_lru(sc) && zone_is_near_oom(zone))
-               return 1;
-       /*
-        * `distress' is a measure of how much trouble we're having
-        * reclaiming pages.  0 -> no problems.  100 -> great trouble.
-        */
-       if (scan_global_lru(sc))
-               prev_priority = zone->prev_priority;
-       else
-               prev_priority = mem_cgroup_get_reclaim_priority(sc->mem_cgroup);
-
-       distress = 100 >> min(prev_priority, priority);
-
-       /*
-        * The point of this algorithm is to decide when to start
-        * reclaiming mapped memory instead of just pagecache.  Work out
-        * how much memory
-        * is mapped.
-        */
-       if (scan_global_lru(sc))
-               mapped_ratio = ((global_page_state(NR_FILE_MAPPED) +
-                               global_page_state(NR_ANON_PAGES)) * 100) /
-                                       vm_total_pages;
-       else
-               mapped_ratio = mem_cgroup_calc_mapped_ratio(sc->mem_cgroup);
-
-       /*
-        * Now decide how much we really want to unmap some pages.  The
-        * mapped ratio is downgraded - just because there's a lot of
-        * mapped memory doesn't necessarily mean that page reclaim
-        * isn't succeeding.
-        *
-        * The distress ratio is important - we don't want to start
-        * going oom.
-        *
-        * A 100% value of vm_swappiness overrides this algorithm
-        * altogether.
-        */
-       swap_tendency = mapped_ratio / 2 + distress + sc->swappiness;
-
-       /*
-        * If there's huge imbalance between active and inactive
-        * (think active 100 times larger than inactive) we should
-        * become more permissive, or the system will take too much
-        * cpu before it start swapping during memory pressure.
-        * Distress is about avoiding early-oom, this is about
-        * making swappiness graceful despite setting it to low
-        * values.
-        *
-        * Avoid div by zero with nr_inactive+1, and max resulting
-        * value is vm_total_pages.
-        */
-       if (scan_global_lru(sc)) {
-               imbalance  = zone_page_state(zone, NR_ACTIVE);
-               imbalance /= zone_page_state(zone, NR_INACTIVE) + 1;
-       } else
-               imbalance = mem_cgroup_reclaim_imbalance(sc->mem_cgroup);
-
-       /*
-        * Reduce the effect of imbalance if swappiness is low,
-        * this means for a swappiness very low, the imbalance
-        * must be much higher than 100 for this logic to make
-        * the difference.
-        *
-        * Max temporary value is vm_total_pages*100.
-        */
-       imbalance *= (vm_swappiness + 1);
-       imbalance /= 100;
-
-       /*
-        * If not much of the ram is mapped, makes the imbalance
-        * less relevant, it's high priority we refill the inactive
-        * list with mapped pages only in presence of high ratio of
-        * mapped pages.
-        *
-        * Max temporary value is vm_total_pages*100.
-        */
-       imbalance *= mapped_ratio;
-       imbalance /= 100;
-
-       /* apply imbalance feedback to swap_tendency */
-       swap_tendency += imbalance;
-
-       /*
-        * Now use this metric to decide whether to start moving mapped
-        * memory onto the inactive list.
-        */
-       if (swap_tendency >= 100)
-               reclaim_mapped = 1;
-
-       return reclaim_mapped;
+       return zone->pages_scanned >= (zone_lru_pages(zone) * 3);
 }
 
 /*
@@ -1093,53 +1195,71 @@ static int calc_reclaim_mapped(struct scan_control *sc, struct zone *zone,
 
 
 static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
-                               struct scan_control *sc, int priority)
+                       struct scan_control *sc, int priority, int file)
 {
        unsigned long pgmoved;
        int pgdeactivate = 0;
        unsigned long pgscanned;
        LIST_HEAD(l_hold);      /* The pages which were snipped off */
-       LIST_HEAD(l_inactive);  /* Pages to go onto the inactive_list */
-       LIST_HEAD(l_active);    /* Pages to go onto the active_list */
+       LIST_HEAD(l_inactive);
        struct page *page;
        struct pagevec pvec;
-       int reclaim_mapped = 0;
-
-       if (sc->may_swap)
-               reclaim_mapped = calc_reclaim_mapped(sc, zone, priority);
+       enum lru_list lru;
 
        lru_add_drain();
        spin_lock_irq(&zone->lru_lock);
        pgmoved = sc->isolate_pages(nr_pages, &l_hold, &pgscanned, sc->order,
                                        ISOLATE_ACTIVE, zone,
-                                       sc->mem_cgroup, 1);
+                                       sc->mem_cgroup, 1, file);
        /*
         * zone->pages_scanned is used for detect zone's oom
         * mem_cgroup remembers nr_scan by itself.
         */
-       if (scan_global_lru(sc))
+       if (scan_global_lru(sc)) {
                zone->pages_scanned += pgscanned;
+               zone->recent_scanned[!!file] += pgmoved;
+       }
 
-       __mod_zone_page_state(zone, NR_ACTIVE, -pgmoved);
+       if (file)
+               __mod_zone_page_state(zone, NR_ACTIVE_FILE, -pgmoved);
+       else
+               __mod_zone_page_state(zone, NR_ACTIVE_ANON, -pgmoved);
        spin_unlock_irq(&zone->lru_lock);
 
+       pgmoved = 0;
        while (!list_empty(&l_hold)) {
                cond_resched();
                page = lru_to_page(&l_hold);
                list_del(&page->lru);
-               if (page_mapped(page)) {
-                       if (!reclaim_mapped ||
-                           (total_swap_pages == 0 && PageAnon(page)) ||
-                           page_referenced(page, 0, sc->mem_cgroup)) {
-                               list_add(&page->lru, &l_active);
-                               continue;
-                       }
+
+               if (unlikely(!page_evictable(page, NULL))) {
+                       putback_lru_page(page);
+                       continue;
                }
+
+               /* page_referenced clears PageReferenced */
+               if (page_mapping_inuse(page) &&
+                   page_referenced(page, 0, sc->mem_cgroup))
+                       pgmoved++;
+
                list_add(&page->lru, &l_inactive);
        }
 
+       /*
+        * Count referenced pages from currently used mappings as
+        * rotated, even though they are moved to the inactive list.
+        * This helps balance scan pressure between file and anonymous
+        * pages in get_scan_ratio.
+        */
+       zone->recent_rotated[!!file] += pgmoved;
+
+       /*
+        * Move the pages to the [file or anon] inactive list.
+        */
        pagevec_init(&pvec, 1);
+
        pgmoved = 0;
+       lru = LRU_BASE + file * LRU_FILE;
        spin_lock_irq(&zone->lru_lock);
        while (!list_empty(&l_inactive)) {
                page = lru_to_page(&l_inactive);
@@ -1149,11 +1269,11 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
                VM_BUG_ON(!PageActive(page));
                ClearPageActive(page);
 
-               list_move(&page->lru, &zone->inactive_list);
-               mem_cgroup_move_lists(page, false);
+               list_move(&page->lru, &zone->lru[lru].list);
+               mem_cgroup_move_lists(page, lru);
                pgmoved++;
                if (!pagevec_add(&pvec, page)) {
-                       __mod_zone_page_state(zone, NR_INACTIVE, pgmoved);
+                       __mod_zone_page_state(zone, NR_LRU_BASE + lru, pgmoved);
                        spin_unlock_irq(&zone->lru_lock);
                        pgdeactivate += pgmoved;
                        pgmoved = 0;
@@ -1163,104 +1283,189 @@ static void shrink_active_list(unsigned long nr_pages, struct zone *zone,
                        spin_lock_irq(&zone->lru_lock);
                }
        }
-       __mod_zone_page_state(zone, NR_INACTIVE, pgmoved);
+       __mod_zone_page_state(zone, NR_LRU_BASE + lru, pgmoved);
        pgdeactivate += pgmoved;
        if (buffer_heads_over_limit) {
                spin_unlock_irq(&zone->lru_lock);
                pagevec_strip(&pvec);
                spin_lock_irq(&zone->lru_lock);
        }
-
-       pgmoved = 0;
-       while (!list_empty(&l_active)) {
-               page = lru_to_page(&l_active);
-               prefetchw_prev_lru_page(page, &l_active, flags);
-               VM_BUG_ON(PageLRU(page));
-               SetPageLRU(page);
-               VM_BUG_ON(!PageActive(page));
-
-               list_move(&page->lru, &zone->active_list);
-               mem_cgroup_move_lists(page, true);
-               pgmoved++;
-               if (!pagevec_add(&pvec, page)) {
-                       __mod_zone_page_state(zone, NR_ACTIVE, pgmoved);
-                       pgmoved = 0;
-                       spin_unlock_irq(&zone->lru_lock);
-                       __pagevec_release(&pvec);
-                       spin_lock_irq(&zone->lru_lock);
-               }
-       }
-       __mod_zone_page_state(zone, NR_ACTIVE, pgmoved);
-
        __count_zone_vm_events(PGREFILL, zone, pgscanned);
        __count_vm_events(PGDEACTIVATE, pgdeactivate);
        spin_unlock_irq(&zone->lru_lock);
+       if (vm_swap_full())
+               pagevec_swap_free(&pvec);
 
        pagevec_release(&pvec);
 }
 
+static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
+       struct zone *zone, struct scan_control *sc, int priority)
+{
+       int file = is_file_lru(lru);
+
+       if (lru == LRU_ACTIVE_FILE) {
+               shrink_active_list(nr_to_scan, zone, sc, priority, file);
+               return 0;
+       }
+
+       if (lru == LRU_ACTIVE_ANON &&
+           (!scan_global_lru(sc) || inactive_anon_is_low(zone))) {
+               shrink_active_list(nr_to_scan, zone, sc, priority, file);
+               return 0;
+       }
+       return shrink_inactive_list(nr_to_scan, zone, sc, priority, file);
+}
+
+/*
+ * Determine how aggressively the anon and file LRU lists should be
+ * scanned.  The relative value of each set of LRU lists is determined
+ * by looking at the fraction of the pages scanned we did rotate back
+ * onto the active list instead of evict.
+ *
+ * percent[0] specifies how much pressure to put on ram/swap backed
+ * memory, while percent[1] determines pressure on the file LRUs.
+ */
+static void get_scan_ratio(struct zone *zone, struct scan_control *sc,
+                                       unsigned long *percent)
+{
+       unsigned long anon, file, free;
+       unsigned long anon_prio, file_prio;
+       unsigned long ap, fp;
+
+       anon  = zone_page_state(zone, NR_ACTIVE_ANON) +
+               zone_page_state(zone, NR_INACTIVE_ANON);
+       file  = zone_page_state(zone, NR_ACTIVE_FILE) +
+               zone_page_state(zone, NR_INACTIVE_FILE);
+       free  = zone_page_state(zone, NR_FREE_PAGES);
+
+       /* If we have no swap space, do not bother scanning anon pages. */
+       if (nr_swap_pages <= 0) {
+               percent[0] = 0;
+               percent[1] = 100;
+               return;
+       }
+
+       /* If we have very few page cache pages, force-scan anon pages. */
+       if (unlikely(file + free <= zone->pages_high)) {
+               percent[0] = 100;
+               percent[1] = 0;
+               return;
+       }
+
+       /*
+        * OK, so we have swap space and a fair amount of page cache
+        * pages.  We use the recently rotated / recently scanned
+        * ratios to determine how valuable each cache is.
+        *
+        * Because workloads change over time (and to avoid overflow)
+        * we keep these statistics as a floating average, which ends
+        * up weighing recent references more than old ones.
+        *
+        * anon in [0], file in [1]
+        */
+       if (unlikely(zone->recent_scanned[0] > anon / 4)) {
+               spin_lock_irq(&zone->lru_lock);
+               zone->recent_scanned[0] /= 2;
+               zone->recent_rotated[0] /= 2;
+               spin_unlock_irq(&zone->lru_lock);
+       }
+
+       if (unlikely(zone->recent_scanned[1] > file / 4)) {
+               spin_lock_irq(&zone->lru_lock);
+               zone->recent_scanned[1] /= 2;
+               zone->recent_rotated[1] /= 2;
+               spin_unlock_irq(&zone->lru_lock);
+       }
+
+       /*
+        * With swappiness at 100, anonymous and file have the same priority.
+        * This scanning priority is essentially the inverse of IO cost.
+        */
+       anon_prio = sc->swappiness;
+       file_prio = 200 - sc->swappiness;
+
+       /*
+        *                  anon       recent_rotated[0]
+        * %anon = 100 * ----------- / ----------------- * IO cost
+        *               anon + file      rotate_sum
+        */
+       ap = (anon_prio + 1) * (zone->recent_scanned[0] + 1);
+       ap /= zone->recent_rotated[0] + 1;
+
+       fp = (file_prio + 1) * (zone->recent_scanned[1] + 1);
+       fp /= zone->recent_rotated[1] + 1;
+
+       /* Normalize to percentages */
+       percent[0] = 100 * ap / (ap + fp + 1);
+       percent[1] = 100 - percent[0];
+}
+
+
 /*
  * This is a basic per-zone page freer.  Used by both kswapd and direct reclaim.
  */
 static unsigned long shrink_zone(int priority, struct zone *zone,
                                struct scan_control *sc)
 {
-       unsigned long nr_active;
-       unsigned long nr_inactive;
+       unsigned long nr[NR_LRU_LISTS];
        unsigned long nr_to_scan;
        unsigned long nr_reclaimed = 0;
+       unsigned long percent[2];       /* anon @ 0; file @ 1 */
+       enum lru_list l;
 
-       if (scan_global_lru(sc)) {
-               /*
-                * Add one to nr_to_scan just to make sure that the kernel
-                * will slowly sift through the active list.
-                */
-               zone->nr_scan_active +=
-                       (zone_page_state(zone, NR_ACTIVE) >> priority) + 1;
-               nr_active = zone->nr_scan_active;
-               zone->nr_scan_inactive +=
-                       (zone_page_state(zone, NR_INACTIVE) >> priority) + 1;
-               nr_inactive = zone->nr_scan_inactive;
-               if (nr_inactive >= sc->swap_cluster_max)
-                       zone->nr_scan_inactive = 0;
-               else
-                       nr_inactive = 0;
-
-               if (nr_active >= sc->swap_cluster_max)
-                       zone->nr_scan_active = 0;
-               else
-                       nr_active = 0;
-       } else {
-               /*
-                * This reclaim occurs not because zone memory shortage but
-                * because memory controller hits its limit.
-                * Then, don't modify zone reclaim related data.
-                */
-               nr_active = mem_cgroup_calc_reclaim_active(sc->mem_cgroup,
-                                       zone, priority);
-
-               nr_inactive = mem_cgroup_calc_reclaim_inactive(sc->mem_cgroup,
-                                       zone, priority);
-       }
+       get_scan_ratio(zone, sc, percent);
 
+       for_each_evictable_lru(l) {
+               if (scan_global_lru(sc)) {
+                       int file = is_file_lru(l);
+                       int scan;
 
-       while (nr_active || nr_inactive) {
-               if (nr_active) {
-                       nr_to_scan = min(nr_active,
-                                       (unsigned long)sc->swap_cluster_max);
-                       nr_active -= nr_to_scan;
-                       shrink_active_list(nr_to_scan, zone, sc, priority);
+                       scan = zone_page_state(zone, NR_LRU_BASE + l);
+                       if (priority) {
+                               scan >>= priority;
+                               scan = (scan * percent[file]) / 100;
+                       }
+                       zone->lru[l].nr_scan += scan;
+                       nr[l] = zone->lru[l].nr_scan;
+                       if (nr[l] >= sc->swap_cluster_max)
+                               zone->lru[l].nr_scan = 0;
+                       else
+                               nr[l] = 0;
+               } else {
+                       /*
+                        * This reclaim occurs not because zone memory shortage
+                        * but because memory controller hits its limit.
+                        * Don't modify zone reclaim related data.
+                        */
+                       nr[l] = mem_cgroup_calc_reclaim(sc->mem_cgroup, zone,
+                                                               priority, l);
                }
+       }
 
-               if (nr_inactive) {
-                       nr_to_scan = min(nr_inactive,
+       while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
+                                       nr[LRU_INACTIVE_FILE]) {
+               for_each_evictable_lru(l) {
+                       if (nr[l]) {
+                               nr_to_scan = min(nr[l],
                                        (unsigned long)sc->swap_cluster_max);
-                       nr_inactive -= nr_to_scan;
-                       nr_reclaimed += shrink_inactive_list(nr_to_scan, zone,
-                                                               sc);
+                               nr[l] -= nr_to_scan;
+
+                               nr_reclaimed += shrink_list(l, nr_to_scan,
+                                                       zone, sc, priority);
+                       }
                }
        }
 
+       /*
+        * Even if we did not try to evict anon pages at all, we want to
+        * rebalance the anon lru active/inactive ratio.
+        */
+       if (!scan_global_lru(sc) || inactive_anon_is_low(zone))
+               shrink_active_list(SWAP_CLUSTER_MAX, zone, sc, priority, 0);
+       else if (!scan_global_lru(sc))
+               shrink_active_list(SWAP_CLUSTER_MAX, zone, sc, priority, 0);
+
        throttle_vm_writeout(sc->gfp_mask);
        return nr_reclaimed;
 }
@@ -1321,7 +1526,7 @@ static unsigned long shrink_zones(int priority, struct zonelist *zonelist,
 
        return nr_reclaimed;
 }
+
 /*
  * This is the main entry point to direct page reclaim.
  *
@@ -1364,8 +1569,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
                        if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
                                continue;
 
-                       lru_pages += zone_page_state(zone, NR_ACTIVE)
-                                       + zone_page_state(zone, NR_INACTIVE);
+                       lru_pages += zone_lru_pages(zone);
                }
        }
 
@@ -1555,6 +1759,14 @@ loop_again:
                            priority != DEF_PRIORITY)
                                continue;
 
+                       /*
+                        * Do some background aging of the anon list, to give
+                        * pages a chance to be referenced before reclaiming.
+                        */
+                       if (inactive_anon_is_low(zone))
+                               shrink_active_list(SWAP_CLUSTER_MAX, zone,
+                                                       &sc, priority, 0);
+
                        if (!zone_watermark_ok(zone, order, zone->pages_high,
                                               0, 0)) {
                                end_zone = i;
@@ -1567,8 +1779,7 @@ loop_again:
                for (i = 0; i <= end_zone; i++) {
                        struct zone *zone = pgdat->node_zones + i;
 
-                       lru_pages += zone_page_state(zone, NR_ACTIVE)
-                                       + zone_page_state(zone, NR_INACTIVE);
+                       lru_pages += zone_lru_pages(zone);
                }
 
                /*
@@ -1612,8 +1823,7 @@ loop_again:
                        if (zone_is_all_unreclaimable(zone))
                                continue;
                        if (nr_slab == 0 && zone->pages_scanned >=
-                               (zone_page_state(zone, NR_ACTIVE)
-                               + zone_page_state(zone, NR_INACTIVE)) * 6)
+                                               (zone_lru_pages(zone) * 6))
                                        zone_set_flag(zone,
                                                      ZONE_ALL_UNRECLAIMABLE);
                        /*
@@ -1667,7 +1877,7 @@ out:
 
 /*
  * The background pageout daemon, started as a kernel thread
- * from the init process. 
+ * from the init process.
  *
  * This basically trickles out pages so that we have _some_
  * free memory available even if there is no other activity
@@ -1761,6 +1971,14 @@ void wakeup_kswapd(struct zone *zone, int order)
        wake_up_interruptible(&pgdat->kswapd_wait);
 }
 
+unsigned long global_lru_pages(void)
+{
+       return global_page_state(NR_ACTIVE_ANON)
+               + global_page_state(NR_ACTIVE_FILE)
+               + global_page_state(NR_INACTIVE_ANON)
+               + global_page_state(NR_INACTIVE_FILE);
+}
+
 #ifdef CONFIG_PM
 /*
  * Helper function for shrink_all_memory().  Tries to reclaim 'nr_pages' pages
@@ -1774,6 +1992,7 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
 {
        struct zone *zone;
        unsigned long nr_to_scan, ret = 0;
+       enum lru_list l;
 
        for_each_zone(zone) {
 
@@ -1783,38 +2002,31 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
                if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY)
                        continue;
 
-               /* For pass = 0 we don't shrink the active list */
-               if (pass > 0) {
-                       zone->nr_scan_active +=
-                               (zone_page_state(zone, NR_ACTIVE) >> prio) + 1;
-                       if (zone->nr_scan_active >= nr_pages || pass > 3) {
-                               zone->nr_scan_active = 0;
+               for_each_evictable_lru(l) {
+                       /* For pass = 0, we don't shrink the active list */
+                       if (pass == 0 &&
+                               (l == LRU_ACTIVE || l == LRU_ACTIVE_FILE))
+                               continue;
+
+                       zone->lru[l].nr_scan +=
+                               (zone_page_state(zone, NR_LRU_BASE + l)
+                                                               >> prio) + 1;
+                       if (zone->lru[l].nr_scan >= nr_pages || pass > 3) {
+                               zone->lru[l].nr_scan = 0;
                                nr_to_scan = min(nr_pages,
-                                       zone_page_state(zone, NR_ACTIVE));
-                               shrink_active_list(nr_to_scan, zone, sc, prio);
+                                       zone_page_state(zone,
+                                                       NR_LRU_BASE + l));
+                               ret += shrink_list(l, nr_to_scan, zone,
+                                                               sc, prio);
+                               if (ret >= nr_pages)
+                                       return ret;
                        }
                }
-
-               zone->nr_scan_inactive +=
-                       (zone_page_state(zone, NR_INACTIVE) >> prio) + 1;
-               if (zone->nr_scan_inactive >= nr_pages || pass > 3) {
-                       zone->nr_scan_inactive = 0;
-                       nr_to_scan = min(nr_pages,
-                               zone_page_state(zone, NR_INACTIVE));
-                       ret += shrink_inactive_list(nr_to_scan, zone, sc);
-                       if (ret >= nr_pages)
-                               return ret;
-               }
        }
 
        return ret;
 }
 
-static unsigned long count_lru_pages(void)
-{
-       return global_page_state(NR_ACTIVE) + global_page_state(NR_INACTIVE);
-}
-
 /*
  * Try to free `nr_pages' of memory, system-wide, and return the number of
  * freed pages.
@@ -1840,7 +2052,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
 
        current->reclaim_state = &reclaim_state;
 
-       lru_pages = count_lru_pages();
+       lru_pages = global_lru_pages();
        nr_slab = global_page_state(NR_SLAB_RECLAIMABLE);
        /* If slab caches are huge, it's better to hit them first */
        while (nr_slab >= lru_pages) {
@@ -1883,7 +2095,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
 
                        reclaim_state.reclaimed_slab = 0;
                        shrink_slab(sc.nr_scanned, sc.gfp_mask,
-                                       count_lru_pages());
+                                       global_lru_pages());
                        ret += reclaim_state.reclaimed_slab;
                        if (ret >= nr_pages)
                                goto out;
@@ -1900,7 +2112,7 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
        if (!ret) {
                do {
                        reclaim_state.reclaimed_slab = 0;
-                       shrink_slab(nr_pages, sc.gfp_mask, count_lru_pages());
+                       shrink_slab(nr_pages, sc.gfp_mask, global_lru_pages());
                        ret += reclaim_state.reclaimed_slab;
                } while (ret < nr_pages && reclaim_state.reclaimed_slab > 0);
        }
@@ -2128,3 +2340,285 @@ int zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
        return ret;
 }
 #endif
+
+#ifdef CONFIG_UNEVICTABLE_LRU
+/*
+ * page_evictable - test whether a page is evictable
+ * @page: the page to test
+ * @vma: the VMA in which the page is or will be mapped, may be NULL
+ *
+ * Test whether page is evictable--i.e., should be placed on active/inactive
+ * lists vs unevictable list.  The vma argument is !NULL when called from the
+ * fault path to determine how to instantate a new page.
+ *
+ * Reasons page might not be evictable:
+ * (1) page's mapping marked unevictable
+ * (2) page is part of an mlocked VMA
+ *
+ */
+int page_evictable(struct page *page, struct vm_area_struct *vma)
+{
+
+       if (mapping_unevictable(page_mapping(page)))
+               return 0;
+
+       if (PageMlocked(page) || (vma && is_mlocked_vma(vma, page)))
+               return 0;
+
+       return 1;
+}
+
+static void show_page_path(struct page *page)
+{
+       char buf[256];
+       if (page_is_file_cache(page)) {
+               struct address_space *mapping = page->mapping;
+               struct dentry *dentry;
+               pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+
+               spin_lock(&mapping->i_mmap_lock);
+               dentry = d_find_alias(mapping->host);
+               printk(KERN_INFO "rescued: %s %lu\n",
+                      dentry_path(dentry, buf, 256), pgoff);
+               spin_unlock(&mapping->i_mmap_lock);
+       } else {
+#if defined(CONFIG_MM_OWNER) && defined(CONFIG_MMU)
+               struct anon_vma *anon_vma;
+               struct vm_area_struct *vma;
+
+               anon_vma = page_lock_anon_vma(page);
+               if (!anon_vma)
+                       return;
+
+               list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
+                       printk(KERN_INFO "rescued: anon %s\n",
+                              vma->vm_mm->owner->comm);
+                       break;
+               }
+               page_unlock_anon_vma(anon_vma);
+#endif
+       }
+}
+
+
+/**
+ * check_move_unevictable_page - check page for evictability and move to appropriate zone lru list
+ * @page: page to check evictability and move to appropriate lru list
+ * @zone: zone page is in
+ *
+ * Checks a page for evictability and moves the page to the appropriate
+ * zone lru list.
+ *
+ * Restrictions: zone->lru_lock must be held, page must be on LRU and must
+ * have PageUnevictable set.
+ */
+static void check_move_unevictable_page(struct page *page, struct zone *zone)
+{
+       VM_BUG_ON(PageActive(page));
+
+retry:
+       ClearPageUnevictable(page);
+       if (page_evictable(page, NULL)) {
+               enum lru_list l = LRU_INACTIVE_ANON + page_is_file_cache(page);
+
+               show_page_path(page);
+
+               __dec_zone_state(zone, NR_UNEVICTABLE);
+               list_move(&page->lru, &zone->lru[l].list);
+               __inc_zone_state(zone, NR_INACTIVE_ANON + l);
+               __count_vm_event(UNEVICTABLE_PGRESCUED);
+       } else {
+               /*
+                * rotate unevictable list
+                */
+               SetPageUnevictable(page);
+               list_move(&page->lru, &zone->lru[LRU_UNEVICTABLE].list);
+               if (page_evictable(page, NULL))
+                       goto retry;
+       }
+}
+
+/**
+ * scan_mapping_unevictable_pages - scan an address space for evictable pages
+ * @mapping: struct address_space to scan for evictable pages
+ *
+ * Scan all pages in mapping.  Check unevictable pages for
+ * evictability and move them to the appropriate zone lru list.
+ */
+void scan_mapping_unevictable_pages(struct address_space *mapping)
+{
+       pgoff_t next = 0;
+       pgoff_t end   = (i_size_read(mapping->host) + PAGE_CACHE_SIZE - 1) >>
+                        PAGE_CACHE_SHIFT;
+       struct zone *zone;
+       struct pagevec pvec;
+
+       if (mapping->nrpages == 0)
+               return;
+
+       pagevec_init(&pvec, 0);
+       while (next < end &&
+               pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+               int i;
+               int pg_scanned = 0;
+
+               zone = NULL;
+
+               for (i = 0; i < pagevec_count(&pvec); i++) {
+                       struct page *page = pvec.pages[i];
+                       pgoff_t page_index = page->index;
+                       struct zone *pagezone = page_zone(page);
+
+                       pg_scanned++;
+                       if (page_index > next)
+                               next = page_index;
+                       next++;
+
+                       if (pagezone != zone) {
+                               if (zone)
+                                       spin_unlock_irq(&zone->lru_lock);
+                               zone = pagezone;
+                               spin_lock_irq(&zone->lru_lock);
+                       }
+
+                       if (PageLRU(page) && PageUnevictable(page))
+                               check_move_unevictable_page(page, zone);
+               }
+               if (zone)
+                       spin_unlock_irq(&zone->lru_lock);
+               pagevec_release(&pvec);
+
+               count_vm_events(UNEVICTABLE_PGSCANNED, pg_scanned);
+       }
+
+}
+
+/**
+ * scan_zone_unevictable_pages - check unevictable list for evictable pages
+ * @zone - zone of which to scan the unevictable list
+ *
+ * Scan @zone's unevictable LRU lists to check for pages that have become
+ * evictable.  Move those that have to @zone's inactive list where they
+ * become candidates for reclaim, unless shrink_inactive_zone() decides
+ * to reactivate them.  Pages that are still unevictable are rotated
+ * back onto @zone's unevictable list.
+ */
+#define SCAN_UNEVICTABLE_BATCH_SIZE 16UL /* arbitrary lock hold batch size */
+void scan_zone_unevictable_pages(struct zone *zone)
+{
+       struct list_head *l_unevictable = &zone->lru[LRU_UNEVICTABLE].list;
+       unsigned long scan;
+       unsigned long nr_to_scan = zone_page_state(zone, NR_UNEVICTABLE);
+
+       while (nr_to_scan > 0) {
+               unsigned long batch_size = min(nr_to_scan,
+                                               SCAN_UNEVICTABLE_BATCH_SIZE);
+
+               spin_lock_irq(&zone->lru_lock);
+               for (scan = 0;  scan < batch_size; scan++) {
+                       struct page *page = lru_to_page(l_unevictable);
+
+                       if (!trylock_page(page))
+                               continue;
+
+                       prefetchw_prev_lru_page(page, l_unevictable, flags);
+
+                       if (likely(PageLRU(page) && PageUnevictable(page)))
+                               check_move_unevictable_page(page, zone);
+
+                       unlock_page(page);
+               }
+               spin_unlock_irq(&zone->lru_lock);
+
+               nr_to_scan -= batch_size;
+       }
+}
+
+
+/**
+ * scan_all_zones_unevictable_pages - scan all unevictable lists for evictable pages
+ *
+ * A really big hammer:  scan all zones' unevictable LRU lists to check for
+ * pages that have become evictable.  Move those back to the zones'
+ * inactive list where they become candidates for reclaim.
+ * This occurs when, e.g., we have unswappable pages on the unevictable lists,
+ * and we add swap to the system.  As such, it runs in the context of a task
+ * that has possibly/probably made some previously unevictable pages
+ * evictable.
+ */
+void scan_all_zones_unevictable_pages(void)
+{
+       struct zone *zone;
+
+       for_each_zone(zone) {
+               scan_zone_unevictable_pages(zone);
+       }
+}
+
+/*
+ * scan_unevictable_pages [vm] sysctl handler.  On demand re-scan of
+ * all nodes' unevictable lists for evictable pages
+ */
+unsigned long scan_unevictable_pages;
+
+int scan_unevictable_handler(struct ctl_table *table, int write,
+                          struct file *file, void __user *buffer,
+                          size_t *length, loff_t *ppos)
+{
+       proc_doulongvec_minmax(table, write, file, buffer, length, ppos);
+
+       if (write && *(unsigned long *)table->data)
+               scan_all_zones_unevictable_pages();
+
+       scan_unevictable_pages = 0;
+       return 0;
+}
+
+/*
+ * per node 'scan_unevictable_pages' attribute.  On demand re-scan of
+ * a specified node's per zone unevictable lists for evictable pages.
+ */
+
+static ssize_t read_scan_unevictable_node(struct sys_device *dev,
+                                         struct sysdev_attribute *attr,
+                                         char *buf)
+{
+       return sprintf(buf, "0\n");     /* always zero; should fit... */
+}
+
+static ssize_t write_scan_unevictable_node(struct sys_device *dev,
+                                          struct sysdev_attribute *attr,
+                                       const char *buf, size_t count)
+{
+       struct zone *node_zones = NODE_DATA(dev->id)->node_zones;
+       struct zone *zone;
+       unsigned long res;
+       unsigned long req = strict_strtoul(buf, 10, &res);
+
+       if (!req)
+               return 1;       /* zero is no-op */
+
+       for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
+               if (!populated_zone(zone))
+                       continue;
+               scan_zone_unevictable_pages(zone);
+       }
+       return 1;
+}
+
+
+static SYSDEV_ATTR(scan_unevictable_pages, S_IRUGO | S_IWUSR,
+                       read_scan_unevictable_node,
+                       write_scan_unevictable_node);
+
+int scan_unevictable_register_node(struct node *node)
+{
+       return sysdev_create_file(&node->sysdev, &attr_scan_unevictable_pages);
+}
+
+void scan_unevictable_unregister_node(struct node *node)
+{
+       sysdev_remove_file(&node->sysdev, &attr_scan_unevictable_pages);
+}
+
+#endif
index d7826af2fb073b15e2488470a67ad5a965fa7518..9343227c5c60b6dc3a1b7e09c64143a53a407003 100644 (file)
@@ -619,8 +619,14 @@ const struct seq_operations pagetypeinfo_op = {
 static const char * const vmstat_text[] = {
        /* Zoned VM counters */
        "nr_free_pages",
-       "nr_inactive",
-       "nr_active",
+       "nr_inactive_anon",
+       "nr_active_anon",
+       "nr_inactive_file",
+       "nr_active_file",
+#ifdef CONFIG_UNEVICTABLE_LRU
+       "nr_unevictable",
+       "nr_mlock",
+#endif
        "nr_anon_pages",
        "nr_mapped",
        "nr_file_pages",
@@ -675,6 +681,16 @@ static const char * const vmstat_text[] = {
        "htlb_buddy_alloc_success",
        "htlb_buddy_alloc_fail",
 #endif
+#ifdef CONFIG_UNEVICTABLE_LRU
+       "unevictable_pgs_culled",
+       "unevictable_pgs_scanned",
+       "unevictable_pgs_rescued",
+       "unevictable_pgs_mlocked",
+       "unevictable_pgs_munlocked",
+       "unevictable_pgs_cleared",
+       "unevictable_pgs_stranded",
+       "unevictable_pgs_mlockfreed",
+#endif
 #endif
 };
 
@@ -688,7 +704,7 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
                   "\n        min      %lu"
                   "\n        low      %lu"
                   "\n        high     %lu"
-                  "\n        scanned  %lu (a: %lu i: %lu)"
+                  "\n        scanned  %lu (aa: %lu ia: %lu af: %lu if: %lu)"
                   "\n        spanned  %lu"
                   "\n        present  %lu",
                   zone_page_state(zone, NR_FREE_PAGES),
@@ -696,7 +712,10 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
                   zone->pages_low,
                   zone->pages_high,
                   zone->pages_scanned,
-                  zone->nr_scan_active, zone->nr_scan_inactive,
+                  zone->lru[LRU_ACTIVE_ANON].nr_scan,
+                  zone->lru[LRU_INACTIVE_ANON].nr_scan,
+                  zone->lru[LRU_ACTIVE_FILE].nr_scan,
+                  zone->lru[LRU_INACTIVE_FILE].nr_scan,
                   zone->spanned_pages,
                   zone->present_pages);
 
@@ -733,10 +752,12 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
        seq_printf(m,
                   "\n  all_unreclaimable: %u"
                   "\n  prev_priority:     %i"
-                  "\n  start_pfn:         %lu",
+                  "\n  start_pfn:         %lu"
+                  "\n  inactive_ratio:    %u",
                           zone_is_all_unreclaimable(zone),
                   zone->prev_priority,
-                  zone->zone_start_pfn);
+                  zone->zone_start_pfn,
+                  zone->inactive_ratio);
        seq_putc(m, '\n');
 }
 
index a4abed5b4c442cba6bb8e5b5f878c8f063f73b49..fa5cda4e552ab0088901a2820f4267d31b303030 100644 (file)
@@ -719,7 +719,7 @@ static unsigned int br_nf_forward_arp(unsigned int hook, struct sk_buff *skb,
                return NF_ACCEPT;
        }
        *d = (struct net_device *)in;
-       NF_HOOK(NF_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in,
+       NF_HOOK(NFPROTO_ARP, NF_ARP_FORWARD, skb, (struct net_device *)in,
                (struct net_device *)out, br_nf_forward_finish);
 
        return NF_STOLEN;
index 868ec0ba8b77dc7088c28816238b2ee557316e01..b8a4fd0806af3fca72224828293a497f13281831 100644 (file)
@@ -924,10 +924,10 @@ int dev_change_name(struct net_device *dev, const char *newname)
                strlcpy(dev->name, newname, IFNAMSIZ);
 
 rollback:
-       err = device_rename(&dev->dev, dev->name);
-       if (err) {
+       ret = device_rename(&dev->dev, dev->name);
+       if (ret) {
                memcpy(dev->name, oldname, IFNAMSIZ);
-               return err;
+               return ret;
        }
 
        write_lock_bh(&dev_base_lock);
index 11062780bb02b84990aa4c89e40d3815940ecec7..d4ce1224e008f13ee4da674cec0c6047a3a9f25f 100644 (file)
@@ -259,7 +259,7 @@ static int dccp_v6_send_response(struct sock *sk, struct request_sock *req)
        fl.fl6_flowlabel = 0;
        fl.oif = ireq6->iif;
        fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-       fl.fl_ip_sport = inet_sk(sk)->sport;
+       fl.fl_ip_sport = inet_rsk(req)->loc_port;
        security_req_classify_flow(req, &fl);
 
        opt = np->opt;
@@ -558,7 +558,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk,
                ipv6_addr_copy(&fl.fl6_src, &ireq6->loc_addr);
                fl.oif = sk->sk_bound_dev_if;
                fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-               fl.fl_ip_sport = inet_sk(sk)->sport;
+               fl.fl_ip_sport = inet_rsk(req)->loc_port;
                security_sk_classify_flow(sk, &fl);
 
                if (ip6_dst_lookup(sk, &dst, &fl))
index b2804e2d1b8cadbc26e266fea24d7e525a89e888..e6bf99e3e41a169aec04880e52d60adb41dc8b62 100644 (file)
@@ -309,6 +309,7 @@ void dccp_reqsk_init(struct request_sock *req, struct sk_buff *skb)
        struct dccp_request_sock *dreq = dccp_rsk(req);
 
        inet_rsk(req)->rmt_port   = dccp_hdr(skb)->dccph_sport;
+       inet_rsk(req)->loc_port   = dccp_hdr(skb)->dccph_dport;
        inet_rsk(req)->acked      = 0;
        req->rcv_wnd              = sysctl_dccp_feat_sequence_window;
        dreq->dreq_timestamp_echo = 0;
index d06945c7d3dfc3e1201a00840516a457e9773303..809d803d5006ec6614821b9d0d48b63cf131a31f 100644 (file)
@@ -347,7 +347,7 @@ struct sk_buff *dccp_make_response(struct sock *sk, struct dst_entry *dst,
        /* Build and checksum header */
        dh = dccp_zeroed_hdr(skb, dccp_header_size);
 
-       dh->dccph_sport = inet_sk(sk)->sport;
+       dh->dccph_sport = inet_rsk(req)->loc_port;
        dh->dccph_dport = inet_rsk(req)->rmt_port;
        dh->dccph_doff  = (dccp_header_size +
                           DCCP_SKB_CB(skb)->dccpd_opt_len) / 4;
index b043eda60b04277734d79112e8357078e66553dc..1a9dd66511fccfadf9e1240334e7dcc2a3f073b0 100644 (file)
@@ -663,7 +663,7 @@ out:
 void arp_xmit(struct sk_buff *skb)
 {
        /* Send it off, maybe filter it using firewalling first.  */
-       NF_HOOK(NF_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
+       NF_HOOK(NFPROTO_ARP, NF_ARP_OUT, skb, NULL, skb->dev, dev_queue_xmit);
 }
 
 /*
@@ -928,7 +928,7 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev,
 
        memset(NEIGH_CB(skb), 0, sizeof(struct neighbour_cb));
 
-       return NF_HOOK(NF_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
+       return NF_HOOK(NFPROTO_ARP, NF_ARP_IN, skb, dev, NULL, arp_process);
 
 freeskb:
        kfree_skb(skb);
index ffeaffc3fffe6c31c78e858b9a1fa61fe71ba03e..8303e4b406c05b15245d7f89d8e0c2d16f50b992 100644 (file)
@@ -742,6 +742,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx,
                        *obj = kmalloc(sizeof(struct snmp_object) + len,
                                       GFP_ATOMIC);
                        if (*obj == NULL) {
+                               kfree(p);
                                kfree(id);
                                if (net_ratelimit())
                                        printk("OOM in bsalg (%d)\n", __LINE__);
index ec394cf5a19bf80b480264199a224be336ee2cea..676c80b5b14b8d13a518ce3a7d7b5f0c48208c5b 100644 (file)
@@ -204,6 +204,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
 
        req->mss = mss;
        ireq->rmt_port = th->source;
+       ireq->loc_port = th->dest;
        ipv6_addr_copy(&ireq6->rmt_addr, &ipv6_hdr(skb)->saddr);
        ipv6_addr_copy(&ireq6->loc_addr, &ipv6_hdr(skb)->daddr);
        if (ipv6_opt_accepted(sk, skb) ||
index e5310c9b84dcb2216f1db0b21ab92c3ed7a222b7..b6b356b7912a57c298a542731c2c9daf24a77bbc 100644 (file)
@@ -476,7 +476,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req)
        fl.fl6_flowlabel = 0;
        fl.oif = treq->iif;
        fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-       fl.fl_ip_sport = inet_sk(sk)->sport;
+       fl.fl_ip_sport = inet_rsk(req)->loc_port;
        security_req_classify_flow(req, &fl);
 
        opt = np->opt;
@@ -1309,7 +1309,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                ipv6_addr_copy(&fl.fl6_src, &treq->loc_addr);
                fl.oif = sk->sk_bound_dev_if;
                fl.fl_ip_dport = inet_rsk(req)->rmt_port;
-               fl.fl_ip_sport = inet_sk(sk)->sport;
+               fl.fl_ip_sport = inet_rsk(req)->loc_port;
                security_req_classify_flow(req, &fl);
 
                if (ip6_dst_lookup(sk, &dst, &fl))
@@ -1865,7 +1865,7 @@ static void get_openreq6(struct seq_file *seq,
                   i,
                   src->s6_addr32[0], src->s6_addr32[1],
                   src->s6_addr32[2], src->s6_addr32[3],
-                  ntohs(inet_sk(sk)->sport),
+                  ntohs(inet_rsk(req)->loc_port),
                   dest->s6_addr32[0], dest->s6_addr32[1],
                   dest->s6_addr32[2], dest->s6_addr32[3],
                   ntohs(inet_rsk(req)->rmt_port),
index 78892cf2b021c0d4a4bedf05075535f44c125f82..25dcef9f219493a597511c157efc9c2fe4f343e6 100644 (file)
@@ -271,7 +271,6 @@ config NF_CONNTRACK_TFTP
 config NF_CT_NETLINK
        tristate 'Connection tracking netlink interface'
        select NETFILTER_NETLINK
-       depends on NF_NAT=n || NF_NAT
        default m if NETFILTER_ADVANCED=n
        help
          This option enables support for a netlink-based userspace interface
index 05048e4032661d7b96477db4b9ed6501713797cd..79a69805221889c91578ef8f45bf6a8313a3420e 100644 (file)
@@ -25,11 +25,13 @@ menuconfig IP_VS
 if IP_VS
 
 config IP_VS_IPV6
-       bool "IPv6 support for IPVS (DANGEROUS)"
+       bool "IPv6 support for IPVS"
        depends on EXPERIMENTAL && (IPV6 = y || IP_VS = IPV6)
        ---help---
          Add IPv6 support to IPVS. This is incomplete and might be dangerous.
 
+         See http://www.mindbasket.com/ipvs for more information.
+
          Say N if unsure.
 
 config IP_VS_DEBUG
index 2e4ad9671e19c0203915a13e7b7108aa65f34a54..a040d46f85d6c8967f88af6c549f23206e6416c7 100644 (file)
@@ -813,6 +813,7 @@ out:
        return err;
 }
 
+#ifdef CONFIG_NF_NAT_NEEDED
 static int
 ctnetlink_parse_nat_setup(struct nf_conn *ct,
                          enum nf_nat_manip_type manip,
@@ -840,6 +841,7 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
 
        return parse_nat_setup(ct, manip, attr);
 }
+#endif
 
 static int
 ctnetlink_change_status(struct nf_conn *ct, struct nlattr *cda[])
index 2cc1fff493071c61a119cc9c93a1d20a03483b62..f9977b3311f75692239c2f7c32ca7a417ed3eddb 100644 (file)
@@ -48,7 +48,7 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = {
        },
        {
                .name           = "NFQUEUE",
-               .family         = NF_ARP,
+               .family         = NFPROTO_ARP,
                .target         = nfqueue_tg,
                .targetsize     = sizeof(struct xt_NFQ_info),
                .me             = THIS_MODULE,
index 6f62c36948d94ef4c25f143334f7b6884fc1d1ae..7ac54eab0b00a6a0249afcc43ca6afea807410a0 100644 (file)
@@ -61,7 +61,7 @@ iprange_mt4(const struct sk_buff *skb, const struct xt_match_param *par)
        if (info->flags & IPRANGE_SRC) {
                m  = ntohl(iph->saddr) < ntohl(info->src_min.ip);
                m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
-               m ^= info->flags & IPRANGE_SRC_INV;
+               m ^= !!(info->flags & IPRANGE_SRC_INV);
                if (m) {
                        pr_debug("src IP " NIPQUAD_FMT " NOT in range %s"
                                 NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
@@ -75,7 +75,7 @@ iprange_mt4(const struct sk_buff *skb, const struct xt_match_param *par)
        if (info->flags & IPRANGE_DST) {
                m  = ntohl(iph->daddr) < ntohl(info->dst_min.ip);
                m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
-               m ^= info->flags & IPRANGE_DST_INV;
+               m ^= !!(info->flags & IPRANGE_DST_INV);
                if (m) {
                        pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s"
                                 NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
@@ -114,14 +114,14 @@ iprange_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
        if (info->flags & IPRANGE_SRC) {
                m  = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0;
                m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0;
-               m ^= info->flags & IPRANGE_SRC_INV;
+               m ^= !!(info->flags & IPRANGE_SRC_INV);
                if (m)
                        return false;
        }
        if (info->flags & IPRANGE_DST) {
                m  = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0;
                m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0;
-               m ^= info->flags & IPRANGE_DST_INV;
+               m ^= !!(info->flags & IPRANGE_DST_INV);
                if (m)
                        return false;
        }
index 4ebd4ca9a991bf871a23bf672ea2b30d5a9095d7..280c471bcdf444fdc2228a46895c2b44baf8d549 100644 (file)
@@ -318,15 +318,15 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
        for (i = 0; i < ip_list_hash_size; i++)
                INIT_LIST_HEAD(&t->iphash[i]);
 #ifdef CONFIG_PROC_FS
-       t->proc = proc_create(t->name, ip_list_perms, recent_proc_dir,
-                 &recent_mt_fops);
+       t->proc = proc_create_data(t->name, ip_list_perms, recent_proc_dir,
+                 &recent_mt_fops, t);
        if (t->proc == NULL) {
                kfree(t);
                goto out;
        }
 #ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
-       t->proc_old = proc_create(t->name, ip_list_perms, proc_old_dir,
-                     &recent_old_fops);
+       t->proc_old = proc_create_data(t->name, ip_list_perms, proc_old_dir,
+                     &recent_old_fops, t);
        if (t->proc_old == NULL) {
                remove_proc_entry(t->name, proc_old_dir);
                kfree(t);
@@ -334,11 +334,9 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
        }
        t->proc_old->uid   = ip_list_uid;
        t->proc_old->gid   = ip_list_gid;
-       t->proc_old->data  = t;
 #endif
        t->proc->uid       = ip_list_uid;
        t->proc->gid       = ip_list_gid;
-       t->proc->data      = t;
 #endif
        spin_lock_bh(&recent_lock);
        list_add_tail(&t->list, &tables);
index 7b5572d6beb59b561e92ad6d030d801f5fd0c72f..93cd30ce65011d2b84541277c15664ed6287fc3d 100644 (file)
@@ -326,6 +326,7 @@ struct Qdisc_ops noop_qdisc_ops __read_mostly = {
 
 static struct netdev_queue noop_netdev_queue = {
        .qdisc          =       &noop_qdisc,
+       .qdisc_sleeping =       &noop_qdisc,
 };
 
 struct Qdisc noop_qdisc = {
@@ -352,6 +353,7 @@ static struct Qdisc_ops noqueue_qdisc_ops __read_mostly = {
 static struct Qdisc noqueue_qdisc;
 static struct netdev_queue noqueue_netdev_queue = {
        .qdisc          =       &noqueue_qdisc,
+       .qdisc_sleeping =       &noqueue_qdisc,
 };
 
 static struct Qdisc noqueue_qdisc = {
index 46f23971f7e4208d9487cbb9cf477790a8fb378a..5ba78701adc3ab868079ee180b1fc2e4ffc3b95f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * dev_cgroup.c - device cgroup subsystem
+ * device_cgroup.c - device cgroup subsystem
  *
  * Copyright 2007 IBM Corp
  */
@@ -10,6 +10,7 @@
 #include <linux/list.h>
 #include <linux/uaccess.h>
 #include <linux/seq_file.h>
+#include <linux/rcupdate.h>
 
 #define ACC_MKNOD 1
 #define ACC_READ  2
 
 /*
  * whitelist locking rules:
- * cgroup_lock() cannot be taken under dev_cgroup->lock.
- * dev_cgroup->lock can be taken with or without cgroup_lock().
- *
- * modifications always require cgroup_lock
- * modifications to a list which is visible require the
- *   dev_cgroup->lock *and* cgroup_lock()
- * walking the list requires dev_cgroup->lock or cgroup_lock().
- *
- * reasoning: dev_whitelist_copy() needs to kmalloc, so needs
- *   a mutex, which the cgroup_lock() is.  Since modifying
- *   a visible list requires both locks, either lock can be
- *   taken for walking the list.
+ * hold cgroup_lock() for update/read.
+ * hold rcu_read_lock() for read.
  */
 
 struct dev_whitelist_item {
@@ -47,7 +38,6 @@ struct dev_whitelist_item {
 struct dev_cgroup {
        struct cgroup_subsys_state css;
        struct list_head whitelist;
-       spinlock_t lock;
 };
 
 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -84,13 +74,9 @@ static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig)
        struct dev_whitelist_item *wh, *tmp, *new;
 
        list_for_each_entry(wh, orig, list) {
-               new = kmalloc(sizeof(*wh), GFP_KERNEL);
+               new = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
                if (!new)
                        goto free_and_exit;
-               new->major = wh->major;
-               new->minor = wh->minor;
-               new->type = wh->type;
-               new->access = wh->access;
                list_add_tail(&new->list, dest);
        }
 
@@ -107,19 +93,16 @@ free_and_exit:
 /* Stupid prototype - don't bother combining existing entries */
 /*
  * called under cgroup_lock()
- * since the list is visible to other tasks, we need the spinlock also
  */
 static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
                        struct dev_whitelist_item *wh)
 {
        struct dev_whitelist_item *whcopy, *walk;
 
-       whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL);
+       whcopy = kmemdup(wh, sizeof(*wh), GFP_KERNEL);
        if (!whcopy)
                return -ENOMEM;
 
-       memcpy(whcopy, wh, sizeof(*whcopy));
-       spin_lock(&dev_cgroup->lock);
        list_for_each_entry(walk, &dev_cgroup->whitelist, list) {
                if (walk->type != wh->type)
                        continue;
@@ -135,7 +118,6 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup,
 
        if (whcopy != NULL)
                list_add_tail_rcu(&whcopy->list, &dev_cgroup->whitelist);
-       spin_unlock(&dev_cgroup->lock);
        return 0;
 }
 
@@ -149,14 +131,12 @@ static void whitelist_item_free(struct rcu_head *rcu)
 
 /*
  * called under cgroup_lock()
- * since the list is visible to other tasks, we need the spinlock also
  */
 static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup,
                        struct dev_whitelist_item *wh)
 {
        struct dev_whitelist_item *walk, *tmp;
 
-       spin_lock(&dev_cgroup->lock);
        list_for_each_entry_safe(walk, tmp, &dev_cgroup->whitelist, list) {
                if (walk->type == DEV_ALL)
                        goto remove;
@@ -174,7 +154,6 @@ remove:
                        call_rcu(&walk->rcu, whitelist_item_free);
                }
        }
-       spin_unlock(&dev_cgroup->lock);
 }
 
 /*
@@ -214,7 +193,6 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss,
                }
        }
 
-       spin_lock_init(&dev_cgroup->lock);
        return &dev_cgroup->css;
 }
 
@@ -330,15 +308,11 @@ static int parent_has_perm(struct dev_cgroup *childcg,
 {
        struct cgroup *pcg = childcg->css.cgroup->parent;
        struct dev_cgroup *parent;
-       int ret;
 
        if (!pcg)
                return 1;
        parent = cgroup_to_devcgroup(pcg);
-       spin_lock(&parent->lock);
-       ret = may_access_whitelist(parent, wh);
-       spin_unlock(&parent->lock);
-       return ret;
+       return may_access_whitelist(parent, wh);
 }
 
 /*
@@ -357,17 +331,14 @@ static int parent_has_perm(struct dev_cgroup *childcg,
 static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                                   int filetype, const char *buffer)
 {
-       struct dev_cgroup *cur_devcgroup;
        const char *b;
        char *endp;
-       int retval = 0, count;
+       int count;
        struct dev_whitelist_item wh;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       cur_devcgroup = task_devcgroup(current);
-
        memset(&wh, 0, sizeof(wh));
        b = buffer;
 
@@ -437,7 +408,6 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        }
 
 handle:
-       retval = 0;
        switch (filetype) {
        case DEVCG_ALLOW:
                if (!parent_has_perm(devcgroup, &wh))
index 89b7f549bebd772bb62378510a541bb0b052e967..ea2bf82c93730505768c28f00174d6484ac2bcf9 100644 (file)
@@ -319,6 +319,7 @@ EXPORT_SYMBOL(snd_pcm_format_physical_width);
 /**
  * snd_pcm_format_size - return the byte size of samples on the given format
  * @format: the format to check
+ * @samples: sampling rate
  *
  * Returns the byte size of the given samples for the format, or a
  * negative error code if unknown format.
index e5e749f3e0ef08df9fea76571c6a552a2724e388..73be7e14a603d56208aec9d9bd741b48c5444750 100644 (file)
@@ -51,7 +51,7 @@ static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
        if (err < 0)
                return err;
        err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX);
-       if (err) < 0)
+       if (err < 0)
                return err;
        return 0;
 }
index b493660deb36b503b39a509861ebf54b2eb8254b..e5d4239949182fd5649456e524436a7fb515e39e 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/cpu/dac.h>
 #include <asm/cpu/timer.h>
 #include <asm/machvec.h>
-#include <asm/hp6xx.h>
+#include <mach/hp6xx.h>
 #include <asm/hd64461.h>
 
 #define MODNAME "sh_dac_audio"
index a7d89662acf66e200c5305ac409fd3bfd7188500..88fbf285d2b74ea6cf1ccc701398d0e730784840 100644 (file)
@@ -759,7 +759,6 @@ static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
                               SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
                               SPCS_GENERATIONSTATUS | 0x00001200 |
                               0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT );
-       }
 #endif
 
        return 0;
index 20d0e328288ab6ae4ea24abe202b6a3d0dd3d442..8f9e3859c37ca70f802fdb5c3f8f25ed75731b8d 100644 (file)
@@ -666,6 +666,7 @@ static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card)
        card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16;
        card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM;
        card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL;
+       memcpy(card->avs.avs_cs_info, ps3av_mode_cs_info, 8);
 
        ret = snd_ps3_change_avsetting(card);
 
@@ -685,6 +686,7 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
 {
        struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream);
        struct snd_ps3_avsetting_info avs;
+       int ret;
 
        avs = card->avs;
 
@@ -729,19 +731,92 @@ static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream)
                return 1;
        }
 
-       if ((card->avs.avs_audio_width != avs.avs_audio_width) ||
-           (card->avs.avs_audio_rate != avs.avs_audio_rate)) {
-               card->avs = avs;
-               snd_ps3_change_avsetting(card);
+       memcpy(avs.avs_cs_info, ps3av_mode_cs_info, 8);
 
+       if (memcmp(&card->avs, &avs, sizeof(avs))) {
                pr_debug("%s: after freq=%d width=%d\n", __func__,
                         card->avs.avs_audio_rate, card->avs.avs_audio_width);
 
-               return 0;
+               card->avs = avs;
+               snd_ps3_change_avsetting(card);
+               ret = 0;
        } else
+               ret = 1;
+
+       /* check CS non-audio bit and mute accordingly */
+       if (avs.avs_cs_info[0] & 0x02)
+               ps3av_audio_mute_analog(1); /* mute if non-audio */
+       else
+               ps3av_audio_mute_analog(0);
+
+       return ret;
+}
+
+/*
+ * SPDIF status bits controls
+ */
+static int snd_ps3_spdif_mask_info(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+       uinfo->count = 1;
+       return 0;
+}
+
+/* FIXME: ps3av_set_audio_mode() assumes only consumer mode */
+static int snd_ps3_spdif_cmask_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       memset(ucontrol->value.iec958.status, 0xff, 8);
+       return 0;
+}
+
+static int snd_ps3_spdif_pmask_get(struct snd_kcontrol *kcontrol,
+                                  struct snd_ctl_elem_value *ucontrol)
+{
+       return 0;
+}
+
+static int snd_ps3_spdif_default_get(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       memcpy(ucontrol->value.iec958.status, ps3av_mode_cs_info, 8);
+       return 0;
+}
+
+static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol,
+                                    struct snd_ctl_elem_value *ucontrol)
+{
+       if (memcmp(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8)) {
+               memcpy(ps3av_mode_cs_info, ucontrol->value.iec958.status, 8);
                return 1;
+       }
+       return 0;
 }
 
+static struct snd_kcontrol_new spdif_ctls[] = {
+       {
+               .access = SNDRV_CTL_ELEM_ACCESS_READ,
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+               .info = snd_ps3_spdif_mask_info,
+               .get = snd_ps3_spdif_cmask_get,
+       },
+       {
+               .access = SNDRV_CTL_ELEM_ACCESS_READ,
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+               .info = snd_ps3_spdif_mask_info,
+               .get = snd_ps3_spdif_pmask_get,
+       },
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+               .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+               .info = snd_ps3_spdif_mask_info,
+               .get = snd_ps3_spdif_default_get,
+               .put = snd_ps3_spdif_default_put,
+       },
+};
 
 
 static int snd_ps3_map_mmio(void)
@@ -842,7 +917,7 @@ static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
 
 static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
 {
-       int ret;
+       int i, ret;
        u64 lpar_addr, lpar_size;
 
        BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1));
@@ -903,6 +978,15 @@ static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
        strcpy(the_card.card->driver, "PS3");
        strcpy(the_card.card->shortname, "PS3");
        strcpy(the_card.card->longname, "PS3 sound");
+
+       /* create control elements */
+       for (i = 0; i < ARRAY_SIZE(spdif_ctls); i++) {
+               ret = snd_ctl_add(the_card.card,
+                                 snd_ctl_new1(&spdif_ctls[i], &the_card));
+               if (ret < 0)
+                       goto clean_card;
+       }
+
        /* create PCM devices instance */
        /* NOTE:this driver works assuming pcm:substream = 1:1 */
        ret = snd_pcm_new(the_card.card,
index 4b7e6fbbe5005769b6dbd059d1181ec5f5d44873..326fb29e82d842e43f4159fe94372b49f49b03b8 100644 (file)
@@ -51,6 +51,7 @@ struct snd_ps3_avsetting_info {
        uint32_t avs_audio_width;
        uint32_t avs_audio_format; /* fixed */
        uint32_t avs_audio_source; /* fixed */
+       unsigned char avs_cs_info[8];
 };
 /*
  * PS3 audio 'card' instance
index 0a063a98a6613820295419a5cab10bd09a8dc338..853b33ae3435297f414eaee086b31bdf6a4b1333 100644 (file)
@@ -43,6 +43,7 @@
 struct omap_mcbsp_data {
        unsigned int                    bus_id;
        struct omap_mcbsp_reg_cfg       regs;
+       unsigned int                    fmt;
        /*
         * Flags indicating is the bus already activated and configured by
         * another substream
@@ -200,6 +201,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
        int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
+       int wlen;
        unsigned long port;
 
        if (cpu_class_is_omap1()) {
@@ -244,19 +246,29 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S16_LE:
                /* Set word lengths */
+               wlen = 16;
                regs->rcr2      |= RWDLEN2(OMAP_MCBSP_WORD_16);
                regs->rcr1      |= RWDLEN1(OMAP_MCBSP_WORD_16);
                regs->xcr2      |= XWDLEN2(OMAP_MCBSP_WORD_16);
                regs->xcr1      |= XWDLEN1(OMAP_MCBSP_WORD_16);
-               /* Set FS period and length in terms of bit clock periods */
-               regs->srgr2     |= FPER(16 * 2 - 1);
-               regs->srgr1     |= FWID(16 - 1);
                break;
        default:
                /* Unsupported PCM format */
                return -EINVAL;
        }
 
+       /* Set FS period and length in terms of bit clock periods */
+       switch (mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+       case SND_SOC_DAIFMT_I2S:
+               regs->srgr2     |= FPER(wlen * 2 - 1);
+               regs->srgr1     |= FWID(wlen - 1);
+               break;
+       case SND_SOC_DAIFMT_DSP_A:
+               regs->srgr2     |= FPER(wlen * 2 - 1);
+               regs->srgr1     |= FWID(0);
+               break;
+       }
+
        omap_mcbsp_config(bus_id, &mcbsp_data->regs);
        mcbsp_data->configured = 1;
 
@@ -272,10 +284,12 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 {
        struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
        struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+       unsigned int temp_fmt = fmt;
 
        if (mcbsp_data->configured)
                return 0;
 
+       mcbsp_data->fmt = fmt;
        memset(regs, 0, sizeof(*regs));
        /* Generic McBSP register settings */
        regs->spcr2     |= XINTM(3) | FREE;
@@ -293,6 +307,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
                /* 0-bit data delay */
                regs->rcr2      |= RDATDLY(0);
                regs->xcr2      |= XDATDLY(0);
+               /* Invert bit clock and FS polarity configuration for DSP_A */
+               temp_fmt ^= SND_SOC_DAIFMT_IB_IF;
                break;
        default:
                /* Unsupported data format */
@@ -316,7 +332,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
        }
 
        /* Set bit clock (CLKX/CLKR) and FS polarities */
-       switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+       switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
        case SND_SOC_DAIFMT_NB_NF:
                /*
                 * Normal BCLK + FS.