Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/dvrabel/uwb
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 25 Oct 2010 15:30:48 +0000 (08:30 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 25 Oct 2010 15:30:48 +0000 (08:30 -0700)
* 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/dvrabel/uwb:
  uwb: Orphan the UWB and WUSB subsystems
  uwb: Remove the WLP subsystem and drivers

452 files changed:
Documentation/ABI/obsolete/dv1394 [deleted file]
Documentation/ABI/removed/dv1394 [new file with mode: 0644]
Documentation/ABI/removed/raw1394 [new file with mode: 0644]
Documentation/ABI/removed/raw1394_legacy_isochronous [deleted file]
Documentation/ABI/removed/video1394 [new file with mode: 0644]
Documentation/ABI/testing/sysfs-devices-system-ibm-rtl [new file with mode: 0644]
Documentation/feature-removal-schedule.txt
MAINTAINERS
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/devices-db8500.c
arch/arm/mach-ux500/include/mach/devices.h
arch/arm/mach-ux500/pins-db8500.h
arch/arm/plat-nomadik/include/plat/ske.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/omap4-keypad.h [new file with mode: 0644]
arch/m68k/include/asm/cacheflush_no.h
arch/m68k/include/asm/coldfire.h
arch/m68k/include/asm/gpio.h
arch/m68k/include/asm/m548xgpt.h [new file with mode: 0644]
arch/m68k/include/asm/m548xsim.h [new file with mode: 0644]
arch/m68k/include/asm/mcfcache.h
arch/m68k/include/asm/mcfsim.h
arch/m68k/include/asm/mcfslt.h [new file with mode: 0644]
arch/m68k/include/asm/mcfuart.h
arch/m68k/kernel/asm-offsets.c
arch/m68knommu/Kconfig
arch/m68knommu/Makefile
arch/m68knommu/kernel/.gitignore [new file with mode: 0644]
arch/m68knommu/kernel/asm-offsets.c
arch/m68knommu/kernel/ptrace.c
arch/m68knommu/kernel/setup.c
arch/m68knommu/kernel/time.c
arch/m68knommu/kernel/traps.c
arch/m68knommu/platform/5206/Makefile
arch/m68knommu/platform/5206e/Makefile
arch/m68knommu/platform/520x/Makefile
arch/m68knommu/platform/523x/Makefile
arch/m68knommu/platform/5249/Makefile
arch/m68knommu/platform/5272/Makefile
arch/m68knommu/platform/5272/config.c
arch/m68knommu/platform/5272/intc.c
arch/m68knommu/platform/527x/Makefile
arch/m68knommu/platform/528x/Makefile
arch/m68knommu/platform/5307/Makefile
arch/m68knommu/platform/532x/Makefile
arch/m68knommu/platform/5407/Makefile
arch/m68knommu/platform/548x/Makefile [new file with mode: 0644]
arch/m68knommu/platform/548x/config.c [new file with mode: 0644]
arch/m68knommu/platform/68328/entry.S
arch/m68knommu/platform/68328/head-de2.S
arch/m68knommu/platform/68328/head-ram.S
arch/m68knommu/platform/68328/ints.c
arch/m68knommu/platform/68360/entry.S
arch/m68knommu/platform/68360/ints.c
arch/m68knommu/platform/68VZ328/config.c
arch/m68knommu/platform/coldfire/Makefile
arch/m68knommu/platform/coldfire/entry.S
arch/m68knommu/platform/coldfire/intc-2.c
arch/m68knommu/platform/coldfire/intc-simr.c
arch/m68knommu/platform/coldfire/intc.c
arch/m68knommu/platform/coldfire/sltimers.c [new file with mode: 0644]
arch/microblaze/kernel/prom.c
arch/mips/Kconfig
arch/mips/include/asm/irq.h
arch/mips/include/asm/prom.h [new file with mode: 0644]
arch/mips/kernel/Makefile
arch/mips/kernel/mips-mt-fpaff.c
arch/mips/kernel/prom.c [new file with mode: 0644]
arch/mips/kernel/setup.c
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/prom.c
arch/sh/Kconfig
arch/sh/boards/Kconfig
arch/sh/boards/Makefile
arch/sh/boards/board-sh2007.c [new file with mode: 0644]
arch/sh/boards/board-sh7757lcr.c [new file with mode: 0644]
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-sdk7786/Makefile
arch/sh/boards/mach-sdk7786/gpio.c [new file with mode: 0644]
arch/sh/boards/mach-sdk7786/setup.c
arch/sh/boards/mach-sdk7786/sram.c [new file with mode: 0644]
arch/sh/boards/mach-x3proto/Makefile
arch/sh/boards/mach-x3proto/gpio.c [new file with mode: 0644]
arch/sh/boards/mach-x3proto/ilsel.c
arch/sh/boards/mach-x3proto/setup.c
arch/sh/boot/compressed/head_32.S
arch/sh/cchips/hd6446x/Makefile
arch/sh/configs/ap325rxa_defconfig
arch/sh/configs/cayman_defconfig
arch/sh/configs/dreamcast_defconfig
arch/sh/configs/ecovec24-romimage_defconfig
arch/sh/configs/edosk7760_defconfig
arch/sh/configs/espt_defconfig
arch/sh/configs/hp6xx_defconfig
arch/sh/configs/kfr2r09-romimage_defconfig
arch/sh/configs/kfr2r09_defconfig
arch/sh/configs/landisk_defconfig
arch/sh/configs/lboxre2_defconfig
arch/sh/configs/magicpanelr2_defconfig
arch/sh/configs/microdev_defconfig
arch/sh/configs/migor_defconfig
arch/sh/configs/polaris_defconfig
arch/sh/configs/r7780mp_defconfig
arch/sh/configs/r7785rp_defconfig
arch/sh/configs/rts7751r2d1_defconfig
arch/sh/configs/rts7751r2dplus_defconfig
arch/sh/configs/sdk7780_defconfig
arch/sh/configs/se7343_defconfig
arch/sh/configs/se7712_defconfig
arch/sh/configs/se7721_defconfig
arch/sh/configs/se7722_defconfig
arch/sh/configs/se7724_defconfig
arch/sh/configs/se7750_defconfig
arch/sh/configs/se7751_defconfig
arch/sh/configs/se7780_defconfig
arch/sh/configs/sh03_defconfig
arch/sh/configs/sh2007_defconfig [new file with mode: 0644]
arch/sh/configs/sh7710voipgw_defconfig
arch/sh/configs/sh7757lcr_defconfig [new file with mode: 0644]
arch/sh/configs/sh7763rdp_defconfig
arch/sh/configs/sh7785lcr_defconfig
arch/sh/configs/shx3_defconfig
arch/sh/configs/snapgear_defconfig
arch/sh/configs/systemh_defconfig
arch/sh/configs/titan_defconfig
arch/sh/configs/ul2_defconfig
arch/sh/drivers/dma/dma-api.c
arch/sh/drivers/pci/Makefile
arch/sh/drivers/pci/fixups-sdk7786.c [new file with mode: 0644]
arch/sh/drivers/pci/ops-sh4.c
arch/sh/drivers/pci/ops-sh7786.c
arch/sh/drivers/pci/pci-sh7751.c
arch/sh/drivers/pci/pci-sh7780.c
arch/sh/drivers/pci/pci-sh7780.h
arch/sh/drivers/pci/pci.c
arch/sh/drivers/pci/pcie-sh7786.c
arch/sh/drivers/pci/pcie-sh7786.h
arch/sh/include/asm/Kbuild
arch/sh/include/asm/elf.h
arch/sh/include/asm/fixmap.h
arch/sh/include/asm/gpio.h
arch/sh/include/asm/ilsel.h [deleted file]
arch/sh/include/asm/irq.h
arch/sh/include/asm/kprobes.h
arch/sh/include/asm/pci.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/ptrace_32.h [new file with mode: 0644]
arch/sh/include/asm/ptrace_64.h [new file with mode: 0644]
arch/sh/include/asm/sizes.h
arch/sh/include/asm/sram.h [new file with mode: 0644]
arch/sh/include/asm/system.h
arch/sh/include/asm/system_32.h
arch/sh/include/asm/tlbflush.h
arch/sh/include/asm/unistd_32.h
arch/sh/include/asm/unistd_64.h
arch/sh/include/cpu-sh3/cpu/mmu_context.h
arch/sh/include/cpu-sh4/cpu/freq.h
arch/sh/include/cpu-sh4/cpu/sh7757.h
arch/sh/include/cpu-sh4/cpu/shx3.h [new file with mode: 0644]
arch/sh/include/mach-common/mach/sh2007.h [new file with mode: 0644]
arch/sh/include/mach-sdk7786/mach/fpga.h
arch/sh/include/mach-x3proto/mach/hardware.h [new file with mode: 0644]
arch/sh/include/mach-x3proto/mach/ilsel.h [new file with mode: 0644]
arch/sh/kernel/Makefile
arch/sh/kernel/clkdev.c
arch/sh/kernel/cpu/sh4/probe.c
arch/sh/kernel/cpu/sh4a/Makefile
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/sh4a/clock-shx3.c
arch/sh/kernel/cpu/sh4a/intc-shx3.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/perf_event.c
arch/sh/kernel/cpu/sh4a/pinmux-sh7757.c
arch/sh/kernel/cpu/sh4a/pinmux-shx3.c [new file with mode: 0644]
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/cpu/sh4a/setup-sh7757.c
arch/sh/kernel/cpu/sh4a/setup-sh7786.c
arch/sh/kernel/cpu/sh4a/setup-shx3.c
arch/sh/kernel/head_32.S
arch/sh/kernel/io_trapped.c
arch/sh/kernel/irq.c
arch/sh/kernel/kdebugfs.c [new file with mode: 0644]
arch/sh/kernel/kprobes.c
arch/sh/kernel/ptrace.c [new file with mode: 0644]
arch/sh/kernel/ptrace_32.c
arch/sh/kernel/ptrace_64.c
arch/sh/kernel/reboot.c
arch/sh/kernel/setup.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sh/kernel/traps_32.c
arch/sh/kernel/traps_64.c
arch/sh/lib/Makefile
arch/sh/math-emu/math.c
arch/sh/mm/Kconfig
arch/sh/mm/Makefile
arch/sh/mm/asids-debugfs.c
arch/sh/mm/cache-debugfs.c
arch/sh/mm/consistent.c
arch/sh/mm/init.c
arch/sh/mm/nommu.c
arch/sh/mm/pmb.c
arch/sh/mm/sram.c [new file with mode: 0644]
arch/sh/mm/tlb-debugfs.c
arch/sh/mm/tlbflush_32.c
arch/sh/mm/tlbflush_64.c
arch/sh/tools/mach-types
arch/sparc/Kconfig
arch/sparc/include/asm/Kbuild
arch/sparc/include/asm/floppy_32.h
arch/sparc/include/asm/openprom.h
arch/sparc/include/asm/oplib_32.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/include/asm/prom.h
arch/sparc/kernel/auxio_32.c
arch/sparc/kernel/btext.c
arch/sparc/kernel/devices.c
arch/sparc/kernel/leon_kernel.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/prom.h
arch/sparc/kernel/prom_common.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/starfire.c
arch/sparc/kernel/tadpole.c
arch/sparc/mm/init_64.c
arch/sparc/mm/srmmu.c
arch/sparc/mm/sun4c.c
arch/sparc/prom/init_32.c
arch/sparc/prom/init_64.c
arch/sparc/prom/memory.c
arch/sparc/prom/misc_64.c
arch/sparc/prom/ranges.c
arch/sparc/prom/tree_32.c
arch/sparc/prom/tree_64.c
arch/x86/include/asm/olpc.h
block/blk-core.c
block/blk-merge.c
block/blk.h
block/genhd.c
drivers/Makefile
drivers/base/platform.c
drivers/block/xsysace.c
drivers/char/keyboard.c
drivers/char/sysrq.c
drivers/clocksource/sh_cmt.c
drivers/firewire/Kconfig
drivers/firewire/Makefile
drivers/firewire/init_ohci1394_dma.c [new file with mode: 0644]
drivers/gpio/xilinx_gpio.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/hdaps.c [deleted file]
drivers/i2c/busses/i2c-sh7760.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/ieee1394/Kconfig [deleted file]
drivers/ieee1394/Makefile [deleted file]
drivers/ieee1394/config_roms.c [deleted file]
drivers/ieee1394/config_roms.h [deleted file]
drivers/ieee1394/csr.c [deleted file]
drivers/ieee1394/csr.h [deleted file]
drivers/ieee1394/csr1212.c [deleted file]
drivers/ieee1394/csr1212.h [deleted file]
drivers/ieee1394/dma.c [deleted file]
drivers/ieee1394/dma.h [deleted file]
drivers/ieee1394/dv1394-private.h [deleted file]
drivers/ieee1394/dv1394.c [deleted file]
drivers/ieee1394/dv1394.h [deleted file]
drivers/ieee1394/eth1394.c [deleted file]
drivers/ieee1394/eth1394.h [deleted file]
drivers/ieee1394/highlevel.c [deleted file]
drivers/ieee1394/highlevel.h [deleted file]
drivers/ieee1394/hosts.c [deleted file]
drivers/ieee1394/hosts.h [deleted file]
drivers/ieee1394/ieee1394-ioctl.h [deleted file]
drivers/ieee1394/ieee1394.h [deleted file]
drivers/ieee1394/ieee1394_core.c [deleted file]
drivers/ieee1394/ieee1394_core.h [deleted file]
drivers/ieee1394/ieee1394_hotplug.h [deleted file]
drivers/ieee1394/ieee1394_transactions.c [deleted file]
drivers/ieee1394/ieee1394_transactions.h [deleted file]
drivers/ieee1394/ieee1394_types.h [deleted file]
drivers/ieee1394/init_ohci1394_dma.c [deleted file]
drivers/ieee1394/iso.c [deleted file]
drivers/ieee1394/iso.h [deleted file]
drivers/ieee1394/nodemgr.c [deleted file]
drivers/ieee1394/nodemgr.h [deleted file]
drivers/ieee1394/ohci1394.c [deleted file]
drivers/ieee1394/ohci1394.h [deleted file]
drivers/ieee1394/pcilynx.c [deleted file]
drivers/ieee1394/pcilynx.h [deleted file]
drivers/ieee1394/raw1394-private.h [deleted file]
drivers/ieee1394/raw1394.c [deleted file]
drivers/ieee1394/raw1394.h [deleted file]
drivers/ieee1394/sbp2.c [deleted file]
drivers/ieee1394/sbp2.h [deleted file]
drivers/ieee1394/video1394.c [deleted file]
drivers/ieee1394/video1394.h [deleted file]
drivers/input/evdev.c
drivers/input/gameport/emu10k1-gp.c
drivers/input/gameport/fm801-gp.c
drivers/input/input.c
drivers/input/keyboard/Kconfig
drivers/input/keyboard/Makefile
drivers/input/keyboard/adp5588-keys.c
drivers/input/keyboard/hil_kbd.c
drivers/input/keyboard/nomadik-ske-keypad.c [new file with mode: 0644]
drivers/input/keyboard/omap4-keypad.c [new file with mode: 0644]
drivers/input/keyboard/twl4030_keypad.c
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/ab8500-ponkey.c [new file with mode: 0644]
drivers/input/misc/ati_remote2.c
drivers/input/misc/powermate.c
drivers/input/mouse/elantech.c
drivers/input/mouse/psmouse-base.c
drivers/input/mouse/synaptics.c
drivers/input/mouse/synaptics.h
drivers/input/mouse/trackpoint.c
drivers/input/mousedev.c
drivers/input/serio/Kconfig
drivers/input/serio/Makefile
drivers/input/serio/i8042.c
drivers/input/serio/ps2mult.c [new file with mode: 0644]
drivers/input/serio/serio.c
drivers/input/sparse-keymap.c
drivers/input/tablet/Kconfig
drivers/input/tablet/Makefile
drivers/input/tablet/hanwang.c [new file with mode: 0644]
drivers/input/tablet/wacom.h
drivers/input/tablet/wacom_sys.c
drivers/input/tablet/wacom_wac.c
drivers/input/tablet/wacom_wac.h
drivers/input/touchscreen/Kconfig
drivers/input/touchscreen/Makefile
drivers/input/touchscreen/ad7877.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/bu21013_ts.c [new file with mode: 0644]
drivers/input/touchscreen/cy8ctmg110_ts.c
drivers/input/touchscreen/hp680_ts_input.c
drivers/input/touchscreen/intel-mid-touch.c [new file with mode: 0644]
drivers/input/touchscreen/lpc32xx_ts.c [new file with mode: 0644]
drivers/input/touchscreen/s3c2410_ts.c
drivers/input/touchscreen/stmpe-ts.c
drivers/input/touchscreen/tps6507x-ts.c
drivers/input/touchscreen/tsc2007.c
drivers/input/touchscreen/wacom_w8001.c
drivers/input/touchscreen/wm97xx-core.c
drivers/media/IR/ir-keytable.c
drivers/mfd/ab8500-core.c
drivers/mfd/sh_mobile_sdhi.c
drivers/mtd/devices/m25p80.c
drivers/mtd/maps/physmap_of.c
drivers/mtd/ofpart.c
drivers/of/Kconfig
drivers/of/Makefile
drivers/of/address.c
drivers/of/base.c
drivers/of/device.c
drivers/of/fdt.c
drivers/of/irq.c
drivers/of/of_i2c.c
drivers/of/pdt.c [new file with mode: 0644]
drivers/of/platform.c
drivers/platform/x86/Kconfig
drivers/platform/x86/Makefile
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/dell-laptop.c
drivers/platform/x86/dell-wmi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/hdaps.c [new file with mode: 0644]
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/ibm_rtl.c [new file with mode: 0644]
drivers/platform/x86/ideapad-laptop.c [new file with mode: 0644]
drivers/platform/x86/ideapad_acpi.c [deleted file]
drivers/platform/x86/intel_pmic_gpio.c
drivers/platform/x86/intel_scu_ipc.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/topstar-laptop.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/wmi.c
drivers/platform/x86/xo1-rfkill.c [new file with mode: 0644]
drivers/sbus/char/jsflash.c
drivers/serial/68328serial.h
drivers/serial/of_serial.c
drivers/serial/sh-sci.h
drivers/sh/Kconfig
drivers/sh/Makefile
drivers/sh/clk-cpg.c [deleted file]
drivers/sh/clk.c [deleted file]
drivers/sh/clk/Makefile [new file with mode: 0644]
drivers/sh/clk/core.c [new file with mode: 0644]
drivers/sh/clk/cpg.c [new file with mode: 0644]
drivers/sh/intc.c [deleted file]
drivers/sh/intc/Kconfig [new file with mode: 0644]
drivers/sh/intc/Makefile [new file with mode: 0644]
drivers/sh/intc/access.c [new file with mode: 0644]
drivers/sh/intc/balancing.c [new file with mode: 0644]
drivers/sh/intc/chip.c [new file with mode: 0644]
drivers/sh/intc/core.c [new file with mode: 0644]
drivers/sh/intc/dynamic.c [new file with mode: 0644]
drivers/sh/intc/handle.c [new file with mode: 0644]
drivers/sh/intc/internals.h [new file with mode: 0644]
drivers/sh/intc/userimask.c [new file with mode: 0644]
drivers/sh/intc/virq-debugfs.c [new file with mode: 0644]
drivers/sh/intc/virq.c [new file with mode: 0644]
drivers/sh/pfc.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/mrst-touchscreen/Kconfig [deleted file]
drivers/staging/mrst-touchscreen/Makefile [deleted file]
drivers/staging/mrst-touchscreen/TODO [deleted file]
drivers/staging/mrst-touchscreen/intel-mid-touch.c [deleted file]
drivers/usb/host/r8a66597-hcd.c
drivers/video/aty/atyfb_base.c
drivers/video/sh_mobile_lcdcfb.c
fs/coda/cache.c
fs/coda/cnode.c
fs/coda/dir.c
fs/coda/file.c
fs/coda/inode.c
fs/coda/pioctl.c
fs/coda/psdev.c
fs/coda/symlink.c
fs/coda/upcall.c
fs/partitions/check.c
include/linux/blkdev.h
include/linux/coda_fs_i.h
include/linux/coda_linux.h
include/linux/coda_psdev.h
include/linux/elevator.h
include/linux/gameport.h
include/linux/genhd.h
include/linux/input.h
include/linux/input/bu21013.h [new file with mode: 0644]
include/linux/of_device.h
include/linux/of_fdt.h
include/linux/of_irq.h
include/linux/of_pdt.h [new file with mode: 0644]
include/linux/pci_ids.h
include/linux/serio.h
include/linux/sh_clk.h
include/linux/sh_intc.h
include/linux/sh_pfc.h
include/media/rc-map.h
sound/soc/sh/siu_pcm.c

diff --git a/Documentation/ABI/obsolete/dv1394 b/Documentation/ABI/obsolete/dv1394
deleted file mode 100644 (file)
index 2ee3686..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-What:          dv1394 (a.k.a. "OHCI-DV I/O support" for FireWire)
-Contact:       linux1394-devel@lists.sourceforge.net
-Description:
-       New application development should use raw1394 + userspace libraries
-       instead, notably libiec61883 which is functionally equivalent.
-
-Users:
-       ffmpeg/libavformat (used by a variety of media players)
-       dvgrab v1.x (replaced by dvgrab2 on top of raw1394 and resp. libraries)
diff --git a/Documentation/ABI/removed/dv1394 b/Documentation/ABI/removed/dv1394
new file mode 100644 (file)
index 0000000..c2310b6
--- /dev/null
@@ -0,0 +1,14 @@
+What:          dv1394 (a.k.a. "OHCI-DV I/O support" for FireWire)
+Date:          May 2010 (scheduled), finally removed in kernel v2.6.37
+Contact:       linux1394-devel@lists.sourceforge.net
+Description:
+       /dev/dv1394/* were character device files, one for each FireWire
+       controller and for NTSC and PAL respectively, from which DV data
+       could be received by read() or transmitted by write().  A few
+       ioctl()s allowed limited control.
+       This special-purpose interface has been superseded by libraw1394 +
+       libiec61883 which are functionally equivalent, support HDV, and
+       transparently work on top of the newer firewire kernel drivers.
+
+Users:
+       ffmpeg/libavformat (if configured for DV1394)
diff --git a/Documentation/ABI/removed/raw1394 b/Documentation/ABI/removed/raw1394
new file mode 100644 (file)
index 0000000..490aa1e
--- /dev/null
@@ -0,0 +1,15 @@
+What:          raw1394 (a.k.a. "Raw IEEE1394 I/O support" for FireWire)
+Date:          May 2010 (scheduled), finally removed in kernel v2.6.37
+Contact:       linux1394-devel@lists.sourceforge.net
+Description:
+       /dev/raw1394 was a character device file that allowed low-level
+       access to FireWire buses.  Its major drawbacks were its inability
+       to implement sensible device security policies, and its low level
+       of abstraction that required userspace clients do duplicate much
+       of the kernel's ieee1394 core functionality.
+       Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
+       firewire-core.
+
+Users:
+       libraw1394 (works with firewire-cdev too, transparent to library ABI
+       users)
diff --git a/Documentation/ABI/removed/raw1394_legacy_isochronous b/Documentation/ABI/removed/raw1394_legacy_isochronous
deleted file mode 100644 (file)
index 1b62962..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-What:          legacy isochronous ABI of raw1394 (1st generation iso ABI)
-Date:          June 2007 (scheduled), removed in kernel v2.6.23
-Contact:       linux1394-devel@lists.sourceforge.net
-Description:
-       The two request types RAW1394_REQ_ISO_SEND, RAW1394_REQ_ISO_LISTEN have
-       been deprecated for quite some time.  They are very inefficient as they
-       come with high interrupt load and several layers of callbacks for each
-       packet.  Because of these deficiencies, the video1394 and dv1394 drivers
-       and the 3rd-generation isochronous ABI in raw1394 (rawiso) were created.
-
-Users:
-       libraw1394 users via the long deprecated API raw1394_iso_write,
-       raw1394_start_iso_write, raw1394_start_iso_rcv, raw1394_stop_iso_rcv
-
-       libdc1394, which optionally uses these old libraw1394 calls
-       alternatively to the more efficient video1394 ABI
diff --git a/Documentation/ABI/removed/video1394 b/Documentation/ABI/removed/video1394
new file mode 100644 (file)
index 0000000..c39c25a
--- /dev/null
@@ -0,0 +1,16 @@
+What:          video1394 (a.k.a. "OHCI-1394 Video support" for FireWire)
+Date:          May 2010 (scheduled), finally removed in kernel v2.6.37
+Contact:       linux1394-devel@lists.sourceforge.net
+Description:
+       /dev/video1394/* were character device files, one for each FireWire
+       controller, which were used for isochronous I/O.  It was added as an
+       alternative to raw1394's isochronous I/O functionality which had
+       performance issues in its first generation.  Any video1394 user had
+       to use raw1394 + libraw1394 too because video1394 did not provide
+       asynchronous I/O for device discovery and configuration.
+       Replaced by /dev/fw*, i.e. the <linux/firewire-cdev.h> ABI of
+       firewire-core.
+
+Users:
+       libdc1394 (works with firewire-cdev too, transparent to library ABI
+       users)
diff --git a/Documentation/ABI/testing/sysfs-devices-system-ibm-rtl b/Documentation/ABI/testing/sysfs-devices-system-ibm-rtl
new file mode 100644 (file)
index 0000000..b82deea
--- /dev/null
@@ -0,0 +1,22 @@
+What:           state
+Date:           Sep 2010
+KernelVersion:  2.6.37
+Contact:        Vernon Mauery <vernux@us.ibm.com>
+Description:    The state file allows a means by which to change in and
+                out of Premium Real-Time Mode (PRTM), as well as the
+                ability to query the current state.
+                    0 => PRTM off
+                    1 => PRTM enabled
+Users:          The ibm-prtm userspace daemon uses this interface.
+
+
+What:           version
+Date:           Sep 2010
+KernelVersion:  2.6.37
+Contact:        Vernon Mauery <vernux@us.ibm.com>
+Description:    The version file provides a means by which to query
+                the RTL table version that lives in the Extended
+                BIOS Data Area (EBDA).
+Users:          The ibm-prtm userspace daemon uses this interface.
+
+
index 9961f15..e833c8c 100644 (file)
@@ -502,16 +502,6 @@ Who:       Thomas Gleixner <tglx@linutronix.de>
 
 ----------------------------
 
-What:  old ieee1394 subsystem (CONFIG_IEEE1394)
-When:  2.6.37
-Files: drivers/ieee1394/ except init_ohci1394_dma.c
-Why:   superseded by drivers/firewire/ (CONFIG_FIREWIRE) which offers more
-       features, better performance, and better security, all with smaller
-       and more modern code base
-Who:   Stefan Richter <stefanr@s5r6.in-berlin.de>
-
-----------------------------
-
 What:  The acpi_sleep=s4_nonvs command line option
 When:  2.6.37
 Files: arch/x86/kernel/acpi/sleep.c
index ebb9f9e..8f72c90 100644 (file)
@@ -2645,10 +2645,10 @@ F:      drivers/net/greth*
 
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 M:     Frank Seidel <frank@f-seidel.de>
-L:     lm-sensors@lm-sensors.org
+L:     platform-driver-x86@vger.kernel.org
 W:     http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
 S:     Maintained
-F:     drivers/hwmon/hdaps.c
+F:     drivers/platform/x86/hdaps.c
 
 HWPOISON MEMORY FAILURE HANDLING
 M:     Andi Kleen <andi@firstfloor.org>
index fcb587f..cac83a6 100644 (file)
 #include <linux/amba/pl022.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
+#include <linux/input/matrix_keypad.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
 #include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/ske.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -49,6 +51,24 @@ static pin_cfg_t mop500_pins[] = {
        GPIO11_I2C2_SCL,
        GPIO229_I2C3_SDA,
        GPIO230_I2C3_SCL,
+
+       /* SKE keypad */
+       GPIO153_KP_I7,
+       GPIO154_KP_I6,
+       GPIO155_KP_I5,
+       GPIO156_KP_I4,
+       GPIO157_KP_O7,
+       GPIO158_KP_O6,
+       GPIO159_KP_O5,
+       GPIO160_KP_O4,
+       GPIO161_KP_I3,
+       GPIO162_KP_I2,
+       GPIO163_KP_I1,
+       GPIO164_KP_I0,
+       GPIO165_KP_O3,
+       GPIO166_KP_O2,
+       GPIO167_KP_O1,
+       GPIO168_KP_O0,
 };
 
 static void ab4500_spi_cs_control(u32 command)
@@ -148,12 +168,120 @@ static struct amba_device *amba_devs[] __initdata = {
        &u8500_ssp0_device,
 };
 
+static const unsigned int ux500_keymap[] = {
+       KEY(2, 5, KEY_END),
+       KEY(4, 1, KEY_POWER),
+       KEY(3, 5, KEY_VOLUMEDOWN),
+       KEY(1, 3, KEY_3),
+       KEY(5, 2, KEY_RIGHT),
+       KEY(5, 0, KEY_9),
+
+       KEY(0, 5, KEY_MENU),
+       KEY(7, 6, KEY_ENTER),
+       KEY(4, 5, KEY_0),
+       KEY(6, 7, KEY_2),
+       KEY(3, 4, KEY_UP),
+       KEY(3, 3, KEY_DOWN),
+
+       KEY(6, 4, KEY_SEND),
+       KEY(6, 2, KEY_BACK),
+       KEY(4, 2, KEY_VOLUMEUP),
+       KEY(5, 5, KEY_1),
+       KEY(4, 3, KEY_LEFT),
+       KEY(3, 2, KEY_7),
+};
+
+static const struct matrix_keymap_data ux500_keymap_data = {
+       .keymap         = ux500_keymap,
+       .keymap_size    = ARRAY_SIZE(ux500_keymap),
+};
+
+/*
+ * Nomadik SKE keypad
+ */
+#define ROW_PIN_I0      164
+#define ROW_PIN_I1      163
+#define ROW_PIN_I2      162
+#define ROW_PIN_I3      161
+#define ROW_PIN_I4      156
+#define ROW_PIN_I5      155
+#define ROW_PIN_I6      154
+#define ROW_PIN_I7      153
+#define COL_PIN_O0      168
+#define COL_PIN_O1      167
+#define COL_PIN_O2      166
+#define COL_PIN_O3      165
+#define COL_PIN_O4      160
+#define COL_PIN_O5      159
+#define COL_PIN_O6      158
+#define COL_PIN_O7      157
+
+#define SKE_KPD_MAX_ROWS        8
+#define SKE_KPD_MAX_COLS        8
+
+static int ske_kp_rows[] = {
+       ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
+       ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
+};
+
+/*
+ * ske_set_gpio_row: request and set gpio rows
+ */
+static int ske_set_gpio_row(int gpio)
+{
+       int ret;
+
+       ret = gpio_request(gpio, "ske-kp");
+       if (ret < 0) {
+               pr_err("ske_set_gpio_row: gpio request failed\n");
+               return ret;
+       }
+
+       ret = gpio_direction_output(gpio, 1);
+       if (ret < 0) {
+               pr_err("ske_set_gpio_row: gpio direction failed\n");
+               gpio_free(gpio);
+       }
+
+       return ret;
+}
+
+/*
+ * ske_kp_init - enable the gpio configuration
+ */
+static int ske_kp_init(void)
+{
+       int ret, i;
+
+       for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
+               ret = ske_set_gpio_row(ske_kp_rows[i]);
+               if (ret < 0) {
+                       pr_err("ske_kp_init: failed init\n");
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static struct ske_keypad_platform_data ske_keypad_board = {
+       .init           = ske_kp_init,
+       .keymap_data    = &ux500_keymap_data,
+       .no_autorepeat  = true,
+       .krow           = SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
+       .kcol           = SKE_KPD_MAX_COLS,
+       .debounce_ms    = 40,                   /* in millsecs */
+};
+
+
+
 /* add any platform devices here - TODO */
 static struct platform_device *platform_devs[] __initdata = {
        &u8500_i2c0_device,
        &ux500_i2c1_device,
        &ux500_i2c2_device,
        &ux500_i2c3_device,
+       &ux500_ske_keypad_device,
 };
 
 static void __init u8500_init_machine(void)
@@ -168,6 +296,7 @@ static void __init u8500_init_machine(void)
        ux500_i2c1_device.dev.platform_data = &u8500_i2c1_data;
        ux500_i2c2_device.dev.platform_data = &u8500_i2c2_data;
        ux500_i2c3_device.dev.platform_data = &u8500_i2c3_data;
+       ux500_ske_keypad_device.dev.platform_data = &ske_keypad_board;
 
        u8500_ssp0_device.dev.platform_data = &ssp0_platform_data;
 
index d8ab7f1..1675047 100644 (file)
@@ -477,6 +477,7 @@ static struct clk_lookup u8500_common_clks[] = {
        CLK(sdi5,       "sdi5",         NULL),
        CLK(uart2,      "uart2",        NULL),
        CLK(ske,        "ske",          NULL),
+       CLK(ske,        "nmk-ske-keypad",       NULL),
        CLK(sdi2,       "sdi2",         NULL),
        CLK(i2c0,       "nmk-i2c.0",    NULL),
        CLK(fsmc,       "fsmc",         NULL),
index 40032fe..cbbe69a 100644 (file)
@@ -292,3 +292,23 @@ void dma40_u8500ed_fixup(void)
        dma40_resources[1].start = U8500_DMA_LCPA_BASE_ED;
        dma40_resources[1].end = U8500_DMA_LCPA_BASE_ED + 2 * SZ_1K - 1;
 }
+
+struct resource keypad_resources[] = {
+       [0] = {
+               .start = U8500_SKE_BASE,
+               .end = U8500_SKE_BASE + SZ_4K - 1,
+               .flags = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start = IRQ_DB8500_KB,
+               .end = IRQ_DB8500_KB,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+struct platform_device ux500_ske_keypad_device = {
+       .name = "nmk-ske-keypad",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(keypad_resources),
+       .resource = keypad_resources,
+};
index 33a120c..b91a4d1 100644 (file)
@@ -26,6 +26,7 @@ extern struct platform_device ux500_i2c3_device;
 extern struct platform_device u8500_i2c0_device;
 extern struct platform_device u8500_i2c4_device;
 extern struct platform_device u8500_dma40_device;
+extern struct platform_device ux500_ske_keypad_device;
 
 extern struct amba_device u8500_sdi0_device;
 extern struct amba_device u8500_sdi1_device;
index 66f8761..f923764 100644 (file)
 #define GPIO152_KP_O9          PIN_CFG(152, ALT_C)
 
 #define GPIO153_GPIO           PIN_CFG(153, GPIO)
-#define GPIO153_KP_I7          PIN_CFG(153, ALT_A)
+#define GPIO153_KP_I7          PIN_CFG_PULL(153, ALT_A, DOWN)
 #define GPIO153_LCD_D24                PIN_CFG(153, ALT_B)
 #define GPIO153_U2_RXD         PIN_CFG(153, ALT_C)
 
 #define GPIO154_GPIO           PIN_CFG(154, GPIO)
-#define GPIO154_KP_I6          PIN_CFG(154, ALT_A)
+#define GPIO154_KP_I6          PIN_CFG_PULL(154, ALT_A, DOWN)
 #define GPIO154_LCD_D25                PIN_CFG(154, ALT_B)
 #define GPIO154_U2_TXD         PIN_CFG(154, ALT_C)
 
 #define GPIO155_GPIO           PIN_CFG(155, GPIO)
-#define GPIO155_KP_I5          PIN_CFG(155, ALT_A)
+#define GPIO155_KP_I5          PIN_CFG_PULL(155, ALT_A, DOWN)
 #define GPIO155_LCD_D26                PIN_CFG(155, ALT_B)
 #define GPIO155_STMAPE_CLK     PIN_CFG(155, ALT_C)
 
 #define GPIO156_GPIO           PIN_CFG(156, GPIO)
-#define GPIO156_KP_I4          PIN_CFG(156, ALT_A)
+#define GPIO156_KP_I4          PIN_CFG_PULL(156, ALT_A, DOWN)
 #define GPIO156_LCD_D27                PIN_CFG(156, ALT_B)
 #define GPIO156_STMAPE_DAT3    PIN_CFG(156, ALT_C)
 
 #define GPIO157_GPIO           PIN_CFG(157, GPIO)
-#define GPIO157_KP_O7          PIN_CFG(157, ALT_A)
+#define GPIO157_KP_O7          PIN_CFG_PULL(157, ALT_A, UP)
 #define GPIO157_LCD_D28                PIN_CFG(157, ALT_B)
 #define GPIO157_STMAPE_DAT2    PIN_CFG(157, ALT_C)
 
 #define GPIO158_GPIO           PIN_CFG(158, GPIO)
-#define GPIO158_KP_O6          PIN_CFG(158, ALT_A)
+#define GPIO158_KP_O6          PIN_CFG_PULL(158, ALT_A, UP)
 #define GPIO158_LCD_D29                PIN_CFG(158, ALT_B)
 #define GPIO158_STMAPE_DAT1    PIN_CFG(158, ALT_C)
 
 #define GPIO159_GPIO           PIN_CFG(159, GPIO)
-#define GPIO159_KP_O5          PIN_CFG(159, ALT_A)
+#define GPIO159_KP_O5          PIN_CFG_PULL(159, ALT_A, UP)
 #define GPIO159_LCD_D30                PIN_CFG(159, ALT_B)
 #define GPIO159_STMAPE_DAT0    PIN_CFG(159, ALT_C)
 
 #define GPIO160_GPIO           PIN_CFG(160, GPIO)
-#define GPIO160_KP_O4          PIN_CFG(160, ALT_A)
+#define GPIO160_KP_O4          PIN_CFG_PULL(160, ALT_A, UP)
 #define GPIO160_LCD_D31                PIN_CFG(160, ALT_B)
 #define GPIO160_NONE           PIN_CFG(160, ALT_C)
 
 #define GPIO161_GPIO           PIN_CFG(161, GPIO)
-#define GPIO161_KP_I3          PIN_CFG(161, ALT_A)
+#define GPIO161_KP_I3          PIN_CFG_PULL(161, ALT_A, DOWN)
 #define GPIO161_LCD_D32                PIN_CFG(161, ALT_B)
 #define GPIO161_UARTMOD_RXD    PIN_CFG(161, ALT_C)
 
 #define GPIO162_GPIO           PIN_CFG(162, GPIO)
-#define GPIO162_KP_I2          PIN_CFG(162, ALT_A)
+#define GPIO162_KP_I2          PIN_CFG_PULL(162, ALT_A, DOWN)
 #define GPIO162_LCD_D33                PIN_CFG(162, ALT_B)
 #define GPIO162_UARTMOD_TXD    PIN_CFG(162, ALT_C)
 
 #define GPIO163_GPIO           PIN_CFG(163, GPIO)
-#define GPIO163_KP_I1          PIN_CFG(163, ALT_A)
+#define GPIO163_KP_I1          PIN_CFG_PULL(163, ALT_A, DOWN)
 #define GPIO163_LCD_D34                PIN_CFG(163, ALT_B)
 #define GPIO163_STMMOD_CLK     PIN_CFG(163, ALT_C)
 
 #define GPIO164_GPIO           PIN_CFG(164, GPIO)
-#define GPIO164_KP_I0          PIN_CFG(164, ALT_A)
+#define GPIO164_KP_I0          PIN_CFG_PULL(164, ALT_A, UP)
 #define GPIO164_LCD_D35                PIN_CFG(164, ALT_B)
 #define GPIO164_STMMOD_DAT3    PIN_CFG(164, ALT_C)
 
 #define GPIO165_GPIO           PIN_CFG(165, GPIO)
-#define GPIO165_KP_O3          PIN_CFG(165, ALT_A)
+#define GPIO165_KP_O3          PIN_CFG_PULL(165, ALT_A, UP)
 #define GPIO165_LCD_D36                PIN_CFG(165, ALT_B)
 #define GPIO165_STMMOD_DAT2    PIN_CFG(165, ALT_C)
 
 #define GPIO166_GPIO           PIN_CFG(166, GPIO)
-#define GPIO166_KP_O2          PIN_CFG(166, ALT_A)
+#define GPIO166_KP_O2          PIN_CFG_PULL(166, ALT_A, UP)
 #define GPIO166_LCD_D37                PIN_CFG(166, ALT_B)
 #define GPIO166_STMMOD_DAT1    PIN_CFG(166, ALT_C)
 
 #define GPIO167_GPIO           PIN_CFG(167, GPIO)
-#define GPIO167_KP_O1          PIN_CFG(167, ALT_A)
+#define GPIO167_KP_O1          PIN_CFG_PULL(167, ALT_A, UP)
 #define GPIO167_LCD_D38                PIN_CFG(167, ALT_B)
 #define GPIO167_STMMOD_DAT0    PIN_CFG(167, ALT_C)
 
 #define GPIO168_GPIO           PIN_CFG(168, GPIO)
-#define GPIO168_KP_O0          PIN_CFG(168, ALT_A)
+#define GPIO168_KP_O0          PIN_CFG_PULL(168, ALT_A, UP)
 #define GPIO168_LCD_D39                PIN_CFG(168, ALT_B)
 #define GPIO168_NONE           PIN_CFG(168, ALT_C)
 
diff --git a/arch/arm/plat-nomadik/include/plat/ske.h b/arch/arm/plat-nomadik/include/plat/ske.h
new file mode 100644 (file)
index 0000000..31382fb
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
+ *
+ * ux500 Scroll key and Keypad Encoder (SKE) header
+ */
+
+#ifndef __SKE_H
+#define __SKE_H
+
+#include <linux/input/matrix_keypad.h>
+
+/* register definitions for SKE peripheral */
+#define SKE_CR         0x00
+#define SKE_VAL0       0x04
+#define SKE_VAL1       0x08
+#define SKE_DBCR       0x0C
+#define SKE_IMSC       0x10
+#define SKE_RIS                0x14
+#define SKE_MIS                0x18
+#define SKE_ICR                0x1C
+
+/*
+ * Keypad module
+ */
+
+/**
+ * struct keypad_platform_data - structure for platform specific data
+ * @init:      pointer to keypad init function
+ * @exit:      pointer to keypad deinitialisation function
+ * @keymap_data: matrix scan code table for keycodes
+ * @krow:      maximum number of rows
+ * @kcol:      maximum number of columns
+ * @debounce_ms: platform specific debounce time
+ * @no_autorepeat: flag for auto repetition
+ * @wakeup_enable: allow waking up the system
+ */
+struct ske_keypad_platform_data {
+       int (*init)(void);
+       int (*exit)(void);
+       const struct matrix_keymap_data *keymap_data;
+       u8 krow;
+       u8 kcol;
+       u8 debounce_ms;
+       bool no_autorepeat;
+       bool wakeup_enable;
+};
+#endif /*__SKE_KPD_H*/
diff --git a/arch/arm/plat-omap/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h
new file mode 100644 (file)
index 0000000..2b1d9bc
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef ARCH_ARM_PLAT_OMAP4_KEYPAD_H
+#define ARCH_ARM_PLAT_OMAP4_KEYPAD_H
+
+#include <linux/input/matrix_keypad.h>
+
+struct omap4_keypad_platform_data {
+       const struct matrix_keymap_data *keymap_data;
+
+       u8 rows;
+       u8 cols;
+};
+
+extern int omap4_keyboard_init(struct omap4_keypad_platform_data *);
+#endif
index 89f1956..7085bd5 100644 (file)
@@ -29,7 +29,7 @@
 
 static inline void __flush_cache_all(void)
 {
-#ifdef CONFIG_M5407
+#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
        /*
         *      Use cpushl to push and invalidate all cache lines.
         *      Gas doesn't seem to know how to generate the ColdFire
index 83a9fa4..3b0a34d 100644 (file)
@@ -32,7 +32,9 @@
  */
 #define        MCF_MBAR        0x10000000
 #define        MCF_MBAR2       0x80000000
-#if defined(CONFIG_M520x)
+#if defined(CONFIG_M548x)
+#define        MCF_IPSBAR      MCF_MBAR
+#elif defined(CONFIG_M520x)
 #define        MCF_IPSBAR      0xFC000000
 #else
 #define        MCF_IPSBAR      0x40000000
index 283214d..1b57adb 100644 (file)
@@ -36,7 +36,8 @@
  */
 #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
     defined(CONFIG_M520x) || defined(CONFIG_M523x) || \
-    defined(CONFIG_M527x) || defined(CONFIG_M528x) || defined(CONFIG_M532x)
+    defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
+    defined(CONFIG_M532x) || defined(CONFIG_M548x)
 
 /* These parts have GPIO organized by 8 bit ports */
 
@@ -136,6 +137,8 @@ static inline u32 __mcf_gpio_ppdr(unsigned gpio)
 #endif
        else
                return MCFGPIO_PPDR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#else
+       return 0;
 #endif
 }
 
@@ -173,6 +176,8 @@ static inline u32 __mcf_gpio_podr(unsigned gpio)
 #endif
        else
                return MCFGPIO_PODR + mcfgpio_port(gpio - MCFGPIO_SCR_START);
+#else
+       return 0;
 #endif
 }
 
diff --git a/arch/m68k/include/asm/m548xgpt.h b/arch/m68k/include/asm/m548xgpt.h
new file mode 100644 (file)
index 0000000..c8ef158
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * File:       m548xgpt.h
+ * Purpose:    Register and bit definitions for the MCF548X
+ *
+ * Notes:
+ *
+ */
+
+#ifndef m548xgpt_h
+#define m548xgpt_h
+
+/*********************************************************************
+*
+* General Purpose Timers (GPT)
+*
+*********************************************************************/
+
+/* Register read/write macros */
+#define MCF_GPT_GMS0       0x000800
+#define MCF_GPT_GCIR0      0x000804
+#define MCF_GPT_GPWM0      0x000808
+#define MCF_GPT_GSR0       0x00080C
+#define MCF_GPT_GMS1       0x000810
+#define MCF_GPT_GCIR1      0x000814
+#define MCF_GPT_GPWM1      0x000818
+#define MCF_GPT_GSR1       0x00081C
+#define MCF_GPT_GMS2       0x000820
+#define MCF_GPT_GCIR2      0x000824
+#define MCF_GPT_GPWM2      0x000828
+#define MCF_GPT_GSR2       0x00082C
+#define MCF_GPT_GMS3       0x000830
+#define MCF_GPT_GCIR3      0x000834
+#define MCF_GPT_GPWM3      0x000838
+#define MCF_GPT_GSR3       0x00083C
+#define MCF_GPT_GMS(x)     (0x000800+((x)*0x010))
+#define MCF_GPT_GCIR(x)    (0x000804+((x)*0x010))
+#define MCF_GPT_GPWM(x)    (0x000808+((x)*0x010))
+#define MCF_GPT_GSR(x)     (0x00080C+((x)*0x010))
+
+/* Bit definitions and macros for MCF_GPT_GMS */
+#define MCF_GPT_GMS_TMS(x)         (((x)&0x00000007)<<0)
+#define MCF_GPT_GMS_GPIO(x)        (((x)&0x00000003)<<4)
+#define MCF_GPT_GMS_IEN            (0x00000100)
+#define MCF_GPT_GMS_OD             (0x00000200)
+#define MCF_GPT_GMS_SC             (0x00000400)
+#define MCF_GPT_GMS_CE             (0x00001000)
+#define MCF_GPT_GMS_WDEN           (0x00008000)
+#define MCF_GPT_GMS_ICT(x)         (((x)&0x00000003)<<16)
+#define MCF_GPT_GMS_OCT(x)         (((x)&0x00000003)<<20)
+#define MCF_GPT_GMS_OCPW(x)        (((x)&0x000000FF)<<24)
+#define MCF_GPT_GMS_OCT_FRCLOW     (0x00000000)
+#define MCF_GPT_GMS_OCT_PULSEHI    (0x00100000)
+#define MCF_GPT_GMS_OCT_PULSELO    (0x00200000)
+#define MCF_GPT_GMS_OCT_TOGGLE     (0x00300000)
+#define MCF_GPT_GMS_ICT_ANY        (0x00000000)
+#define MCF_GPT_GMS_ICT_RISE       (0x00010000)
+#define MCF_GPT_GMS_ICT_FALL       (0x00020000)
+#define MCF_GPT_GMS_ICT_PULSE      (0x00030000)
+#define MCF_GPT_GMS_GPIO_INPUT     (0x00000000)
+#define MCF_GPT_GMS_GPIO_OUTLO     (0x00000020)
+#define MCF_GPT_GMS_GPIO_OUTHI     (0x00000030)
+#define MCF_GPT_GMS_TMS_DISABLE    (0x00000000)
+#define MCF_GPT_GMS_TMS_INCAPT     (0x00000001)
+#define MCF_GPT_GMS_TMS_OUTCAPT    (0x00000002)
+#define MCF_GPT_GMS_TMS_PWM        (0x00000003)
+#define MCF_GPT_GMS_TMS_GPIO       (0x00000004)
+
+/* Bit definitions and macros for MCF_GPT_GCIR */
+#define MCF_GPT_GCIR_CNT(x)        (((x)&0x0000FFFF)<<0)
+#define MCF_GPT_GCIR_PRE(x)        (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GPWM */
+#define MCF_GPT_GPWM_LOAD          (0x00000001)
+#define MCF_GPT_GPWM_PWMOP         (0x00000100)
+#define MCF_GPT_GPWM_WIDTH(x)      (((x)&0x0000FFFF)<<16)
+
+/* Bit definitions and macros for MCF_GPT_GSR */
+#define MCF_GPT_GSR_CAPT           (0x00000001)
+#define MCF_GPT_GSR_COMP           (0x00000002)
+#define MCF_GPT_GSR_PWMP           (0x00000004)
+#define MCF_GPT_GSR_TEXP           (0x00000008)
+#define MCF_GPT_GSR_PIN            (0x00000100)
+#define MCF_GPT_GSR_OVF(x)         (((x)&0x00000007)<<12)
+#define MCF_GPT_GSR_CAPTURE(x)     (((x)&0x0000FFFF)<<16)
+
+/********************************************************************/
+
+#endif /* m548xgpt_h */
diff --git a/arch/m68k/include/asm/m548xsim.h b/arch/m68k/include/asm/m548xsim.h
new file mode 100644 (file)
index 0000000..149135e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *     m548xsim.h -- ColdFire 547x/548x System Integration Unit support.
+ */
+
+#ifndef        m548xsim_h
+#define m548xsim_h
+
+#define MCFINT_VECBASE      64
+
+/*
+ *      Interrupt Controller Registers
+ */
+#define MCFICM_INTC0           0x0700          /* Base for Interrupt Ctrl 0 */
+#define MCFINTC_IPRH           0x00            /* Interrupt pending 32-63 */
+#define MCFINTC_IPRL           0x04            /* Interrupt pending 1-31 */
+#define MCFINTC_IMRH           0x08            /* Interrupt mask 32-63 */
+#define MCFINTC_IMRL           0x0c            /* Interrupt mask 1-31 */
+#define MCFINTC_INTFRCH                0x10            /* Interrupt force 32-63 */
+#define MCFINTC_INTFRCL                0x14            /* Interrupt force 1-31 */
+#define MCFINTC_IRLR           0x18            /* */
+#define MCFINTC_IACKL          0x19            /* */
+#define MCFINTC_ICR0           0x40            /* Base ICR register */
+
+/*
+ *     Define system peripheral IRQ usage.
+ */
+#define MCF_IRQ_TIMER          (64 + 54)       /* Slice Timer 0 */
+#define MCF_IRQ_PROFILER       (64 + 53)       /* Slice Timer 1 */
+
+/*
+ *     Generic GPIO support
+ */
+#define MCFGPIO_PIN_MAX                0       /* I am too lazy to count */
+#define MCFGPIO_IRQ_MAX                -1
+#define MCFGPIO_IRQ_VECBASE    -1
+
+/*
+ *     Some PSC related definitions
+ */
+#define MCF_PAR_PSC(x)         (0x000A4F-((x)&0x3))
+#define MCF_PAR_SDA            (0x0008)
+#define MCF_PAR_SCL            (0x0004)
+#define MCF_PAR_PSC_TXD                (0x04)
+#define MCF_PAR_PSC_RXD                (0x08)
+#define MCF_PAR_PSC_RTS(x)     (((x)&0x03)<<4)
+#define MCF_PAR_PSC_CTS(x)     (((x)&0x03)<<6)
+#define MCF_PAR_PSC_CTS_GPIO   (0x00)
+#define MCF_PAR_PSC_CTS_BCLK   (0x80)
+#define MCF_PAR_PSC_CTS_CTS    (0xC0)
+#define MCF_PAR_PSC_RTS_GPIO    (0x00)
+#define MCF_PAR_PSC_RTS_FSYNC  (0x20)
+#define MCF_PAR_PSC_RTS_RTS    (0x30)
+#define MCF_PAR_PSC_CANRX      (0x40)
+
+#endif /* m548xsim_h */
index c042634..f49dfc0 100644 (file)
 .endm
 #endif /* CONFIG_M532x */
 
-#if defined(CONFIG_M5407)
+#if defined(CONFIG_M5407) || defined(CONFIG_M548x)
 /*
  *     Version 4 cores have a true harvard style separate instruction
  *     and data cache. Invalidate and enable cache, also enable write
index 9c70a67..6901fd6 100644 (file)
@@ -41,6 +41,8 @@
 #elif defined(CONFIG_M5407)
 #include <asm/m5407sim.h>
 #include <asm/mcfintc.h>
+#elif defined(CONFIG_M548x)
+#include <asm/m548xsim.h>
 #endif
 
 /****************************************************************************/
diff --git a/arch/m68k/include/asm/mcfslt.h b/arch/m68k/include/asm/mcfslt.h
new file mode 100644 (file)
index 0000000..d0d0ecb
--- /dev/null
@@ -0,0 +1,44 @@
+/****************************************************************************/
+
+/*
+ *     mcfslt.h -- ColdFire internal Slice (SLT) timer support defines.
+ *
+ *     (C) Copyright 2004, Greg Ungerer (gerg@snapgear.com)
+ *     (C) Copyright 2009, Philippe De Muyter (phdm@macqel.be)
+ */
+
+/****************************************************************************/
+#ifndef mcfslt_h
+#define mcfslt_h
+/****************************************************************************/
+
+/*
+ *     Get address specific defines for the 547x.
+ */
+#define MCFSLT_TIMER0          0x900   /* Base address of TIMER0 */
+#define MCFSLT_TIMER1          0x910   /* Base address of TIMER1 */
+
+
+/*
+ *     Define the SLT timer register set addresses.
+ */
+#define MCFSLT_STCNT           0x00    /* Terminal count */
+#define MCFSLT_SCR             0x04    /* Control */
+#define MCFSLT_SCNT            0x08    /* Current count */
+#define MCFSLT_SSR             0x0C    /* Status */
+
+/*
+ *     Bit definitions for the SCR control register.
+ */
+#define MCFSLT_SCR_RUN         0x04000000      /* Run mode (continuous) */
+#define MCFSLT_SCR_IEN         0x02000000      /* Interrupt enable */
+#define MCFSLT_SCR_TEN         0x01000000      /* Timer enable */
+
+/*
+ *     Bit definitions for the SSR status register.
+ */
+#define MCFSLT_SSR_BE          0x02000000      /* Bus error condition */
+#define MCFSLT_SSR_TE          0x01000000      /* Timeout condition */
+
+/****************************************************************************/
+#endif /* mcfslt_h */
index 01a8716..db72e2b 100644 (file)
 #define MCFUART_BASE1          0xfc060000      /* Base address of UART1 */
 #define MCFUART_BASE2          0xfc064000      /* Base address of UART2 */
 #define MCFUART_BASE3          0xfc068000      /* Base address of UART3 */
+#elif defined(CONFIG_M548x)
+#define MCFUART_BASE1          0x8600          /* on M548x */
+#define MCFUART_BASE2          0x8700          /* on M548x */
+#define MCFUART_BASE3          0x8800          /* on M548x */
+#define MCFUART_BASE4          0x8900          /* on M548x */
 #endif
 
 
@@ -212,7 +217,9 @@ struct mcf_platform_uart {
 #define        MCFUART_URF_RXS         0xc0            /* Receiver status */
 #endif
 
-#if defined(CONFIG_M5272)
+#if defined(CONFIG_M548x)
+#define MCFUART_TXFIFOSIZE     512
+#elif defined(CONFIG_M5272)
 #define MCFUART_TXFIFOSIZE     25
 #else
 #define MCFUART_TXFIFOSIZE     1
index 73e5e58..78e59b8 100644 (file)
 int main(void)
 {
        /* offsets into the task struct */
-       DEFINE(TASK_STATE, offsetof(struct task_struct, state));
-       DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
-       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
        DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
        DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
-       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
 #ifdef CONFIG_MMU
        DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info));
 #endif
@@ -64,14 +60,6 @@ int main(void)
        /* bitfields are a bit difficult */
        DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
 
-       /* offsets into the irq_handler struct */
-       DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
-       DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
-       DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
-
-       /* offsets into the kernel_stat struct */
-       DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
-
        /* offsets into the irq_cpustat_t struct */
        DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
 
index 2609c39..9287150 100644 (file)
@@ -59,6 +59,10 @@ config GENERIC_HARDIRQS
        bool
        default y
 
+config GENERIC_HARDIRQS_NO__DO_IRQ
+       bool
+       default y
+
 config GENERIC_CALIBRATE_DELAY
        bool
        default y
@@ -171,6 +175,11 @@ config M5407
        help
          Motorola ColdFire 5407 processor support.
 
+config M548x
+       bool "MCF548x"
+       help
+         Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
+
 endchoice
 
 config M527x
@@ -181,7 +190,7 @@ config M527x
 
 config COLDFIRE
        bool
-       depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407)
+       depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M548x)
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
        default y
index 1404257..026ef16 100644 (file)
@@ -25,6 +25,7 @@ platform-$(CONFIG_M528x)      := 528x
 platform-$(CONFIG_M5307)       := 5307
 platform-$(CONFIG_M532x)       := 532x
 platform-$(CONFIG_M5407)       := 5407
+platform-$(CONFIG_M548x)       := 548x
 PLATFORM := $(platform-y)
 
 board-$(CONFIG_PILOT)          := pilot
@@ -73,6 +74,7 @@ cpuclass-$(CONFIG_M528x)      := coldfire
 cpuclass-$(CONFIG_M5307)       := coldfire
 cpuclass-$(CONFIG_M532x)       := coldfire
 cpuclass-$(CONFIG_M5407)       := coldfire
+cpuclass-$(CONFIG_M548x)       := coldfire
 cpuclass-$(CONFIG_M68328)      := 68328
 cpuclass-$(CONFIG_M68EZ328)    := 68328
 cpuclass-$(CONFIG_M68VZ328)    := 68328
@@ -100,6 +102,7 @@ cflags-$(CONFIG_M528x)              := $(call cc-option,-m528x,-m5307)
 cflags-$(CONFIG_M5307)         := $(call cc-option,-m5307,-m5200)
 cflags-$(CONFIG_M532x)         := $(call cc-option,-mcpu=532x,-m5307)
 cflags-$(CONFIG_M5407)         := $(call cc-option,-m5407,-m5200)
+cflags-$(CONFIG_M548x)         := $(call cc-option,-m5407,-m5200)
 cflags-$(CONFIG_M68328)                := -m68000
 cflags-$(CONFIG_M68EZ328)      := -m68000
 cflags-$(CONFIG_M68VZ328)      := -m68000
diff --git a/arch/m68knommu/kernel/.gitignore b/arch/m68knommu/kernel/.gitignore
new file mode 100644 (file)
index 0000000..c5f676c
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.lds
index 2433502..ffe02f4 100644 (file)
 int main(void)
 {
        /* offsets into the task struct */
-       DEFINE(TASK_STATE, offsetof(struct task_struct, state));
-       DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
-       DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace));
-       DEFINE(TASK_BLOCKED, offsetof(struct task_struct, blocked));
        DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-       DEFINE(TASK_THREAD_INFO, offsetof(struct task_struct, stack));
        DEFINE(TASK_MM, offsetof(struct task_struct, mm));
-       DEFINE(TASK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
 
        /* offsets into the irq_cpustat_t struct */
        DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
@@ -63,7 +57,7 @@ int main(void)
        DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
 #else
        /* bitfields are a bit difficult */
-       DEFINE(PT_OFF_VECTOR, offsetof(struct pt_regs, pc) + 4);
+       DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
 #endif
 
        /* signal defines */
@@ -75,11 +69,8 @@ int main(void)
        DEFINE(PT_PTRACED, PT_PTRACED);
 
        /* Offsets in thread_info structure */
-       DEFINE(TI_TASK, offsetof(struct thread_info, task));
-       DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain));
        DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
        DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
-       DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
 
        return 0;
 }
index f6be124..6fe7c38 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/signal.h>
+#include <linux/tracehook.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -134,14 +135,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                                        tmp >>= 16;
                        } else if (addr >= 21 && addr < 49) {
                                tmp = child->thread.fp[addr - 21];
-#ifdef CONFIG_M68KFPU_EMU
-                               /* Convert internal fpu reg representation
-                                * into long double format
-                                */
-                               if (FPU_IS_EMU && (addr < 45) && !(addr % 3))
-                                       tmp = ((tmp & 0xffff0000) << 15) |
-                                             ((tmp & 0x0000ffff) << 16);
-#endif
                        } else if (addr == 49) {
                                tmp = child->mm->start_code;
                        } else if (addr == 50) {
@@ -175,16 +168,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
                        }
                        if (addr >= 21 && addr < 48)
                        {
-#ifdef CONFIG_M68KFPU_EMU
-                               /* Convert long double format
-                                * into internal fpu reg representation
-                                */
-                               if (FPU_IS_EMU && (addr < 45) && !(addr % 3)) {
-                                       data = (unsigned long)data << 15;
-                                       data = (data & 0xffff0000) |
-                                              ((data & 0x0000ffff) >> 1);
-                               }
-#endif
                                child->thread.fp[addr - 21] = data;
                                ret = 0;
                        }
@@ -259,21 +242,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
        return ret;
 }
 
-asmlinkage void syscall_trace(void)
+asmlinkage int syscall_trace_enter(void)
 {
-       if (!test_thread_flag(TIF_SYSCALL_TRACE))
-               return;
-       if (!(current->ptrace & PT_PTRACED))
-               return;
-       ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-                                ? 0x80 : 0));
-       /*
-        * this isn't the same as continuing with a signal, but it will do
-        * for normal use.  strace only continues with a signal if the
-        * stopping signal is not SIGTRAP.  -brl
-        */
-       if (current->exit_code) {
-               send_sig(current->exit_code, current, 1);
-               current->exit_code = 0;
-       }
+       int ret = 0;
+
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               ret = tracehook_report_syscall_entry(task_pt_regs(current));
+       return ret;
+}
+
+asmlinkage void syscall_trace_leave(void)
+{
+       if (test_thread_flag(TIF_SYSCALL_TRACE))
+               tracehook_report_syscall_exit(task_pt_regs(current), 0);
 }
index ba92b90..c684adf 100644 (file)
@@ -54,9 +54,6 @@ void (*mach_reset)(void);
 void (*mach_halt)(void);
 void (*mach_power_off)(void);
 
-#ifdef CONFIG_M68000
-       #define CPU "MC68000"
-#endif
 #ifdef CONFIG_M68328
        #define CPU "MC68328"
 #endif
index 7089dd9..d6ac2a4 100644 (file)
@@ -60,13 +60,16 @@ static unsigned long read_rtc_mmss(void)
 {
        unsigned int year, mon, day, hour, min, sec;
 
-       if (mach_gettod)
+       if (mach_gettod) {
                mach_gettod(&year, &mon, &day, &hour, &min, &sec);
-       else
-               year = mon = day = hour = min = sec = 0;
+               if ((year += 1900) < 1970)
+                       year += 100;
+       } else {
+               year = 1970;
+               mon = day = 1;
+               hour = min = sec = 0;
+       }
 
-       if ((year += 1900) < 1970)
-               year += 100;
 
        return  mktime(year, mon, day, hour, min, sec);
 }
index 3739c8f..a768008 100644 (file)
@@ -179,14 +179,16 @@ static void __show_stack(struct task_struct *task, unsigned long *stack)
 
 void bad_super_trap(struct frame *fp)
 {
+       int vector = (fp->ptregs.vector >> 2) & 0xff;
+
        console_verbose();
-       if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
+       if (vector < ARRAY_SIZE(vec_names))
                printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
-                       vec_names[(fp->ptregs.vector) >> 2],
+                       vec_names[vector],
                        fp->ptregs.format);
        else
                printk (KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
-                       (fp->ptregs.vector) >> 2, 
+                       vector,
                        fp->ptregs.format);
        printk (KERN_WARNING "Current process id is %d\n", current->pid);
        die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
@@ -195,10 +197,11 @@ void bad_super_trap(struct frame *fp)
 asmlinkage void trap_c(struct frame *fp)
 {
        int sig;
+       int vector = (fp->ptregs.vector >> 2) & 0xff;
        siginfo_t info;
 
        if (fp->ptregs.sr & PS_S) {
-               if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
+               if (vector == VEC_TRACE) {
                        /* traced a trapping instruction */
                } else
                        bad_super_trap(fp);
@@ -206,7 +209,7 @@ asmlinkage void trap_c(struct frame *fp)
        }
 
        /* send the appropriate signal to the user program */
-       switch ((fp->ptregs.vector) >> 2) {
+       switch (vector) {
            case VEC_ADDRERR:
                info.si_code = BUS_ADRALN;
                sig = SIGBUS;
@@ -360,16 +363,3 @@ void show_stack(struct task_struct *task, unsigned long *stack)
        else
                __show_stack(task, stack);
 }
-
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpemu_signal(int signal, int code, void *addr)
-{
-       siginfo_t info;
-
-       info.si_signo = signal;
-       info.si_errno = 0;
-       info.si_code = code;
-       info.si_addr = addr;
-       force_sig_info(signal, &info, current);
-}
-#endif
index 113c333..b5db056 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 113c333..b5db056 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 435ab34..ad3f4e5 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index b8f9b45..c04b8f7 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index f56225d..4bed30f 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 93673ef..34110fc 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 59278c0..65bb582 100644 (file)
@@ -13,6 +13,8 @@
 #include <linux/param.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
 #include <asm/machdep.h>
 #include <asm/coldfire.h>
 #include <asm/mcfsim.h>
@@ -148,9 +150,23 @@ void __init config_BSP(char *commandp, int size)
 
 /***************************************************************************/
 
+/*
+ * Some 5272 based boards have the FEC ethernet diectly connected to
+ * an ethernet switch. In this case we need to use the fixed phy type,
+ * and we need to declare it early in boot.
+ */
+static struct fixed_phy_status nettel_fixed_phy_status __initdata = {
+       .link   = 1,
+       .speed  = 100,
+       .duplex = 0,
+};
+
+/***************************************************************************/
+
 static int __init init_BSP(void)
 {
        m5272_uarts_init();
+       fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status);
        platform_add_devices(m5272_devices, ARRAY_SIZE(m5272_devices));
        return 0;
 }
index 7081e0a..3cf681c 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/coldfire.h>
  * via a set of 4 "Interrupt Controller Registers" (ICR). There is a
  * loose mapping of vector number to register and internal bits, but
  * a table is the easiest and quickest way to map them.
+ *
+ * Note that the external interrupts are edge triggered (unlike the
+ * internal interrupt sources which are level triggered). Which means
+ * they also need acknowledgeing via acknowledge bits.
  */
 struct irqmap {
        unsigned char   icr;
@@ -68,6 +73,11 @@ static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
        /*MCF_IRQ_SWTO*/        { .icr = MCFSIM_ICR4, .index = 16, .ack = 0, },
 };
 
+/*
+ * The act of masking the interrupt also has a side effect of 'ack'ing
+ * an interrupt on this irq (for the external irqs). So this mask function
+ * is also an ack_mask function.
+ */
 static void intc_irq_mask(unsigned int irq)
 {
        if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
@@ -95,7 +105,9 @@ static void intc_irq_ack(unsigned int irq)
                irq -= MCFINT_VECBASE;
                if (intc_irqmap[irq].ack) {
                        u32 v;
-                       v = 0xd << intc_irqmap[irq].index;
+                       v = readl(MCF_MBAR + intc_irqmap[irq].icr);
+                       v &= (0x7 << intc_irqmap[irq].index);
+                       v |= (0x8 << intc_irqmap[irq].index);
                        writel(v, MCF_MBAR + intc_irqmap[irq].icr);
                }
        }
@@ -103,21 +115,47 @@ static void intc_irq_ack(unsigned int irq)
 
 static int intc_irq_set_type(unsigned int irq, unsigned int type)
 {
-       /* We can set the edge type here for external interrupts */
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+               irq -= MCFINT_VECBASE;
+               if (intc_irqmap[irq].ack) {
+                       u32 v;
+                       v = readl(MCF_MBAR + MCFSIM_PITR);
+                       if (type == IRQ_TYPE_EDGE_FALLING)
+                               v &= ~(0x1 << (32 - irq));
+                       else
+                               v |= (0x1 << (32 - irq));
+                       writel(v, MCF_MBAR + MCFSIM_PITR);
+               }
+       }
        return 0;
 }
 
+/*
+ * Simple flow handler to deal with the external edge triggered interrupts.
+ * We need to be careful with the masking/acking due to the side effects
+ * of masking an interrupt.
+ */
+static void intc_external_irq(unsigned int irq, struct irq_desc *desc)
+{
+       kstat_incr_irqs_this_cpu(irq, desc);
+       desc->status |= IRQ_INPROGRESS;
+       desc->chip->ack(irq);
+       handle_IRQ_event(irq, desc->action);
+       desc->status &= ~IRQ_INPROGRESS;
+}
+
 static struct irq_chip intc_irq_chip = {
        .name           = "CF-INTC",
        .mask           = intc_irq_mask,
        .unmask         = intc_irq_unmask,
+       .mask_ack       = intc_irq_mask,
        .ack            = intc_irq_ack,
        .set_type       = intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
 {
-       int irq;
+       int irq, edge;
 
        init_vectors();
 
@@ -128,11 +166,17 @@ void __init init_IRQ(void)
        writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
-               intc_irq_set_type(irq, 0);
+               set_irq_chip(irq, &intc_irq_chip);
+               edge = 0;
+               if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX))
+                       edge = intc_irqmap[irq - MCFINT_VECBASE].ack;
+               if (edge) {
+                       set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+                       set_irq_handler(irq, intc_external_irq);
+               } else {
+                       set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+                       set_irq_handler(irq, handle_level_irq);
+               }
        }
 }
 
index 3d90e6d..6ac4b57 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 3d90e6d..6ac4b57 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs.  You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 6de5269..d4293b7 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index 4cc2324..ce01669 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
index dee62c5..e83fe14 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
diff --git a/arch/m68knommu/platform/548x/Makefile b/arch/m68knommu/platform/548x/Makefile
new file mode 100644 (file)
index 0000000..e6035e7
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o
+
diff --git a/arch/m68knommu/platform/548x/config.c b/arch/m68knommu/platform/548x/config.c
new file mode 100644 (file)
index 0000000..9888846
--- /dev/null
@@ -0,0 +1,115 @@
+/***************************************************************************/
+
+/*
+ *     linux/arch/m68knommu/platform/548x/config.c
+ *
+ *     Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/m548xsim.h>
+#include <asm/mcfuart.h>
+#include <asm/m548xgpt.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m548x_uart_platform[] = {
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE1,
+               .irq            = 64 + 35,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE2,
+               .irq            = 64 + 34,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE3,
+               .irq            = 64 + 33,
+       },
+       {
+               .mapbase        = MCF_MBAR + MCFUART_BASE4,
+               .irq            = 64 + 32,
+       },
+};
+
+static struct platform_device m548x_uart = {
+       .name                   = "mcfuart",
+       .id                     = 0,
+       .dev.platform_data      = m548x_uart_platform,
+};
+
+static struct platform_device *m548x_devices[] __initdata = {
+       &m548x_uart,
+};
+
+
+/***************************************************************************/
+
+static void __init m548x_uart_init_line(int line, int irq)
+{
+       int rts_cts;
+
+       /* enable io pins */
+       switch (line) {
+       case 0:
+               rts_cts = 0; break;
+       case 1:
+               rts_cts = MCF_PAR_PSC_RTS_RTS; break;
+       case 2:
+               rts_cts = MCF_PAR_PSC_RTS_RTS | MCF_PAR_PSC_CTS_CTS; break;
+       case 3:
+               rts_cts = 0; break;
+       }
+       __raw_writeb(MCF_PAR_PSC_TXD | rts_cts | MCF_PAR_PSC_RXD,
+                                               MCF_MBAR + MCF_PAR_PSC(line));
+}
+
+static void __init m548x_uarts_init(void)
+{
+       const int nrlines = ARRAY_SIZE(m548x_uart_platform);
+       int line;
+
+       for (line = 0; (line < nrlines); line++)
+               m548x_uart_init_line(line, m548x_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void mcf548x_reset(void)
+{
+       /* disable interrupts and enable the watchdog */
+       asm("movew #0x2700, %sr\n");
+       __raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
+       __raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
+       __raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
+                                               MCF_MBAR + MCF_GPT_GMS0);
+}
+
+/***************************************************************************/
+
+void __init config_BSP(char *commandp, int size)
+{
+       mach_reset = mcf548x_reset;
+       m548x_uarts_init();
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+
+       platform_add_devices(m548x_devices, ARRAY_SIZE(m548x_devices));
+       return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
index 9d80d2c..27241e1 100644 (file)
@@ -43,10 +43,10 @@ badsys:
        jra     ret_from_exception
 
 do_trace:
-       movel   #-ENOSYS,%sp@(PT_OFF_D0)        /* needed for strace*/
+       movel   #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
        subql   #4,%sp
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_enter
        RESTORE_SWITCH_STACK
        addql   #4,%sp
        movel   %sp@(PT_OFF_ORIG_D0),%d1
@@ -57,10 +57,10 @@ do_trace:
        lea     sys_call_table, %a0
        jbsr    %a0@(%d1)
 
-1:     movel   %d0,%sp@(PT_OFF_D0)             /* save the return value */
+1:     movel   %d0,%sp@(PT_OFF_D0)     /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_leave
 
 ret_from_signal:
        RESTORE_SWITCH_STACK
@@ -71,16 +71,16 @@ ENTRY(system_call)
        SAVE_ALL
 
        /* save top of frame*/
-       pea     %sp@
-       jbsr    set_esp0
-       addql   #4,%sp
+       pea     %sp@
+       jbsr    set_esp0
+       addql   #4,%sp
 
        movel   %sp@(PT_OFF_ORIG_D0),%d0
 
        movel   %sp,%d1                 /* get thread_info pointer */
        andl    #-THREAD_SIZE,%d1
        movel   %d1,%a2
-       btst    #TIF_SYSCALL_TRACE,%a2@(TI_FLAGS)
+       btst    #(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
        jne     do_trace
        cmpl    #NR_syscalls,%d0
        jcc     badsys
@@ -88,10 +88,10 @@ ENTRY(system_call)
        lea     sys_call_table,%a0
        movel   %a0@(%d0), %a0
        jbsr    %a0@
-       movel   %d0,%sp@(PT_OFF_D0)             /* save the return value*/
+       movel   %d0,%sp@(PT_OFF_D0)     /* save the return value*/
 
 ret_from_exception:
-       btst    #5,%sp@(PT_OFF_SR)              /* check if returning to kernel*/
+       btst    #5,%sp@(PT_OFF_SR)      /* check if returning to kernel*/
        jeq     Luser_return            /* if so, skip resched, signals*/
 
 Lkernel_return:
@@ -133,7 +133,7 @@ Lreturn:
  */
 inthandler1:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -144,7 +144,7 @@ inthandler1:
 
 inthandler2:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -155,7 +155,7 @@ inthandler2:
 
 inthandler3:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -166,7 +166,7 @@ inthandler3:
 
 inthandler4:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -177,7 +177,7 @@ inthandler4:
 
 inthandler5:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -188,7 +188,7 @@ inthandler5:
 
 inthandler6:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -199,7 +199,7 @@ inthandler6:
 
 inthandler7:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
@@ -210,7 +210,7 @@ inthandler7:
 
 inthandler:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and     #0x3ff, %d0
 
        movel   %sp,%sp@-
index 92d9645..f632fdc 100644 (file)
@@ -1,11 +1,5 @@
 
-#if defined(CONFIG_RAM32MB)
-#define        MEM_END 0x02000000      /* Memory size 32Mb */
-#elif defined(CONFIG_RAM16MB)
-#define        MEM_END 0x01000000      /* Memory size 16Mb */
-#else
 #define        MEM_END 0x00800000      /* Memory size 8Mb */
-#endif
 
 #undef CRT_DEBUG
 
index 252b80b..7f1aeea 100644 (file)
@@ -67,33 +67,6 @@ pclp1:
        beq     pclp1
 #endif /* DEBUG */
 
-#ifdef CONFIG_RELOCATE
-       /* Copy me to RAM */
-       moveal  #__rom_start, %a0
-       moveal  #_stext, %a1
-       moveal  #_edata, %a2
-
-       /* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
-       movel   %a0@+, %d0
-       movel   %d0, %a1@+
-       cmpal   %a1, %a2
-       bhi     LD1
-       
-#ifdef DEBUG
-       moveq   #74, %d7                /* 'J' */
-       moveb   %d7,0xfffff907          /* No absolute addresses */
-pclp2:
-       movew   0xfffff906, %d7
-       andw    #0x2000, %d7
-       beq     pclp2
-#endif /* DEBUG */
-       /* jump into the RAM copy */
-       jmp     ram_jump
-ram_jump:
-
-#endif /* CONFIG_RELOCATE */
-
 #ifdef DEBUG
        moveq   #82, %d7                /* 'R' */
        moveb   %d7,0xfffff907          /* No absolute addresses */
index b91ee85..8658528 100644 (file)
@@ -179,10 +179,8 @@ void __init init_IRQ(void)
        IMR = ~0;
 
        for (i = 0; (i < NR_IRQS); i++) {
-               irq_desc[i].status = IRQ_DISABLED;
-               irq_desc[i].action = NULL;
-               irq_desc[i].depth = 1;
-               irq_desc[i].chip = &intc_irq_chip;
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index 6d3460a..c131c6e 100644 (file)
@@ -42,7 +42,7 @@ do_trace:
        movel   #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
        subql   #4,%sp
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_enter
        RESTORE_SWITCH_STACK
        addql   #4,%sp
        movel   %sp@(PT_OFF_ORIG_D0),%d1
@@ -56,7 +56,7 @@ do_trace:
 1:     movel   %d0,%sp@(PT_OFF_D0)     /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_leave
 
 ret_from_signal:
        RESTORE_SWITCH_STACK
@@ -71,7 +71,12 @@ ENTRY(system_call)
        jbsr    set_esp0
        addql   #4,%sp
 
-       btst    #PF_TRACESYS_BIT,%a2@(TASK_FLAGS+PF_TRACESYS_OFF)
+       movel   %sp@(PT_OFF_ORIG_D0),%d0
+
+       movel   %sp,%d1                 /* get thread_info pointer */
+       andl    #-THREAD_SIZE,%d1
+       movel   %d1,%a2
+       btst    #(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
        jne     do_trace
        cmpl    #NR_syscalls,%d0
        jcc     badsys
@@ -124,7 +129,7 @@ Lreturn:
  */
 inthandler:
        SAVE_ALL
-       movew   %sp@(PT_OFF_VECTOR), %d0
+       movew   %sp@(PT_OFF_FORMATVEC), %d0
        and.l   #0x3ff, %d0
        lsr.l   #0x02,  %d0
 
index 6f22970..ad96ab1 100644 (file)
@@ -132,10 +132,8 @@ void init_IRQ(void)
        pquicc->intr_cimr = 0x00000000;
 
        for (i = 0; (i < NR_IRQS); i++) {
-               irq_desc[i].status = IRQ_DISABLED;
-               irq_desc[i].action = NULL;
-               irq_desc[i].depth = 1;
-               irq_desc[i].chip = &intc_irq_chip;
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index fc5c630..eabaabe 100644 (file)
@@ -90,11 +90,6 @@ static void init_hardware(char *command, int size)
        PDIQEG &= ~PD(1);
        PDIRQEN |= PD(1);                       /* IRQ enabled */
 
-#ifdef CONFIG_68328_SERIAL_UART2
-       /* Enable RXD TXD port bits to enable UART2 */
-       PJSEL &= ~(PJ(5) | PJ(4));
-#endif
-
 #ifdef CONFIG_INIT_LCD
        /* initialize LCD controller */
        LSSA = (long) screen_bits;
index f72a0e5..45f501f 100644 (file)
@@ -8,8 +8,8 @@
 # on the console port whenever a DBG interrupt occurs. You have to
 # set up you HW breakpoints to trigger a DBG interrupt:
 #
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
 #
 
 asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
@@ -26,6 +26,7 @@ obj-$(CONFIG_M528x)   += pit.o intc-2.o
 obj-$(CONFIG_M5307)    += timers.o intc.o
 obj-$(CONFIG_M532x)    += timers.o intc-simr.o
 obj-$(CONFIG_M5407)    += timers.o intc.o
+obj-$(CONFIG_M548x)    += sltimers.o intc-2.o
 
 obj-y                  += pinmux.o gpio.o
 extra-y := head.o
index cd79d7e..5e92bed 100644 (file)
@@ -88,7 +88,7 @@ ENTRY(system_call)
        movel   %d2,PT_OFF_D0(%sp)      /* on syscall entry */
        subql   #4,%sp
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_enter
        RESTORE_SWITCH_STACK
        addql   #4,%sp
        movel   %d3,%a0
@@ -96,7 +96,7 @@ ENTRY(system_call)
        movel   %d0,%sp@(PT_OFF_D0)             /* save the return value */
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
-       jbsr    syscall_trace
+       jbsr    syscall_trace_leave
 
 ret_from_signal:
        RESTORE_SWITCH_STACK
index 5598c8b..85daa2b 100644 (file)
@@ -1,5 +1,11 @@
 /*
- * intc-1.c
+ * intc-2.c
+ *
+ * General interrupt controller code for the many ColdFire cores that use
+ * interrupt controllers with 63 interrupt sources, organized as 56 fully-
+ * programmable + 7 fixed-level interrupt sources. This includes the 523x
+ * family, the 5270, 5271, 5274, 5275, and the 528x family which have two such
+ * controllers, and the 547x and 548x families which have only one of them.
  *
  * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
  *
 #include <asm/traps.h>
 
 /*
- *     Each vector needs a unique priority and level asscoiated with it.
+ * Bit definitions for the ICR family of registers.
+ */
+#define MCFSIM_ICR_LEVEL(l)    ((l)<<3)        /* Level l intr */
+#define MCFSIM_ICR_PRI(p)      (p)             /* Priority p intr */
+
+/*
+ *     Each vector needs a unique priority and level associated with it.
  *     We don't really care so much what they are, we don't rely on the
- *     tranditional priority interrupt scheme of the m68k/ColdFire.
+ *     traditional priority interrupt scheme of the m68k/ColdFire.
  */
-static u8 intc_intpri = 0x36;
+static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
+
+#ifdef MCFICM_INTC1
+#define NR_VECS        128
+#else
+#define NR_VECS        64
+#endif
 
 static void intc_irq_mask(unsigned int irq)
 {
-       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
                unsigned long imraddr;
                u32 val, imrbit;
 
                irq -= MCFINT_VECBASE;
                imraddr = MCF_IPSBAR;
+#ifdef MCFICM_INTC1
                imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+               imraddr += MCFICM_INTC0;
+#endif
                imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
                imrbit = 0x1 << (irq & 0x1f);
 
@@ -44,13 +66,17 @@ static void intc_irq_mask(unsigned int irq)
 
 static void intc_irq_unmask(unsigned int irq)
 {
-       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + 128)) {
+       if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
                unsigned long intaddr, imraddr, icraddr;
                u32 val, imrbit;
 
                irq -= MCFINT_VECBASE;
                intaddr = MCF_IPSBAR;
+#ifdef MCFICM_INTC1
                intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+               intaddr += MCFICM_INTC0;
+#endif
                imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
                icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
                imrbit = 0x1 << (irq & 0x1f);
@@ -67,10 +93,16 @@ static void intc_irq_unmask(unsigned int irq)
        }
 }
 
+static int intc_irq_set_type(unsigned int irq, unsigned int type)
+{
+       return 0;
+}
+
 static struct irq_chip intc_irq_chip = {
        .name           = "CF-INTC",
        .mask           = intc_irq_mask,
        .unmask         = intc_irq_unmask,
+       .set_type       = intc_irq_set_type,
 };
 
 void __init init_IRQ(void)
@@ -81,13 +113,14 @@ void __init init_IRQ(void)
 
        /* Mask all interrupt sources */
        __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
+#ifdef MCFICM_INTC1
        __raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);
+#endif
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index 1b01e79..bb70486 100644 (file)
@@ -1,6 +1,8 @@
 /*
  * intc-simr.c
  *
+ * Interrupt controller code for the ColdFire 5208, 5207 & 532x parts.
+ *
  * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.com>
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -68,11 +70,9 @@ void __init init_IRQ(void)
                __raw_writeb(0xff, MCFINTC1_SIMR);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
-               intc_irq_set_type(irq, 0);
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
index a4560c8..60d2fcb 100644 (file)
@@ -143,11 +143,9 @@ void __init init_IRQ(void)
        mcf_maskimr(0xffffffff);
 
        for (irq = 0; (irq < NR_IRQS); irq++) {
-               irq_desc[irq].status = IRQ_DISABLED;
-               irq_desc[irq].action = NULL;
-               irq_desc[irq].depth = 1;
-               irq_desc[irq].chip = &intc_irq_chip;
-               intc_irq_set_type(irq, 0);
+               set_irq_chip(irq, &intc_irq_chip);
+               set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+               set_irq_handler(irq, handle_level_irq);
        }
 }
 
diff --git a/arch/m68knommu/platform/coldfire/sltimers.c b/arch/m68knommu/platform/coldfire/sltimers.c
new file mode 100644 (file)
index 0000000..0a1b937
--- /dev/null
@@ -0,0 +1,145 @@
+/***************************************************************************/
+
+/*
+ *     sltimers.c -- generic ColdFire slice timer support.
+ *
+ *     Copyright (C) 2009-2010, Philippe De Muyter <phdm@macqel.be>
+ *     based on
+ *     timers.c -- generic ColdFire hardware timer support.
+ *     Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/clocksource.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfslt.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+#ifdef CONFIG_HIGHPROFILE
+
+/*
+ *     By default use Slice Timer 1 as the profiler clock timer.
+ */
+#define        PA(a)   (MCF_MBAR + MCFSLT_TIMER1 + (a))
+
+/*
+ *     Choose a reasonably fast profile timer. Make it an odd value to
+ *     try and get good coverage of kernel operations.
+ */
+#define        PROFILEHZ       1013
+
+irqreturn_t mcfslt_profile_tick(int irq, void *dummy)
+{
+       /* Reset Slice Timer 1 */
+       __raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, PA(MCFSLT_SSR));
+       if (current->pid)
+               profile_tick(CPU_PROFILING);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction mcfslt_profile_irq = {
+       .name    = "profile timer",
+       .flags   = IRQF_DISABLED | IRQF_TIMER,
+       .handler = mcfslt_profile_tick,
+};
+
+void mcfslt_profile_init(void)
+{
+       printk(KERN_INFO "PROFILE: lodging TIMER 1 @ %dHz as profile timer\n",
+              PROFILEHZ);
+
+       setup_irq(MCF_IRQ_PROFILER, &mcfslt_profile_irq);
+
+       /* Set up TIMER 2 as high speed profile clock */
+       __raw_writel(MCF_BUSCLK / PROFILEHZ - 1, PA(MCFSLT_STCNT));
+       __raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+                                                               PA(MCFSLT_SCR));
+
+}
+
+#endif /* CONFIG_HIGHPROFILE */
+
+/***************************************************************************/
+
+/*
+ *     By default use Slice Timer 0 as the system clock timer.
+ */
+#define        TA(a)   (MCF_MBAR + MCFSLT_TIMER0 + (a))
+
+static u32 mcfslt_cycles_per_jiffy;
+static u32 mcfslt_cnt;
+
+static irqreturn_t mcfslt_tick(int irq, void *dummy)
+{
+       /* Reset Slice Timer 0 */
+       __raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, TA(MCFSLT_SSR));
+       mcfslt_cnt += mcfslt_cycles_per_jiffy;
+       return arch_timer_interrupt(irq, dummy);
+}
+
+static struct irqaction mcfslt_timer_irq = {
+       .name    = "timer",
+       .flags   = IRQF_DISABLED | IRQF_TIMER,
+       .handler = mcfslt_tick,
+};
+
+static cycle_t mcfslt_read_clk(struct clocksource *cs)
+{
+       unsigned long flags;
+       u32 cycles;
+       u16 scnt;
+
+       local_irq_save(flags);
+       scnt = __raw_readl(TA(MCFSLT_SCNT));
+       cycles = mcfslt_cnt;
+       local_irq_restore(flags);
+
+       /* substract because slice timers count down */
+       return cycles - scnt;
+}
+
+static struct clocksource mcfslt_clk = {
+       .name   = "slt",
+       .rating = 250,
+       .read   = mcfslt_read_clk,
+       .shift  = 20,
+       .mask   = CLOCKSOURCE_MASK(32),
+       .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void hw_timer_init(void)
+{
+       mcfslt_cycles_per_jiffy = MCF_BUSCLK / HZ;
+       /*
+        *      The coldfire slice timer (SLT) runs from STCNT to 0 included,
+        *      then STCNT again and so on.  It counts thus actually
+        *      STCNT + 1 steps for 1 tick, not STCNT.  So if you want
+        *      n cycles, initialize STCNT with n - 1.
+        */
+       __raw_writel(mcfslt_cycles_per_jiffy - 1, TA(MCFSLT_STCNT));
+       __raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+                                                               TA(MCFSLT_SCR));
+       /* initialize mcfslt_cnt knowing that slice timers count down */
+       mcfslt_cnt = mcfslt_cycles_per_jiffy;
+
+       setup_irq(MCF_IRQ_TIMER, &mcfslt_timer_irq);
+
+       mcfslt_clk.mult = clocksource_hz2mult(MCF_BUSCLK, mcfslt_clk.shift);
+       clocksource_register(&mcfslt_clk);
+
+#ifdef CONFIG_HIGHPROFILE
+       mcfslt_profile_init();
+#endif
+}
index 427b13b..bacbd3d 100644 (file)
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
 
-void __init early_init_dt_scan_chosen_arch(unsigned long node)
-{
-       /* No Microblaze specific code here */
-}
-
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
 {
        memblock_add(base, size);
index 784cf82..46cae2b 100644 (file)
@@ -2128,6 +2128,13 @@ config SECCOMP
 
          If unsure, say Y. Only embedded should say N here.
 
+config USE_OF
+       bool "Flattened Device Tree support"
+       select OF
+       select OF_FLATTREE
+       help
+         Include support for flattened device tree machine descriptions.
+
 endmenu
 
 config LOCKDEP_SUPPORT
index dea4aed..b003ed5 100644 (file)
 
 #include <irq.h>
 
+static inline void irq_dispose_mapping(unsigned int virq)
+{
+       return;
+}
+
 #ifdef CONFIG_I8259
 static inline int irq_canonicalize(int irq)
 {
diff --git a/arch/mips/include/asm/prom.h b/arch/mips/include/asm/prom.h
new file mode 100644 (file)
index 0000000..f29b862
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ *  arch/mips/include/asm/prom.h
+ *
+ *  Copyright (C) 2010 Cisco Systems Inc. <dediao@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_MIPS_PROM_H
+#define __ASM_MIPS_PROM_H
+
+#ifdef CONFIG_OF
+#include <asm/bootinfo.h>
+
+/* which is compatible with the flattened device tree (FDT) */
+#define cmd_line arcs_cmdline
+
+extern int early_init_dt_scan_memory_arch(unsigned long node,
+       const char *uname, int depth, void *data);
+
+extern int reserve_mem_mach(unsigned long addr, unsigned long size);
+extern void free_mem_mach(unsigned long addr, unsigned long size);
+
+extern void device_tree_init(void);
+#else /* CONFIG_OF */
+static inline void device_tree_init(void) { }
+#endif /* CONFIG_OF */
+
+#endif /* _ASM_MIPS_PROM_H */
index 06f8482..8088498 100644 (file)
@@ -96,6 +96,8 @@ obj-$(CONFIG_KEXEC)           += machine_kexec.o relocate_kernel.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_SPINLOCK_TEST)    += spinlock_test.o
 
+obj-$(CONFIG_OF)               += prom.o
+
 CFLAGS_cpu-bugs64.o    = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi)
 
 obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT)  += 8250-platform.o
index 9a526ba..802e616 100644 (file)
@@ -103,7 +103,7 @@ asmlinkage long mipsmt_sys_sched_setaffinity(pid_t pid, unsigned int len,
        if (!check_same_owner(p) && !capable(CAP_SYS_NICE))
                goto out_unlock;
 
-       retval = security_task_setscheduler(p)
+       retval = security_task_setscheduler(p);
        if (retval)
                goto out_unlock;
 
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
new file mode 100644 (file)
index 0000000..e000b27
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * MIPS support for CONFIG_OF device tree support
+ *
+ * Copyright (C) 2010 Cisco Systems Inc. <dediao@cisco.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/bootmem.h>
+#include <linux/initrd.h>
+#include <linux/debugfs.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/page.h>
+#include <asm/prom.h>
+
+int __init early_init_dt_scan_memory_arch(unsigned long node,
+                                         const char *uname, int depth,
+                                         void *data)
+{
+       return early_init_dt_scan_memory(node, uname, depth, data);
+}
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+       return add_memory_region(base, size, BOOT_MEM_RAM);
+}
+
+int __init reserve_mem_mach(unsigned long addr, unsigned long size)
+{
+       return reserve_bootmem(addr, size, BOOTMEM_DEFAULT);
+}
+
+void __init free_mem_mach(unsigned long addr, unsigned long size)
+{
+       return free_bootmem(addr, size);
+}
+
+u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+       return virt_to_phys(
+               __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS))
+               );
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void __init early_init_dt_setup_initrd_arch(unsigned long start,
+                                           unsigned long end)
+{
+       initrd_start = (unsigned long)__va(start);
+       initrd_end = (unsigned long)__va(end);
+       initrd_below_start_ok = 1;
+}
+#endif
+
+/*
+ * irq_create_of_mapping - Hook to resolve OF irq specifier into a Linux irq#
+ *
+ * Currently the mapping mechanism is trivial; simple flat hwirq numbers are
+ * mapped 1:1 onto Linux irq numbers.  Cascaded irq controllers are not
+ * supported.
+ */
+unsigned int irq_create_of_mapping(struct device_node *controller,
+                                  const u32 *intspec, unsigned int intsize)
+{
+       return intspec[0];
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+void __init early_init_devtree(void *params)
+{
+       /* Setup flat device-tree pointer */
+       initial_boot_params = params;
+
+       /* Retrieve various informations from the /chosen node of the
+        * device-tree, including the platform type, initrd location and
+        * size, and more ...
+        */
+       of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
+
+       /* Scan memory nodes */
+       of_scan_flat_dt(early_init_dt_scan_root, NULL);
+       of_scan_flat_dt(early_init_dt_scan_memory_arch, NULL);
+}
+
+void __init device_tree_init(void)
+{
+       unsigned long base, size;
+
+       if (!initial_boot_params)
+               return;
+
+       base = virt_to_phys((void *)initial_boot_params);
+       size = initial_boot_params->totalsize;
+
+       /* Before we do anything, lets reserve the dt blob */
+       reserve_mem_mach(base, size);
+
+       unflatten_device_tree();
+
+       /* free the space reserved for the dt blob */
+       free_mem_mach(base, size);
+}
index 85aef3f..a6b900f 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/setup.h>
 #include <asm/smp-ops.h>
 #include <asm/system.h>
+#include <asm/prom.h>
 
 struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly;
 
@@ -487,6 +488,7 @@ static void __init arch_mem_init(char **cmdline_p)
        }
 
        bootmem_init();
+       device_tree_init();
        sparse_init();
        paging_init();
 }
index 9b626cf..f62efdf 100644 (file)
@@ -162,13 +162,10 @@ static int ibmebus_create_device(struct device_node *dn)
        dev->dev.bus = &ibmebus_bus_type;
        dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
 
-       ret = of_device_register(dev);
-       if (ret) {
-               of_device_free(dev);
-               return ret;
-       }
-
-       return 0;
+       ret = of_device_add(dev);
+       if (ret)
+               platform_device_put(dev);
+       return ret;
 }
 
 static int ibmebus_create_devices(const struct of_device_id *matches)
index c1fd0f9..c834757 100644 (file)
@@ -52,14 +52,14 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
                                  phys_addr_t taddr, unsigned long irq,
                                  upf_t flags, int irq_check_parent)
 {
-       const u32 *clk, *spd;
+       const __be32 *clk, *spd;
        u32 clock = BASE_BAUD * 16;
        int index;
 
        /* get clock freq. if present */
        clk = of_get_property(np, "clock-frequency", NULL);
        if (clk && *clk)
-               clock = *clk;
+               clock = be32_to_cpup(clk);
 
        /* get default speed if present */
        spd = of_get_property(np, "current-speed", NULL);
@@ -109,7 +109,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index,
        legacy_serial_infos[index].taddr = taddr;
        legacy_serial_infos[index].np = of_node_get(np);
        legacy_serial_infos[index].clock = clock;
-       legacy_serial_infos[index].speed = spd ? *spd : 0;
+       legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0;
        legacy_serial_infos[index].irq_check_parent = irq_check_parent;
 
        printk(KERN_DEBUG "Found legacy serial port %d for %s\n",
@@ -168,7 +168,7 @@ static int __init add_legacy_soc_port(struct device_node *np,
 static int __init add_legacy_isa_port(struct device_node *np,
                                      struct device_node *isa_brg)
 {
-       const u32 *reg;
+       const __be32 *reg;
        const char *typep;
        int index = -1;
        u64 taddr;
@@ -181,7 +181,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
                return -1;
 
        /* Verify it's an IO port, we don't support anything else */
-       if (!(reg[0] & 0x00000001))
+       if (!(be32_to_cpu(reg[0]) & 0x00000001))
                return -1;
 
        /* Now look for an "ibm,aix-loc" property that gives us ordering
@@ -202,7 +202,7 @@ static int __init add_legacy_isa_port(struct device_node *np,
                taddr = 0;
 
        /* Add port, irq will be dealt with later */
-       return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr,
+       return add_legacy_port(np, index, UPIO_PORT, be32_to_cpu(reg[1]), taddr,
                               NO_IRQ, UPF_BOOT_AUTOCONF, 0);
 
 }
@@ -251,9 +251,9 @@ static int __init add_legacy_pci_port(struct device_node *np,
         * we get to their "reg" property
         */
        if (np != pci_dev) {
-               const u32 *reg = of_get_property(np, "reg", NULL);
-               if (reg && (*reg < 4))
-                       index = lindex = *reg;
+               const __be32 *reg = of_get_property(np, "reg", NULL);
+               if (reg && (be32_to_cpup(reg) < 4))
+                       index = lindex = be32_to_cpup(reg);
        }
 
        /* Local index means it's the Nth port in the PCI chip. Unfortunately
@@ -507,7 +507,7 @@ static int __init check_legacy_serial_console(void)
        struct device_node *prom_stdout = NULL;
        int i, speed = 0, offset = 0;
        const char *name;
-       const u32 *spd;
+       const __be32 *spd;
 
        DBG(" -> check_legacy_serial_console()\n");
 
@@ -547,7 +547,7 @@ static int __init check_legacy_serial_console(void)
        }
        spd = of_get_property(prom_stdout, "current-speed", NULL);
        if (spd)
-               speed = *spd;
+               speed = be32_to_cpup(spd);
 
        if (strcmp(name, "serial") != 0)
                goto not_found;
index c3c6a88..9e3132d 100644 (file)
@@ -364,10 +364,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
        return 0;
 }
 
-void __init early_init_dt_scan_chosen_arch(unsigned long node)
+int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname,
+                                        int depth, void *data)
 {
        unsigned long *lprop;
 
+       /* Use common scan routine to determine if this is the chosen node */
+       if (early_init_dt_scan_chosen(node, uname, depth, data) == 0)
+               return 0;
+
 #ifdef CONFIG_PPC64
        /* check if iommu is forced on or off */
        if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
@@ -399,6 +404,9 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node)
        if (lprop)
                crashk_res.end = crashk_res.start + *lprop - 1;
 #endif
+
+       /* break now */
+       return 1;
 }
 
 #ifdef CONFIG_PPC_PSERIES
@@ -683,7 +691,7 @@ void __init early_init_devtree(void *params)
         * device-tree, including the platform type, initrd location and
         * size, TCE reserve, and more ...
         */
-       of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
+       of_scan_flat_dt(early_init_dt_scan_chosen_ppc, NULL);
 
        /* Scan memory nodes and rebuild MEMBLOCKs */
        memblock_init();
index 35b6879..0f40fc3 100644 (file)
@@ -24,6 +24,7 @@ config SUPERH
        select HAVE_KERNEL_LZMA
        select HAVE_KERNEL_LZO
        select HAVE_SYSCALL_TRACEPOINTS
+       select HAVE_REGS_AND_STACK_ACCESS_API
        select RTC_LIB
        select GENERIC_ATOMIC64
        help
@@ -46,7 +47,7 @@ config SUPERH32
        select HAVE_ARCH_KGDB
        select HAVE_HW_BREAKPOINT
        select HAVE_MIXED_BREAKPOINTS_REGS
-       select PERF_EVENTS if HAVE_HW_BREAKPOINT
+       select PERF_EVENTS
        select ARCH_HIBERNATION_POSSIBLE if MMU
 
 config SUPERH64
@@ -471,6 +472,7 @@ config CPU_SUBTYPE_SHX3
        select CPU_SH4A
        select CPU_SHX3
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
+       select ARCH_REQUIRE_GPIOLIB
 
 # SH4AL-DSP Processor Support
 
@@ -575,7 +577,7 @@ config SH_CLK_CPG
 config SH_CLK_CPG_LEGACY
        depends on SH_CLK_CPG
        def_bool y if !CPU_SUBTYPE_SH7785 && !ARCH_SHMOBILE && \
-                     !CPU_SUBTYPE_SH7786
+                     !CPU_SHX3 && !CPU_SUBTYPE_SH7757
 
 config SH_CLK_MD
        int "CPU Mode Pin Setting"
index 07b35ca..9c94711 100644 (file)
@@ -155,6 +155,8 @@ config SH_SDK7786
        depends on CPU_SUBTYPE_SH7786
        select SYS_SUPPORTS_PCI
        select NO_IOPORT if !PCI
+       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select HAVE_SRAM_POOL
        help
          Select SDK7786 if configuring for a Renesas Technology Europe
          SH7786-65nm board.
@@ -165,6 +167,11 @@ config SH_HIGHLANDER
        select SYS_SUPPORTS_PCI
        select IO_TRAPPED if MMU
 
+config SH_SH7757LCR
+       bool "SH7757LCR"
+       depends on CPU_SUBTYPE_SH7757
+       select ARCH_REQUIRE_GPIOLIB
+
 config SH_SH7785LCR
        bool "SH7785LCR"
        depends on CPU_SUBTYPE_SH7785
@@ -309,6 +316,17 @@ config SH_POLARIS
        help
          Select if configuring for an SMSC Polaris development board
 
+config SH_SH2007
+       bool "SH-2007 board"
+       select NO_IOPORT
+       depends on CPU_SUBTYPE_SH7780
+       help
+         SH-2007 is a single-board computer based around SH7780 chip
+         intended for embedded applications.
+         It has an Ethernet interface (SMC9118), direct connected
+         Compact Flash socket, two serial ports and PC-104 bus.
+         More information at <http://sh2000.sh-linux.org>.
+
 endmenu
 
 source "arch/sh/boards/mach-r2d/Kconfig"
index 4f90f9b..38ef655 100644 (file)
@@ -2,6 +2,7 @@
 # Specific board support, not covered by a mach group.
 #
 obj-$(CONFIG_SH_MAGIC_PANEL_R2)        += board-magicpanelr2.o
+obj-$(CONFIG_SH_SH2007)                += board-sh2007.o
 obj-$(CONFIG_SH_SH7785LCR)     += board-sh7785lcr.o
 obj-$(CONFIG_SH_URQUELL)       += board-urquell.o
 obj-$(CONFIG_SH_SHMIN)         += board-shmin.o
@@ -9,3 +10,4 @@ obj-$(CONFIG_SH_EDOSK7760)     += board-edosk7760.o
 obj-$(CONFIG_SH_ESPT)          += board-espt.o
 obj-$(CONFIG_SH_POLARIS)       += board-polaris.o
 obj-$(CONFIG_SH_TITAN)         += board-titan.o
+obj-$(CONFIG_SH_SH7757LCR)     += board-sh7757lcr.o
diff --git a/arch/sh/boards/board-sh2007.c b/arch/sh/boards/board-sh2007.c
new file mode 100644 (file)
index 0000000..b90b78f
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * SH-2007 board support.
+ *
+ * Copyright (C) 2003, 2004  SUGIOKA Toshinobu
+ * Copyright (C) 2010  Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
+ */
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/smsc911x.h>
+#include <linux/platform_device.h>
+#include <linux/ata_platform.h>
+#include <linux/io.h>
+#include <asm/machvec.h>
+#include <mach/sh2007.h>
+
+struct smsc911x_platform_config smc911x_info = {
+       .flags          = SMSC911X_USE_32BIT,
+       .irq_polarity   = SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
+       .irq_type       = SMSC911X_IRQ_TYPE_PUSH_PULL,
+};
+
+static struct resource smsc9118_0_resources[] = {
+       [0] = {
+               .start  = SMC0_BASE,
+               .end    = SMC0_BASE + 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = evt2irq(0x240),
+               .end    = evt2irq(0x240),
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct resource smsc9118_1_resources[] = {
+       [0] = {
+               .start  = SMC1_BASE,
+               .end    = SMC1_BASE + 0xff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = evt2irq(0x280),
+               .end    = evt2irq(0x280),
+               .flags  = IORESOURCE_IRQ,
+       }
+};
+
+static struct platform_device smsc9118_0_device = {
+       .name           = "smsc911x",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(smsc9118_0_resources),
+       .resource       = smsc9118_0_resources,
+       .dev = {
+               .platform_data = &smc911x_info,
+       },
+};
+
+static struct platform_device smsc9118_1_device = {
+       .name           = "smsc911x",
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(smsc9118_1_resources),
+       .resource       = smsc9118_1_resources,
+       .dev = {
+               .platform_data = &smc911x_info,
+       },
+};
+
+static struct resource cf_resources[] = {
+       [0] = {
+               .start  = CF_BASE + CF_OFFSET,
+               .end    = CF_BASE + CF_OFFSET + 0x0f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = CF_BASE + CF_OFFSET + 0x206,
+               .end    = CF_BASE + CF_OFFSET + 0x20f,
+               .flags  = IORESOURCE_MEM,
+       },
+       [2] = {
+               .start  = evt2irq(0x2c0),
+               .end    = evt2irq(0x2c0),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device cf_device  = {
+       .name           = "pata_platform",
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(cf_resources),
+       .resource       = cf_resources,
+};
+
+static struct platform_device *sh2007_devices[] __initdata = {
+       &smsc9118_0_device,
+       &smsc9118_1_device,
+       &cf_device,
+};
+
+static int __init sh2007_io_init(void)
+{
+       platform_add_devices(sh2007_devices, ARRAY_SIZE(sh2007_devices));
+       return 0;
+}
+subsys_initcall(sh2007_io_init);
+
+static void __init sh2007_init_irq(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRQ);
+}
+
+/*
+ * Initialize the board
+ */
+static void __init sh2007_setup(char **cmdline_p)
+{
+       printk(KERN_INFO "SH-2007 Setup...");
+
+       /* setup wait control registers for area 5 */
+       __raw_writel(CS5BCR_D, CS5BCR);
+       __raw_writel(CS5WCR_D, CS5WCR);
+       __raw_writel(CS5PCR_D, CS5PCR);
+
+       printk(KERN_INFO " done.\n");
+}
+
+/*
+ * The Machine Vector
+ */
+struct sh_machine_vector mv_sh2007 __initmv = {
+       .mv_setup               = sh2007_setup,
+       .mv_name                = "sh2007",
+       .mv_init_irq            = sh2007_init_irq,
+};
diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c
new file mode 100644 (file)
index 0000000..c475f10
--- /dev/null
@@ -0,0 +1,374 @@
+/*
+ * Renesas R0P7757LC0012RL Support.
+ *
+ * Copyright (C) 2009 - 2010  Renesas Solutions Corp.
+ *
+ * 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/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include <linux/io.h>
+#include <cpu/sh7757.h>
+#include <asm/sh_eth.h>
+#include <asm/heartbeat.h>
+
+static struct resource heartbeat_resource = {
+       .start  = 0xffec005c,   /* PUDR */
+       .end    = 0xffec005c,
+       .flags  = IORESOURCE_MEM | IORESOURCE_MEM_8BIT,
+};
+
+static unsigned char heartbeat_bit_pos[] = { 0, 1, 2, 3 };
+
+static struct heartbeat_data heartbeat_data = {
+       .bit_pos        = heartbeat_bit_pos,
+       .nr_bits        = ARRAY_SIZE(heartbeat_bit_pos),
+       .flags          = HEARTBEAT_INVERTED,
+};
+
+static struct platform_device heartbeat_device = {
+       .name           = "heartbeat",
+       .id             = -1,
+       .dev    = {
+               .platform_data  = &heartbeat_data,
+       },
+       .num_resources  = 1,
+       .resource       = &heartbeat_resource,
+};
+
+/* Fast Ethernet */
+static struct resource sh_eth0_resources[] = {
+       {
+               .start  = 0xfef00000,
+               .end    = 0xfef001ff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = 84,
+               .end    = 84,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct sh_eth_plat_data sh7757_eth0_pdata = {
+       .phy = 1,
+       .edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device sh7757_eth0_device = {
+       .name           = "sh-eth",
+       .resource       = sh_eth0_resources,
+       .id             = 0,
+       .num_resources  = ARRAY_SIZE(sh_eth0_resources),
+       .dev            = {
+               .platform_data = &sh7757_eth0_pdata,
+       },
+};
+
+static struct resource sh_eth1_resources[] = {
+       {
+               .start  = 0xfef00800,
+               .end    = 0xfef009ff,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = 84,
+               .end    = 84,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct sh_eth_plat_data sh7757_eth1_pdata = {
+       .phy = 1,
+       .edmac_endian = EDMAC_LITTLE_ENDIAN,
+};
+
+static struct platform_device sh7757_eth1_device = {
+       .name           = "sh-eth",
+       .resource       = sh_eth1_resources,
+       .id             = 1,
+       .num_resources  = ARRAY_SIZE(sh_eth1_resources),
+       .dev            = {
+               .platform_data = &sh7757_eth1_pdata,
+       },
+};
+
+static struct platform_device *sh7757lcr_devices[] __initdata = {
+       &heartbeat_device,
+       &sh7757_eth0_device,
+       &sh7757_eth1_device,
+};
+
+static int __init sh7757lcr_devices_setup(void)
+{
+       /* RGMII (PTA) */
+       gpio_request(GPIO_FN_ET0_MDC, NULL);
+       gpio_request(GPIO_FN_ET0_MDIO, NULL);
+       gpio_request(GPIO_FN_ET1_MDC, NULL);
+       gpio_request(GPIO_FN_ET1_MDIO, NULL);
+
+       /* ONFI (PTB, PTZ) */
+       gpio_request(GPIO_FN_ON_NRE, NULL);
+       gpio_request(GPIO_FN_ON_NWE, NULL);
+       gpio_request(GPIO_FN_ON_NWP, NULL);
+       gpio_request(GPIO_FN_ON_NCE0, NULL);
+       gpio_request(GPIO_FN_ON_R_B0, NULL);
+       gpio_request(GPIO_FN_ON_ALE, NULL);
+       gpio_request(GPIO_FN_ON_CLE, NULL);
+
+       gpio_request(GPIO_FN_ON_DQ7, NULL);
+       gpio_request(GPIO_FN_ON_DQ6, NULL);
+       gpio_request(GPIO_FN_ON_DQ5, NULL);
+       gpio_request(GPIO_FN_ON_DQ4, NULL);
+       gpio_request(GPIO_FN_ON_DQ3, NULL);
+       gpio_request(GPIO_FN_ON_DQ2, NULL);
+       gpio_request(GPIO_FN_ON_DQ1, NULL);
+       gpio_request(GPIO_FN_ON_DQ0, NULL);
+
+       /* IRQ8 to 0 (PTB, PTC) */
+       gpio_request(GPIO_FN_IRQ8, NULL);
+       gpio_request(GPIO_FN_IRQ7, NULL);
+       gpio_request(GPIO_FN_IRQ6, NULL);
+       gpio_request(GPIO_FN_IRQ5, NULL);
+       gpio_request(GPIO_FN_IRQ4, NULL);
+       gpio_request(GPIO_FN_IRQ3, NULL);
+       gpio_request(GPIO_FN_IRQ2, NULL);
+       gpio_request(GPIO_FN_IRQ1, NULL);
+       gpio_request(GPIO_FN_IRQ0, NULL);
+
+       /* SPI0 (PTD) */
+       gpio_request(GPIO_FN_SP0_MOSI, NULL);
+       gpio_request(GPIO_FN_SP0_MISO, NULL);
+       gpio_request(GPIO_FN_SP0_SCK, NULL);
+       gpio_request(GPIO_FN_SP0_SCK_FB, NULL);
+       gpio_request(GPIO_FN_SP0_SS0, NULL);
+       gpio_request(GPIO_FN_SP0_SS1, NULL);
+       gpio_request(GPIO_FN_SP0_SS2, NULL);
+       gpio_request(GPIO_FN_SP0_SS3, NULL);
+
+       /* RMII 0/1 (PTE, PTF) */
+       gpio_request(GPIO_FN_RMII0_CRS_DV, NULL);
+       gpio_request(GPIO_FN_RMII0_TXD1, NULL);
+       gpio_request(GPIO_FN_RMII0_TXD0, NULL);
+       gpio_request(GPIO_FN_RMII0_TXEN, NULL);
+       gpio_request(GPIO_FN_RMII0_REFCLK, NULL);
+       gpio_request(GPIO_FN_RMII0_RXD1, NULL);
+       gpio_request(GPIO_FN_RMII0_RXD0, NULL);
+       gpio_request(GPIO_FN_RMII0_RX_ER, NULL);
+       gpio_request(GPIO_FN_RMII1_CRS_DV, NULL);
+       gpio_request(GPIO_FN_RMII1_TXD1, NULL);
+       gpio_request(GPIO_FN_RMII1_TXD0, NULL);
+       gpio_request(GPIO_FN_RMII1_TXEN, NULL);
+       gpio_request(GPIO_FN_RMII1_REFCLK, NULL);
+       gpio_request(GPIO_FN_RMII1_RXD1, NULL);
+       gpio_request(GPIO_FN_RMII1_RXD0, NULL);
+       gpio_request(GPIO_FN_RMII1_RX_ER, NULL);
+
+       /* eMMC (PTG) */
+       gpio_request(GPIO_FN_MMCCLK, NULL);
+       gpio_request(GPIO_FN_MMCCMD, NULL);
+       gpio_request(GPIO_FN_MMCDAT7, NULL);
+       gpio_request(GPIO_FN_MMCDAT6, NULL);
+       gpio_request(GPIO_FN_MMCDAT5, NULL);
+       gpio_request(GPIO_FN_MMCDAT4, NULL);
+       gpio_request(GPIO_FN_MMCDAT3, NULL);
+       gpio_request(GPIO_FN_MMCDAT2, NULL);
+       gpio_request(GPIO_FN_MMCDAT1, NULL);
+       gpio_request(GPIO_FN_MMCDAT0, NULL);
+
+       /* LPC (PTG, PTH, PTQ, PTU) */
+       gpio_request(GPIO_FN_SERIRQ, NULL);
+       gpio_request(GPIO_FN_LPCPD, NULL);
+       gpio_request(GPIO_FN_LDRQ, NULL);
+       gpio_request(GPIO_FN_WP, NULL);
+       gpio_request(GPIO_FN_FMS0, NULL);
+       gpio_request(GPIO_FN_LAD3, NULL);
+       gpio_request(GPIO_FN_LAD2, NULL);
+       gpio_request(GPIO_FN_LAD1, NULL);
+       gpio_request(GPIO_FN_LAD0, NULL);
+       gpio_request(GPIO_FN_LFRAME, NULL);
+       gpio_request(GPIO_FN_LRESET, NULL);
+       gpio_request(GPIO_FN_LCLK, NULL);
+       gpio_request(GPIO_FN_LGPIO7, NULL);
+       gpio_request(GPIO_FN_LGPIO6, NULL);
+       gpio_request(GPIO_FN_LGPIO5, NULL);
+       gpio_request(GPIO_FN_LGPIO4, NULL);
+
+       /* SPI1 (PTH) */
+       gpio_request(GPIO_FN_SP1_MOSI, NULL);
+       gpio_request(GPIO_FN_SP1_MISO, NULL);
+       gpio_request(GPIO_FN_SP1_SCK, NULL);
+       gpio_request(GPIO_FN_SP1_SCK_FB, NULL);
+       gpio_request(GPIO_FN_SP1_SS0, NULL);
+       gpio_request(GPIO_FN_SP1_SS1, NULL);
+
+       /* SDHI (PTI) */
+       gpio_request(GPIO_FN_SD_WP, NULL);
+       gpio_request(GPIO_FN_SD_CD, NULL);
+       gpio_request(GPIO_FN_SD_CLK, NULL);
+       gpio_request(GPIO_FN_SD_CMD, NULL);
+       gpio_request(GPIO_FN_SD_D3, NULL);
+       gpio_request(GPIO_FN_SD_D2, NULL);
+       gpio_request(GPIO_FN_SD_D1, NULL);
+       gpio_request(GPIO_FN_SD_D0, NULL);
+
+       /* SCIF3/4 (PTJ, PTW) */
+       gpio_request(GPIO_FN_RTS3, NULL);
+       gpio_request(GPIO_FN_CTS3, NULL);
+       gpio_request(GPIO_FN_TXD3, NULL);
+       gpio_request(GPIO_FN_RXD3, NULL);
+       gpio_request(GPIO_FN_RTS4, NULL);
+       gpio_request(GPIO_FN_RXD4, NULL);
+       gpio_request(GPIO_FN_TXD4, NULL);
+       gpio_request(GPIO_FN_CTS4, NULL);
+
+       /* SERMUX (PTK, PTL, PTO, PTV) */
+       gpio_request(GPIO_FN_COM2_TXD, NULL);
+       gpio_request(GPIO_FN_COM2_RXD, NULL);
+       gpio_request(GPIO_FN_COM2_RTS, NULL);
+       gpio_request(GPIO_FN_COM2_CTS, NULL);
+       gpio_request(GPIO_FN_COM2_DTR, NULL);
+       gpio_request(GPIO_FN_COM2_DSR, NULL);
+       gpio_request(GPIO_FN_COM2_DCD, NULL);
+       gpio_request(GPIO_FN_COM2_RI, NULL);
+       gpio_request(GPIO_FN_RAC_RXD, NULL);
+       gpio_request(GPIO_FN_RAC_RTS, NULL);
+       gpio_request(GPIO_FN_RAC_CTS, NULL);
+       gpio_request(GPIO_FN_RAC_DTR, NULL);
+       gpio_request(GPIO_FN_RAC_DSR, NULL);
+       gpio_request(GPIO_FN_RAC_DCD, NULL);
+       gpio_request(GPIO_FN_RAC_TXD, NULL);
+       gpio_request(GPIO_FN_COM1_TXD, NULL);
+       gpio_request(GPIO_FN_COM1_RXD, NULL);
+       gpio_request(GPIO_FN_COM1_RTS, NULL);
+       gpio_request(GPIO_FN_COM1_CTS, NULL);
+
+       writeb(0x10, 0xfe470000);       /* SMR0: SerMux mode 0 */
+
+       /* IIC (PTM, PTR, PTS) */
+       gpio_request(GPIO_FN_SDA7, NULL);
+       gpio_request(GPIO_FN_SCL7, NULL);
+       gpio_request(GPIO_FN_SDA6, NULL);
+       gpio_request(GPIO_FN_SCL6, NULL);
+       gpio_request(GPIO_FN_SDA5, NULL);
+       gpio_request(GPIO_FN_SCL5, NULL);
+       gpio_request(GPIO_FN_SDA4, NULL);
+       gpio_request(GPIO_FN_SCL4, NULL);
+       gpio_request(GPIO_FN_SDA3, NULL);
+       gpio_request(GPIO_FN_SCL3, NULL);
+       gpio_request(GPIO_FN_SDA2, NULL);
+       gpio_request(GPIO_FN_SCL2, NULL);
+       gpio_request(GPIO_FN_SDA1, NULL);
+       gpio_request(GPIO_FN_SCL1, NULL);
+       gpio_request(GPIO_FN_SDA0, NULL);
+       gpio_request(GPIO_FN_SCL0, NULL);
+
+       /* USB (PTN) */
+       gpio_request(GPIO_FN_VBUS_EN, NULL);
+       gpio_request(GPIO_FN_VBUS_OC, NULL);
+
+       /* SGPIO1/0 (PTN, PTO) */
+       gpio_request(GPIO_FN_SGPIO1_CLK, NULL);
+       gpio_request(GPIO_FN_SGPIO1_LOAD, NULL);
+       gpio_request(GPIO_FN_SGPIO1_DI, NULL);
+       gpio_request(GPIO_FN_SGPIO1_DO, NULL);
+       gpio_request(GPIO_FN_SGPIO0_CLK, NULL);
+       gpio_request(GPIO_FN_SGPIO0_LOAD, NULL);
+       gpio_request(GPIO_FN_SGPIO0_DI, NULL);
+       gpio_request(GPIO_FN_SGPIO0_DO, NULL);
+
+       /* WDT (PTN) */
+       gpio_request(GPIO_FN_SUB_CLKIN, NULL);
+
+       /* System (PTT) */
+       gpio_request(GPIO_FN_STATUS1, NULL);
+       gpio_request(GPIO_FN_STATUS0, NULL);
+
+       /* PWMX (PTT) */
+       gpio_request(GPIO_FN_PWMX1, NULL);
+       gpio_request(GPIO_FN_PWMX0, NULL);
+
+       /* R-SPI (PTV) */
+       gpio_request(GPIO_FN_R_SPI_MOSI, NULL);
+       gpio_request(GPIO_FN_R_SPI_MISO, NULL);
+       gpio_request(GPIO_FN_R_SPI_RSPCK, NULL);
+       gpio_request(GPIO_FN_R_SPI_SSL0, NULL);
+       gpio_request(GPIO_FN_R_SPI_SSL1, NULL);
+
+       /* EVC (PTV, PTW) */
+       gpio_request(GPIO_FN_EVENT7, NULL);
+       gpio_request(GPIO_FN_EVENT6, NULL);
+       gpio_request(GPIO_FN_EVENT5, NULL);
+       gpio_request(GPIO_FN_EVENT4, NULL);
+       gpio_request(GPIO_FN_EVENT3, NULL);
+       gpio_request(GPIO_FN_EVENT2, NULL);
+       gpio_request(GPIO_FN_EVENT1, NULL);
+       gpio_request(GPIO_FN_EVENT0, NULL);
+
+       /* LED for heartbeat */
+       gpio_request(GPIO_PTU3, NULL);
+       gpio_direction_output(GPIO_PTU3, 1);
+       gpio_request(GPIO_PTU2, NULL);
+       gpio_direction_output(GPIO_PTU2, 1);
+       gpio_request(GPIO_PTU1, NULL);
+       gpio_direction_output(GPIO_PTU1, 1);
+       gpio_request(GPIO_PTU0, NULL);
+       gpio_direction_output(GPIO_PTU0, 1);
+
+       /* control for MDIO of Gigabit Ethernet */
+       gpio_request(GPIO_PTT4, NULL);
+       gpio_direction_output(GPIO_PTT4, 1);
+
+       /* control for eMMC */
+       gpio_request(GPIO_PTT7, NULL);          /* eMMC_RST# */
+       gpio_direction_output(GPIO_PTT7, 0);
+       gpio_request(GPIO_PTT6, NULL);          /* eMMC_INDEX# */
+       gpio_direction_output(GPIO_PTT6, 0);
+       gpio_request(GPIO_PTT5, NULL);          /* eMMC_PRST# */
+       gpio_direction_output(GPIO_PTT5, 1);
+
+       /* General platform */
+       return platform_add_devices(sh7757lcr_devices,
+                                   ARRAY_SIZE(sh7757lcr_devices));
+}
+arch_initcall(sh7757lcr_devices_setup);
+
+/* Initialize IRQ setting */
+void __init init_sh7757lcr_IRQ(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRQ7654);
+       plat_irq_setup_pins(IRQ_MODE_IRQ3210);
+}
+
+/* Initialize the board */
+static void __init sh7757lcr_setup(char **cmdline_p)
+{
+       printk(KERN_INFO "Renesas R0P7757LC0012RL support.\n");
+}
+
+static int sh7757lcr_mode_pins(void)
+{
+       int value = 0;
+
+       /* These are the factory default settings of S3 (Low active).
+        * If you change these dip switches then you will need to
+        * adjust the values below as well.
+        */
+       value |= MODE_PIN0;     /* Clock Mode: 1 */
+
+       return value;
+}
+
+/* The Machine Vector */
+static struct sh_machine_vector mv_sh7757lcr __initmv = {
+       .mv_name                = "SH7757LCR",
+       .mv_setup               = sh7757lcr_setup,
+       .mv_init_irq            = init_sh7757lcr_IRQ,
+       .mv_mode_pins           = sh7757lcr_mode_pins,
+};
+
index 1d7b495..71a3368 100644 (file)
@@ -1248,14 +1248,14 @@ static int __init arch_setup(void)
 
        /* set SPU2 clock to 83.4 MHz */
        clk = clk_get(NULL, "spu_clk");
-       if (clk) {
+       if (!IS_ERR(clk)) {
                clk_set_rate(clk, clk_round_rate(clk, 83333333));
                clk_put(clk);
        }
 
        /* change parent of FSI B */
        clk = clk_get(NULL, "fsib_clk");
-       if (clk) {
+       if (!IS_ERR(clk)) {
                clk_register(&fsimckb_clk);
                clk_set_parent(clk, &fsimckb_clk);
                clk_set_rate(clk, 11000);
@@ -1273,7 +1273,7 @@ static int __init arch_setup(void)
 
        /* set VPU clock to 166 MHz */
        clk = clk_get(NULL, "vpu_clk");
-       if (clk) {
+       if (!IS_ERR(clk)) {
                clk_set_rate(clk, clk_round_rate(clk, 166000000));
                clk_put(clk);
        }
index a29f19e..23ff7d4 100644 (file)
@@ -1 +1,4 @@
-obj-y  := setup.o fpga.o irq.o
+obj-y  := fpga.o irq.o setup.o
+
+obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
+obj-$(CONFIG_HAVE_SRAM_POOL)   += sram.o
diff --git a/arch/sh/boards/mach-sdk7786/gpio.c b/arch/sh/boards/mach-sdk7786/gpio.c
new file mode 100644 (file)
index 0000000..f71ce09
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * SDK7786 FPGA USRGPIR Support.
+ *
+ * Copyright (C) 2010  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/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <mach/fpga.h>
+
+#define NR_FPGA_GPIOS  8
+
+static const char *usrgpir_gpio_names[NR_FPGA_GPIOS] = {
+       "in0", "in1", "in2", "in3", "in4", "in5", "in6", "in7",
+};
+
+static int usrgpir_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       /* always in */
+       return 0;
+}
+
+static int usrgpir_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+       return !!(fpga_read_reg(USRGPIR) & (1 << gpio));
+}
+
+static struct gpio_chip usrgpir_gpio_chip = {
+       .label                  = "sdk7786-fpga",
+       .names                  = usrgpir_gpio_names,
+       .direction_input        = usrgpir_gpio_direction_input,
+       .get                    = usrgpir_gpio_get,
+       .base                   = -1, /* don't care */
+       .ngpio                  = NR_FPGA_GPIOS,
+};
+
+static int __init usrgpir_gpio_setup(void)
+{
+       return gpiochip_add(&usrgpir_gpio_chip);
+}
+device_initcall(usrgpir_gpio_setup);
index 2ec1ea5..7e0c4e3 100644 (file)
@@ -20,6 +20,8 @@
 #include <asm/machvec.h>
 #include <asm/heartbeat.h>
 #include <asm/sizes.h>
+#include <asm/clock.h>
+#include <asm/clkdev.h>
 #include <asm/reboot.h>
 #include <asm/smp-ops.h>
 
@@ -140,6 +142,45 @@ static int sdk7786_mode_pins(void)
        return fpga_read_reg(MODSWR);
 }
 
+/*
+ * FPGA-driven PCIe clocks
+ *
+ * Historically these include the oscillator, clock B (slots 2/3/4) and
+ * clock A (slot 1 and the CPU clock). Newer revs of the PCB shove
+ * everything under a single PCIe clocks enable bit that happens to map
+ * to the same bit position as the oscillator bit for earlier FPGA
+ * versions.
+ *
+ * Given that the legacy clocks have the side-effect of shutting the CPU
+ * off through the FPGA along with the PCI slots, we simply leave them in
+ * their initial state and don't bother registering them with the clock
+ * framework.
+ */
+static int sdk7786_pcie_clk_enable(struct clk *clk)
+{
+       fpga_write_reg(fpga_read_reg(PCIECR) | PCIECR_CLKEN, PCIECR);
+       return 0;
+}
+
+static void sdk7786_pcie_clk_disable(struct clk *clk)
+{
+       fpga_write_reg(fpga_read_reg(PCIECR) & ~PCIECR_CLKEN, PCIECR);
+}
+
+static struct clk_ops sdk7786_pcie_clk_ops = {
+       .enable         = sdk7786_pcie_clk_enable,
+       .disable        = sdk7786_pcie_clk_disable,
+};
+
+static struct clk sdk7786_pcie_clk = {
+       .ops            = &sdk7786_pcie_clk_ops,
+};
+
+static struct clk_lookup sdk7786_pcie_cl = {
+       .con_id         = "pcie_plat_clk",
+       .clk            = &sdk7786_pcie_clk,
+};
+
 static int sdk7786_clk_init(void)
 {
        struct clk *clk;
@@ -158,7 +199,18 @@ static int sdk7786_clk_init(void)
        ret = clk_set_rate(clk, 33333333);
        clk_put(clk);
 
-       return ret;
+       /*
+        * Setup the FPGA clocks.
+        */
+       ret = clk_register(&sdk7786_pcie_clk);
+       if (unlikely(ret)) {
+               pr_err("FPGA clock registration failed\n");
+               return ret;
+       }
+
+       clkdev_add(&sdk7786_pcie_cl);
+
+       return 0;
 }
 
 static void sdk7786_restart(char *cmd)
diff --git a/arch/sh/boards/mach-sdk7786/sram.c b/arch/sh/boards/mach-sdk7786/sram.c
new file mode 100644 (file)
index 0000000..c81c3ab
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * SDK7786 FPGA SRAM Support.
+ *
+ * Copyright (C) 2010  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.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/string.h>
+#include <mach/fpga.h>
+#include <asm/sram.h>
+#include <asm/sizes.h>
+
+static int __init fpga_sram_init(void)
+{
+       unsigned long phys;
+       unsigned int area;
+       void __iomem *vaddr;
+       int ret;
+       u16 data;
+
+       /* Enable FPGA SRAM */
+       data = fpga_read_reg(LCLASR);
+       data |= LCLASR_FRAMEN;
+       fpga_write_reg(data, LCLASR);
+
+       /*
+        * FPGA_SEL determines the area mapping
+        */
+       area = (data & LCLASR_FPGA_SEL_MASK) >> LCLASR_FPGA_SEL_SHIFT;
+       if (unlikely(area == LCLASR_AREA_MASK)) {
+               pr_err("FPGA memory unmapped.\n");
+               return -ENXIO;
+       }
+
+       /*
+        * The memory itself occupies a 2KiB range at the top of the area
+        * immediately below the system registers.
+        */
+       phys = (area << 26) + SZ_64M - SZ_4K;
+
+       /*
+        * The FPGA SRAM resides in translatable physical space, so set
+        * up a mapping prior to inserting it in to the pool.
+        */
+       vaddr = ioremap(phys, SZ_2K);
+       if (unlikely(!vaddr)) {
+               pr_err("Failed remapping FPGA memory.\n");
+               return -ENXIO;
+       }
+
+       pr_info("Adding %dKiB of FPGA memory at 0x%08lx-0x%08lx "
+               "(area %d) to pool.\n",
+               SZ_2K >> 10, phys, phys + SZ_2K - 1, area);
+
+       ret = gen_pool_add(sram_pool, (unsigned long)vaddr, SZ_2K, -1);
+       if (unlikely(ret < 0)) {
+               pr_err("Failed adding memory\n");
+               iounmap(vaddr);
+               return ret;
+       }
+
+       return 0;
+}
+postcore_initcall(fpga_sram_init);
index 983e455..708c21c 100644 (file)
@@ -1 +1,3 @@
 obj-y += setup.o ilsel.o
+
+obj-$(CONFIG_GENERIC_GPIO)     += gpio.o
diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c
new file mode 100644 (file)
index 0000000..594adf7
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * arch/sh/boards/mach-x3proto/gpio.c
+ *
+ * Renesas SH-X3 Prototype Baseboard GPIO Support.
+ *
+ * Copyright (C) 2010  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.
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <mach/ilsel.h>
+#include <mach/hardware.h>
+
+#define KEYCTLR        0xb81c0000
+#define KEYOUTR        0xb81c0002
+#define KEYDETR 0xb81c0004
+
+static DEFINE_SPINLOCK(x3proto_gpio_lock);
+static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, };
+
+static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       unsigned long flags;
+       unsigned int data;
+
+       spin_lock_irqsave(&x3proto_gpio_lock, flags);
+       data = __raw_readw(KEYCTLR);
+       data |= (1 << gpio);
+       __raw_writew(data, KEYCTLR);
+       spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
+
+       return 0;
+}
+
+static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio)
+{
+       return !!(__raw_readw(KEYDETR) & (1 << gpio));
+}
+
+static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
+{
+       return x3proto_gpio_irq_map[gpio];
+}
+
+static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct irq_chip *chip = get_irq_desc_chip(desc);
+       unsigned long mask;
+       int pin;
+
+       chip->mask_ack(irq);
+
+       mask = __raw_readw(KEYDETR);
+
+       for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS)
+               generic_handle_irq(x3proto_gpio_to_irq(NULL, pin));
+
+       chip->unmask(irq);
+}
+
+struct gpio_chip x3proto_gpio_chip = {
+       .label                  = "x3proto-gpio",
+       .direction_input        = x3proto_gpio_direction_input,
+       .get                    = x3proto_gpio_get,
+       .to_irq                 = x3proto_gpio_to_irq,
+       .base                   = -1,
+       .ngpio                  = NR_BASEBOARD_GPIOS,
+};
+
+int __init x3proto_gpio_setup(void)
+{
+       int ilsel;
+       int ret, i;
+
+       ilsel = ilsel_enable(ILSEL_KEY);
+       if (unlikely(ilsel < 0))
+               return ilsel;
+
+       ret = gpiochip_add(&x3proto_gpio_chip);
+       if (unlikely(ret))
+               goto err_gpio;
+
+       for (i = 0; i < NR_BASEBOARD_GPIOS; i++) {
+               unsigned long flags;
+               int irq = create_irq();
+
+               if (unlikely(irq < 0)) {
+                       ret = -EINVAL;
+                       goto err_irq;
+               }
+
+               spin_lock_irqsave(&x3proto_gpio_lock, flags);
+               x3proto_gpio_irq_map[i] = irq;
+               set_irq_chip_and_handler_name(irq, &dummy_irq_chip,
+                                       handle_simple_irq, "gpio");
+               spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
+       }
+
+       pr_info("registering '%s' support, handling GPIOs %u -> %u, "
+               "bound to IRQ %u\n",
+               x3proto_gpio_chip.label, x3proto_gpio_chip.base,
+               x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio,
+               ilsel);
+
+       set_irq_chained_handler(ilsel, x3proto_gpio_irq_handler);
+       set_irq_wake(ilsel, 1);
+
+       return 0;
+
+err_irq:
+       for (; i >= 0; --i)
+               if (x3proto_gpio_irq_map[i])
+                       destroy_irq(x3proto_gpio_irq_map[i]);
+
+       ret = gpiochip_remove(&x3proto_gpio_chip);
+       if (unlikely(ret))
+               pr_err("Failed deregistering GPIO\n");
+
+err_gpio:
+       synchronize_irq(ilsel);
+
+       ilsel_disable(ILSEL_KEY);
+
+       return ret;
+}
index 5c98427..95e3461 100644 (file)
@@ -1,20 +1,22 @@
 /*
- * arch/sh/boards/renesas/x3proto/ilsel.c
+ * arch/sh/boards/mach-x3proto/ilsel.c
  *
  * Helper routines for SH-X3 proto board ILSEL.
  *
- * Copyright (C) 2007 Paul Mundt
+ * Copyright (C) 2007 - 2010  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.
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/bitmap.h>
 #include <linux/io.h>
-#include <asm/ilsel.h>
+#include <mach/ilsel.h>
 
 /*
  * ILSEL is split across:
@@ -64,6 +66,8 @@ static void __ilsel_enable(ilsel_source_t set, unsigned int bit)
        unsigned int tmp, shift;
        unsigned long addr;
 
+       pr_notice("enabling ILSEL set %d\n", set);
+
        addr = mk_ilsel_addr(bit);
        shift = mk_ilsel_shift(bit);
 
@@ -92,8 +96,10 @@ int ilsel_enable(ilsel_source_t set)
 {
        unsigned int bit;
 
-       /* Aliased sources must use ilsel_enable_fixed() */
-       BUG_ON(set > ILSEL_KEY);
+       if (unlikely(set > ILSEL_KEY)) {
+               pr_err("Aliased sources must use ilsel_enable_fixed()\n");
+               return -EINVAL;
+       }
 
        do {
                bit = find_first_zero_bit(&ilsel_level_map, ILSEL_LEVELS);
@@ -140,6 +146,8 @@ void ilsel_disable(unsigned int irq)
        unsigned long addr;
        unsigned int tmp;
 
+       pr_notice("disabling ILSEL set %d\n", irq);
+
        addr = mk_ilsel_addr(irq);
 
        tmp = __raw_readw(addr);
index 102bf56..d682e2b 100644 (file)
@@ -1,9 +1,9 @@
 /*
- * arch/sh/boards/renesas/x3proto/setup.c
+ * arch/sh/boards/mach-x3proto/setup.c
  *
  * Renesas SH-X3 Prototype Board Support.
  *
- * Copyright (C) 2007 - 2008 Paul Mundt
+ * Copyright (C) 2007 - 2010  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
 #include <linux/smc91x.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/input.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/m66592.h>
-#include <asm/ilsel.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <mach/ilsel.h>
+#include <mach/hardware.h>
 #include <asm/smp-ops.h>
 
 static struct resource heartbeat_resources[] = {
@@ -122,15 +126,128 @@ static struct platform_device m66592_usb_peripheral_device = {
        .resource       = m66592_usb_peripheral_resources,
 };
 
+static struct gpio_keys_button baseboard_buttons[NR_BASEBOARD_GPIOS] = {
+       {
+               .desc           = "key44",
+               .code           = KEY_POWER,
+               .active_low     = 1,
+               .wakeup         = 1,
+       }, {
+               .desc           = "key43",
+               .code           = KEY_SUSPEND,
+               .active_low     = 1,
+               .wakeup         = 1,
+       }, {
+               .desc           = "key42",
+               .code           = KEY_KATAKANAHIRAGANA,
+               .active_low     = 1,
+       }, {
+               .desc           = "key41",
+               .code           = KEY_SWITCHVIDEOMODE,
+               .active_low     = 1,
+       }, {
+               .desc           = "key34",
+               .code           = KEY_F12,
+               .active_low     = 1,
+       }, {
+               .desc           = "key33",
+               .code           = KEY_F11,
+               .active_low     = 1,
+       }, {
+               .desc           = "key32",
+               .code           = KEY_F10,
+               .active_low     = 1,
+       }, {
+               .desc           = "key31",
+               .code           = KEY_F9,
+               .active_low     = 1,
+       }, {
+               .desc           = "key24",
+               .code           = KEY_F8,
+               .active_low     = 1,
+       }, {
+               .desc           = "key23",
+               .code           = KEY_F7,
+               .active_low     = 1,
+       }, {
+               .desc           = "key22",
+               .code           = KEY_F6,
+               .active_low     = 1,
+       }, {
+               .desc           = "key21",
+               .code           = KEY_F5,
+               .active_low     = 1,
+       }, {
+               .desc           = "key14",
+               .code           = KEY_F4,
+               .active_low     = 1,
+       }, {
+               .desc           = "key13",
+               .code           = KEY_F3,
+               .active_low     = 1,
+       }, {
+               .desc           = "key12",
+               .code           = KEY_F2,
+               .active_low     = 1,
+       }, {
+               .desc           = "key11",
+               .code           = KEY_F1,
+               .active_low     = 1,
+       },
+};
+
+static struct gpio_keys_platform_data baseboard_buttons_data = {
+       .buttons        = baseboard_buttons,
+       .nbuttons       = ARRAY_SIZE(baseboard_buttons),
+};
+
+static struct platform_device baseboard_buttons_device = {
+       .name           = "gpio-keys",
+       .id             = -1,
+       .dev            = {
+               .platform_data  = &baseboard_buttons_data,
+       },
+};
+
 static struct platform_device *x3proto_devices[] __initdata = {
        &heartbeat_device,
        &smc91x_device,
        &r8a66597_usb_host_device,
        &m66592_usb_peripheral_device,
+       &baseboard_buttons_device,
 };
 
+static void __init x3proto_init_irq(void)
+{
+       plat_irq_setup_pins(IRQ_MODE_IRL3210);
+
+       /* Set ICR0.LVLMODE */
+       __raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000);
+}
+
 static int __init x3proto_devices_setup(void)
 {
+       int ret, i;
+
+       /*
+        * IRLs are only needed for ILSEL mappings, so flip over the INTC
+        * pins at a later point to enable the GPIOs to settle.
+        */
+       x3proto_init_irq();
+
+       /*
+        * Now that ILSELs are available, set up the baseboard GPIOs.
+        */
+       ret = x3proto_gpio_setup();
+       if (unlikely(ret))
+               return ret;
+
+       /*
+        * Propagate dynamic GPIOs for the baseboard button device.
+        */
+       for (i = 0; i < ARRAY_SIZE(baseboard_buttons); i++)
+               baseboard_buttons[i].gpio = x3proto_gpio_chip.base + i;
+
        r8a66597_usb_host_resources[1].start =
                r8a66597_usb_host_resources[1].end = ilsel_enable(ILSEL_USBH_I);
 
@@ -145,14 +262,6 @@ static int __init x3proto_devices_setup(void)
 }
 device_initcall(x3proto_devices_setup);
 
-static void __init x3proto_init_irq(void)
-{
-       plat_irq_setup_pins(IRQ_MODE_IRL3210);
-
-       /* Set ICR0.LVLMODE */
-       __raw_writel(__raw_readl(0xfe410000) | (1 << 21), 0xfe410000);
-}
-
 static void __init x3proto_setup(char **cmdline_p)
 {
        register_smp_ops(&shx3_smp_ops);
@@ -161,5 +270,4 @@ static void __init x3proto_setup(char **cmdline_p)
 static struct sh_machine_vector mv_x3proto __initmv = {
        .mv_name                = "x3proto",
        .mv_setup               = x3proto_setup,
-       .mv_init_irq            = x3proto_init_irq,
 };
index 200c1d4..3e15032 100644 (file)
@@ -91,7 +91,9 @@ bss_start_addr:
 end_addr:
        .long   _end
 init_sr:
-       .long   0x400000F0      /* Privileged mode, Bank=0, Block=0, IMASK=0xF */
+       .long   0x500000F0      /* Privileged mode, Bank=0, Block=1, IMASK=0xF */
+kexec_magic:
+       .long   0x400000F0      /* magic used by kexec to parse zImage format */
 init_stack_addr:
        .long   stack_start
 decompress_kernel_addr:
index 9682e3a..59c3483 100644 (file)
@@ -1,3 +1,3 @@
 obj-$(CONFIG_HD64461)  += hd64461.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index 238d683..e533512 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index b3bf11b..67e1506 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index 3cdee4f..ec243ca 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
index 021633b..5fcb17b 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
index 365f231..e1077a0 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
index ca7fc1b..67cb109 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
 CONFIG_IPC_NS=y
index 45c18a3..496edcd 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
index d4268b1..029a506 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
index ad5d296..fac13de 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
index 14e658e..3670e93 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
index 6be7eaa..e3c0894 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_SLAB=y
index 4d61b77..9479872 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_AUDIT=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
index 0e32a24..f1d2e1b 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index c19fcdf..9ad904a 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index 984e3fe..f3d5d9f 100644 (file)
@@ -7,7 +7,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_AUDIT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index e8b5472..920b847 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
index fd88480..c77da6b 100644 (file)
@@ -8,7 +8,6 @@ CONFIG_RCU_TRACE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
index a42f7c2..a3d0810 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
index 742aa61..b1a04f3 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
index aed394d..ae11158 100644 (file)
@@ -6,7 +6,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=18
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
index 7a7e138..be9c474 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
index 3620a7f..1248635 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_BUG is not set
index fe22f59..c3ba6e8 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
 # CONFIG_BUG is not set
index b9b64c3..ae998c7 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
index 03e7367..ed35093 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_KALLSYMS is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
index 1a686b6..912c985 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
index 7e03451..75c92fc 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index 4cfc4de..c8c5e7f 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_KALLSYMS is not set
 # CONFIG_HOTPLUG is not set
 # CONFIG_EPOLL is not set
index b95dc76..2051821 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_SLAB=y
diff --git a/arch/sh/configs/sh2007_defconfig b/arch/sh/configs/sh2007_defconfig
new file mode 100644 (file)
index 0000000..0d2f414
--- /dev/null
@@ -0,0 +1,212 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_AUDIT=y
+CONFIG_AUDITSYSCALL=y
+CONFIG_IKCONFIG=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_SLAB=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_CPU_SUBTYPE_SH7780=y
+CONFIG_MEMORY_SIZE=0x08000000
+# CONFIG_VSYSCALL is not set
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_SH_SH2007=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SH_DMA=y
+CONFIG_SH_DMA_API=y
+CONFIG_NR_DMA_CHANNELS_BOOL=y
+CONFIG_HZ_100=y
+CONFIG_CMDLINE_OVERWRITE=y
+CONFIG_CMDLINE="console=ttySC1,115200 ip=dhcp root=/dev/nfs rw nfsroot=/nfs/rootfs,rsize=1024,wsize=1024 earlyprintk=sh-sci.1"
+CONFIG_PCCARD=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPIP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_NETWORK_SECMARK=y
+CONFIG_NET_PKTGEN=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_CDROM_PKTCDVD=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_RAID_ATTRS=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=y
+CONFIG_SCSI_SRP_ATTRS=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_EQUALIZER=y
+CONFIG_TUN=y
+CONFIG_VETH=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_SH_WDT=y
+CONFIG_SSB=y
+CONFIG_FB=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_LOGO=y
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_DMADEVICES=y
+CONFIG_TIMB_DMA=y
+CONFIG_EXT3_FS=y
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=932
+CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CONFIGFS_FS=y
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=y
+CONFIG_NLS_CODEPAGE_775=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_CODEPAGE_852=y
+CONFIG_NLS_CODEPAGE_855=y
+CONFIG_NLS_CODEPAGE_857=y
+CONFIG_NLS_CODEPAGE_860=y
+CONFIG_NLS_CODEPAGE_861=y
+CONFIG_NLS_CODEPAGE_862=y
+CONFIG_NLS_CODEPAGE_863=y
+CONFIG_NLS_CODEPAGE_864=y
+CONFIG_NLS_CODEPAGE_865=y
+CONFIG_NLS_CODEPAGE_866=y
+CONFIG_NLS_CODEPAGE_869=y
+CONFIG_NLS_CODEPAGE_936=y
+CONFIG_NLS_CODEPAGE_950=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_CODEPAGE_949=y
+CONFIG_NLS_CODEPAGE_874=y
+CONFIG_NLS_ISO8859_8=y
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_ISO8859_3=y
+CONFIG_NLS_ISO8859_4=y
+CONFIG_NLS_ISO8859_5=y
+CONFIG_NLS_ISO8859_6=y
+CONFIG_NLS_ISO8859_7=y
+CONFIG_NLS_ISO8859_9=y
+CONFIG_NLS_ISO8859_13=y
+CONFIG_NLS_ISO8859_14=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_KOI8_R=y
+CONFIG_NLS_KOI8_U=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SH_STANDARD_BIOS=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_XTS=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_SHA1=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_FCRYPT=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_SEED=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+CONFIG_LIBCRC32C=y
index b804641..f92ad17 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
diff --git a/arch/sh/configs/sh7757lcr_defconfig b/arch/sh/configs/sh7757lcr_defconfig
new file mode 100644 (file)
index 0000000..273f3fa
--- /dev/null
@@ -0,0 +1,85 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_CPU_SUBTYPE_SH7757=y
+CONFIG_MEMORY_START=0x40000000
+CONFIG_MEMORY_SIZE=0x0f000000
+CONFIG_PMB=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_SH_SH7757LCR=y
+CONFIG_HEARTBEAT=y
+CONFIG_SECCOMP=y
+CONFIG_CMDLINE_OVERWRITE=y
+CONFIG_CMDLINE="console=ttySC2,115200 root=/dev/nfs ip=dhcp"
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_INET_LRO is not set
+CONFIG_IPV6=y
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_FW_LOADER is not set
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_PHYLIB=y
+CONFIG_VITESSE_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_NR_UARTS=3
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_INOTIFY=y
+CONFIG_ISO9660_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_SQUASHFS=y
+CONFIG_MINIX_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_932=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DETECT_SOFTLOCKUP is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_FTRACE is not set
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
index 3618767..4795364 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
 CONFIG_IPC_NS=y
index ee6b81f..51561f5 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_SLAB=y
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
index bb4f60c..3f92d37 100644 (file)
@@ -15,7 +15,6 @@ CONFIG_CGROUP_DEVICE=y
 CONFIG_CGROUP_CPUACCT=y
 CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_MEM_RES_CTLR=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_NAMESPACES=y
 CONFIG_UTS_NS=y
index f38c983..7eae4e5 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_HOTPLUG is not set
index 7007d00..b58dfc5 100644 (file)
@@ -1,6 +1,5 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index 45c309f..0f55891 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 # CONFIG_SYSCTL_SYSCALL is not set
index e107d42..2d288b8 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_PROFILING=y
 CONFIG_MODULES=y
index 4a27722..f46848f 100644 (file)
@@ -412,8 +412,8 @@ EXPORT_SYMBOL(unregister_dmac);
 static int __init dma_api_init(void)
 {
        printk(KERN_NOTICE "DMA: Registering DMA API.\n");
-       create_proc_read_entry("dma", 0, 0, dma_read_proc, 0);
-       return 0;
+       return create_proc_read_entry("dma", 0, 0, dma_read_proc, 0)
+                   ? 0 : -ENOMEM;
 }
 subsys_initcall(dma_api_init);
 
index 4a59e68..82f0a33 100644 (file)
@@ -19,6 +19,7 @@ obj-$(CONFIG_SH_RTS7751R2D)           += fixups-rts7751r2d.o
 obj-$(CONFIG_SH_SH03)                  += fixups-sh03.o
 obj-$(CONFIG_SH_HIGHLANDER)            += fixups-r7780rp.o
 obj-$(CONFIG_SH_SH7785LCR)             += fixups-r7780rp.o
+obj-$(CONFIG_SH_SDK7786)               += fixups-sdk7786.o
 obj-$(CONFIG_SH_SDK7780)               += fixups-sdk7780.o
 obj-$(CONFIG_SH_7780_SOLUTION_ENGINE)  += fixups-sdk7780.o
 obj-$(CONFIG_SH_TITAN)                 += fixups-titan.o
diff --git a/arch/sh/drivers/pci/fixups-sdk7786.c b/arch/sh/drivers/pci/fixups-sdk7786.c
new file mode 100644 (file)
index 0000000..0e18ee3
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * SDK7786 FPGA PCIe mux handling
+ *
+ * Copyright (C) 2010  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.
+ */
+#define pr_fmt(fmt) "PCI: " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <mach/fpga.h>
+
+/*
+ * The SDK7786 FPGA supports mangling of most of the slots in some way or
+ * another. Slots 3/4 are special in that only one can be supported at a
+ * time, and both appear on port 3 to the PCI bus scan. Enabling slot 4
+ * (the horizontal edge connector) will disable slot 3 entirely.
+ *
+ * Misconfigurations can be detected through the FPGA via the slot
+ * resistors to determine card presence. Hotplug remains unsupported.
+ */
+static unsigned int slot4en __devinitdata;
+
+char *__devinit pcibios_setup(char *str)
+{
+       if (strcmp(str, "slot4en") == 0) {
+               slot4en = 1;
+               return NULL;
+       }
+
+       return str;
+}
+
+static int __init sdk7786_pci_init(void)
+{
+       u16 data = fpga_read_reg(PCIECR);
+
+       /*
+        * Enable slot #4 if it's been specified on the command line.
+        *
+        * Optionally reroute if slot #4 has a card present while slot #3
+        * does not, regardless of command line value.
+        *
+        * Card presence is logically inverted.
+        */
+       slot4en ?: (!(data & PCIECR_PRST4) && (data & PCIECR_PRST3));
+       if (slot4en) {
+               pr_info("Activating PCIe slot#4 (disabling slot#3)\n");
+
+               data &= ~PCIECR_PCIEMUX1;
+               fpga_write_reg(data, PCIECR);
+
+               /* Warn about forced rerouting if slot#3 is occupied */
+               if ((data & PCIECR_PRST3) == 0) {
+                       pr_warning("Unreachable card detected in slot#3\n");
+                       return -EBUSY;
+               }
+       } else
+               pr_info("PCIe slot#4 disabled\n");
+
+       return 0;
+}
+postcore_initcall(sdk7786_pci_init);
index 0b81999..b623420 100644 (file)
@@ -9,6 +9,7 @@
  */
 #include <linux/pci.h>
 #include <linux/io.h>
+#include <linux/spinlock.h>
 #include <asm/addrspace.h>
 #include "pci-sh4.h"
 
@@ -18,8 +19,6 @@
 #define CONFIG_CMD(bus, devfn, where) \
        (0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
 
-static DEFINE_SPINLOCK(sh4_pci_lock);
-
 /*
  * Functions for accessing PCI configuration space with type 1 accesses
  */
@@ -34,10 +33,10 @@ static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
         * PCIPDR may only be accessed as 32 bit words,
         * so we must do byte alignment by hand
         */
-       spin_lock_irqsave(&sh4_pci_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
        data = pci_read_reg(chan, SH4_PCIPDR);
-       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 
        switch (size) {
        case 1:
@@ -69,10 +68,10 @@ static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
        int shift;
        u32 data;
 
-       spin_lock_irqsave(&sh4_pci_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
        data = pci_read_reg(chan, SH4_PCIPDR);
-       spin_unlock_irqrestore(&sh4_pci_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
 
        switch (size) {
        case 1:
index 48f594b..1284210 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Generic SH7786 PCI-Express operations.
  *
- *  Copyright (C) 2009  Paul Mundt
+ *  Copyright (C) 2009 - 2010  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License v2. See the file "COPYING" in the main directory of this archive
@@ -19,37 +19,72 @@ enum {
        PCI_ACCESS_WRITE,
 };
 
-static DEFINE_SPINLOCK(sh7786_pcie_lock);
-
 static int sh7786_pcie_config_access(unsigned char access_type,
                struct pci_bus *bus, unsigned int devfn, int where, u32 *data)
 {
        struct pci_channel *chan = bus->sysdata;
-       int dev, func;
+       int dev, func, type, reg;
 
        dev = PCI_SLOT(devfn);
        func = PCI_FUNC(devfn);
+       type = !!bus->parent;
+       reg = where & ~3;
 
        if (bus->number > 255 || dev > 31 || func > 7)
                return PCIBIOS_FUNC_NOT_SUPPORTED;
-       if (devfn)
-               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /*
+        * While each channel has its own memory-mapped extended config
+        * space, it's generally only accessible when in endpoint mode.
+        * When in root complex mode, the controller is unable to target
+        * itself with either type 0 or type 1 accesses, and indeed, any
+        * controller initiated target transfer to its own config space
+        * result in a completer abort.
+        *
+        * Each channel effectively only supports a single device, but as
+        * the same channel <-> device access works for any PCI_SLOT()
+        * value, we cheat a bit here and bind the controller's config
+        * space to devfn 0 in order to enable self-enumeration. In this
+        * case the regular PAR/PDR path is sidelined and the mangled
+        * config access itself is initiated as a SuperHyway transaction.
+        */
+       if (pci_is_root_bus(bus)) {
+               if (dev == 0) {
+                       if (access_type == PCI_ACCESS_READ)
+                               *data = pci_read_reg(chan, PCI_REG(reg));
+                       else
+                               pci_write_reg(chan, *data, PCI_REG(reg));
+
+                       return PCIBIOS_SUCCESSFUL;
+               } else if (dev > 1)
+                       return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+
+       /* Clear errors */
+       pci_write_reg(chan, pci_read_reg(chan, SH4A_PCIEERRFR), SH4A_PCIEERRFR);
 
        /* Set the PIO address */
        pci_write_reg(chan, (bus->number << 24) | (dev << 19) |
-                               (func << 16) | (where & ~3), SH4A_PCIEPAR);
+                               (func << 16) | reg, SH4A_PCIEPAR);
 
        /* Enable the configuration access */
-       pci_write_reg(chan, (1 << 31), SH4A_PCIEPCTLR);
+       pci_write_reg(chan, (1 << 31) | (type << 8), SH4A_PCIEPCTLR);
+
+       /* Check for errors */
+       if (pci_read_reg(chan, SH4A_PCIEERRFR) & 0x10)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
+       /* Check for master and target aborts */
+       if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
+               return PCIBIOS_DEVICE_NOT_FOUND;
 
        if (access_type == PCI_ACCESS_READ)
                *data = pci_read_reg(chan, SH4A_PCIEPDR);
        else
                pci_write_reg(chan, *data, SH4A_PCIEPDR);
 
-       /* Check for master and target aborts */
-       if (pci_read_reg(chan, SH4A_PCIEPCICONF1) & ((1 << 29) | (1 << 28)))
-               return PCIBIOS_DEVICE_NOT_FOUND;
+       /* Disable the configuration access */
+       pci_write_reg(chan, 0, SH4A_PCIEPCTLR);
 
        return PCIBIOS_SUCCESSFUL;
 }
@@ -66,11 +101,13 @@ static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
        else if ((size == 4) && (where & 3))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       spin_lock_irqsave(&sh7786_pcie_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
                                        devfn, where, &data);
-       if (ret != PCIBIOS_SUCCESSFUL)
+       if (ret != PCIBIOS_SUCCESSFUL) {
+               *val = 0xffffffff;
                goto out;
+       }
 
        if (size == 1)
                *val = (data >> ((where & 3) << 3)) & 0xff;
@@ -84,7 +121,7 @@ static int sh7786_pcie_read(struct pci_bus *bus, unsigned int devfn,
                devfn, where, size, (unsigned long)*val);
 
 out:
-       spin_unlock_irqrestore(&sh7786_pcie_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
        return ret;
 }
 
@@ -100,7 +137,7 @@ static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
        else if ((size == 4) && (where & 3))
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
-       spin_lock_irqsave(&sh7786_pcie_lock, flags);
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
        ret = sh7786_pcie_config_access(PCI_ACCESS_READ, bus,
                                        devfn, where, &data);
        if (ret != PCIBIOS_SUCCESSFUL)
@@ -124,7 +161,7 @@ static int sh7786_pcie_write(struct pci_bus *bus, unsigned int devfn,
        ret = sh7786_pcie_config_access(PCI_ACCESS_WRITE, bus,
                                        devfn, where, &data);
 out:
-       spin_unlock_irqrestore(&sh7786_pcie_lock, flags);
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
        return ret;
 }
 
index f98141b..86adb1e 100644 (file)
@@ -81,7 +81,7 @@ static int __init sh7751_pci_init(void)
        unsigned int id;
        u32 word, reg;
 
-       printk(KERN_NOTICE "PCI: Starting intialization.\n");
+       printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
        chan->reg_base = 0xfe200000;
 
index ffdcbf1..edb7cca 100644 (file)
@@ -246,7 +246,7 @@ static int __init sh7780_pci_init(void)
        const char *type;
        int ret, i;
 
-       printk(KERN_NOTICE "PCI: Starting intialization.\n");
+       printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
        chan->reg_base = 0xfe040000;
 
index 205dcbe..1742e2c 100644 (file)
 #ifndef _PCI_SH7780_H_
 #define _PCI_SH7780_H_
 
-#define PCI_VENDOR_ID_RENESAS          0x1912
-#define PCI_DEVICE_ID_RENESAS_SH7781   0x0001
-#define PCI_DEVICE_ID_RENESAS_SH7780   0x0002
-#define PCI_DEVICE_ID_RENESAS_SH7763   0x0004
-#define PCI_DEVICE_ID_RENESAS_SH7785   0x0007
-
 /* SH7780 Control Registers */
 #define        PCIECR                  0xFE000008
 #define PCIECR_ENBL            0x01
index 1e9598d..60ee09a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/dma-debug.h>
 #include <linux/io.h>
 #include <linux/mutex.h>
+#include <linux/spinlock.h>
 
 unsigned long PCIBIOS_MIN_IO = 0x0000;
 unsigned long PCIBIOS_MIN_MEM = 0;
@@ -56,6 +57,11 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
        }
 }
 
+/*
+ * This interrupt-safe spinlock protects all accesses to PCI
+ * configuration space.
+ */
+DEFINE_RAW_SPINLOCK(pci_config_lock);
 static DEFINE_MUTEX(pci_scan_mutex);
 
 int __devinit register_pci_controller(struct pci_channel *hose)
@@ -233,40 +239,7 @@ void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
 
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
-       u16 cmd, old_cmd;
-       int idx;
-       struct resource *r;
-
-       pci_read_config_word(dev, PCI_COMMAND, &cmd);
-       old_cmd = cmd;
-       for (idx=0; idx < PCI_NUM_RESOURCES; idx++) {
-               /* Only set up the requested stuff */
-               if (!(mask & (1<<idx)))
-                       continue;
-
-               r = &dev->resource[idx];
-               if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
-                       continue;
-               if ((idx == PCI_ROM_RESOURCE) &&
-                               (!(r->flags & IORESOURCE_ROM_ENABLE)))
-                       continue;
-               if (!r->start && r->end) {
-                       printk(KERN_ERR "PCI: Device %s not available "
-                              "because of resource collisions\n",
-                              pci_name(dev));
-                       return -EINVAL;
-               }
-               if (r->flags & IORESOURCE_IO)
-                       cmd |= PCI_COMMAND_IO;
-               if (r->flags & IORESOURCE_MEM)
-                       cmd |= PCI_COMMAND_MEMORY;
-       }
-       if (cmd != old_cmd) {
-               printk("PCI: Enabling device %s (%04x -> %04x)\n",
-                      pci_name(dev), old_cmd, cmd);
-               pci_write_config_word(dev, PCI_COMMAND, cmd);
-       }
-       return 0;
+       return pci_enable_resources(dev, mask);
 }
 
 /*
@@ -295,7 +268,7 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq)
        pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
-char * __devinit pcibios_setup(char *str)
+char * __devinit __weak pcibios_setup(char *str)
 {
        return str;
 }
index 68cb9b0..96e9b05 100644 (file)
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
 #include "pcie-sh7786.h"
 #include <asm/sizes.h>
 
 struct sh7786_pcie_port {
        struct pci_channel      *hose;
+       struct clk              *fclk, phy_clk;
        unsigned int            index;
        int                     endpoint;
        int                     link;
@@ -51,6 +54,7 @@ static struct resource sh7786_pci0_resources[] = {
                .name   = "PCIe0 MEM 2",
                .start  = 0xfe100000,
                .end    = 0xfe100000 + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
        },
 };
 
@@ -74,6 +78,7 @@ static struct resource sh7786_pci1_resources[] = {
                .name   = "PCIe1 MEM 2",
                .start  = 0xfe300000,
                .end    = 0xfe300000 + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
        },
 };
 
@@ -82,6 +87,7 @@ static struct resource sh7786_pci2_resources[] = {
                .name   = "PCIe2 IO",
                .start  = 0xfc800000,
                .end    = 0xfc800000 + SZ_4M - 1,
+               .flags  = IORESOURCE_IO,
        }, {
                .name   = "PCIe2 MEM 0",
                .start  = 0x80000000,
@@ -96,6 +102,7 @@ static struct resource sh7786_pci2_resources[] = {
                .name   = "PCIe2 MEM 2",
                .start  = 0xfcd00000,
                .end    = 0xfcd00000 + SZ_1M - 1,
+               .flags  = IORESOURCE_MEM,
        },
 };
 
@@ -117,7 +124,29 @@ static struct pci_channel sh7786_pci_channels[] = {
        DEFINE_CONTROLLER(0xfcc00000, 2),
 };
 
-static int phy_wait_for_ack(struct pci_channel *chan)
+static struct clk fixed_pciexclkp = {
+       .rate = 100000000,      /* 100 MHz reference clock */
+};
+
+static void __devinit sh7786_pci_fixup(struct pci_dev *dev)
+{
+       /*
+        * Prevent enumeration of root complex resources.
+        */
+       if (pci_is_root_bus(dev->bus) && dev->devfn == 0) {
+               int i;
+
+               for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+                       dev->resource[i].start  = 0;
+                       dev->resource[i].end    = 0;
+                       dev->resource[i].flags  = 0;
+               }
+       }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786,
+                        sh7786_pci_fixup);
+
+static int __init phy_wait_for_ack(struct pci_channel *chan)
 {
        unsigned int timeout = 100;
 
@@ -131,7 +160,7 @@ static int phy_wait_for_ack(struct pci_channel *chan)
        return -ETIMEDOUT;
 }
 
-static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
+static int __init pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
 {
        unsigned int timeout = 100;
 
@@ -145,19 +174,14 @@ static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
        return -ETIMEDOUT;
 }
 
-static void phy_write_reg(struct pci_channel *chan, unsigned int addr,
-                         unsigned int lane, unsigned int data)
+static void __init phy_write_reg(struct pci_channel *chan, unsigned int addr,
+                                unsigned int lane, unsigned int data)
 {
-       unsigned long phyaddr, ctrl;
+       unsigned long phyaddr;
 
        phyaddr = (1 << BITS_CMD) + ((lane & 0xf) << BITS_LANE) +
                        ((addr & 0xff) << BITS_ADR);
 
-       /* Enable clock */
-       ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
-       ctrl |= (1 << BITS_CKE);
-       pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
-
        /* Set write data */
        pci_write_reg(chan, data, SH4A_PCIEPHYDOUTR);
        pci_write_reg(chan, phyaddr, SH4A_PCIEPHYADRR);
@@ -165,20 +189,74 @@ static void phy_write_reg(struct pci_channel *chan, unsigned int addr,
        phy_wait_for_ack(chan);
 
        /* Clear command */
+       pci_write_reg(chan, 0, SH4A_PCIEPHYDOUTR);
        pci_write_reg(chan, 0, SH4A_PCIEPHYADRR);
 
        phy_wait_for_ack(chan);
+}
 
-       /* Disable clock */
-       ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
-       ctrl &= ~(1 << BITS_CKE);
-       pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
+static int __init pcie_clk_init(struct sh7786_pcie_port *port)
+{
+       struct pci_channel *chan = port->hose;
+       struct clk *clk;
+       char fclk_name[16];
+       int ret;
+
+       /*
+        * First register the fixed clock
+        */
+       ret = clk_register(&fixed_pciexclkp);
+       if (unlikely(ret != 0))
+               return ret;
+
+       /*
+        * Grab the port's function clock, which the PHY clock depends
+        * on. clock lookups don't help us much at this point, since no
+        * dev_id is available this early. Lame.
+        */
+       snprintf(fclk_name, sizeof(fclk_name), "pcie%d_fck", port->index);
+
+       port->fclk = clk_get(NULL, fclk_name);
+       if (IS_ERR(port->fclk)) {
+               ret = PTR_ERR(port->fclk);
+               goto err_fclk;
+       }
+
+       clk_enable(port->fclk);
+
+       /*
+        * And now, set up the PHY clock
+        */
+       clk = &port->phy_clk;
+
+       memset(clk, 0, sizeof(struct clk));
+
+       clk->parent = &fixed_pciexclkp;
+       clk->enable_reg = (void __iomem *)(chan->reg_base + SH4A_PCIEPHYCTLR);
+       clk->enable_bit = BITS_CKE;
+
+       ret = sh_clk_mstp32_register(clk, 1);
+       if (unlikely(ret < 0))
+               goto err_phy;
+
+       return 0;
+
+err_phy:
+       clk_disable(port->fclk);
+       clk_put(port->fclk);
+err_fclk:
+       clk_unregister(&fixed_pciexclkp);
+
+       return ret;
 }
 
-static int phy_init(struct pci_channel *chan)
+static int __init phy_init(struct sh7786_pcie_port *port)
 {
+       struct pci_channel *chan = port->hose;
        unsigned int timeout = 100;
 
+       clk_enable(&port->phy_clk);
+
        /* Initialize the phy */
        phy_write_reg(chan, 0x60, 0xf, 0x004b008b);
        phy_write_reg(chan, 0x61, 0xf, 0x00007b41);
@@ -187,9 +265,13 @@ static int phy_init(struct pci_channel *chan)
        phy_write_reg(chan, 0x66, 0xf, 0x00000010);
        phy_write_reg(chan, 0x74, 0xf, 0x0007001c);
        phy_write_reg(chan, 0x79, 0xf, 0x01fc000d);
+       phy_write_reg(chan, 0xb0, 0xf, 0x00000610);
 
        /* Deassert Standby */
-       phy_write_reg(chan, 0x67, 0xf, 0x00000400);
+       phy_write_reg(chan, 0x67, 0x1, 0x00000400);
+
+       /* Disable clock */
+       clk_disable(&port->phy_clk);
 
        while (timeout--) {
                if (pci_read_reg(chan, SH4A_PCIEPHYSR))
@@ -201,22 +283,33 @@ static int phy_init(struct pci_channel *chan)
        return -ETIMEDOUT;
 }
 
-static int pcie_init(struct sh7786_pcie_port *port)
+static void __init pcie_reset(struct sh7786_pcie_port *port)
+{
+       struct pci_channel *chan = port->hose;
+
+       pci_write_reg(chan, 1, SH4A_PCIESRSTR);
+       pci_write_reg(chan, 0, SH4A_PCIETCTLR);
+       pci_write_reg(chan, 0, SH4A_PCIESRSTR);
+       pci_write_reg(chan, 0, SH4A_PCIETXVC0SR);
+}
+
+static int __init pcie_init(struct sh7786_pcie_port *port)
 {
        struct pci_channel *chan = port->hose;
        unsigned int data;
        phys_addr_t memphys;
        size_t memsize;
-       int ret, i;
+       int ret, i, win;
 
        /* Begin initialization */
-       pci_write_reg(chan, 0, SH4A_PCIETCTLR);
+       pcie_reset(port);
 
-       /* Initialize as type1. */
-       data = pci_read_reg(chan, SH4A_PCIEPCICONF3);
-       data &= ~(0x7f << 16);
-       data |= PCI_HEADER_TYPE_BRIDGE << 16;
-       pci_write_reg(chan, data, SH4A_PCIEPCICONF3);
+       /*
+        * Initial header for port config space is type 1, set the device
+        * class to match. Hardware takes care of propagating the IDSETR
+        * settings, so there is no need to bother with a quirk.
+        */
+       pci_write_reg(chan, PCI_CLASS_BRIDGE_PCI << 16, SH4A_PCIEIDSETR1);
 
        /* Initialize default capabilities. */
        data = pci_read_reg(chan, SH4A_PCIEEXPCAP0);
@@ -268,30 +361,33 @@ static int pcie_init(struct sh7786_pcie_port *port)
         * LAR1/LAMR1.
         */
        if (memsize > SZ_512M) {
-               __raw_writel(memphys + SZ_512M, chan->reg_base + SH4A_PCIELAR1);
-               __raw_writel(((memsize - SZ_512M) - SZ_256) | 1,
-                            chan->reg_base + SH4A_PCIELAMR1);
+               pci_write_reg(chan, memphys + SZ_512M, SH4A_PCIELAR1);
+               pci_write_reg(chan, ((memsize - SZ_512M) - SZ_256) | 1,
+                             SH4A_PCIELAMR1);
                memsize = SZ_512M;
        } else {
                /*
                 * Otherwise just zero it out and disable it.
                 */
-               __raw_writel(0, chan->reg_base + SH4A_PCIELAR1);
-               __raw_writel(0, chan->reg_base + SH4A_PCIELAMR1);
+               pci_write_reg(chan, 0, SH4A_PCIELAR1);
+               pci_write_reg(chan, 0, SH4A_PCIELAMR1);
        }
 
        /*
         * LAR0/LAMR0 covers up to the first 512MB, which is enough to
         * cover all of lowmem on most platforms.
         */
-       __raw_writel(memphys, chan->reg_base + SH4A_PCIELAR0);
-       __raw_writel((memsize - SZ_256) | 1, chan->reg_base + SH4A_PCIELAMR0);
+       pci_write_reg(chan, memphys, SH4A_PCIELAR0);
+       pci_write_reg(chan, (memsize - SZ_256) | 1, SH4A_PCIELAMR0);
 
        /* Finish initialization */
        data = pci_read_reg(chan, SH4A_PCIETCTLR);
        data |= 0x1;
        pci_write_reg(chan, data, SH4A_PCIETCTLR);
 
+       /* Let things settle down a bit.. */
+       mdelay(100);
+
        /* Enable DL_Active Interrupt generation */
        data = pci_read_reg(chan, SH4A_PCIEDLINTENR);
        data |= PCIEDLINTENR_DLL_ACT_ENABLE;
@@ -302,9 +398,12 @@ static int pcie_init(struct sh7786_pcie_port *port)
        data |= PCIEMACCTLR_SCR_DIS | (0xff << 16);
        pci_write_reg(chan, data, SH4A_PCIEMACCTLR);
 
+       /*
+        * This will timeout if we don't have a link, but we permit the
+        * port to register anyways in order to support hotplug on future
+        * hardware.
+        */
        ret = pci_wait_for_irq(chan, MASK_INT_TX_CTRL);
-       if (unlikely(ret != 0))
-               return -ENODEV;
 
        data = pci_read_reg(chan, SH4A_PCIEPCICONF1);
        data &= ~(PCI_STATUS_DEVSEL_MASK << 16);
@@ -317,35 +416,48 @@ static int pcie_init(struct sh7786_pcie_port *port)
 
        wmb();
 
-       data = pci_read_reg(chan, SH4A_PCIEMACSR);
-       printk(KERN_NOTICE "PCI: PCIe#%d link width %d\n",
-              port->index, (data >> 20) & 0x3f);
-
+       if (ret == 0) {
+               data = pci_read_reg(chan, SH4A_PCIEMACSR);
+               printk(KERN_NOTICE "PCI: PCIe#%d x%d link detected\n",
+                      port->index, (data >> 20) & 0x3f);
+       } else
+               printk(KERN_NOTICE "PCI: PCIe#%d link down\n",
+                      port->index);
 
-       for (i = 0; i < chan->nr_resources; i++) {
+       for (i = win = 0; i < chan->nr_resources; i++) {
                struct resource *res = chan->resources + i;
                resource_size_t size;
-               u32 enable_mask;
+               u32 mask;
 
-               pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(i));
+               /*
+                * We can't use the 32-bit mode windows in legacy 29-bit
+                * mode, so just skip them entirely.
+                */
+               if ((res->flags & IORESOURCE_MEM_32BIT) && __in_29bit_mode())
+                       continue;
 
-               size = resource_size(res);
+               pci_write_reg(chan, 0x00000000, SH4A_PCIEPTCTLR(win));
 
                /*
                 * The PAMR mask is calculated in units of 256kB, which
                 * keeps things pretty simple.
                 */
-               __raw_writel(((roundup_pow_of_two(size) / SZ_256K) - 1) << 18,
-                            chan->reg_base + SH4A_PCIEPAMR(i));
+               size = resource_size(res);
+               mask = (roundup_pow_of_two(size) / SZ_256K) - 1;
+               pci_write_reg(chan, mask << 18, SH4A_PCIEPAMR(win));
 
-               pci_write_reg(chan, 0x00000000, SH4A_PCIEPARH(i));
-               pci_write_reg(chan, 0x00000000, SH4A_PCIEPARL(i));
+               pci_write_reg(chan, upper_32_bits(res->start),
+                             SH4A_PCIEPARH(win));
+               pci_write_reg(chan, lower_32_bits(res->start),
+                             SH4A_PCIEPARL(win));
 
-               enable_mask = MASK_PARE;
+               mask = MASK_PARE;
                if (res->flags & IORESOURCE_IO)
-                       enable_mask |= MASK_SPC;
+                       mask |= MASK_SPC;
+
+               pci_write_reg(chan, mask, SH4A_PCIEPTCTLR(win));
 
-               pci_write_reg(chan, enable_mask, SH4A_PCIEPTCTLR(i));
+               win++;
        }
 
        return 0;
@@ -356,26 +468,33 @@ int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin)
         return 71;
 }
 
-static int sh7786_pcie_core_init(void)
+static int __init sh7786_pcie_core_init(void)
 {
        /* Return the number of ports */
        return test_mode_pin(MODE_PIN12) ? 3 : 2;
 }
 
-static int __devinit sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
+static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
 {
        int ret;
 
-       ret = phy_init(port->hose);
-       if (unlikely(ret < 0))
-               return ret;
-
        /*
         * Check if we are configured in endpoint or root complex mode,
         * this is a fixed pin setting that applies to all PCIe ports.
         */
        port->endpoint = test_mode_pin(MODE_PIN11);
 
+       /*
+        * Setup clocks, needed both for PHY and PCIe registers.
+        */
+       ret = pcie_clk_init(port);
+       if (unlikely(ret < 0))
+               return ret;
+
+       ret = phy_init(port);
+       if (unlikely(ret < 0))
+               return ret;
+
        ret = pcie_init(port);
        if (unlikely(ret < 0))
                return ret;
@@ -390,9 +509,10 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
 
 static int __init sh7786_pcie_init(void)
 {
+       struct clk *platclk;
        int ret = 0, i;
 
-       printk(KERN_NOTICE "PCI: Starting intialization.\n");
+       printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
        sh7786_pcie_hwops = &sh7786_65nm_pcie_hwops;
 
@@ -407,6 +527,22 @@ static int __init sh7786_pcie_init(void)
        if (unlikely(!sh7786_pcie_ports))
                return -ENOMEM;
 
+       /*
+        * Fetch any optional platform clock associated with this block.
+        *
+        * This is a rather nasty hack for boards with spec-mocking FPGAs
+        * that have a secondary set of clocks outside of the on-chip
+        * ones that need to be accounted for before there is any chance
+        * of touching the existing MSTP bits or CPG clocks.
+        */
+       platclk = clk_get(NULL, "pcie_plat_clk");
+       if (IS_ERR(platclk)) {
+               /* Sane hardware should probably get a WARN_ON.. */
+               platclk = NULL;
+       }
+
+       clk_enable(platclk);
+
        printk(KERN_NOTICE "PCI: probing %d ports.\n", nr_ports);
 
        for (i = 0; i < nr_ports; i++) {
@@ -419,8 +555,11 @@ static int __init sh7786_pcie_init(void)
                ret |= sh7786_pcie_hwops->port_init_hw(port);
        }
 
-       if (unlikely(ret))
+       if (unlikely(ret)) {
+               clk_disable(platclk);
+               clk_put(platclk);
                return ret;
+       }
 
        return 0;
 }
index 90a6992..1ee054e 100644 (file)
 #define                BITS_ERRRCV     (0)             /* 0 ERRRCV 0 */
 #define                MASK_ERRRCV     (1<<BITS_ERRRCV)
 
+/*     PCIEENBLR        */
+#define        SH4A_PCIEENBLR          (0x000008)      /* R/W - 0x0000 0001 32 */
+
 /*     PCIEECR         */
-#define        SH4A_PCIEECR            (0x000008)      /* R/W - 0x0000 0000 32 */
+#define        SH4A_PCIEECR            (0x00000C)      /* R/W - 0x0000 0000 32 */
 #define                BITS_ENBL       (0)     /* 0 ENBL 0 R/W */
 #define                MASK_ENBL       (1<<BITS_ENBL)
 
 #define                BITS_MDATA      (0)
 #define                MASK_MDATA      (0xffffffff<<BITS_MDATA)
 
+/*     PCIEUNLOCKCR    */
+#define        SH4A_PCIEUNLOCKCR       (0x000048)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIEIDR         */
+#define        SH4A_PCIEIDR            (0x000060)      /* R/W - 0x0101 1101 32 */
+
+/*     PCIEDBGCTLR     */
+#define        SH4A_PCIEDBGCTLR        (0x000100)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIEINTXR       */
+#define        SH4A_PCIEINTXR          (0x004000)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIERMSGR       */
+#define        SH4A_PCIERMSGR          (0x004010)      /* R/W - 0x0000 0000 32 */
+
+/*     PCIERSTR        */
+#define SH4A_PCIERSTR(x)       (0x008000 + ((x) * 0x4)) /* R/W - 0x0000 0000 32 */
+
+/*     PCIESRSTR        */
+#define SH4A_PCIESRSTR         (0x008040)      /* R/W - 0x0000 0000 32 */
+
 /*     PCIEPHYCTLR     */
 #define        SH4A_PCIEPHYCTLR        (0x010000)      /* R/W - 0x0000 0000 32 */
 #define                BITS_CKE        (0)
 /*     PCIERMSGIER     */
 #define        SH4A_PCIERMSGIER        (0x004040)      /* R/W - 0x0000 0000 32 */
 
+/*     PCIEPHYCTLR     */
+#define SH4A_PCIEPHYCTLR       (0x010000)      /* R/W - 0x0000 0000 32 */
+
 /*     PCIEPHYADRR     */
 #define        SH4A_PCIEPHYADRR        (0x010004)      /* R/W - 0x0000 0000 32 */
 #define                BITS_ACK        (24)                    // Rev1.171
 #define                MASK_CFINT      (1<<BITS_CFINT)
 
 /*     PCIETSTR        */
-#define        SH4A_PCIETSTR           (0x020004)      /* R/W R/W 0x0000 0000 32  */
+#define        SH4A_PCIETSTR           (0x020004)      /* R 0x0000 0000 32  */
 
 /*     PCIEINTR        */
 #define        SH4A_PCIEINTR           (0x020008)      /* R/W R/W 0x0000 0000 32  */
 #define                BITS_INTPM                      (8)
 #define                MASK_INTPM                      (1<<BITS_INTPM)
 
+/*     PCIEEH0R        */
+#define SH4A_PCIEEHR(x)                (0x020010 + ((x) * 0x4)) /* R - 0x0000 0000 32 */
+
 /*     PCIEAIR  */
 #define        SH4A_PCIEAIR            (SH4A_PCIE_BASE + 0x020010)     /* R/W R/W 0xxxxx xxxx 32 */
 
 
 /*      PCIEERRFR       */                                                             // Rev1.18
 #define        SH4A_PCIEERRFR          (0x020020)              /* R/W R/W 0xxxxx xxxx 32 */    // Rev1.18
+
+/*     PCIEERRFER      */
+#define SH4A_PCIEERRFER                (0x020024)              /* R/W R/W 0x0000 0000 32 */
+
+/*     PCIEERRFR2      */
+#define SH4A_PCIEERRFR2                (0x020028)              /* R/W R/W 0x0000 0000 32 */
+
+/*     PCIEMSIR        */
+#define SH4A_PCIEMSIR          (0x020040)              /* R/W - 0x0000 0000 32 */
+
+/*     PCIEMSIFR       */
+#define SH4A_PCIEMSIFR         (0x020044)              /* R/W R/W 0x0000 0000 32 */
+
+/*     PCIEPWRCTLR     */
+#define SH4A_PCIEPWRCTLR       (0x020100)              /* R/W - 0x0000 0000 32 */
+
+/*     PCIEPCCTLR      */
+#define SH4A_PCIEPCCTLR                (0x020180)              /* R/W - 0x0000 0000 32 */
+
                                                                                        // Rev1.18
 /*     PCIELAR0        */
 #define        SH4A_PCIELAR0           (0x020200)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCCR0         (0x021120)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCC2R0        (0x021124)      /* R/W R/W 0x0000 0000 - */
 #define        SH4A_PCIEDMCCCR0        (0x021128)      /* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR0       (0x02112C)      /* R/W - 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAR1         (0x021140)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAHR1        (0x021144)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMDAR1         (0x021148)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCCR1         (0x021160)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCC2R1        (0x021164)      /* R/W R/W 0x0000 0000 - */
 #define        SH4A_PCIEDMCCCR1        (0x021168)      /* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR1       (0x02116C)      /* R/W - 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAR2         (0x021180)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMSAHR2        (0x021184)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMDAR2         (0x021188)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCCR3         (0x0211E0)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEDMCC2R3        (0x0211E4)      /* R/W R/W 0x0000 0000 -  */
 #define        SH4A_PCIEDMCCCR3        (0x0211E8)      /* R/W R/W 0x0000 0000 32 */
+#define SH4A_PCIEDMCHSR3       (0x0211EC)      /* R/W R/W 0x0000 0000 32 */
 #define        SH4A_PCIEPCICONF0       (0x040000)      /* R R - 8/16/32 */
 #define        SH4A_PCIEPCICONF1       (0x040004)      /* R/W R/W 0x0008 0000 8/16/32 */
 #define        SH4A_PCIEPCICONF2       (0x040008)      /* R/W R/W 0xFF00 0000 8/16/32 */
index 0eed47b..7beb423 100644 (file)
@@ -5,5 +5,7 @@ header-y += cpu-features.h
 header-y += hw_breakpoint.h
 header-y += posix_types_32.h
 header-y += posix_types_64.h
+header-y += ptrace_32.h
+header-y += ptrace_64.h
 header-y += unistd_32.h
 header-y += unistd_64.h
index ce830fa..f38112b 100644 (file)
 #define        R_SH_GOTPC              167
 
 /* FDPIC relocs */
-#define R_SH_GOT20             70
-#define R_SH_GOTOFF20          71
-#define R_SH_GOTFUNCDESC       72
-#define R_SH_GOTFUNCDESC20     73
-#define R_SH_GOTOFFFUNCDESC    74
-#define R_SH_GOTOFFFUNCDESC20  75
-#define R_SH_FUNCDESC          76
-#define R_SH_FUNCDESC_VALUE    77
-
-#if 0 /* XXX - later .. */
-#define R_SH_GOT20             198
-#define R_SH_GOTOFF20          199
-#define R_SH_GOTFUNCDESC       200
-#define R_SH_GOTFUNCDESC20     201
-#define R_SH_GOTOFFFUNCDESC    202
-#define R_SH_GOTOFFFUNCDESC20  203
-#define R_SH_FUNCDESC          204
-#define R_SH_FUNCDESC_VALUE    205
-#endif
+#define R_SH_GOT20             201
+#define R_SH_GOTOFF20          202
+#define R_SH_GOTFUNCDESC       203
+#define R_SH_GOTFUNCDESC20     204
+#define R_SH_GOTOFFFUNCDESC    205
+#define R_SH_GOTOFFFUNCDESC20  206
+#define R_SH_FUNCDESC          207
+#define R_SH_FUNCDESC_VALUE    208
 
 /* SHmedia relocs */
 #define R_SH_IMM_LOW16         246
index 6e7cea4..bd7e79a 100644 (file)
@@ -58,7 +58,7 @@ enum fixed_addresses {
 
 #ifdef CONFIG_HIGHMEM
        FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
-       FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+       FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1,
 #endif
 
 #ifdef CONFIG_IOREMAP_FIXED
@@ -69,7 +69,7 @@ enum fixed_addresses {
         */
 #define FIX_N_IOREMAPS 32
        FIX_IOREMAP_BEGIN,
-       FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS,
+       FIX_IOREMAP_END = FIX_IOREMAP_BEGIN + FIX_N_IOREMAPS - 1,
 #endif
 
        __end_of_fixed_addresses
index f8d9a73..04f53d3 100644 (file)
@@ -41,14 +41,12 @@ static inline int gpio_cansleep(unsigned gpio)
 
 static inline int gpio_to_irq(unsigned gpio)
 {
-       WARN_ON(1);
-       return -ENOSYS;
+       return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
 {
-       WARN_ON(1);
-       return -EINVAL;
+       return -ENOSYS;
 }
 
 #endif /* CONFIG_GPIOLIB */
diff --git a/arch/sh/include/asm/ilsel.h b/arch/sh/include/asm/ilsel.h
deleted file mode 100644 (file)
index e3d304b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef __ASM_SH_ILSEL_H
-#define __ASM_SH_ILSEL_H
-
-typedef enum {
-       ILSEL_NONE,
-       ILSEL_LAN,
-       ILSEL_USBH_I,
-       ILSEL_USBH_S,
-       ILSEL_USBH_V,
-       ILSEL_RTC,
-       ILSEL_USBP_I,
-       ILSEL_USBP_S,
-       ILSEL_USBP_V,
-       ILSEL_KEY,
-
-       /*
-        * ILSEL Aliases - corner cases for interleaved level tables.
-        *
-        * Someone thought this was a good idea and less hassle than
-        * demuxing a shared vector, really.
-        */
-
-       /* ILSEL0 and 2 */
-       ILSEL_FPGA0,
-       ILSEL_FPGA1,
-       ILSEL_EX1,
-       ILSEL_EX2,
-       ILSEL_EX3,
-       ILSEL_EX4,
-
-       /* ILSEL1 and 3 */
-       ILSEL_FPGA2 = ILSEL_FPGA0,
-       ILSEL_FPGA3 = ILSEL_FPGA1,
-       ILSEL_EX5 = ILSEL_EX1,
-       ILSEL_EX6 = ILSEL_EX2,
-       ILSEL_EX7 = ILSEL_EX3,
-       ILSEL_EX8 = ILSEL_EX4,
-} ilsel_source_t;
-
-/* arch/sh/boards/renesas/x3proto/ilsel.c */
-int ilsel_enable(ilsel_source_t set);
-int ilsel_enable_fixed(ilsel_source_t set, unsigned int level);
-void ilsel_disable(unsigned int irq);
-
-#endif /* __ASM_SH_ILSEL_H */
index 02c2f01..45d08b6 100644 (file)
@@ -9,7 +9,7 @@
  * advised to cap this at the hard limit that they're interested in
  * through the machvec.
  */
-#define NR_IRQS                        256
+#define NR_IRQS                        512
 #define NR_IRQS_LEGACY         8       /* Legacy external IRQ0-7 */
 
 /*
index 036c331..134f398 100644 (file)
@@ -16,7 +16,6 @@ typedef insn_size_t kprobe_opcode_t;
        ? (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
 
index 8bd952f..f0efe97 100644 (file)
@@ -37,6 +37,8 @@ struct pci_channel {
 };
 
 /* arch/sh/drivers/pci/pci.c */
+extern raw_spinlock_t pci_config_lock;
+
 extern int register_pci_controller(struct pci_channel *hose);
 extern void pcibios_report_status(unsigned int status_mask, int warn);
 
index 61a445d..46d5179 100644 (file)
@@ -13,7 +13,6 @@
 #include <linux/linkage.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/ptrace.h>
 #include <asm/hw_breakpoint.h>
 
 /*
@@ -194,8 +193,6 @@ 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])
-
 #if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH4)
 #define PREFETCH_STRIDE                L1_CACHE_BYTES
 #define ARCH_HAS_PREFETCH
index 621bc46..2a541dd 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/compiler.h>
 #include <asm/page.h>
 #include <asm/types.h>
-#include <asm/ptrace.h>
 #include <cpu/registers.h>
 
 /*
@@ -231,7 +230,5 @@ 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)->regs[15])
-
 #endif /* __ASSEMBLY__ */
 #endif /* __ASM_SH_PROCESSOR_64_H */
index 2168fde..f6edc10 100644 (file)
@@ -3,90 +3,7 @@
 
 /*
  * Copyright (C) 1999, 2000  Niibe Yutaka
- *
- */
-#if defined(__SH5__)
-struct pt_regs {
-       unsigned long long pc;
-       unsigned long long sr;
-       long long syscall_nr;
-       unsigned long long regs[63];
-       unsigned long long tregs[8];
-       unsigned long long pad[2];
-};
-#else
-/*
- * GCC defines register number like this:
- * -----------------------------
- *      0 - 15 are integer registers
- *     17 - 22 are control/special registers
- *     24 - 39 fp registers
- *     40 - 47 xd registers
- *     48 -    fpscr register
- * -----------------------------
- *
- * We follows above, except:
- *     16 --- program counter (PC)
- *     22 --- syscall #
- *     23 --- floating point communication register
  */
-#define REG_REG0        0
-#define REG_REG15      15
-
-#define REG_PC         16
-
-#define REG_PR         17
-#define REG_SR         18
-#define REG_GBR                19
-#define REG_MACH       20
-#define REG_MACL       21
-
-#define REG_SYSCALL    22
-
-#define REG_FPREG0     23
-#define REG_FPREG15    38
-#define REG_XFREG0     39
-#define REG_XFREG15    54
-
-#define REG_FPSCR      55
-#define REG_FPUL       56
-
-/*
- * This struct defines the way the registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_regs {
-       unsigned long regs[16];
-       unsigned long pc;
-       unsigned long pr;
-       unsigned long sr;
-       unsigned long gbr;
-       unsigned long mach;
-       unsigned long macl;
-       long tra;
-};
-
-/*
- * This struct defines the way the DSP registers are stored on the
- * kernel stack during a system call or other kernel entry.
- */
-struct pt_dspregs {
-       unsigned long   a1;
-       unsigned long   a0g;
-       unsigned long   a1g;
-       unsigned long   m0;
-       unsigned long   m1;
-       unsigned long   a0;
-       unsigned long   x0;
-       unsigned long   x1;
-       unsigned long   y0;
-       unsigned long   y1;
-       unsigned long   dsr;
-       unsigned long   rs;
-       unsigned long   re;
-       unsigned long   mod;
-};
-#endif
 
 #define PTRACE_GETREGS         12      /* General registers */
 #define PTRACE_SETREGS         13
@@ -107,22 +24,102 @@ struct pt_dspregs {
 #define PT_DATA_ADDR           248     /* &(struct user)->start_data */
 #define PT_TEXT_LEN            252
 
+#if defined(__SH5__) || defined(CONFIG_CPU_SH5)
+#include "ptrace_64.h"
+#else
+#include "ptrace_32.h"
+#endif
+
 #ifdef __KERNEL__
+
+#include <linux/stringify.h>
+#include <linux/stddef.h>
+#include <linux/thread_info.h>
 #include <asm/addrspace.h>
 #include <asm/page.h>
 #include <asm/system.h>
 
 #define user_mode(regs)                        (((regs)->sr & 0x40000000)==0)
+#define user_stack_pointer(regs)       ((unsigned long)(regs)->regs[15])
+#define kernel_stack_pointer(regs)     ((unsigned long)(regs)->regs[15])
 #define instruction_pointer(regs)      ((unsigned long)(regs)->pc)
 
 extern void show_regs(struct pt_regs *);
 
+#define arch_has_single_step() (1)
+
 /*
- * These are defined as per linux/ptrace.h.
+ * kprobe-based event tracer support
  */
-struct task_struct;
+struct pt_regs_offset {
+       const char *name;
+       int offset;
+};
 
-#define arch_has_single_step() (1)
+#define REG_OFFSET_NAME(r) {.name = #r, .offset = offsetof(struct pt_regs, r)}
+#define REGS_OFFSET_NAME(num)  \
+       {.name = __stringify(r##num), .offset = offsetof(struct pt_regs, regs[num])}
+#define TREGS_OFFSET_NAME(num) \
+       {.name = __stringify(tr##num), .offset = offsetof(struct pt_regs, tregs[num])}
+#define REG_OFFSET_END {.name = NULL, .offset = 0}
+
+/* Query offset/name of register from its name/offset */
+extern int regs_query_register_offset(const char *name);
+extern const char *regs_query_register_name(unsigned int offset);
+
+extern const struct pt_regs_offset regoffset_table[];
+
+/**
+ * regs_get_register() - get register value from its offset
+ * @regs:      pt_regs from which register value is gotten.
+ * @offset:    offset number of the register.
+ *
+ * regs_get_register returns the value of a register. The @offset is the
+ * offset of the register in struct pt_regs address which specified by @regs.
+ * If @offset is bigger than MAX_REG_OFFSET, this returns 0.
+ */
+static inline unsigned long regs_get_register(struct pt_regs *regs,
+                                             unsigned int offset)
+{
+       if (unlikely(offset > MAX_REG_OFFSET))
+               return 0;
+       return *(unsigned long *)((unsigned long)regs + offset);
+}
+
+/**
+ * regs_within_kernel_stack() - check the address in the stack
+ * @regs:      pt_regs which contains kernel stack pointer.
+ * @addr:      address which is checked.
+ *
+ * regs_within_kernel_stack() checks @addr is within the kernel stack page(s).
+ * If @addr is within the kernel stack, it returns true. If not, returns false.
+ */
+static inline int regs_within_kernel_stack(struct pt_regs *regs,
+                                          unsigned long addr)
+{
+       return ((addr & ~(THREAD_SIZE - 1))  ==
+               (kernel_stack_pointer(regs) & ~(THREAD_SIZE - 1)));
+}
+
+/**
+ * regs_get_kernel_stack_nth() - get Nth entry of the stack
+ * @regs:      pt_regs which contains kernel stack pointer.
+ * @n:         stack entry number.
+ *
+ * regs_get_kernel_stack_nth() returns @n th entry of the kernel stack which
+ * is specified by @regs. If the @n th entry is NOT in the kernel stack,
+ * this returns 0.
+ */
+static inline unsigned long regs_get_kernel_stack_nth(struct pt_regs *regs,
+                                                     unsigned int n)
+{
+       unsigned long *addr = (unsigned long *)kernel_stack_pointer(regs);
+       addr += n;
+       if (regs_within_kernel_stack(regs, (unsigned long)addr))
+               return *addr;
+       else
+               return 0;
+}
 
 struct perf_event;
 struct perf_sample_data;
diff --git a/arch/sh/include/asm/ptrace_32.h b/arch/sh/include/asm/ptrace_32.h
new file mode 100644 (file)
index 0000000..35d9e25
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __ASM_SH_PTRACE_32_H
+#define __ASM_SH_PTRACE_32_H
+
+/*
+ * GCC defines register number like this:
+ * -----------------------------
+ *      0 - 15 are integer registers
+ *     17 - 22 are control/special registers
+ *     24 - 39 fp registers
+ *     40 - 47 xd registers
+ *     48 -    fpscr register
+ * -----------------------------
+ *
+ * We follows above, except:
+ *     16 --- program counter (PC)
+ *     22 --- syscall #
+ *     23 --- floating point communication register
+ */
+#define REG_REG0        0
+#define REG_REG15      15
+
+#define REG_PC         16
+
+#define REG_PR         17
+#define REG_SR         18
+#define REG_GBR                19
+#define REG_MACH       20
+#define REG_MACL       21
+
+#define REG_SYSCALL    22
+
+#define REG_FPREG0     23
+#define REG_FPREG15    38
+#define REG_XFREG0     39
+#define REG_XFREG15    54
+
+#define REG_FPSCR      55
+#define REG_FPUL       56
+
+/*
+ * This struct defines the way the registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_regs {
+       unsigned long regs[16];
+       unsigned long pc;
+       unsigned long pr;
+       unsigned long sr;
+       unsigned long gbr;
+       unsigned long mach;
+       unsigned long macl;
+       long tra;
+};
+
+/*
+ * This struct defines the way the DSP registers are stored on the
+ * kernel stack during a system call or other kernel entry.
+ */
+struct pt_dspregs {
+       unsigned long   a1;
+       unsigned long   a0g;
+       unsigned long   a1g;
+       unsigned long   m0;
+       unsigned long   m1;
+       unsigned long   a0;
+       unsigned long   x0;
+       unsigned long   x1;
+       unsigned long   y0;
+       unsigned long   y1;
+       unsigned long   dsr;
+       unsigned long   rs;
+       unsigned long   re;
+       unsigned long   mod;
+};
+
+#ifdef __KERNEL__
+
+#define MAX_REG_OFFSET         offsetof(struct pt_regs, tra)
+#define regs_return_value(regs)        ((regs)->regs[0])
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_PTRACE_32_H */
diff --git a/arch/sh/include/asm/ptrace_64.h b/arch/sh/include/asm/ptrace_64.h
new file mode 100644 (file)
index 0000000..d43c1cb
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef __ASM_SH_PTRACE_64_H
+#define __ASM_SH_PTRACE_64_H
+
+struct pt_regs {
+       unsigned long long pc;
+       unsigned long long sr;
+       long long syscall_nr;
+       unsigned long long regs[63];
+       unsigned long long tregs[8];
+       unsigned long long pad[2];
+};
+
+#ifdef __KERNEL__
+
+#define MAX_REG_OFFSET         offsetof(struct pt_regs, tregs[7])
+#define regs_return_value(regs)        ((regs)->regs[3])
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_SH_PTRACE_64_H */
index 3a1fb97..0b9fe2d 100644 (file)
@@ -32,6 +32,7 @@
 #define SZ_512                         0x00000200
 
 #define SZ_1K                           0x00000400
+#define SZ_2K                           0x00000800
 #define SZ_4K                           0x00001000
 #define SZ_8K                           0x00002000
 #define SZ_16K                          0x00004000
diff --git a/arch/sh/include/asm/sram.h b/arch/sh/include/asm/sram.h
new file mode 100644 (file)
index 0000000..a2808ce
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __ASM_SRAM_H
+#define __ASM_SRAM_H
+
+#ifdef CONFIG_HAVE_SRAM_POOL
+
+#include <linux/spinlock.h>
+#include <linux/genalloc.h>
+
+/* arch/sh/mm/sram.c */
+extern struct gen_pool *sram_pool;
+
+static inline unsigned long sram_alloc(size_t len)
+{
+       if (!sram_pool)
+               return 0UL;
+
+       return gen_pool_alloc(sram_pool, len);
+}
+
+static inline void sram_free(unsigned long addr, size_t len)
+{
+       return gen_pool_free(sram_pool, addr, len);
+}
+
+#else
+
+static inline unsigned long sram_alloc(size_t len)
+{
+       return 0;
+}
+
+static inline void sram_free(unsigned long addr, size_t len)
+{
+}
+
+#endif /* CONFIG_HAVE_SRAM_POOL */
+
+#endif /* __ASM_SRAM_H */
index 0bd7a17..1f1af5a 100644 (file)
@@ -140,8 +140,6 @@ extern unsigned int instruction_size(unsigned int insn);
 extern unsigned long cached_to_uncached;
 extern unsigned long uncached_size;
 
-extern struct dentry *sh_debugfs_root;
-
 void per_cpu_trap_init(void);
 void default_idle(void);
 void cpu_idle_wait(void);
index 51296b3..c941b27 100644 (file)
@@ -212,17 +212,16 @@ static inline reg_size_t register_align(void *val)
 }
 
 int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma, int);
+                           struct mem_access *ma, int, unsigned long address);
 
 static inline void trigger_address_error(void)
 {
-       if (__in_29bit_mode())
-               __asm__ __volatile__ (
-                       "ldc %0, sr\n\t"
-                       "mov.l @%1, %0"
-                       :
-                       : "r" (0x10000000), "r" (0x80000001)
-               );
+       __asm__ __volatile__ (
+               "ldc %0, sr\n\t"
+               "mov.l @%1, %0"
+               :
+               : "r" (0x10000000), "r" (0x80000001)
+       );
 }
 
 asmlinkage void do_address_error(struct pt_regs *regs,
index e0ac972..0df66f0 100644 (file)
@@ -21,6 +21,8 @@ extern void local_flush_tlb_kernel_range(unsigned long start,
                                         unsigned long end);
 extern void local_flush_tlb_one(unsigned long asid, unsigned long page);
 
+extern void __flush_tlb_global(void);
+
 #ifdef CONFIG_SMP
 
 extern void flush_tlb_all(void);
index 0e7f0fc..903cd61 100644 (file)
 #define __NR_pwritev           334
 #define __NR_rt_tgsigqueueinfo 335
 #define __NR_perf_event_open   336
+#define __NR_fanotify_init     337
+#define __NR_fanotify_mark     338
+#define __NR_prlimit64         339
 
-#define NR_syscalls 337
+/* Non-multiplexed socket family */
+#define __NR_socket            340
+#define __NR_bind              341
+#define __NR_connect           342
+#define __NR_listen            343
+#define __NR_accept            344
+#define __NR_getsockname       345
+#define __NR_getpeername       346
+#define __NR_socketpair                347
+#define __NR_send              348
+#define __NR_sendto            349
+#define __NR_recv              350
+#define __NR_recvfrom          351
+#define __NR_shutdown          352
+#define __NR_setsockopt                353
+#define __NR_getsockopt                354
+#define __NR_sendmsg           355
+#define __NR_recvmsg           356
+#define __NR_recvmmsg          357
 
-#ifdef __KERNEL__
+#define NR_syscalls 358
 
-#define __IGNORE_recvmmsg
+#ifdef __KERNEL__
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 0580c33..09aa93f 100644 (file)
 #define __NR_perf_event_open   364
 #define __NR_recvmmsg          365
 #define __NR_accept4           366
+#define __NR_fanotify_init     367
+#define __NR_fanotify_mark     368
+#define __NR_prlimit64         369
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 367
+#define NR_syscalls 370
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index ab09da7..0c7c735 100644 (file)
@@ -16,6 +16,7 @@
 #define MMU_TEA                0xFFFFFFFC      /* TLB Exception Address */
 
 #define MMUCR          0xFFFFFFE0      /* MMU Control Register */
+#define MMUCR_TI       (1 << 2)        /* TLB flush bit */
 
 #define MMU_TLB_ADDRESS_ARRAY  0xF2000000
 #define MMU_PAGE_ASSOC_BIT     0x80
index e1e9096..cffd25e 100644 (file)
@@ -56,7 +56,9 @@
 #define FRQCR1                 0xffc40004
 #define FRQMR1                 0xffc40014
 #elif defined(CONFIG_CPU_SUBTYPE_SHX3)
-#define FRQCR                  0xffc00014
+#define FRQCR0                 0xffc00000
+#define FRQCR1                 0xffc00004
+#define FRQMR1                 0xffc00014
 #else
 #define FRQCR                  0xffc00000
 #define FRQCR_PSTBY            0x0200
index f4d267e..15f3de1 100644 (file)
 
 enum {
        /* PTA */
-       GPIO_PTA7, GPIO_PTA6, GPIO_PTA5, GPIO_PTA4,
-       GPIO_PTA3, GPIO_PTA2, GPIO_PTA1, GPIO_PTA0,
+       GPIO_PTA0, GPIO_PTA1, GPIO_PTA2, GPIO_PTA3,
+       GPIO_PTA4, GPIO_PTA5, GPIO_PTA6, GPIO_PTA7,
 
        /* PTB */
-       GPIO_PTB7, GPIO_PTB6, GPIO_PTB5, GPIO_PTB4,
-       GPIO_PTB3, GPIO_PTB2, GPIO_PTB1, GPIO_PTB0,
+       GPIO_PTB0, GPIO_PTB1, GPIO_PTB2, GPIO_PTB3,
+       GPIO_PTB4, GPIO_PTB5, GPIO_PTB6, GPIO_PTB7,
 
        /* PTC */
-       GPIO_PTC7, GPIO_PTC6, GPIO_PTC5, GPIO_PTC4,
-       GPIO_PTC3, GPIO_PTC2, GPIO_PTC1, GPIO_PTC0,
+       GPIO_PTC0, GPIO_PTC1, GPIO_PTC2, GPIO_PTC3,
+       GPIO_PTC4, GPIO_PTC5, GPIO_PTC6, GPIO_PTC7,
 
        /* PTD */
-       GPIO_PTD7, GPIO_PTD6, GPIO_PTD5, GPIO_PTD4,
-       GPIO_PTD3, GPIO_PTD2, GPIO_PTD1, GPIO_PTD0,
+       GPIO_PTD0, GPIO_PTD1, GPIO_PTD2, GPIO_PTD3,
+       GPIO_PTD4, GPIO_PTD5, GPIO_PTD6, GPIO_PTD7,
 
        /* PTE */
-       GPIO_PTE7, GPIO_PTE6, GPIO_PTE5, GPIO_PTE4,
-       GPIO_PTE3, GPIO_PTE2, GPIO_PTE1, GPIO_PTE0,
+       GPIO_PTE0, GPIO_PTE1, GPIO_PTE2, GPIO_PTE3,
+       GPIO_PTE4, GPIO_PTE5, GPIO_PTE6, GPIO_PTE7,
 
        /* PTF */
-       GPIO_PTF7, GPIO_PTF6, GPIO_PTF5, GPIO_PTF4,
-       GPIO_PTF3, GPIO_PTF2, GPIO_PTF1, GPIO_PTF0,
+       GPIO_PTF0, GPIO_PTF1, GPIO_PTF2, GPIO_PTF3,
+       GPIO_PTF4, GPIO_PTF5, GPIO_PTF6, GPIO_PTF7,
 
        /* PTG */
-       GPIO_PTG7, GPIO_PTG6, GPIO_PTG5, GPIO_PTG4,
-       GPIO_PTG3, GPIO_PTG2, GPIO_PTG1, GPIO_PTG0,
+       GPIO_PTG0, GPIO_PTG1, GPIO_PTG2, GPIO_PTG3,
+       GPIO_PTG4, GPIO_PTG5, GPIO_PTG6, GPIO_PTG7,
 
        /* PTH */
-       GPIO_PTH7, GPIO_PTH6, GPIO_PTH5, GPIO_PTH4,
-       GPIO_PTH3, GPIO_PTH2, GPIO_PTH1, GPIO_PTH0,
+       GPIO_PTH0, GPIO_PTH1, GPIO_PTH2, GPIO_PTH3,
+       GPIO_PTH4, GPIO_PTH5, GPIO_PTH6, GPIO_PTH7,
 
        /* PTI */
-       GPIO_PTI7, GPIO_PTI6, GPIO_PTI5, GPIO_PTI4,
-       GPIO_PTI3, GPIO_PTI2, GPIO_PTI1, GPIO_PTI0,
+       GPIO_PTI0, GPIO_PTI1, GPIO_PTI2, GPIO_PTI3,
+       GPIO_PTI4, GPIO_PTI5, GPIO_PTI6, GPIO_PTI7,
 
        /* PTJ */
-       GPIO_PTJ7, GPIO_PTJ6, GPIO_PTJ5, GPIO_PTJ4,
-       GPIO_PTJ3, GPIO_PTJ2, GPIO_PTJ1, GPIO_PTJ0,
+       GPIO_PTJ0, GPIO_PTJ1, GPIO_PTJ2, GPIO_PTJ3,
+       GPIO_PTJ4, GPIO_PTJ5, GPIO_PTJ6, GPIO_PTJ7_RESV,
 
        /* PTK */
-       GPIO_PTK7, GPIO_PTK6, GPIO_PTK5, GPIO_PTK4,
-       GPIO_PTK3, GPIO_PTK2, GPIO_PTK1, GPIO_PTK0,
+       GPIO_PTK0, GPIO_PTK1, GPIO_PTK2, GPIO_PTK3,
+       GPIO_PTK4, GPIO_PTK5, GPIO_PTK6, GPIO_PTK7,
 
        /* PTL */
-       GPIO_PTL7, GPIO_PTL6, GPIO_PTL5, GPIO_PTL4,
-       GPIO_PTL3, GPIO_PTL2, GPIO_PTL1, GPIO_PTL0,
+       GPIO_PTL0, GPIO_PTL1, GPIO_PTL2, GPIO_PTL3,
+       GPIO_PTL4, GPIO_PTL5, GPIO_PTL6, GPIO_PTL7_RESV,
 
        /* PTM */
-                  GPIO_PTM6, GPIO_PTM5, GPIO_PTM4,
-       GPIO_PTM3, GPIO_PTM2, GPIO_PTM1, GPIO_PTM0,
+       GPIO_PTM0, GPIO_PTM1, GPIO_PTM2, GPIO_PTM3,
+       GPIO_PTM4, GPIO_PTM5, GPIO_PTM6, GPIO_PTM7,
 
        /* PTN */
-       GPIO_PTN7, GPIO_PTN6, GPIO_PTN5, GPIO_PTN4,
-       GPIO_PTN3, GPIO_PTN2, GPIO_PTN1, GPIO_PTN0,
+       GPIO_PTN0, GPIO_PTN1, GPIO_PTN2, GPIO_PTN3,
+       GPIO_PTN4, GPIO_PTN5, GPIO_PTN6, GPIO_PTN7_RESV,
 
        /* PTO */
-       GPIO_PTO7, GPIO_PTO6, GPIO_PTO5, GPIO_PTO4,
-       GPIO_PTO3, GPIO_PTO2, GPIO_PTO1, GPIO_PTO0,
+       GPIO_PTO0, GPIO_PTO1, GPIO_PTO2, GPIO_PTO3,
+       GPIO_PTO4, GPIO_PTO5, GPIO_PTO6, GPIO_PTO7,
 
        /* PTP */
-                  GPIO_PTP6, GPIO_PTP5, GPIO_PTP4,
-       GPIO_PTP3, GPIO_PTP2, GPIO_PTP1, GPIO_PTP0,
+       GPIO_PTP0, GPIO_PTP1, GPIO_PTP2, GPIO_PTP3,
+       GPIO_PTP4, GPIO_PTP5, GPIO_PTP6, GPIO_PTP7,
 
        /* PTQ */
-                  GPIO_PTQ6, GPIO_PTQ5, GPIO_PTQ4,
-       GPIO_PTQ3, GPIO_PTQ2, GPIO_PTQ1, GPIO_PTQ0,
+       GPIO_PTQ0, GPIO_PTQ1, GPIO_PTQ2, GPIO_PTQ3,
+       GPIO_PTQ4, GPIO_PTQ5, GPIO_PTQ6, GPIO_PTQ7_RESV,
 
        /* PTR */
-       GPIO_PTR7, GPIO_PTR6, GPIO_PTR5, GPIO_PTR4,
-       GPIO_PTR3, GPIO_PTR2, GPIO_PTR1, GPIO_PTR0,
+       GPIO_PTR0, GPIO_PTR1, GPIO_PTR2, GPIO_PTR3,
+       GPIO_PTR4, GPIO_PTR5, GPIO_PTR6, GPIO_PTR7,
 
        /* PTS */
-       GPIO_PTS7, GPIO_PTS6, GPIO_PTS5, GPIO_PTS4,
-       GPIO_PTS3, GPIO_PTS2, GPIO_PTS1, GPIO_PTS0,
+       GPIO_PTS0, GPIO_PTS1, GPIO_PTS2, GPIO_PTS3,
+       GPIO_PTS4, GPIO_PTS5, GPIO_PTS6, GPIO_PTS7,
 
        /* PTT */
-                             GPIO_PTT5, GPIO_PTT4,
-       GPIO_PTT3, GPIO_PTT2, GPIO_PTT1, GPIO_PTT0,
+       GPIO_PTT0, GPIO_PTT1, GPIO_PTT2, GPIO_PTT3,
+       GPIO_PTT4, GPIO_PTT5, GPIO_PTT6, GPIO_PTT7,
 
        /* PTU */
-       GPIO_PTU7, GPIO_PTU6, GPIO_PTU5, GPIO_PTU4,
-       GPIO_PTU3, GPIO_PTU2, GPIO_PTU1, GPIO_PTU0,
+       GPIO_PTU0, GPIO_PTU1, GPIO_PTU2, GPIO_PTU3,
+       GPIO_PTU4, GPIO_PTU5, GPIO_PTU6, GPIO_PTU7,
 
        /* PTV */
-       GPIO_PTV7, GPIO_PTV6, GPIO_PTV5, GPIO_PTV4,
-       GPIO_PTV3, GPIO_PTV2, GPIO_PTV1, GPIO_PTV0,
+       GPIO_PTV0, GPIO_PTV1, GPIO_PTV2, GPIO_PTV3,
+       GPIO_PTV4, GPIO_PTV5, GPIO_PTV6, GPIO_PTV7,
 
        /* PTW */
-       GPIO_PTW7, GPIO_PTW6, GPIO_PTW5, GPIO_PTW4,
-       GPIO_PTW3, GPIO_PTW2, GPIO_PTW1, GPIO_PTW0,
+       GPIO_PTW0, GPIO_PTW1, GPIO_PTW2, GPIO_PTW3,
+       GPIO_PTW4, GPIO_PTW5, GPIO_PTW6, GPIO_PTW7,
 
        /* PTX */
-       GPIO_PTX7, GPIO_PTX6, GPIO_PTX5, GPIO_PTX4,
-       GPIO_PTX3, GPIO_PTX2, GPIO_PTX1, GPIO_PTX0,
+       GPIO_PTX0, GPIO_PTX1, GPIO_PTX2, GPIO_PTX3,
+       GPIO_PTX4, GPIO_PTX5, GPIO_PTX6, GPIO_PTX7,
 
        /* PTY */
-       GPIO_PTY7, GPIO_PTY6, GPIO_PTY5, GPIO_PTY4,
-       GPIO_PTY3, GPIO_PTY2, GPIO_PTY1, GPIO_PTY0,
+       GPIO_PTY0, GPIO_PTY1, GPIO_PTY2, GPIO_PTY3,
+       GPIO_PTY4, GPIO_PTY5, GPIO_PTY6, GPIO_PTY7,
 
        /* PTZ */
-       GPIO_PTZ7, GPIO_PTZ6, GPIO_PTZ5, GPIO_PTZ4,
-       GPIO_PTZ3, GPIO_PTZ2, GPIO_PTZ1, GPIO_PTZ0,
+       GPIO_PTZ0, GPIO_PTZ1, GPIO_PTZ2, GPIO_PTZ3,
+       GPIO_PTZ4, GPIO_PTZ5, GPIO_PTZ6, GPIO_PTZ7,
 
 
-       /* PTA (mobule: LBSC, CPG, LPC) */
+       /* PTA (mobule: LBSC, RGMII) */
        GPIO_FN_BS,     GPIO_FN_RDWR,   GPIO_FN_WE1,    GPIO_FN_RDY,
-       GPIO_FN_MD10,   GPIO_FN_MD9,    GPIO_FN_MD8,
-       GPIO_FN_LGPIO7, GPIO_FN_LGPIO6, GPIO_FN_LGPIO5, GPIO_FN_LGPIO4,
-       GPIO_FN_LGPIO3, GPIO_FN_LGPIO2, GPIO_FN_LGPIO1, GPIO_FN_LGPIO0,
-
-       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
-       GPIO_FN_D15,    GPIO_FN_D14,    GPIO_FN_D13,    GPIO_FN_D12,
-       GPIO_FN_D11,    GPIO_FN_D10,    GPIO_FN_D9,     GPIO_FN_D8,
-       GPIO_FN_ET0_MDC,                GPIO_FN_ET0_MDIO,
-       GPIO_FN_ET1_MDC,                GPIO_FN_ET1_MDIO,
-       GPIO_FN_SIM_D,  GPIO_FN_SIM_CLK,                GPIO_FN_SIM_RST,
-       GPIO_FN_WPSZ1,  GPIO_FN_WPSZ0,  GPIO_FN_FWID,   GPIO_FN_FLSHSZ,
-       GPIO_FN_LPC_SPIEN,              GPIO_FN_BASEL,
+       GPIO_FN_ET0_MDC,        GPIO_FN_ET0_MDIO,
+       GPIO_FN_ET1_MDC,        GPIO_FN_ET1_MDIO,
 
-       /* PTC (mobule: SD) */
-       GPIO_FN_SD_WP,  GPIO_FN_SD_CD,  GPIO_FN_SD_CLK, GPIO_FN_SD_CMD,
-       GPIO_FN_SD_D3,  GPIO_FN_SD_D2,  GPIO_FN_SD_D1,  GPIO_FN_SD_D0,
+       /* PTB (mobule: INTC, ONFI, TMU) */
+       GPIO_FN_IRQ15,  GPIO_FN_IRQ14,  GPIO_FN_IRQ13,  GPIO_FN_IRQ12,
+       GPIO_FN_IRQ11,  GPIO_FN_IRQ10,  GPIO_FN_IRQ9,   GPIO_FN_IRQ8,
+       GPIO_FN_ON_NRE, GPIO_FN_ON_NWE, GPIO_FN_ON_NWP, GPIO_FN_ON_NCE0,
+       GPIO_FN_ON_R_B0,        GPIO_FN_ON_ALE, GPIO_FN_ON_CLE,
+       GPIO_FN_TCLK,
 
-       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       /* PTC (mobule: IRQ, PWMU) */
        GPIO_FN_IRQ7,   GPIO_FN_IRQ6,   GPIO_FN_IRQ5,   GPIO_FN_IRQ4,
        GPIO_FN_IRQ3,   GPIO_FN_IRQ2,   GPIO_FN_IRQ1,   GPIO_FN_IRQ0,
-       GPIO_FN_MD6,    GPIO_FN_MD5,    GPIO_FN_MD3,    GPIO_FN_MD2,
-       GPIO_FN_MD1,    GPIO_FN_MD0,    GPIO_FN_ADTRG1, GPIO_FN_ADTRG0,
-
-       /* PTE (mobule: EtherC) */
-       GPIO_FN_ET0_CRS_DV,             GPIO_FN_ET0_TXD1,
-       GPIO_FN_ET0_TXD0,               GPIO_FN_ET0_TX_EN,
-       GPIO_FN_ET0_REF_CLK,            GPIO_FN_ET0_RXD1,
-       GPIO_FN_ET0_RXD0,               GPIO_FN_ET0_RX_ER,
-
-       /* PTF (mobule: EtherC) */
-       GPIO_FN_ET1_CRS_DV,             GPIO_FN_ET1_TXD1,
-       GPIO_FN_ET1_TXD0,               GPIO_FN_ET1_TX_EN,
-       GPIO_FN_ET1_REF_CLK,            GPIO_FN_ET1_RXD1,
-       GPIO_FN_ET1_RXD0,               GPIO_FN_ET1_RX_ER,
-
-       /* PTG (mobule: SYSTEM, PWMX, LPC) */
-       GPIO_FN_STATUS0,                GPIO_FN_STATUS1,
-       GPIO_FN_PWX0,   GPIO_FN_PWX1,   GPIO_FN_PWX2,   GPIO_FN_PWX3,
-       GPIO_FN_SERIRQ, GPIO_FN_CLKRUN, GPIO_FN_LPCPD,  GPIO_FN_LDRQ,
-
-       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
-       GPIO_FN_TCLK,   GPIO_FN_RXD4,   GPIO_FN_TXD4,
+       GPIO_FN_PWMU0,  GPIO_FN_PWMU1,  GPIO_FN_PWMU2,  GPIO_FN_PWMU3,
+       GPIO_FN_PWMU4,  GPIO_FN_PWMU5,
+
+       /* PTD (mobule: SPI0, DMAC) */
+       GPIO_FN_SP0_MOSI,       GPIO_FN_SP0_MISO,       GPIO_FN_SP0_SCK,
+       GPIO_FN_SP0_SCK_FB,     GPIO_FN_SP0_SS0,        GPIO_FN_SP0_SS1,
+       GPIO_FN_SP0_SS2,        GPIO_FN_SP0_SS3,        GPIO_FN_DREQ0,
+       GPIO_FN_DACK0,          GPIO_FN_TEND0,
+
+       /* PTE (mobule: RMII) */
+       GPIO_FN_RMII0_CRS_DV,   GPIO_FN_RMII0_TXD1,     GPIO_FN_RMII0_TXD0,
+       GPIO_FN_RMII0_TXEN,     GPIO_FN_RMII0_REFCLK,   GPIO_FN_RMII0_RXD1,
+       GPIO_FN_RMII0_RXD0,     GPIO_FN_RMII0_RX_ER,
+
+       /* PTF (mobule: RMII, SerMux) */
+       GPIO_FN_RMII1_CRS_DV,   GPIO_FN_RMII1_TXD1,     GPIO_FN_RMII1_TXD0,
+       GPIO_FN_RMII1_TXEN,     GPIO_FN_RMII1_REFCLK,   GPIO_FN_RMII1_RXD1,
+       GPIO_FN_RMII1_RXD0,     GPIO_FN_RMII1_RX_ER,    GPIO_FN_RAC_RI,
+
+       /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */
+       GPIO_FN_BOOTFMS,                GPIO_FN_BOOTWP,
+       GPIO_FN_A25,    GPIO_FN_A24,    GPIO_FN_SERIRQ, GPIO_FN_WDTOVF,
+       GPIO_FN_LPCPD,  GPIO_FN_LDRQ,   GPIO_FN_MMCCLK, GPIO_FN_MMCCMD,
+
+       /* PTH (mobule: SPI1, LPC, DMAC, ADC) */
        GPIO_FN_SP1_MOSI,               GPIO_FN_SP1_MISO,
        GPIO_FN_SP1_SCK,                GPIO_FN_SP1_SCK_FB,
        GPIO_FN_SP1_SS0,                GPIO_FN_SP1_SS1,
-       GPIO_FN_SP0_SS1,
-
-       /* PTI (mobule: INTC) */
-       GPIO_FN_IRQ15,  GPIO_FN_IRQ14,  GPIO_FN_IRQ13,  GPIO_FN_IRQ12,
-       GPIO_FN_IRQ11,  GPIO_FN_IRQ10,  GPIO_FN_IRQ9,   GPIO_FN_IRQ8,
-
-       /* PTJ (mobule: SCIF234, SERMUX) */
-       GPIO_FN_RXD3,   GPIO_FN_TXD3,   GPIO_FN_RXD2,   GPIO_FN_TXD2,
-       GPIO_FN_COM1_TXD,               GPIO_FN_COM1_RXD,
-       GPIO_FN_COM1_RTS,               GPIO_FN_COM1_CTS,
-
-       /* PTK (mobule: SERMUX) */
-       GPIO_FN_COM2_TXD,               GPIO_FN_COM2_RXD,
-       GPIO_FN_COM2_RTS,               GPIO_FN_COM2_CTS,
-       GPIO_FN_COM2_DTR,               GPIO_FN_COM2_DSR,
-       GPIO_FN_COM2_DCD,               GPIO_FN_COM2_RI,
+       GPIO_FN_WP,     GPIO_FN_FMS0,   GPIO_FN_TEND1,  GPIO_FN_DREQ1,
+       GPIO_FN_DACK1,  GPIO_FN_ADTRG1, GPIO_FN_ADTRG0,
 
-       /* PTL (mobule: SERMUX) */
-       GPIO_FN_RAC_TXD,                GPIO_FN_RAC_RXD,
-       GPIO_FN_RAC_RTS,                GPIO_FN_RAC_CTS,
-       GPIO_FN_RAC_DTR,                GPIO_FN_RAC_DSR,
-       GPIO_FN_RAC_DCD,                GPIO_FN_RAC_RI,
+       /* PTI (mobule: LBSC, SDHI) */
+       GPIO_FN_D15,    GPIO_FN_D14,    GPIO_FN_D13,    GPIO_FN_D12,
+       GPIO_FN_D11,    GPIO_FN_D10,    GPIO_FN_D9,     GPIO_FN_D8,
+       GPIO_FN_SD_WP,  GPIO_FN_SD_CD,  GPIO_FN_SD_CLK, GPIO_FN_SD_CMD,
+       GPIO_FN_SD_D3,  GPIO_FN_SD_D2,  GPIO_FN_SD_D1,  GPIO_FN_SD_D0,
 
-       /* PTM (mobule: IIC, LPC) */
+       /* PTJ (mobule: SCIF234) */
+       GPIO_FN_RTS3,   GPIO_FN_CTS3,   GPIO_FN_TXD3,   GPIO_FN_RXD3,
+       GPIO_FN_RTS4,   GPIO_FN_RXD4,   GPIO_FN_TXD4,
+
+       /* PTK (mobule: SERMUX, LBSC, SCIF) */
+       GPIO_FN_COM2_TXD,       GPIO_FN_COM2_RXD,       GPIO_FN_COM2_RTS,
+       GPIO_FN_COM2_CTS,       GPIO_FN_COM2_DTR,       GPIO_FN_COM2_DSR,
+       GPIO_FN_COM2_DCD,       GPIO_FN_CLKOUT,
+       GPIO_FN_SCK2,           GPIO_FN_SCK4,   GPIO_FN_SCK3,
+
+       /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */
+       GPIO_FN_RAC_RXD,        GPIO_FN_RAC_RTS,        GPIO_FN_RAC_CTS,
+       GPIO_FN_RAC_DTR,        GPIO_FN_RAC_DSR,        GPIO_FN_RAC_DCD,
+       GPIO_FN_RAC_TXD,        GPIO_FN_RXD2,           GPIO_FN_CS5,
+       GPIO_FN_CS6,            GPIO_FN_AUDSYNC,        GPIO_FN_AUDCK,
+       GPIO_FN_TXD2,
+
+       /* PTM (mobule: LBSC, IIC) */
+       GPIO_FN_CS4,    GPIO_FN_RD,     GPIO_FN_WE0,    GPIO_FN_CS0,
        GPIO_FN_SDA6,   GPIO_FN_SCL6,   GPIO_FN_SDA7,   GPIO_FN_SCL7,
-       GPIO_FN_WP,     GPIO_FN_FMS0,   GPIO_FN_FMS1,
-
-       /* PTN (mobule: SCIF234, EVC) */
-       GPIO_FN_SCK2,   GPIO_FN_RTS4,   GPIO_FN_RTS3,   GPIO_FN_RTS2,
-       GPIO_FN_CTS4,   GPIO_FN_CTS3,   GPIO_FN_CTS2,
-       GPIO_FN_EVENT7, GPIO_FN_EVENT6, GPIO_FN_EVENT5, GPIO_FN_EVENT4,
-       GPIO_FN_EVENT3, GPIO_FN_EVENT2, GPIO_FN_EVENT1, GPIO_FN_EVENT0,
 
-       /* PTO (mobule: SGPIO) */
-       GPIO_FN_SGPIO0_CLK,             GPIO_FN_SGPIO0_LOAD,
-       GPIO_FN_SGPIO0_DI,              GPIO_FN_SGPIO0_DO,
-       GPIO_FN_SGPIO1_CLK,             GPIO_FN_SGPIO1_LOAD,
-       GPIO_FN_SGPIO1_DI,              GPIO_FN_SGPIO1_DO,
+       /* PTN (mobule: USB, JMC, SGPIO, WDT) */
+       GPIO_FN_VBUS_EN,        GPIO_FN_VBUS_OC,        GPIO_FN_JMCTCK,
+       GPIO_FN_JMCTMS,         GPIO_FN_JMCTDO,         GPIO_FN_JMCTDI,
+       GPIO_FN_JMCTRST,
+       GPIO_FN_SGPIO1_CLK,     GPIO_FN_SGPIO1_LOAD,    GPIO_FN_SGPIO1_DI,
+       GPIO_FN_SGPIO1_DO,      GPIO_FN_SUB_CLKIN,
 
-       /* PTP (mobule: JMC, SCIF234) */
-       GPIO_FN_JMCTCK, GPIO_FN_JMCTMS, GPIO_FN_JMCTDO, GPIO_FN_JMCTDI,
-       GPIO_FN_JMCRST, GPIO_FN_SCK4,   GPIO_FN_SCK3,
+       /* PTO (mobule: SGPIO, SerMux) */
+       GPIO_FN_SGPIO0_CLK,     GPIO_FN_SGPIO0_LOAD,    GPIO_FN_SGPIO0_DI,
+       GPIO_FN_SGPIO0_DO,      GPIO_FN_SGPIO2_CLK,     GPIO_FN_SGPIO2_LOAD,
+       GPIO_FN_SGPIO2_DI,      GPIO_FN_SGPIO2_DO,      GPIO_FN_COM1_TXD,
+       GPIO_FN_COM1_RXD,       GPIO_FN_COM1_RTS,       GPIO_FN_COM1_CTS,
 
        /* PTQ (mobule: LPC) */
        GPIO_FN_LAD3,   GPIO_FN_LAD2,   GPIO_FN_LAD1,   GPIO_FN_LAD0,
        GPIO_FN_LFRAME, GPIO_FN_LRESET, GPIO_FN_LCLK,
 
        /* PTR (mobule: GRA, IIC) */
-       GPIO_FN_DDC3,   GPIO_FN_DDC2,
-       GPIO_FN_SDA8,   GPIO_FN_SCL8,   GPIO_FN_SDA2,   GPIO_FN_SCL2,
+       GPIO_FN_DDC3,   GPIO_FN_DDC2,   GPIO_FN_SDA2,   GPIO_FN_SCL2,
        GPIO_FN_SDA1,   GPIO_FN_SCL1,   GPIO_FN_SDA0,   GPIO_FN_SCL0,
+       GPIO_FN_SDA8,   GPIO_FN_SCL8,
 
        /* PTS (mobule: GRA, IIC) */
-       GPIO_FN_DDC1,   GPIO_FN_DDC0,
-       GPIO_FN_SDA9,   GPIO_FN_SCL9,   GPIO_FN_SDA5,   GPIO_FN_SCL5,
+       GPIO_FN_DDC1,   GPIO_FN_DDC0,   GPIO_FN_SDA5,   GPIO_FN_SCL5,
        GPIO_FN_SDA4,   GPIO_FN_SCL4,   GPIO_FN_SDA3,   GPIO_FN_SCL3,
+       GPIO_FN_SDA9,   GPIO_FN_SCL9,
 
-       /* PTT (mobule: SYSTEM, PWMX) */
-       GPIO_FN_AUDSYNC,                GPIO_FN_AUDCK,
-       GPIO_FN_AUDATA3,                GPIO_FN_AUDATA2,
-       GPIO_FN_AUDATA1,                GPIO_FN_AUDATA0,
-       GPIO_FN_PWX7,   GPIO_FN_PWX6,   GPIO_FN_PWX5,   GPIO_FN_PWX4,
+       /* PTT (mobule: PWMX, AUD) */
+       GPIO_FN_PWMX7,  GPIO_FN_PWMX6,  GPIO_FN_PWMX5,  GPIO_FN_PWMX4,
+       GPIO_FN_PWMX3,  GPIO_FN_PWMX2,  GPIO_FN_PWMX1,  GPIO_FN_PWMX0,
+       GPIO_FN_AUDATA3,        GPIO_FN_AUDATA2,        GPIO_FN_AUDATA1,
+       GPIO_FN_AUDATA0,        GPIO_FN_STATUS1,        GPIO_FN_STATUS0,
 
-       /* PTU (mobule: LBSC, DMAC) */
-       GPIO_FN_CS6,    GPIO_FN_CS5,    GPIO_FN_CS4,    GPIO_FN_CS0,
-       GPIO_FN_RD,     GPIO_FN_WE0,    GPIO_FN_A25,    GPIO_FN_A24,
-       GPIO_FN_DREQ0,  GPIO_FN_DACK0,
+       /* PTU (mobule: LPC, APM) */
+       GPIO_FN_LGPIO7, GPIO_FN_LGPIO6, GPIO_FN_LGPIO5, GPIO_FN_LGPIO4,
+       GPIO_FN_LGPIO3, GPIO_FN_LGPIO2, GPIO_FN_LGPIO1, GPIO_FN_LGPIO0,
+       GPIO_FN_APMONCTL_O,     GPIO_FN_APMPWBTOUT_O,   GPIO_FN_APMSCI_O,
+       GPIO_FN_APMVDDON,       GPIO_FN_APMSLPBTN,      GPIO_FN_APMPWRBTN,
+       GPIO_FN_APMS5N,         GPIO_FN_APMS3N,
 
-       /* PTV (mobule: LBSC, DMAC) */
+       /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */
        GPIO_FN_A23,    GPIO_FN_A22,    GPIO_FN_A21,    GPIO_FN_A20,
        GPIO_FN_A19,    GPIO_FN_A18,    GPIO_FN_A17,    GPIO_FN_A16,
-       GPIO_FN_TEND0,  GPIO_FN_DREQ1,  GPIO_FN_DACK1,  GPIO_FN_TEND1,
+       GPIO_FN_COM2_RI,        GPIO_FN_R_SPI_MOSI,     GPIO_FN_R_SPI_MISO,
+       GPIO_FN_R_SPI_RSPCK,    GPIO_FN_R_SPI_SSL0,     GPIO_FN_R_SPI_SSL1,
+       GPIO_FN_EVENT7,         GPIO_FN_EVENT6,         GPIO_FN_VBIOS_DI,
+       GPIO_FN_VBIOS_DO,       GPIO_FN_VBIOS_CLK,      GPIO_FN_VBIOS_CS,
 
-       /* PTW (mobule: LBSC) */
+       /* PTW (mobule: LBSC, EVC, SCIF) */
        GPIO_FN_A15,    GPIO_FN_A14,    GPIO_FN_A13,    GPIO_FN_A12,
        GPIO_FN_A11,    GPIO_FN_A10,    GPIO_FN_A9,     GPIO_FN_A8,
+       GPIO_FN_EVENT5, GPIO_FN_EVENT4, GPIO_FN_EVENT3, GPIO_FN_EVENT2,
+       GPIO_FN_EVENT1, GPIO_FN_EVENT0, GPIO_FN_CTS4,   GPIO_FN_CTS2,
 
-       /* PTX (mobule: LBSC) */
+       /* PTX (mobule: LBSC, SCIF, SIM) */
        GPIO_FN_A7,     GPIO_FN_A6,     GPIO_FN_A5,     GPIO_FN_A4,
        GPIO_FN_A3,     GPIO_FN_A2,     GPIO_FN_A1,     GPIO_FN_A0,
+       GPIO_FN_RTS2,   GPIO_FN_SIM_D,  GPIO_FN_SIM_CLK, GPIO_FN_SIM_RST,
 
        /* PTY (mobule: LBSC) */
        GPIO_FN_D7,     GPIO_FN_D6,     GPIO_FN_D5,     GPIO_FN_D4,
        GPIO_FN_D3,     GPIO_FN_D2,     GPIO_FN_D1,     GPIO_FN_D0,
+
+       /* PTZ (mobule: eMMC, ONFI) */
+       GPIO_FN_MMCDAT7,        GPIO_FN_MMCDAT6,        GPIO_FN_MMCDAT5,
+       GPIO_FN_MMCDAT4,        GPIO_FN_MMCDAT3,        GPIO_FN_MMCDAT2,
+       GPIO_FN_MMCDAT1,        GPIO_FN_MMCDAT0,
+       GPIO_FN_ON_DQ7, GPIO_FN_ON_DQ6, GPIO_FN_ON_DQ5, GPIO_FN_ON_DQ4,
+       GPIO_FN_ON_DQ3, GPIO_FN_ON_DQ2, GPIO_FN_ON_DQ1, GPIO_FN_ON_DQ0,
 };
 
 #endif /* __ASM_SH7757_H__ */
diff --git a/arch/sh/include/cpu-sh4/cpu/shx3.h b/arch/sh/include/cpu-sh4/cpu/shx3.h
new file mode 100644 (file)
index 0000000..68d9080
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __CPU_SHX3_H
+#define __CPU_SHX3_H
+
+enum {
+       /* PA */
+       GPIO_PA7, GPIO_PA6, GPIO_PA5, GPIO_PA4,
+       GPIO_PA3, GPIO_PA2, GPIO_PA1, GPIO_PA0,
+
+       /* PB */
+       GPIO_PB7, GPIO_PB6, GPIO_PB5, GPIO_PB4,
+       GPIO_PB3, GPIO_PB2, GPIO_PB1, GPIO_PB0,
+
+       /* PC */
+       GPIO_PC7, GPIO_PC6, GPIO_PC5, GPIO_PC4,
+       GPIO_PC3, GPIO_PC2, GPIO_PC1, GPIO_PC0,
+
+       /* PD */
+       GPIO_PD7, GPIO_PD6, GPIO_PD5, GPIO_PD4,
+       GPIO_PD3, GPIO_PD2, GPIO_PD1, GPIO_PD0,
+
+       /* PE */
+       GPIO_PE7, GPIO_PE6, GPIO_PE5, GPIO_PE4,
+       GPIO_PE3, GPIO_PE2, GPIO_PE1, GPIO_PE0,
+
+       /* PF */
+       GPIO_PF7, GPIO_PF6, GPIO_PF5, GPIO_PF4,
+       GPIO_PF3, GPIO_PF2, GPIO_PF1, GPIO_PF0,
+
+       /* PG */
+       GPIO_PG7, GPIO_PG6, GPIO_PG5, GPIO_PG4,
+       GPIO_PG3, GPIO_PG2, GPIO_PG1, GPIO_PG0,
+
+       /* PH */
+       GPIO_PH5, GPIO_PH4,
+       GPIO_PH3, GPIO_PH2, GPIO_PH1, GPIO_PH0,
+
+       /* SCIF */
+       GPIO_FN_SCK3, GPIO_FN_TXD3, GPIO_FN_RXD3,
+       GPIO_FN_SCK2, GPIO_FN_TXD2, GPIO_FN_RXD2,
+       GPIO_FN_SCK1, GPIO_FN_TXD1, GPIO_FN_RXD1,
+       GPIO_FN_SCK0, GPIO_FN_TXD0, GPIO_FN_RXD0,
+
+       /* LBSC */
+       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_WE3, GPIO_FN_WE2, GPIO_FN_CS6, GPIO_FN_CS5,
+       GPIO_FN_CS4, GPIO_FN_CLKOUTENB, GPIO_FN_BREQ,
+       GPIO_FN_IOIS16, GPIO_FN_CE2B, GPIO_FN_CE2A, GPIO_FN_BACK,
+
+       /* DMAC */
+       GPIO_FN_DACK0, GPIO_FN_DREQ0, GPIO_FN_DRAK0,
+       GPIO_FN_DACK1, GPIO_FN_DREQ1, GPIO_FN_DRAK1,
+       GPIO_FN_DACK2, GPIO_FN_DREQ2, GPIO_FN_DRAK2,
+       GPIO_FN_DACK3, GPIO_FN_DREQ3, GPIO_FN_DRAK3,
+
+       /* INTC */
+       GPIO_FN_IRQ3, GPIO_FN_IRQ2, GPIO_FN_IRQ1, GPIO_FN_IRQ0,
+       GPIO_FN_IRL3, GPIO_FN_IRL2, GPIO_FN_IRL1, GPIO_FN_IRL0,
+       GPIO_FN_IRQOUT, GPIO_FN_STATUS1, GPIO_FN_STATUS0,
+};
+
+#endif /* __CPU_SHX3_H */
diff --git a/arch/sh/include/mach-common/mach/sh2007.h b/arch/sh/include/mach-common/mach/sh2007.h
new file mode 100644 (file)
index 0000000..48180b9
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef __MACH_SH2007_H
+#define __MACH_SH2007_H
+
+#define CS5BCR         0xff802050
+#define CS5WCR         0xff802058
+#define CS5PCR         0xff802070
+
+#define BUS_SZ8                1
+#define BUS_SZ16       2
+#define BUS_SZ32       3
+
+#define PCMCIA_IODYN   1
+#define PCMCIA_ATA     0
+#define PCMCIA_IO8     2
+#define PCMCIA_IO16    3
+#define PCMCIA_COMM8   4
+#define PCMCIA_COMM16  5
+#define PCMCIA_ATTR8   6
+#define PCMCIA_ATTR16  7
+
+#define TYPE_SRAM      0
+#define TYPE_PCMCIA    4
+
+/* write-read/write-write delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWW5           0
+#define IWW6           3
+/* different area, read-write delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRWD5         2
+#define IWRWD6         2
+/* same area, read-write delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRWS5         2
+#define IWRWS6         2
+/* different area, read-read delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRRD5         2
+#define IWRRD6         2
+/* same area, read-read delay (0-7:0,1,2,3,4,5,6,7) */
+#define IWRRS5         0
+#define IWRRS6         2
+/* burst count (0-3:4,8,16,32) */
+#define BST5           0
+#define BST6           0
+/* bus size */
+#define SZ5            BUS_SZ16
+#define SZ6            BUS_SZ16
+/* RD hold for SRAM (0-1:0,1) */
+#define RDSPL5         0
+#define RDSPL6         0
+/* Burst pitch (0-7:0,1,2,3,4,5,6,7) */
+#define BW5            0
+#define BW6            0
+/* Multiplex (0-1:0,1) */
+#define MPX5           0
+#define MPX6           0
+/* device type */
+#define TYPE5          TYPE_PCMCIA
+#define TYPE6          TYPE_PCMCIA
+/* address setup before assert CSn for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define ADS5           0
+#define ADS6           0
+/* address hold after negate CSn for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define ADH5           0
+#define ADH6           0
+/* CSn assert to RD assert delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define RDS5           0
+#define RDS6           0
+/* RD negate to CSn negate delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define RDH5           0
+#define RDH6           0
+/* CSn assert to WE assert delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define WTS5           0
+#define WTS6           0
+/* WE negate to CSn negate delay for SRAM (0-7:0,1,2,3,4,5,6,7) */
+#define WTH5           0
+#define WTH6           0
+/* BS hold (0-1:1,2) */
+#define BSH5           0
+#define BSH6           0
+/* wait cycle (0-15:0,1,2,3,4,5,6,7,8,9,11,13,15,17,21,25) */
+#define IW5            6       /* 60ns PIO mode 4 */
+#define IW6            15      /* 250ns */
+
+#define SAA5           PCMCIA_IODYN    /* IDE area b4000000-b5ffffff */
+#define SAB5           PCMCIA_IODYN    /* CF  area b6000000-b7ffffff */
+#define PCWA5          0       /* additional wait A (0-3:0,15,30,50) */
+#define PCWB5          0       /* additional wait B (0-3:0,15,30,50) */
+/* wait B (0-15:0,1,2,3,4,5,6,7,8,9,11,13,15,17,21,25) */
+#define PCIW5          12
+/* Address->OE/WE assert delay A (0-7:0,1,2,3,6,9,12,15) */
+#define TEDA5          2
+/* Address->OE/WE assert delay B (0-7:0,1,2,3,6,9,12,15) */
+#define TEDB5          4
+/* OE/WE negate->Address delay A (0-7:0,1,2,3,6,9,12,15) */
+#define TEHA5          2
+/* OE/WE negate->Address delay B (0-7:0,1,2,3,6,9,12,15) */
+#define TEHB5          3
+
+#define CS5BCR_D       ((IWW5<<28)|(IWRWD5<<24)|(IWRWS5<<20)|          \
+                       (IWRRD5<<16)|(IWRRS5<<12)|(BST5<<10)|           \
+                       (SZ5<<8)|(RDSPL5<<7)|(BW5<<4)|(MPX5<<3)|TYPE5)
+#define CS5WCR_D       ((ADS5<<28)|(ADH5<<24)|(RDS5<<20)|      \
+                       (RDH5<<16)|(WTS5<<12)|(WTH5<<8)|(BSH5<<4)|IW5)
+#define CS5PCR_D       ((SAA5<<28)|(SAB5<<24)|(PCWA5<<22)|             \
+                       (PCWB5<<20)|(PCIW5<<16)|(TEDA5<<12)|            \
+                       (TEDB5<<8)|(TEHA5<<4)|TEHB5)
+
+#define SMC0_BASE       0xb0800000      /* eth0 */
+#define SMC1_BASE       0xb0900000      /* eth1 */
+#define CF_BASE         0xb6100000      /* Compact Flash (I/O area) */
+#define IDE_BASE        0xb4000000      /* IDE */
+#define PC104_IO_BASE   0xb8000000
+#define PC104_MEM_BASE  0xba000000
+#define SMC_IO_SIZE     0x100
+
+#define CF_OFFSET       0x1f0
+#define IDE_OFFSET      0x170
+
+#endif /* __MACH_SH2007_H */
index 416b621..40f0c2d 100644 (file)
 #define EXTASR         0x110
 #define SPCAR          0x120
 #define INTMSR         0x130
+
 #define PCIECR         0x140
+#define  PCIECR_PCIEMUX1       BIT(15)
+#define  PCIECR_PCIEMUX0       BIT(14)
+#define  PCIECR_PRST4          BIT(12) /* slot 4 card present */
+#define  PCIECR_PRST3          BIT(11) /* slot 3 card present */
+#define  PCIECR_PRST2          BIT(10) /* slot 2 card present */
+#define  PCIECR_PRST1          BIT(9)  /* slot 1 card present */
+#define  PCIECR_CLKEN          BIT(4)  /* oscillator enable */
+
 #define FAER           0x150
 #define USRGPIR                0x160
+
 /* 0x170 reserved */
-#define LCLASR         0x180
+
+#define LCLASR                 0x180
+#define  LCLASR_FRAMEN         BIT(15)
+
+#define  LCLASR_FPGA_SEL_SHIFT 12
+#define  LCLASR_NAND_SEL_SHIFT 8
+#define  LCLASR_NORB_SEL_SHIFT 4
+#define  LCLASR_NORA_SEL_SHIFT 0
+
+#define  LCLASR_AREA_MASK      0x7
+
+#define  LCLASR_FPGA_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_FPGA_SEL_SHIFT)
+#define  LCLASR_NAND_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_NAND_SEL_SHIFT)
+#define  LCLASR_NORB_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_NORB_SEL_SHIFT)
+#define  LCLASR_NORA_SEL_MASK  (LCLASR_AREA_MASK << LCLASR_NORA_SEL_SHIFT)
 
 #define SBCR           0x190
 #define  SCBR_I2CMEN   BIT(0)  /* FPGA I2C master enable */
diff --git a/arch/sh/include/mach-x3proto/mach/hardware.h b/arch/sh/include/mach-x3proto/mach/hardware.h
new file mode 100644 (file)
index 0000000..52bca57
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __MACH_X3PROTO_HARDWARE_H
+#define __MACH_X3PROTO_HARDWARE_H
+
+struct gpio_chip;
+
+/* arch/sh/boards/mach-x3proto/gpio.c */
+int x3proto_gpio_setup(void);
+extern struct gpio_chip x3proto_gpio_chip;
+
+#define NR_BASEBOARD_GPIOS     16
+
+#endif /* __MACH_X3PROTO_HARDWARE_H */
diff --git a/arch/sh/include/mach-x3proto/mach/ilsel.h b/arch/sh/include/mach-x3proto/mach/ilsel.h
new file mode 100644 (file)
index 0000000..e3d304b
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __ASM_SH_ILSEL_H
+#define __ASM_SH_ILSEL_H
+
+typedef enum {
+       ILSEL_NONE,
+       ILSEL_LAN,
+       ILSEL_USBH_I,
+       ILSEL_USBH_S,
+       ILSEL_USBH_V,
+       ILSEL_RTC,
+       ILSEL_USBP_I,
+       ILSEL_USBP_S,
+       ILSEL_USBP_V,
+       ILSEL_KEY,
+
+       /*
+        * ILSEL Aliases - corner cases for interleaved level tables.
+        *
+        * Someone thought this was a good idea and less hassle than
+        * demuxing a shared vector, really.
+        */
+
+       /* ILSEL0 and 2 */
+       ILSEL_FPGA0,
+       ILSEL_FPGA1,
+       ILSEL_EX1,
+       ILSEL_EX2,
+       ILSEL_EX3,
+       ILSEL_EX4,
+
+       /* ILSEL1 and 3 */
+       ILSEL_FPGA2 = ILSEL_FPGA0,
+       ILSEL_FPGA3 = ILSEL_FPGA1,
+       ILSEL_EX5 = ILSEL_EX1,
+       ILSEL_EX6 = ILSEL_EX2,
+       ILSEL_EX7 = ILSEL_EX3,
+       ILSEL_EX8 = ILSEL_EX4,
+} ilsel_source_t;
+
+/* arch/sh/boards/renesas/x3proto/ilsel.c */
+int ilsel_enable(ilsel_source_t set);
+int ilsel_enable_fixed(ilsel_source_t set, unsigned int level);
+void ilsel_disable(unsigned int irq);
+
+#endif /* __ASM_SH_ILSEL_H */
index e25f3c6..8eed6a4 100644 (file)
@@ -12,9 +12,9 @@ endif
 CFLAGS_REMOVE_return_address.o = -pg
 
 obj-y  := clkdev.o debugtraps.o dma-nommu.o dumpstack.o                \
-          idle.o io.o irq.o                                            \
-          irq_$(BITS).o machvec.o nmi_debug.o process.o                \
-          process_$(BITS).o ptrace_$(BITS).o                           \
+          idle.o io.o irq.o irq_$(BITS).o kdebugfs.o                   \
+          machvec.o nmi_debug.o process.o                              \
+          process_$(BITS).o ptrace.o ptrace_$(BITS).o                  \
           reboot.o return_address.o                                    \
           setup.o signal_$(BITS).o sys_sh.o sys_sh$(BITS).o            \
           syscalls_$(BITS).o time.o topology.o traps.o                 \
@@ -44,4 +44,4 @@ obj-$(CONFIG_HAS_IOPORT)      += io_generic.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)               += hw_breakpoint.o
 obj-$(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)    += localtimer.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index befc255..1f800ef 100644 (file)
@@ -161,9 +161,11 @@ EXPORT_SYMBOL(clk_add_alias);
  */
 void clkdev_drop(struct clk_lookup *cl)
 {
+       struct clk_lookup_alloc *cla = container_of(cl, struct clk_lookup_alloc, cl);
+
        mutex_lock(&clocks_mutex);
        list_del(&cl->node);
        mutex_unlock(&clocks_mutex);
-       kfree(cl);
+       kfree(cla);
 }
 EXPORT_SYMBOL(clkdev_drop);
index d180f16..b93458f 100644 (file)
@@ -150,7 +150,7 @@ void __cpuinit cpu_probe(void)
                        boot_cpu_data.type = CPU_SH7724;
                        boot_cpu_data.flags |= CPU_HAS_L2_CACHE;
                        break;
-               case 0x50:
+               case 0x10:
                        boot_cpu_data.type = CPU_SH7757;
                        break;
                }
index b144e8a..cc122b1 100644 (file)
@@ -8,13 +8,13 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7763)      += setup-sh7763.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7770)       += setup-sh7770.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7780)       += setup-sh7780.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7785)       += setup-sh7785.o
-obj-$(CONFIG_CPU_SUBTYPE_SH7786)       += setup-sh7786.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7786)       += setup-sh7786.o intc-shx3.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7343)       += setup-sh7343.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7722)       += setup-sh7722.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7723)       += setup-sh7723.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7724)       += setup-sh7724.o
 obj-$(CONFIG_CPU_SUBTYPE_SH7366)       += setup-sh7366.o
-obj-$(CONFIG_CPU_SUBTYPE_SHX3)         += setup-shx3.o
+obj-$(CONFIG_CPU_SUBTYPE_SHX3)         += setup-shx3.o intc-shx3.o
 
 # SMP setup
 smp-$(CONFIG_CPU_SHX3)                 := smp-shx3.o
@@ -40,6 +40,7 @@ pinmux-$(CONFIG_CPU_SUBTYPE_SH7724)   := pinmux-sh7724.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7757)    := pinmux-sh7757.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7785)    := pinmux-sh7785.o
 pinmux-$(CONFIG_CPU_SUBTYPE_SH7786)    := pinmux-sh7786.o
+pinmux-$(CONFIG_CPU_SUBTYPE_SHX3)      := pinmux-shx3.o
 
 obj-y                                  += $(clock-y)
 obj-$(CONFIG_SMP)                      += $(smp-y)
index 0a752bd..ce39a2a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * SH7757 support for the clock framework
  *
- *  Copyright (C) 2009  Renesas Solutions Corp.
+ *  Copyright (C) 2009-2010  Renesas Solutions Corp.
  *
  * 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 <asm/clock.h>
 #include <asm/freq.h>
 
-static int ifc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                             16, 1, 1, 32, 1, 1, 1, 1 };
-static int sfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                             16, 1, 1, 32, 1, 1, 1, 1 };
-static int bfc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                             16, 1, 1, 32, 1, 1, 1, 1 };
-static int p1fc_divisors[] = { 2, 1, 4, 1, 1, 8, 1, 1,
-                              16, 1, 1, 32, 1, 1, 1, 1 };
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+       .rate           = 48000000,
+};
 
-static void master_clk_init(struct clk *clk)
+static unsigned long pll_recalc(struct clk *clk)
 {
-       clk->rate = CONFIG_SH_PCLK_FREQ * 16;
-}
+       int multiplier;
 
-static struct clk_ops sh7757_master_clk_ops = {
-       .init           = master_clk_init,
-};
+       multiplier = test_mode_pin(MODE_PIN0) ? 24 : 16;
 
-static void module_clk_recalc(struct clk *clk)
-{
-       int idx = __raw_readl(FRQCR) & 0x0000000f;
-       clk->rate = clk->parent->rate / p1fc_divisors[idx];
+       return clk->parent->rate * multiplier;
 }
 
-static struct clk_ops sh7757_module_clk_ops = {
-       .recalc         = module_clk_recalc,
+static struct clk_ops pll_clk_ops = {
+       .recalc         = pll_recalc,
 };
 
-static void bus_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readl(FRQCR) >> 8) & 0x0000000f;
-       clk->rate = clk->parent->rate / bfc_divisors[idx];
-}
+static struct clk pll_clk = {
+       .ops            = &pll_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+};
 
-static struct clk_ops sh7757_bus_clk_ops = {
-       .recalc         = bus_clk_recalc,
+static struct clk *clks[] = {
+       &extal_clk,
+       &pll_clk,
 };
 
-static void cpu_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readl(FRQCR) >> 20) & 0x0000000f;
-       clk->rate = clk->parent->rate / ifc_divisors[idx];
-}
+static unsigned int div2[] = { 1, 1, 2, 1, 1, 4, 1, 6,
+                              1, 1, 1, 16, 1, 24, 1, 1 };
 
-static struct clk_ops sh7757_cpu_clk_ops = {
-       .recalc         = cpu_clk_recalc,
+static struct clk_div_mult_table div4_div_mult_table = {
+       .divisors = div2,
+       .nr_divisors = ARRAY_SIZE(div2),
 };
 
-static struct clk_ops *sh7757_clk_ops[] = {
-       &sh7757_master_clk_ops,
-       &sh7757_module_clk_ops,
-       &sh7757_bus_clk_ops,
-       &sh7757_cpu_clk_ops,
+static struct clk_div4_table div4_table = {
+       .div_mult_table = &div4_div_mult_table,
 };
 
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-       if (idx < ARRAY_SIZE(sh7757_clk_ops))
-               *ops = sh7757_clk_ops[idx];
-}
+enum { DIV4_I, DIV4_SH, DIV4_P, DIV4_NR };
 
-static void shyway_clk_recalc(struct clk *clk)
-{
-       int idx = (__raw_readl(FRQCR) >> 12) & 0x0000000f;
-       clk->rate = clk->parent->rate / sfc_divisors[idx];
-}
-
-static struct clk_ops sh7757_shyway_clk_ops = {
-       .recalc         = shyway_clk_recalc,
-};
+#define DIV4(_bit, _mask, _flags) \
+  SH_CLK_DIV4(&pll_clk, FRQCR, _bit, _mask, _flags)
 
-static struct clk sh7757_shyway_clk = {
-       .flags          = CLK_ENABLE_ON_INIT,
-       .ops            = &sh7757_shyway_clk_ops,
+struct clk div4_clks[DIV4_NR] = {
+       /*
+        * P clock is always enable, because some P clock modules is used
+        * by Host PC.
+        */
+       [DIV4_P] = DIV4(0, 0x2800, CLK_ENABLE_ON_INIT),
+       [DIV4_SH] = DIV4(12, 0x00a0, CLK_ENABLE_ON_INIT),
+       [DIV4_I] = DIV4(20, 0x0004, CLK_ENABLE_ON_INIT),
 };
 
-/*
- * Additional sh7757-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *sh7757_onchip_clocks[] = {
-       &sh7757_shyway_clk,
+#define MSTPCR0                0xffc80030
+#define MSTPCR1                0xffc80034
+
+enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112,
+       MSTP111, MSTP110, MSTP103, MSTP102,
+       MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+       /* MSTPCR0 */
+       [MSTP004] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 4, 0),
+       [MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0),
+
+       /* MSTPCR1 */
+       [MSTP114] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 14, 0),
+       [MSTP113] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 13, 0),
+       [MSTP112] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 12, 0),
+       [MSTP111] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 11, 0),
+       [MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0),
+       [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
+       [MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0),
 };
 
 #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
 
 static struct clk_lookup lookups[] = {
        /* main clocks */
-       CLKDEV_CON_ID("shyway_clk", &sh7757_shyway_clk),
+       CLKDEV_CON_ID("extal", &extal_clk),
+       CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+       CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+       CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+       /* MSTP32 clocks */
+       CLKDEV_CON_ID("sdhi0", &mstp_clks[MSTP004]),
+       CLKDEV_CON_ID("riic", &mstp_clks[MSTP000]),
+       {
+               /* TMU0 */
+               .dev_id         = "sh_tmu.0",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP113],
+       }, {
+               /* TMU1 */
+               .dev_id         = "sh_tmu.1",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP114],
+       },
+       {
+               /* SCIF4 (But, ID is 2) */
+               .dev_id         = "sh-sci.2",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP112],
+       }, {
+               /* SCIF3 */
+               .dev_id         = "sh-sci.1",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP111],
+       }, {
+               /* SCIF2 */
+               .dev_id         = "sh-sci.0",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP110],
+       },
+       CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
 };
 
-static int __init sh7757_clk_init(void)
+int __init arch_clk_init(void)
 {
-       struct clk *clk = clk_get(NULL, "master_clk");
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(sh7757_onchip_clocks); i++) {
-               struct clk *clkp = sh7757_onchip_clocks[i];
+       int i, ret = 0;
 
-               clkp->parent = clk;
-               clk_register(clkp);
-               clk_enable(clkp);
-       }
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               ret |= clk_register(clks[i]);
+       for (i = 0; i < ARRAY_SIZE(lookups); i++)
+               clkdev_add(&lookups[i]);
 
-       /*
-        * Now that we have the rest of the clocks registered, we need to
-        * force the parent clock to propagate so that these clocks will
-        * automatically figure out their rate. We cheat by handing the
-        * parent clock its current rate and forcing child propagation.
-        */
-       clk_set_rate(clk, clk_get_rate(clk));
+       if (!ret)
+               ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+                                          &div4_table);
+       if (!ret)
+               ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
 
-       clk_put(clk);
-
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
-       return 0;
+       return ret;
 }
 
-arch_initcall(sh7757_clk_init);
-
index 236a628..4f70df6 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  Copyright (C) 2006-2007  Renesas Technology Corp.
  *  Copyright (C) 2006-2007  Renesas Solutions Corp.
- *  Copyright (C) 2006-2007  Paul Mundt
+ *  Copyright (C) 2006-2010  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
 #include <asm/clock.h>
 #include <asm/freq.h>
 
-static int ifc_divisors[] = { 1, 2, 4 ,6 };
-static int bfc_divisors[] = { 1, 1, 1, 1, 1, 12, 16, 18, 24, 32, 36, 48 };
-static int pfc_divisors[] = { 1, 1, 1, 1, 1, 1, 1, 18, 24, 32, 36, 48 };
-static int cfc_divisors[] = { 1, 1, 4, 6 };
-
-#define IFC_POS                28
-#define IFC_MSK                0x0003
-#define BFC_MSK                0x000f
-#define PFC_MSK                0x000f
-#define CFC_MSK                0x0003
-#define BFC_POS                16
-#define PFC_POS                0
-#define CFC_POS                20
-
-static void master_clk_init(struct clk *clk)
-{
-       clk->rate *= pfc_divisors[(__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK];
-}
-
-static struct clk_ops shx3_master_clk_ops = {
-       .init           = master_clk_init,
+/*
+ * Default rate for the root input clock, reset this with clk_set_rate()
+ * from the platform code.
+ */
+static struct clk extal_clk = {
+       .rate           = 16666666,
 };
 
-static unsigned long module_clk_recalc(struct clk *clk)
+static unsigned long pll_recalc(struct clk *clk)
 {
-       int idx = ((__raw_readl(FRQCR) >> PFC_POS) & PFC_MSK);
-       return clk->parent->rate / pfc_divisors[idx];
+       /* PLL1 has a fixed x72 multiplier.  */
+       return clk->parent->rate * 72;
 }
 
-static struct clk_ops shx3_module_clk_ops = {
-       .recalc         = module_clk_recalc,
+static struct clk_ops pll_clk_ops = {
+       .recalc         = pll_recalc,
 };
 
-static unsigned long bus_clk_recalc(struct clk *clk)
-{
-       int idx = ((__raw_readl(FRQCR) >> BFC_POS) & BFC_MSK);
-       return clk->parent->rate / bfc_divisors[idx];
-}
+static struct clk pll_clk = {
+       .ops            = &pll_clk_ops,
+       .parent         = &extal_clk,
+       .flags          = CLK_ENABLE_ON_INIT,
+};
 
-static struct clk_ops shx3_bus_clk_ops = {
-       .recalc         = bus_clk_recalc,
+static struct clk *clks[] = {
+       &extal_clk,
+       &pll_clk,
 };
 
-static unsigned long cpu_clk_recalc(struct clk *clk)
-{
-       int idx = ((__raw_readl(FRQCR) >> IFC_POS) & IFC_MSK);
-       return clk->parent->rate / ifc_divisors[idx];
-}
+static unsigned int div2[] = { 1, 2, 4, 6, 8, 12, 16, 18,
+                              24, 32, 36, 48 };
 
-static struct clk_ops shx3_cpu_clk_ops = {
-       .recalc         = cpu_clk_recalc,
+static struct clk_div_mult_table div4_div_mult_table = {
+       .divisors = div2,
+       .nr_divisors = ARRAY_SIZE(div2),
 };
 
-static struct clk_ops *shx3_clk_ops[] = {
-       &shx3_master_clk_ops,
-       &shx3_module_clk_ops,
-       &shx3_bus_clk_ops,
-       &shx3_cpu_clk_ops,
+static struct clk_div4_table div4_table = {
+       .div_mult_table = &div4_div_mult_table,
 };
 
-void __init arch_init_clk_ops(struct clk_ops **ops, int idx)
-{
-       if (idx < ARRAY_SIZE(shx3_clk_ops))
-               *ops = shx3_clk_ops[idx];
-}
+enum { DIV4_I, DIV4_SH, DIV4_B, DIV4_DDR, DIV4_SHA, DIV4_P, DIV4_NR };
 
-static unsigned long shyway_clk_recalc(struct clk *clk)
-{
-       int idx = ((__raw_readl(FRQCR) >> CFC_POS) & CFC_MSK);
-       return clk->parent->rate / cfc_divisors[idx];
-}
+#define DIV4(_bit, _mask, _flags) \
+  SH_CLK_DIV4(&pll_clk, FRQMR1, _bit, _mask, _flags)
 
-static struct clk_ops shx3_shyway_clk_ops = {
-       .recalc         = shyway_clk_recalc,
+struct clk div4_clks[DIV4_NR] = {
+       [DIV4_P] = DIV4(0, 0x0f80, 0),
+       [DIV4_SHA] = DIV4(4, 0x0ff0, 0),
+       [DIV4_DDR] = DIV4(12, 0x000c, CLK_ENABLE_ON_INIT),
+       [DIV4_B] = DIV4(16, 0x0fe0, CLK_ENABLE_ON_INIT),
+       [DIV4_SH] = DIV4(20, 0x000c, CLK_ENABLE_ON_INIT),
+       [DIV4_I] = DIV4(28, 0x000e, CLK_ENABLE_ON_INIT),
 };
 
-static struct clk shx3_shyway_clk = {
-       .flags          = CLK_ENABLE_ON_INIT,
-       .ops            = &shx3_shyway_clk_ops,
-};
-
-/*
- * Additional SHx3-specific on-chip clocks that aren't already part of the
- * clock framework
- */
-static struct clk *shx3_onchip_clocks[] = {
-       &shx3_shyway_clk,
+#define MSTPCR0                0xffc00030
+#define MSTPCR1                0xffc00034
+
+enum { MSTP027, MSTP026, MSTP025, MSTP024,
+       MSTP009, MSTP008, MSTP003, MSTP002,
+       MSTP001, MSTP000, MSTP119, MSTP105,
+       MSTP104, MSTP_NR };
+
+static struct clk mstp_clks[MSTP_NR] = {
+       /* MSTPCR0 */
+       [MSTP027] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 27, 0),
+       [MSTP026] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 26, 0),
+       [MSTP025] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 25, 0),
+       [MSTP024] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 24, 0),
+       [MSTP009] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 9, 0),
+       [MSTP008] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 8, 0),
+       [MSTP003] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 3, 0),
+       [MSTP002] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 2, 0),
+       [MSTP001] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 1, 0),
+       [MSTP000] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 0, 0),
+
+       /* MSTPCR1 */
+       [MSTP119] = SH_CLK_MSTP32(NULL, MSTPCR1, 19, 0),
+       [MSTP105] = SH_CLK_MSTP32(NULL, MSTPCR1, 5, 0),
+       [MSTP104] = SH_CLK_MSTP32(NULL, MSTPCR1, 4, 0),
 };
 
 #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
 
 static struct clk_lookup lookups[] = {
        /* main clocks */
-       CLKDEV_CON_ID("shyway_clk", &shx3_shyway_clk),
+       CLKDEV_CON_ID("extal", &extal_clk),
+       CLKDEV_CON_ID("pll_clk", &pll_clk),
+
+       /* DIV4 clocks */
+       CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
+       CLKDEV_CON_ID("shywaya_clk", &div4_clks[DIV4_SHA]),
+       CLKDEV_CON_ID("ddr_clk", &div4_clks[DIV4_DDR]),
+       CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),
+       CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),
+       CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),
+
+       /* MSTP32 clocks */
+       {
+               /* SCIF3 */
+               .dev_id         = "sh-sci.3",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP027],
+       }, {
+               /* SCIF2 */
+               .dev_id         = "sh-sci.2",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP026],
+       }, {
+               /* SCIF1 */
+               .dev_id         = "sh-sci.1",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP025],
+       }, {
+               /* SCIF0 */
+               .dev_id         = "sh-sci.0",
+               .con_id         = "sci_fck",
+               .clk            = &mstp_clks[MSTP024],
+       },
+       CLKDEV_CON_ID("h8ex_fck", &mstp_clks[MSTP003]),
+       CLKDEV_CON_ID("csm_fck", &mstp_clks[MSTP002]),
+       CLKDEV_CON_ID("fe1_fck", &mstp_clks[MSTP001]),
+       CLKDEV_CON_ID("fe0_fck", &mstp_clks[MSTP000]),
+       {
+               /* TMU0 */
+               .dev_id         = "sh_tmu.0",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP008],
+       }, {
+               /* TMU1 */
+               .dev_id         = "sh_tmu.1",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP008],
+       }, {
+               /* TMU2 */
+               .dev_id         = "sh_tmu.2",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP008],
+       }, {
+               /* TMU3 */
+               .dev_id         = "sh_tmu.3",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP009],
+       }, {
+               /* TMU4 */
+               .dev_id         = "sh_tmu.4",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP009],
+       }, {
+               /* TMU5 */
+               .dev_id         = "sh_tmu.5",
+               .con_id         = "tmu_fck",
+               .clk            = &mstp_clks[MSTP009],
+       },
+       CLKDEV_CON_ID("hudi_fck", &mstp_clks[MSTP119]),
+       CLKDEV_CON_ID("dmac_11_6_fck", &mstp_clks[MSTP105]),
+       CLKDEV_CON_ID("dmac_5_0_fck", &mstp_clks[MSTP104]),
 };
 
 int __init arch_clk_init(void)
 {
-       struct clk *clk;
        int i, ret = 0;
 
-       cpg_clk_init();
-
-       clk = clk_get(NULL, "master_clk");
-       for (i = 0; i < ARRAY_SIZE(shx3_onchip_clocks); i++) {
-               struct clk *clkp = shx3_onchip_clocks[i];
-
-               clkp->parent = clk;
-               ret |= clk_register(clkp);
-       }
-
-       clk_put(clk);
+       for (i = 0; i < ARRAY_SIZE(clks); i++)
+               ret |= clk_register(clks[i]);
+       for (i = 0; i < ARRAY_SIZE(lookups); i++)
+               clkdev_add(&lookups[i]);
 
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+       if (!ret)
+               ret = sh_clk_div4_register(div4_clks, ARRAY_SIZE(div4_clks),
+                                          &div4_table);
+       if (!ret)
+               ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
 
        return ret;
 }
diff --git a/arch/sh/kernel/cpu/sh4a/intc-shx3.c b/arch/sh/kernel/cpu/sh4a/intc-shx3.c
new file mode 100644 (file)
index 0000000..78c9714
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Shared support for SH-X3 interrupt controllers.
+ *
+ *  Copyright (C) 2009 - 2010  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/irq.h>
+#include <linux/io.h>
+#include <linux/init.h>
+
+#define INTACK         0xfe4100b8
+#define INTACKCLR      0xfe4100bc
+#define INTC_USERIMASK 0xfe411000
+
+#ifdef CONFIG_INTC_BALANCING
+unsigned int irq_lookup(unsigned int irq)
+{
+       return __raw_readl(INTACK) & 1 ? irq : NO_IRQ_IGNORE;
+}
+
+void irq_finish(unsigned int irq)
+{
+       __raw_writel(irq2evt(irq), INTACKCLR);
+}
+#endif
+
+static int __init shx3_irq_setup(void)
+{
+       return register_intc_userimask(INTC_USERIMASK);
+}
+arch_initcall(shx3_irq_setup);
index eddc219..b8b873d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Performance events support for SH-4A performance counters
  *
- *  Copyright (C) 2009  Paul Mundt
+ *  Copyright (C) 2009, 2010  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
 #define CCBR_CMDS      (1 << 1)
 #define CCBR_PPCE      (1 << 0)
 
+#ifdef CONFIG_CPU_SHX3
+/*
+ * The PMCAT location for SH-X3 CPUs was quietly moved, while the CCBR
+ * and PMCTR locations remains tentatively constant. This change remains
+ * wholly undocumented, and was simply found through trial and error.
+ *
+ * Early cuts of SH-X3 still appear to use the SH-X/SH-X2 locations, and
+ * it's unclear when this ceased to be the case. For now we always use
+ * the new location (if future parts keep up with this trend then
+ * scanning for them at runtime also remains a viable option.)
+ *
+ * The gap in the register space also suggests that there are other
+ * undocumented counters, so this will need to be revisited at a later
+ * point in time.
+ */
+#define PPC_PMCAT      0xfc100240
+#else
 #define PPC_PMCAT      0xfc100080
+#endif
 
 #define PMCAT_OVF3     (1 << 27)
 #define PMCAT_CNN3     (1 << 26)
index ed23b15..4c74bd0 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * SH7757 (A0 step) Pinmux
+ * SH7757 (B0 step) Pinmux
  *
- *  Copyright (C) 2009  Renesas Solutions Corp.
+ *  Copyright (C) 2009-2010  Renesas Solutions Corp.
  *
  *  Author : Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
  *
- * Based on SH7757 Pinmux
+ * Based on SH7723 Pinmux
  *  Copyright (C) 2008  Magnus Damm
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -40,27 +40,27 @@ enum {
        PTH3_DATA, PTH2_DATA, PTH1_DATA, PTH0_DATA,
        PTI7_DATA, PTI6_DATA, PTI5_DATA, PTI4_DATA,
        PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA,
-       PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+                  PTJ6_DATA, PTJ5_DATA, PTJ4_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,
+                  PTL6_DATA, PTL5_DATA, PTL4_DATA,
        PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA,
-       PTM6_DATA, PTM5_DATA, PTM4_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,
+                  PTN6_DATA, PTN5_DATA, PTN4_DATA,
        PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA,
        PTO7_DATA, PTO6_DATA, PTO5_DATA, PTO4_DATA,
        PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA,
-       PTP6_DATA, PTP5_DATA, PTP4_DATA,
+       PTP7_DATA, PTP6_DATA, PTP5_DATA, PTP4_DATA,
        PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA,
-       PTQ6_DATA, PTQ5_DATA, PTQ4_DATA,
+                  PTQ6_DATA, PTQ5_DATA, PTQ4_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,
+       PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
        PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA,
        PTU7_DATA, PTU6_DATA, PTU5_DATA, PTU4_DATA,
        PTU3_DATA, PTU2_DATA, PTU1_DATA, PTU0_DATA,
@@ -95,27 +95,27 @@ enum {
        PTH3_IN, PTH2_IN, PTH1_IN, PTH0_IN,
        PTI7_IN, PTI6_IN, PTI5_IN, PTI4_IN,
        PTI3_IN, PTI2_IN, PTI1_IN, PTI0_IN,
-       PTJ7_IN, PTJ6_IN, PTJ5_IN, PTJ4_IN,
+                PTJ6_IN, PTJ5_IN, PTJ4_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,
+                PTL6_IN, PTL5_IN, PTL4_IN,
        PTL3_IN, PTL2_IN, PTL1_IN, PTL0_IN,
-       PTM6_IN, PTM5_IN, PTM4_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,
+                PTN6_IN, PTN5_IN, PTN4_IN,
        PTN3_IN, PTN2_IN, PTN1_IN, PTN0_IN,
        PTO7_IN, PTO6_IN, PTO5_IN, PTO4_IN,
        PTO3_IN, PTO2_IN, PTO1_IN, PTO0_IN,
-       PTP6_IN, PTP5_IN, PTP4_IN,
+       PTP7_IN, PTP6_IN, PTP5_IN, PTP4_IN,
        PTP3_IN, PTP2_IN, PTP1_IN, PTP0_IN,
-       PTQ6_IN, PTQ5_IN, PTQ4_IN,
+                PTQ6_IN, PTQ5_IN, PTQ4_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,
+       PTT7_IN, PTT6_IN, PTT5_IN, PTT4_IN,
        PTT3_IN, PTT2_IN, PTT1_IN, PTT0_IN,
        PTU7_IN, PTU6_IN, PTU5_IN, PTU4_IN,
        PTU3_IN, PTU2_IN, PTU1_IN, PTU0_IN,
@@ -132,16 +132,43 @@ enum {
        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,
+       PTD7_IN_PU, PTD6_IN_PU, PTD5_IN_PU, PTD4_IN_PU,
+       PTD3_IN_PU, PTD2_IN_PU, PTD1_IN_PU, PTD0_IN_PU,
+       PTE7_IN_PU, PTE6_IN_PU, PTE5_IN_PU, PTE4_IN_PU,
+       PTE3_IN_PU, PTE2_IN_PU, PTE1_IN_PU, PTE0_IN_PU,
+       PTF7_IN_PU, PTF6_IN_PU, PTF5_IN_PU, PTF4_IN_PU,
+       PTF3_IN_PU, PTF2_IN_PU, PTF1_IN_PU, PTF0_IN_PU,
+       PTG7_IN_PU, PTG6_IN_PU,             PTG4_IN_PU,
+       PTH7_IN_PU, PTH6_IN_PU, PTH5_IN_PU, PTH4_IN_PU,
+       PTH3_IN_PU, PTH2_IN_PU, PTH1_IN_PU, PTH0_IN_PU,
+       PTI7_IN_PU, PTI6_IN_PU,             PTI4_IN_PU,
+       PTI3_IN_PU, PTI2_IN_PU, PTI1_IN_PU, PTI0_IN_PU,
+                   PTJ6_IN_PU, PTJ5_IN_PU, PTJ4_IN_PU,
+       PTJ3_IN_PU, PTJ2_IN_PU, PTJ1_IN_PU, PTJ0_IN_PU,
+       PTK7_IN_PU, PTK6_IN_PU, PTK5_IN_PU, PTK4_IN_PU,
+       PTK3_IN_PU, PTK2_IN_PU, PTK1_IN_PU, PTK0_IN_PU,
+                   PTL6_IN_PU, PTL5_IN_PU, PTL4_IN_PU,
+       PTL3_IN_PU, PTL2_IN_PU, PTL1_IN_PU, PTL0_IN_PU,
+       PTM7_IN_PU, PTM6_IN_PU, PTM5_IN_PU, PTM4_IN_PU,
+                                           PTN4_IN_PU,
+       PTN3_IN_PU, PTN2_IN_PU, PTN1_IN_PU, PTN0_IN_PU,
+       PTO7_IN_PU, PTO6_IN_PU, PTO5_IN_PU, PTO4_IN_PU,
+       PTO3_IN_PU, PTO2_IN_PU, PTO1_IN_PU, PTO0_IN_PU,
+       PTT7_IN_PU, PTT6_IN_PU, PTT5_IN_PU, PTT4_IN_PU,
+       PTT3_IN_PU, PTT2_IN_PU, PTT1_IN_PU, PTT0_IN_PU,
        PTU7_IN_PU, PTU6_IN_PU, PTU5_IN_PU, PTU4_IN_PU,
        PTU3_IN_PU, PTU2_IN_PU, PTU1_IN_PU, PTU0_IN_PU,
        PTV7_IN_PU, PTV6_IN_PU, PTV5_IN_PU, PTV4_IN_PU,
-       PTV3_IN_PU, PTV2_IN_PU, PTV1_IN_PU, PTV0_IN_PU,
-       PTW7_IN_PU, PTW6_IN_PU, PTW5_IN_PU, PTW4_IN_PU,
-       PTW3_IN_PU, PTW2_IN_PU, PTW1_IN_PU, PTW0_IN_PU,
+       PTV3_IN_PU, PTV2_IN_PU,
+                               PTW1_IN_PU, PTW0_IN_PU,
        PTX7_IN_PU, PTX6_IN_PU, PTX5_IN_PU, PTX4_IN_PU,
        PTX3_IN_PU, PTX2_IN_PU, PTX1_IN_PU, PTX0_IN_PU,
        PTY7_IN_PU, PTY6_IN_PU, PTY5_IN_PU, PTY4_IN_PU,
        PTY3_IN_PU, PTY2_IN_PU, PTY1_IN_PU, PTY0_IN_PU,
+       PTZ7_IN_PU, PTZ6_IN_PU, PTZ5_IN_PU, PTZ4_IN_PU,
+       PTZ3_IN_PU, PTZ2_IN_PU, PTZ1_IN_PU, PTZ0_IN_PU,
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_OUTPUT_BEGIN,
@@ -163,27 +190,27 @@ enum {
        PTH3_OUT, PTH2_OUT, PTH1_OUT, PTH0_OUT,
        PTI7_OUT, PTI6_OUT, PTI5_OUT, PTI4_OUT,
        PTI3_OUT, PTI2_OUT, PTI1_OUT, PTI0_OUT,
-       PTJ7_OUT, PTJ6_OUT, PTJ5_OUT, PTJ4_OUT,
+                 PTJ6_OUT, PTJ5_OUT, PTJ4_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,
+                 PTL6_OUT, PTL5_OUT, PTL4_OUT,
        PTL3_OUT, PTL2_OUT, PTL1_OUT, PTL0_OUT,
-       PTM6_OUT, PTM5_OUT, PTM4_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,
+                 PTN6_OUT, PTN5_OUT, PTN4_OUT,
        PTN3_OUT, PTN2_OUT, PTN1_OUT, PTN0_OUT,
        PTO7_OUT, PTO6_OUT, PTO5_OUT, PTO4_OUT,
        PTO3_OUT, PTO2_OUT, PTO1_OUT, PTO0_OUT,
-       PTP6_OUT, PTP5_OUT, PTP4_OUT,
+       PTP7_OUT, PTP6_OUT, PTP5_OUT, PTP4_OUT,
        PTP3_OUT, PTP2_OUT, PTP1_OUT, PTP0_OUT,
-       PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
+                 PTQ6_OUT, PTQ5_OUT, PTQ4_OUT,
        PTQ3_OUT, PTQ2_OUT, PTQ1_OUT, PTQ0_OUT,
        PTR7_OUT, PTR6_OUT, PTR5_OUT, PTR4_OUT,
        PTR3_OUT, PTR2_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,
+       PTT7_OUT, PTT6_OUT, PTT5_OUT, PTT4_OUT,
        PTT3_OUT, PTT2_OUT, PTT1_OUT, PTT0_OUT,
        PTU7_OUT, PTU6_OUT, PTU5_OUT, PTU4_OUT,
        PTU3_OUT, PTU2_OUT, PTU1_OUT, PTU0_OUT,
@@ -218,27 +245,27 @@ enum {
        PTH3_FN, PTH2_FN, PTH1_FN, PTH0_FN,
        PTI7_FN, PTI6_FN, PTI5_FN, PTI4_FN,
        PTI3_FN, PTI2_FN, PTI1_FN, PTI0_FN,
-       PTJ7_FN, PTJ6_FN, PTJ5_FN, PTJ4_FN,
+                PTJ6_FN, PTJ5_FN, PTJ4_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,
+                PTL6_FN, PTL5_FN, PTL4_FN,
        PTL3_FN, PTL2_FN, PTL1_FN, PTL0_FN,
-       PTM6_FN, PTM5_FN, PTM4_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,
+                PTN6_FN, PTN5_FN, PTN4_FN,
        PTN3_FN, PTN2_FN, PTN1_FN, PTN0_FN,
        PTO7_FN, PTO6_FN, PTO5_FN, PTO4_FN,
        PTO3_FN, PTO2_FN, PTO1_FN, PTO0_FN,
-       PTP6_FN, PTP5_FN, PTP4_FN,
+       PTP7_FN, PTP6_FN, PTP5_FN, PTP4_FN,
        PTP3_FN, PTP2_FN, PTP1_FN, PTP0_FN,
-       PTQ6_FN, PTQ5_FN, PTQ4_FN,
+                PTQ6_FN, PTQ5_FN, PTQ4_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,
+       PTT7_FN, PTT6_FN, PTT5_FN, PTT4_FN,
        PTT3_FN, PTT2_FN, PTT1_FN, PTT0_FN,
        PTU7_FN, PTU6_FN, PTU5_FN, PTU4_FN,
        PTU3_FN, PTU2_FN, PTU1_FN, PTU0_FN,
@@ -253,181 +280,248 @@ enum {
        PTZ7_FN, PTZ6_FN, PTZ5_FN, PTZ4_FN,
        PTZ3_FN, PTZ2_FN, PTZ1_FN, PTZ0_FN,
 
-       PS0_15_FN1, PS0_15_FN3,
-       PS0_14_FN1, PS0_14_FN3,
-       PS0_13_FN1, PS0_13_FN3,
-       PS0_12_FN1, PS0_12_FN3,
+       PS0_15_FN1, PS0_15_FN2,
+       PS0_14_FN1, PS0_14_FN2,
+       PS0_13_FN1, PS0_13_FN2,
+       PS0_12_FN1, PS0_12_FN2,
+       PS0_11_FN1, PS0_11_FN2,
+       PS0_10_FN1, PS0_10_FN2,
+       PS0_9_FN1, PS0_9_FN2,
+       PS0_8_FN1, PS0_8_FN2,
        PS0_7_FN1, PS0_7_FN2,
        PS0_6_FN1, PS0_6_FN2,
        PS0_5_FN1, PS0_5_FN2,
        PS0_4_FN1, PS0_4_FN2,
        PS0_3_FN1, PS0_3_FN2,
        PS0_2_FN1, PS0_2_FN2,
-       PS0_1_FN1, PS0_1_FN2,
 
-       PS1_7_FN1, PS1_7_FN3,
-       PS1_6_FN1, PS1_6_FN3,
+       PS1_10_FN1, PS1_10_FN2,
+       PS1_9_FN1, PS1_9_FN2,
+       PS1_8_FN1, PS1_8_FN2,
+       PS1_2_FN1, PS1_2_FN2,
+
+       PS2_13_FN1, PS2_13_FN2,
+       PS2_12_FN1, PS2_12_FN2,
+       PS2_7_FN1, PS2_7_FN2,
+       PS2_6_FN1, PS2_6_FN2,
+       PS2_5_FN1, PS2_5_FN2,
+       PS2_4_FN1, PS2_4_FN2,
+       PS2_2_FN1, PS2_2_FN2,
+
+       PS3_15_FN1, PS3_15_FN2,
+       PS3_14_FN1, PS3_14_FN2,
+       PS3_13_FN1, PS3_13_FN2,
+       PS3_12_FN1, PS3_12_FN2,
+       PS3_11_FN1, PS3_11_FN2,
+       PS3_10_FN1, PS3_10_FN2,
+       PS3_9_FN1, PS3_9_FN2,
+       PS3_8_FN1, PS3_8_FN2,
+       PS3_7_FN1, PS3_7_FN2,
+       PS3_2_FN1, PS3_2_FN2,
+       PS3_1_FN1, PS3_1_FN2,
 
-       PS2_13_FN1, PS2_13_FN3,
-       PS2_12_FN1, PS2_12_FN3,
-       PS2_1_FN1, PS2_1_FN2,
-       PS2_0_FN1, PS2_0_FN2,
-
-       PS4_15_FN1, PS4_15_FN2,
        PS4_14_FN1, PS4_14_FN2,
        PS4_13_FN1, PS4_13_FN2,
        PS4_12_FN1, PS4_12_FN2,
-       PS4_11_FN1, PS4_11_FN2,
        PS4_10_FN1, PS4_10_FN2,
        PS4_9_FN1, PS4_9_FN2,
+       PS4_8_FN1, PS4_8_FN2,
+       PS4_4_FN1, PS4_4_FN2,
        PS4_3_FN1, PS4_3_FN2,
        PS4_2_FN1, PS4_2_FN2,
        PS4_1_FN1, PS4_1_FN2,
        PS4_0_FN1, PS4_0_FN2,
 
+       PS5_11_FN1, PS5_11_FN2,
+       PS5_10_FN1, PS5_10_FN2,
        PS5_9_FN1, PS5_9_FN2,
        PS5_8_FN1, PS5_8_FN2,
        PS5_7_FN1, PS5_7_FN2,
        PS5_6_FN1, PS5_6_FN2,
        PS5_5_FN1, PS5_5_FN2,
        PS5_4_FN1, PS5_4_FN2,
-
-       /* AN15 to 8 : EVENT15 to 8 */
-       PS6_7_FN_AN, PS6_7_FN_EV,
-       PS6_6_FN_AN, PS6_6_FN_EV,
-       PS6_5_FN_AN, PS6_5_FN_EV,
-       PS6_4_FN_AN, PS6_4_FN_EV,
-       PS6_3_FN_AN, PS6_3_FN_EV,
-       PS6_2_FN_AN, PS6_2_FN_EV,
-       PS6_1_FN_AN, PS6_1_FN_EV,
-       PS6_0_FN_AN, PS6_0_FN_EV,
-
+       PS5_3_FN1, PS5_3_FN2,
+       PS5_2_FN1, PS5_2_FN2,
+
+       PS6_15_FN1, PS6_15_FN2,
+       PS6_14_FN1, PS6_14_FN2,
+       PS6_13_FN1, PS6_13_FN2,
+       PS6_12_FN1, PS6_12_FN2,
+       PS6_11_FN1, PS6_11_FN2,
+       PS6_10_FN1, PS6_10_FN2,
+       PS6_9_FN1, PS6_9_FN2,
+       PS6_8_FN1, PS6_8_FN2,
+       PS6_7_FN1, PS6_7_FN2,
+       PS6_6_FN1, PS6_6_FN2,
+       PS6_5_FN1, PS6_5_FN2,
+       PS6_4_FN1, PS6_4_FN2,
+       PS6_3_FN1, PS6_3_FN2,
+       PS6_2_FN1, PS6_2_FN2,
+       PS6_1_FN1, PS6_1_FN2,
+       PS6_0_FN1, PS6_0_FN2,
+
+       PS7_15_FN1, PS7_15_FN2,
+       PS7_14_FN1, PS7_14_FN2,
+       PS7_13_FN1, PS7_13_FN2,
+       PS7_12_FN1, PS7_12_FN2,
+       PS7_11_FN1, PS7_11_FN2,
+       PS7_10_FN1, PS7_10_FN2,
+       PS7_9_FN1, PS7_9_FN2,
+       PS7_8_FN1, PS7_8_FN2,
+       PS7_7_FN1, PS7_7_FN2,
+       PS7_6_FN1, PS7_6_FN2,
+       PS7_5_FN1, PS7_5_FN2,
+       PS7_4_FN1, PS7_4_FN2,
+
+       PS8_15_FN1, PS8_15_FN2,
+       PS8_14_FN1, PS8_14_FN2,
+       PS8_13_FN1, PS8_13_FN2,
+       PS8_12_FN1, PS8_12_FN2,
+       PS8_11_FN1, PS8_11_FN2,
+       PS8_10_FN1, PS8_10_FN2,
+       PS8_9_FN1, PS8_9_FN2,
+       PS8_8_FN1, PS8_8_FN2,
        PINMUX_FUNCTION_END,
 
        PINMUX_MARK_BEGIN,
-       /* PTA (mobule: LBSC, CPG, LPC) */
+       /* PTA (mobule: LBSC, RGMII) */
        BS_MARK,        RDWR_MARK,      WE1_MARK,       RDY_MARK,
-       MD10_MARK,      MD9_MARK,       MD8_MARK,
-       LGPIO7_MARK,    LGPIO6_MARK,    LGPIO5_MARK,    LGPIO4_MARK,
-       LGPIO3_MARK,    LGPIO2_MARK,    LGPIO1_MARK,    LGPIO0_MARK,
-
-       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
-       D15_MARK,       D14_MARK,       D13_MARK,       D12_MARK,
-       D11_MARK,       D10_MARK,       D9_MARK,        D8_MARK,
        ET0_MDC_MARK,   ET0_MDIO_MARK,  ET1_MDC_MARK,   ET1_MDIO_MARK,
-       SIM_D_MARK,     SIM_CLK_MARK,   SIM_RST_MARK,
-       WPSZ1_MARK,     WPSZ0_MARK,     FWID_MARK,      FLSHSZ_MARK,
-       LPC_SPIEN_MARK, BASEL_MARK,
 
-       /* PTC (mobule: SD) */
-       SD_WP_MARK,     SD_CD_MARK,     SD_CLK_MARK,    SD_CMD_MARK,
-       SD_D3_MARK,     SD_D2_MARK,     SD_D1_MARK,     SD_D0_MARK,
+       /* PTB (mobule: INTC, ONFI, TMU) */
+       IRQ15_MARK,     IRQ14_MARK,     IRQ13_MARK,     IRQ12_MARK,
+       IRQ11_MARK,     IRQ10_MARK,     IRQ9_MARK,      IRQ8_MARK,
+       ON_NRE_MARK,    ON_NWE_MARK,    ON_NWP_MARK,    ON_NCE0_MARK,
+       ON_R_B0_MARK,   ON_ALE_MARK,    ON_CLE_MARK,    TCLK_MARK,
 
-       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       /* PTC (mobule: IRQ, PWMU) */
        IRQ7_MARK,      IRQ6_MARK,      IRQ5_MARK,      IRQ4_MARK,
        IRQ3_MARK,      IRQ2_MARK,      IRQ1_MARK,      IRQ0_MARK,
-       MD6_MARK,       MD5_MARK,       MD3_MARK,       MD2_MARK,
-       MD1_MARK,       MD0_MARK,       ADTRG1_MARK,    ADTRG0_MARK,
-
-       /* PTE (mobule: EtherC) */
-       ET0_CRS_DV_MARK,        ET0_TXD1_MARK,
-       ET0_TXD0_MARK,          ET0_TX_EN_MARK,
-       ET0_REF_CLK_MARK,       ET0_RXD1_MARK,
-       ET0_RXD0_MARK,          ET0_RX_ER_MARK,
-
-       /* PTF (mobule: EtherC) */
-       ET1_CRS_DV_MARK,        ET1_TXD1_MARK,
-       ET1_TXD0_MARK,          ET1_TX_EN_MARK,
-       ET1_REF_CLK_MARK,       ET1_RXD1_MARK,
-       ET1_RXD0_MARK,          ET1_RX_ER_MARK,
-
-       /* PTG (mobule: SYSTEM, PWMX, LPC) */
-       STATUS0_MARK,   STATUS1_MARK,
-       PWX0_MARK,      PWX1_MARK,      PWX2_MARK,      PWX3_MARK,
-       SERIRQ_MARK,    CLKRUN_MARK,    LPCPD_MARK,     LDRQ_MARK,
-
-       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
-       TCLK_MARK,      RXD4_MARK,      TXD4_MARK,
+       PWMU0_MARK,     PWMU1_MARK,     PWMU2_MARK,     PWMU3_MARK,
+       PWMU4_MARK,     PWMU5_MARK,
+
+       /* PTD (mobule: SPI0, DMAC) */
+       SP0_MOSI_MARK,  SP0_MISO_MARK,  SP0_SCK_MARK,   SP0_SCK_FB_MARK,
+       SP0_SS0_MARK,   SP0_SS1_MARK,   SP0_SS2_MARK,   SP0_SS3_MARK,
+       DREQ0_MARK,     DACK0_MARK,     TEND0_MARK,
+
+       /* PTE (mobule: RMII) */
+       RMII0_CRS_DV_MARK,      RMII0_TXD1_MARK,
+       RMII0_TXD0_MARK,        RMII0_TXEN_MARK,
+       RMII0_REFCLK_MARK,      RMII0_RXD1_MARK,
+       RMII0_RXD0_MARK,        RMII0_RX_ER_MARK,
+
+       /* PTF (mobule: RMII, SerMux) */
+       RMII1_CRS_DV_MARK,      RMII1_TXD1_MARK,
+       RMII1_TXD0_MARK,        RMII1_TXEN_MARK,
+       RMII1_REFCLK_MARK,      RMII1_RXD1_MARK,
+       RMII1_RXD0_MARK,        RMII1_RX_ER_MARK,
+       RAC_RI_MARK,
+
+       /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */
+       BOOTFMS_MARK,   BOOTWP_MARK,    A25_MARK,       A24_MARK,
+       SERIRQ_MARK,    WDTOVF_MARK,    LPCPD_MARK,     LDRQ_MARK,
+       MMCCLK_MARK,    MMCCMD_MARK,
+
+       /* PTH (mobule: SPI1, LPC, DMAC, ADC) */
        SP1_MOSI_MARK,  SP1_MISO_MARK,  SP1_SCK_MARK,   SP1_SCK_FB_MARK,
-       SP1_SS0_MARK,   SP1_SS1_MARK,   SP0_SS1_MARK,
+       SP1_SS0_MARK,   SP1_SS1_MARK,   WP_MARK,        FMS0_MARK,
+       TEND1_MARK,     DREQ1_MARK,     DACK1_MARK,     ADTRG1_MARK,
+       ADTRG0_MARK,
 
-       /* PTI (mobule: INTC) */
-       IRQ15_MARK,     IRQ14_MARK,     IRQ13_MARK,     IRQ12_MARK,
-       IRQ11_MARK,     IRQ10_MARK,     IRQ9_MARK,      IRQ8_MARK,
+       /* PTI (mobule: LBSC, SDHI) */
+       D15_MARK,       D14_MARK,       D13_MARK,       D12_MARK,
+       D11_MARK,       D10_MARK,       D9_MARK,        D8_MARK,
+       SD_WP_MARK,     SD_CD_MARK,     SD_CLK_MARK,    SD_CMD_MARK,
+       SD_D3_MARK,     SD_D2_MARK,     SD_D1_MARK,     SD_D0_MARK,
 
-       /* PTJ (mobule: SCIF234, SERMUX) */
-       RXD3_MARK,      TXD3_MARK,      RXD2_MARK,      TXD2_MARK,
-       COM1_TXD_MARK,  COM1_RXD_MARK,  COM1_RTS_MARK,  COM1_CTS_MARK,
+       /* PTJ (mobule: SCIF234) */
+       RTS3_MARK,      CTS3_MARK,      TXD3_MARK,      RXD3_MARK,
+       RTS4_MARK,      RXD4_MARK,      TXD4_MARK,
 
-       /* PTK (mobule: SERMUX) */
+       /* PTK (mobule: SERMUX, LBSC, SCIF) */
        COM2_TXD_MARK,  COM2_RXD_MARK,  COM2_RTS_MARK,  COM2_CTS_MARK,
-       COM2_DTR_MARK,  COM2_DSR_MARK,  COM2_DCD_MARK,  COM2_RI_MARK,
+       COM2_DTR_MARK,  COM2_DSR_MARK,  COM2_DCD_MARK,  CLKOUT_MARK,
+       SCK2_MARK,      SCK4_MARK,      SCK3_MARK,
 
-       /* PTL (mobule: SERMUX) */
-       RAC_TXD_MARK,   RAC_RXD_MARK,   RAC_RTS_MARK,   RAC_CTS_MARK,
-       RAC_DTR_MARK,   RAC_DSR_MARK,   RAC_DCD_MARK,   RAC_RI_MARK,
+       /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */
+       RAC_RXD_MARK,   RAC_RTS_MARK,   RAC_CTS_MARK,   RAC_DTR_MARK,
+       RAC_DSR_MARK,   RAC_DCD_MARK,   RAC_TXD_MARK,   RXD2_MARK,
+       CS5_MARK,       CS6_MARK,       AUDSYNC_MARK,   AUDCK_MARK,
+       TXD2_MARK,
 
-       /* PTM (mobule: IIC, LPC) */
+       /* PTM (mobule: LBSC, IIC) */
+       CS4_MARK,       RD_MARK,        WE0_MARK,       CS0_MARK,
        SDA6_MARK,      SCL6_MARK,      SDA7_MARK,      SCL7_MARK,
-       WP_MARK,        FMS0_MARK,      FMS1_MARK,
 
-       /* PTN (mobule: SCIF234, EVC) */
-       SCK2_MARK,      RTS4_MARK,      RTS3_MARK,      RTS2_MARK,
-       CTS4_MARK,      CTS3_MARK,      CTS2_MARK,
-       EVENT7_MARK,    EVENT6_MARK,    EVENT5_MARK,    EVENT4_MARK,
-       EVENT3_MARK,    EVENT2_MARK,    EVENT1_MARK,    EVENT0_MARK,
+       /* PTN (mobule: USB, JMC, SGPIO, WDT) */
+       VBUS_EN_MARK,   VBUS_OC_MARK,   JMCTCK_MARK,    JMCTMS_MARK,
+       JMCTDO_MARK,    JMCTDI_MARK,    JMCTRST_MARK,
+       SGPIO1_CLK_MARK,        SGPIO1_LOAD_MARK,       SGPIO1_DI_MARK,
+       SGPIO1_DO_MARK,         SUB_CLKIN_MARK,
 
-       /* PTO (mobule: SGPIO) */
-       SGPIO0_CLK_MARK,        SGPIO0_LOAD_MARK,
-       SGPIO0_DI_MARK,         SGPIO0_DO_MARK,
-       SGPIO1_CLK_MARK,        SGPIO1_LOAD_MARK,
-       SGPIO1_DI_MARK,         SGPIO1_DO_MARK,
-
-       /* PTP (mobule: JMC, SCIF234) */
-       JMCTCK_MARK,    JMCTMS_MARK,    JMCTDO_MARK,    JMCTDI_MARK,
-       JMCRST_MARK,    SCK4_MARK,      SCK3_MARK,
+       /* PTO (mobule: SGPIO, SerMux) */
+       SGPIO0_CLK_MARK,        SGPIO0_LOAD_MARK,       SGPIO0_DI_MARK,
+       SGPIO0_DO_MARK,         SGPIO2_CLK_MARK,        SGPIO2_LOAD_MARK,
+       SGPIO2_DI_MARK,         SGPIO2_DO_MARK,
+       COM1_TXD_MARK,  COM1_RXD_MARK,  COM1_RTS_MARK,  COM1_CTS_MARK,
 
        /* PTQ (mobule: LPC) */
        LAD3_MARK,      LAD2_MARK,      LAD1_MARK,      LAD0_MARK,
        LFRAME_MARK,    LRESET_MARK,    LCLK_MARK,
 
        /* PTR (mobule: GRA, IIC) */
-       DDC3_MARK,      DDC2_MARK,
-       SDA8_MARK,      SCL8_MARK,      SDA2_MARK,      SCL2_MARK,
+       DDC3_MARK,      DDC2_MARK,      SDA2_MARK,      SCL2_MARK,
        SDA1_MARK,      SCL1_MARK,      SDA0_MARK,      SCL0_MARK,
+       SDA8_MARK,      SCL8_MARK,
 
        /* PTS (mobule: GRA, IIC) */
-       DDC1_MARK,      DDC0_MARK,
-       SDA9_MARK,      SCL9_MARK,      SDA5_MARK,      SCL5_MARK,
+       DDC1_MARK,      DDC0_MARK,      SDA5_MARK,      SCL5_MARK,
        SDA4_MARK,      SCL4_MARK,      SDA3_MARK,      SCL3_MARK,
+       SDA9_MARK,      SCL9_MARK,
 
-       /* PTT (mobule: SYSTEM, PWMX) */
-       AUDSYNC_MARK,           AUDCK_MARK,
-       AUDATA3_MARK,           AUDATA2_MARK,
-       AUDATA1_MARK,           AUDATA0_MARK,
-       PWX7_MARK,      PWX6_MARK,      PWX5_MARK,      PWX4_MARK,
+       /* PTT (mobule: PWMX, AUD) */
+       PWMX7_MARK,     PWMX6_MARK,     PWMX5_MARK,     PWMX4_MARK,
+       PWMX3_MARK,     PWMX2_MARK,     PWMX1_MARK,     PWMX0_MARK,
+       AUDATA3_MARK,   AUDATA2_MARK,   AUDATA1_MARK,   AUDATA0_MARK,
+       STATUS1_MARK,   STATUS0_MARK,
 
-       /* PTU (mobule: LBSC, DMAC) */
-       CS6_MARK,       CS5_MARK,       CS4_MARK,       CS0_MARK,
-       RD_MARK,        WE0_MARK,       A25_MARK,       A24_MARK,
-       DREQ0_MARK,     DACK0_MARK,
+       /* PTU (mobule: LPC, APM) */
+       LGPIO7_MARK,    LGPIO6_MARK,    LGPIO5_MARK,    LGPIO4_MARK,
+       LGPIO3_MARK,    LGPIO2_MARK,    LGPIO1_MARK,    LGPIO0_MARK,
+       APMONCTL_O_MARK,        APMPWBTOUT_O_MARK,      APMSCI_O_MARK,
+       APMVDDON_MARK,  APMSLPBTN_MARK, APMPWRBTN_MARK, APMS5N_MARK,
+       APMS3N_MARK,
 
-       /* PTV (mobule: LBSC, DMAC) */
+       /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */
        A23_MARK,       A22_MARK,       A21_MARK,       A20_MARK,
        A19_MARK,       A18_MARK,       A17_MARK,       A16_MARK,
-       TEND0_MARK,     DREQ1_MARK,     DACK1_MARK,     TEND1_MARK,
+       COM2_RI_MARK,           R_SPI_MOSI_MARK,        R_SPI_MISO_MARK,
+       R_SPI_RSPCK_MARK,       R_SPI_SSL0_MARK,        R_SPI_SSL1_MARK,
+       EVENT7_MARK,    EVENT6_MARK,    VBIOS_DI_MARK,  VBIOS_DO_MARK,
+       VBIOS_CLK_MARK, VBIOS_CS_MARK,
 
-       /* PTW (mobule: LBSC) */
+       /* PTW (mobule: LBSC, EVC, SCIF) */
        A15_MARK,       A14_MARK,       A13_MARK,       A12_MARK,
        A11_MARK,       A10_MARK,       A9_MARK,        A8_MARK,
+       EVENT5_MARK,    EVENT4_MARK,    EVENT3_MARK,    EVENT2_MARK,
+       EVENT1_MARK,    EVENT0_MARK,    CTS4_MARK,      CTS2_MARK,
 
-       /* PTX (mobule: LBSC) */
+       /* PTX (mobule: LBSC, SCIF, SIM) */
        A7_MARK,        A6_MARK,        A5_MARK,        A4_MARK,
        A3_MARK,        A2_MARK,        A1_MARK,        A0_MARK,
+       RTS2_MARK,      SIM_D_MARK,     SIM_CLK_MARK,   SIM_RST_MARK,
 
        /* PTY (mobule: LBSC) */
        D7_MARK,        D6_MARK,        D5_MARK,        D4_MARK,
        D3_MARK,        D2_MARK,        D1_MARK,        D0_MARK,
+
+       /* PTZ (mobule: eMMC, ONFI) */
+       MMCDAT7_MARK,   MMCDAT6_MARK,   MMCDAT5_MARK,   MMCDAT4_MARK,
+       MMCDAT3_MARK,   MMCDAT2_MARK,   MMCDAT1_MARK,   MMCDAT0_MARK,
+       ON_DQ7_MARK,    ON_DQ6_MARK,    ON_DQ5_MARK,    ON_DQ4_MARK,
+       ON_DQ3_MARK,    ON_DQ2_MARK,    ON_DQ1_MARK,    ON_DQ0_MARK,
+
        PINMUX_MARK_END,
 };
 
@@ -473,6 +567,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTD0_DATA, PTD0_IN, PTD0_OUT),
 
        /* PTE GPIO */
+       PINMUX_DATA(PTE7_DATA, PTE7_IN, PTE7_OUT),
+       PINMUX_DATA(PTE6_DATA, PTE6_IN, PTE6_OUT),
        PINMUX_DATA(PTE5_DATA, PTE5_IN, PTE5_OUT),
        PINMUX_DATA(PTE4_DATA, PTE4_IN, PTE4_OUT),
        PINMUX_DATA(PTE3_DATA, PTE3_IN, PTE3_OUT),
@@ -521,7 +617,6 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTI0_DATA, PTI0_IN, PTI0_OUT),
 
        /* PTJ GPIO */
-       PINMUX_DATA(PTJ7_DATA, PTJ7_IN, PTJ7_OUT),
        PINMUX_DATA(PTJ6_DATA, PTJ6_IN, PTJ6_OUT),
        PINMUX_DATA(PTJ5_DATA, PTJ5_IN, PTJ5_OUT),
        PINMUX_DATA(PTJ4_DATA, PTJ4_IN, PTJ4_OUT),
@@ -541,7 +636,6 @@ static pinmux_enum_t pinmux_data[] = {
        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),
@@ -560,7 +654,6 @@ static pinmux_enum_t pinmux_data[] = {
        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),
@@ -609,6 +702,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTS0_DATA, PTS0_IN, PTS0_OUT),
 
        /* PTT GPIO */
+       PINMUX_DATA(PTT7_DATA, PTT7_IN, PTT7_OUT),
+       PINMUX_DATA(PTT6_DATA, PTT6_IN, PTT6_OUT),
        PINMUX_DATA(PTT5_DATA, PTT5_IN, PTT5_OUT),
        PINMUX_DATA(PTT4_DATA, PTT4_IN, PTT4_OUT),
        PINMUX_DATA(PTT3_DATA, PTT3_IN, PTT3_OUT),
@@ -677,186 +772,204 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(PTZ0_DATA, PTZ0_IN, PTZ0_OUT),
 
        /* PTA FN */
-       PINMUX_DATA(BS_MARK, PS0_15_FN1, PTA7_FN),
-       PINMUX_DATA(LGPIO7_MARK, PS0_15_FN3, PTA7_FN),
-       PINMUX_DATA(RDWR_MARK, PS0_14_FN1, PTA6_FN),
-       PINMUX_DATA(LGPIO6_MARK, PS0_14_FN3, PTA6_FN),
-       PINMUX_DATA(WE1_MARK, PS0_13_FN1, PTA5_FN),
-       PINMUX_DATA(LGPIO5_MARK, PS0_13_FN3, PTA5_FN),
-       PINMUX_DATA(RDY_MARK, PS0_12_FN1, PTA4_FN),
-       PINMUX_DATA(LGPIO4_MARK, PS0_12_FN3, PTA4_FN),
-       PINMUX_DATA(LGPIO3_MARK, PTA3_FN),
-       PINMUX_DATA(LGPIO2_MARK, PTA2_FN),
-       PINMUX_DATA(LGPIO1_MARK, PTA1_FN),
-       PINMUX_DATA(LGPIO0_MARK, PTA0_FN),
+       PINMUX_DATA(BS_MARK, PTA7_FN),
+       PINMUX_DATA(RDWR_MARK, PTA6_FN),
+       PINMUX_DATA(WE1_MARK, PTA5_FN),
+       PINMUX_DATA(RDY_MARK, PTA4_FN),
+       PINMUX_DATA(ET0_MDC_MARK, PTA3_FN),
+       PINMUX_DATA(ET0_MDIO_MARK, PTA2_FN),
+       PINMUX_DATA(ET1_MDC_MARK, PTA1_FN),
+       PINMUX_DATA(ET1_MDIO_MARK, PTA0_FN),
 
        /* PTB FN */
-       PINMUX_DATA(D15_MARK, PS0_7_FN1, PTB7_FN),
-       PINMUX_DATA(ET0_MDC_MARK, PS0_7_FN2, PTB7_FN),
-       PINMUX_DATA(D14_MARK, PS0_6_FN1, PTB6_FN),
-       PINMUX_DATA(ET0_MDIO_MARK, PS0_6_FN2, PTB6_FN),
-       PINMUX_DATA(D13_MARK, PS0_5_FN1, PTB5_FN),
-       PINMUX_DATA(ET1_MDC_MARK, PS0_5_FN2, PTB5_FN),
-       PINMUX_DATA(D12_MARK, PS0_4_FN1, PTB4_FN),
-       PINMUX_DATA(ET1_MDIO_MARK, PS0_4_FN2, PTB4_FN),
-       PINMUX_DATA(D11_MARK, PS0_3_FN1, PTB3_FN),
-       PINMUX_DATA(SIM_D_MARK, PS0_3_FN2, PTB3_FN),
-       PINMUX_DATA(D10_MARK, PS0_2_FN1, PTB2_FN),
-       PINMUX_DATA(SIM_CLK_MARK, PS0_2_FN2, PTB2_FN),
-       PINMUX_DATA(D9_MARK, PS0_1_FN1, PTB1_FN),
-       PINMUX_DATA(SIM_RST_MARK, PS0_1_FN2, PTB1_FN),
-       PINMUX_DATA(D8_MARK, PTB0_FN),
+       PINMUX_DATA(IRQ15_MARK, PS0_15_FN1, PTB7_FN),
+       PINMUX_DATA(ON_NRE_MARK, PS0_15_FN2, PTB7_FN),
+       PINMUX_DATA(IRQ14_MARK, PS0_14_FN1, PTB6_FN),
+       PINMUX_DATA(ON_NWE_MARK, PS0_14_FN2, PTB6_FN),
+       PINMUX_DATA(IRQ13_MARK, PS0_13_FN1, PTB5_FN),
+       PINMUX_DATA(ON_NWP_MARK, PS0_13_FN2, PTB5_FN),
+       PINMUX_DATA(IRQ12_MARK, PS0_12_FN1, PTB4_FN),
+       PINMUX_DATA(ON_NCE0_MARK, PS0_12_FN2, PTB4_FN),
+       PINMUX_DATA(IRQ11_MARK, PS0_11_FN1, PTB3_FN),
+       PINMUX_DATA(ON_R_B0_MARK, PS0_11_FN2, PTB3_FN),
+       PINMUX_DATA(IRQ10_MARK, PS0_10_FN1, PTB2_FN),
+       PINMUX_DATA(ON_ALE_MARK, PS0_10_FN2, PTB2_FN),
+       PINMUX_DATA(IRQ9_MARK, PS0_9_FN1, PTB1_FN),
+       PINMUX_DATA(ON_CLE_MARK, PS0_9_FN2, PTB1_FN),
+       PINMUX_DATA(IRQ8_MARK, PS0_8_FN1, PTB0_FN),
+       PINMUX_DATA(TCLK_MARK, PS0_8_FN2, PTB0_FN),
 
        /* PTC FN */
-       PINMUX_DATA(SD_WP_MARK, PTC7_FN),
-       PINMUX_DATA(SD_CD_MARK, PTC6_FN),
-       PINMUX_DATA(SD_CLK_MARK, PTC5_FN),
-       PINMUX_DATA(SD_CMD_MARK, PTC4_FN),
-       PINMUX_DATA(SD_D3_MARK, PTC3_FN),
-       PINMUX_DATA(SD_D2_MARK, PTC2_FN),
-       PINMUX_DATA(SD_D1_MARK, PTC1_FN),
-       PINMUX_DATA(SD_D0_MARK, PTC0_FN),
+       PINMUX_DATA(IRQ7_MARK, PS0_7_FN1, PTC7_FN),
+       PINMUX_DATA(PWMU0_MARK, PS0_7_FN2, PTC7_FN),
+       PINMUX_DATA(IRQ6_MARK, PS0_6_FN1, PTC6_FN),
+       PINMUX_DATA(PWMU1_MARK, PS0_6_FN2, PTC6_FN),
+       PINMUX_DATA(IRQ5_MARK, PS0_5_FN1, PTC5_FN),
+       PINMUX_DATA(PWMU2_MARK, PS0_5_FN2, PTC5_FN),
+       PINMUX_DATA(IRQ4_MARK, PS0_4_FN1, PTC5_FN),
+       PINMUX_DATA(PWMU3_MARK, PS0_4_FN2, PTC4_FN),
+       PINMUX_DATA(IRQ3_MARK, PS0_3_FN1, PTC3_FN),
+       PINMUX_DATA(PWMU4_MARK, PS0_3_FN2, PTC3_FN),
+       PINMUX_DATA(IRQ2_MARK, PS0_2_FN1, PTC2_FN),
+       PINMUX_DATA(PWMU5_MARK, PS0_2_FN2, PTC2_FN),
+       PINMUX_DATA(IRQ1_MARK, PTC1_FN),
+       PINMUX_DATA(IRQ0_MARK, PTC0_FN),
 
        /* PTD FN */
-       PINMUX_DATA(IRQ7_MARK, PS1_7_FN1, PTD7_FN),
-       PINMUX_DATA(ADTRG1_MARK, PS1_7_FN3, PTD7_FN),
-       PINMUX_DATA(IRQ6_MARK, PS1_6_FN1, PTD6_FN),
-       PINMUX_DATA(ADTRG0_MARK, PS1_6_FN3, PTD6_FN),
-       PINMUX_DATA(IRQ5_MARK, PTD5_FN),
-       PINMUX_DATA(IRQ4_MARK, PTD4_FN),
-       PINMUX_DATA(IRQ3_MARK, PTD3_FN),
-       PINMUX_DATA(IRQ2_MARK, PTD2_FN),
-       PINMUX_DATA(IRQ1_MARK, PTD1_FN),
-       PINMUX_DATA(IRQ0_MARK, PTD0_FN),
+       PINMUX_DATA(SP0_MOSI_MARK, PTD7_FN),
+       PINMUX_DATA(SP0_MISO_MARK, PTD6_FN),
+       PINMUX_DATA(SP0_SCK_MARK, PTD5_FN),
+       PINMUX_DATA(SP0_SCK_FB_MARK, PTD4_FN),
+       PINMUX_DATA(SP0_SS0_MARK, PTD3_FN),
+       PINMUX_DATA(SP0_SS1_MARK, PS1_10_FN1, PTD2_FN),
+       PINMUX_DATA(DREQ0_MARK, PS1_10_FN2, PTD2_FN),
+       PINMUX_DATA(SP0_SS2_MARK, PS1_9_FN1, PTD1_FN),
+       PINMUX_DATA(DACK0_MARK, PS1_9_FN2, PTD1_FN),
+       PINMUX_DATA(SP0_SS3_MARK, PS1_8_FN1, PTD0_FN),
+       PINMUX_DATA(TEND0_MARK, PS1_8_FN2, PTD0_FN),
 
        /* PTE FN */
-       PINMUX_DATA(ET0_CRS_DV_MARK, PTE7_FN),
-       PINMUX_DATA(ET0_TXD1_MARK, PTE6_FN),
-       PINMUX_DATA(ET0_TXD0_MARK, PTE5_FN),
-       PINMUX_DATA(ET0_TX_EN_MARK, PTE4_FN),
-       PINMUX_DATA(ET0_REF_CLK_MARK, PTE3_FN),
-       PINMUX_DATA(ET0_RXD1_MARK, PTE2_FN),
-       PINMUX_DATA(ET0_RXD0_MARK, PTE1_FN),
-       PINMUX_DATA(ET0_RX_ER_MARK, PTE0_FN),
+       PINMUX_DATA(RMII0_CRS_DV_MARK, PTE7_FN),
+       PINMUX_DATA(RMII0_TXD1_MARK, PTE6_FN),
+       PINMUX_DATA(RMII0_TXD0_MARK, PTE5_FN),
+       PINMUX_DATA(RMII0_TXEN_MARK, PTE4_FN),
+       PINMUX_DATA(RMII0_REFCLK_MARK, PTE3_FN),
+       PINMUX_DATA(RMII0_RXD1_MARK, PTE2_FN),
+       PINMUX_DATA(RMII0_RXD0_MARK, PTE1_FN),
+       PINMUX_DATA(RMII0_RX_ER_MARK, PTE0_FN),
 
        /* PTF FN */
-       PINMUX_DATA(ET1_CRS_DV_MARK, PTF7_FN),
-       PINMUX_DATA(ET1_TXD1_MARK, PTF6_FN),
-       PINMUX_DATA(ET1_TXD0_MARK, PTF5_FN),
-       PINMUX_DATA(ET1_TX_EN_MARK, PTF4_FN),
-       PINMUX_DATA(ET1_REF_CLK_MARK, PTF3_FN),
-       PINMUX_DATA(ET1_RXD1_MARK, PTF2_FN),
-       PINMUX_DATA(ET1_RXD0_MARK, PTF1_FN),
-       PINMUX_DATA(ET1_RX_ER_MARK, PTF0_FN),
+       PINMUX_DATA(RMII1_CRS_DV_MARK, PTF7_FN),
+       PINMUX_DATA(RMII1_TXD1_MARK, PTF6_FN),
+       PINMUX_DATA(RMII1_TXD0_MARK, PTF5_FN),
+       PINMUX_DATA(RMII1_TXEN_MARK, PTF4_FN),
+       PINMUX_DATA(RMII1_REFCLK_MARK, PTF3_FN),
+       PINMUX_DATA(RMII1_RXD1_MARK, PS1_2_FN1, PTF2_FN),
+       PINMUX_DATA(RAC_RI_MARK, PS1_2_FN2, PTF2_FN),
+       PINMUX_DATA(RMII1_RXD0_MARK, PTF1_FN),
+       PINMUX_DATA(RMII1_RX_ER_MARK, PTF0_FN),
 
        /* PTG FN */
-       PINMUX_DATA(PWX0_MARK, PTG7_FN),
-       PINMUX_DATA(PWX1_MARK, PTG6_FN),
-       PINMUX_DATA(STATUS0_MARK, PS2_13_FN1, PTG5_FN),
-       PINMUX_DATA(PWX2_MARK, PS2_13_FN3, PTG5_FN),
-       PINMUX_DATA(STATUS1_MARK, PS2_12_FN1, PTG4_FN),
-       PINMUX_DATA(PWX3_MARK, PS2_12_FN3, PTG4_FN),
+       PINMUX_DATA(BOOTFMS_MARK, PTG7_FN),
+       PINMUX_DATA(BOOTWP_MARK, PTG6_FN),
+       PINMUX_DATA(A25_MARK, PS2_13_FN1, PTG5_FN),
+       PINMUX_DATA(MMCCLK_MARK, PS2_13_FN2, PTG5_FN),
+       PINMUX_DATA(A24_MARK, PS2_12_FN1, PTG4_FN),
+       PINMUX_DATA(MMCCMD_MARK, PS2_12_FN2, PTG4_FN),
        PINMUX_DATA(SERIRQ_MARK, PTG3_FN),
-       PINMUX_DATA(CLKRUN_MARK, PTG2_FN),
+       PINMUX_DATA(WDTOVF_MARK, PTG2_FN),
        PINMUX_DATA(LPCPD_MARK, PTG1_FN),
        PINMUX_DATA(LDRQ_MARK, PTG0_FN),
 
        /* PTH FN */
-       PINMUX_DATA(SP1_MOSI_MARK, PTH7_FN),
-       PINMUX_DATA(SP1_MISO_MARK, PTH6_FN),
-       PINMUX_DATA(SP1_SCK_MARK, PTH5_FN),
-       PINMUX_DATA(SP1_SCK_FB_MARK, PTH4_FN),
+       PINMUX_DATA(SP1_MOSI_MARK, PS2_7_FN1, PTH7_FN),
+       PINMUX_DATA(TEND1_MARK, PS2_7_FN2, PTH7_FN),
+       PINMUX_DATA(SP1_MISO_MARK, PS2_6_FN1, PTH6_FN),
+       PINMUX_DATA(DREQ1_MARK, PS2_6_FN2, PTH6_FN),
+       PINMUX_DATA(SP1_SCK_MARK, PS2_5_FN1, PTH5_FN),
+       PINMUX_DATA(DACK1_MARK, PS2_5_FN2, PTH5_FN),
+       PINMUX_DATA(SP1_SCK_FB_MARK, PS2_4_FN1, PTH4_FN),
+       PINMUX_DATA(ADTRG1_MARK, PS2_4_FN2, PTH4_FN),
        PINMUX_DATA(SP1_SS0_MARK, PTH3_FN),
-       PINMUX_DATA(TCLK_MARK, PTH2_FN),
-       PINMUX_DATA(RXD4_MARK, PS2_1_FN1, PTH1_FN),
-       PINMUX_DATA(SP1_SS1_MARK, PS2_1_FN2, PTH1_FN),
-       PINMUX_DATA(TXD4_MARK, PS2_0_FN1, PTH0_FN),
-       PINMUX_DATA(SP0_SS1_MARK, PS2_0_FN2, PTH0_FN),
+       PINMUX_DATA(SP1_SS1_MARK, PS2_2_FN1, PTH2_FN),
+       PINMUX_DATA(ADTRG0_MARK, PS2_2_FN2, PTH2_FN),
+       PINMUX_DATA(WP_MARK, PTH1_FN),
+       PINMUX_DATA(FMS0_MARK, PTH0_FN),
 
        /* PTI FN */
-       PINMUX_DATA(IRQ15_MARK, PTI7_FN),
-       PINMUX_DATA(IRQ14_MARK, PTI6_FN),
-       PINMUX_DATA(IRQ13_MARK, PTI5_FN),
-       PINMUX_DATA(IRQ12_MARK, PTI4_FN),
-       PINMUX_DATA(IRQ11_MARK, PTI3_FN),
-       PINMUX_DATA(IRQ10_MARK, PTI2_FN),
-       PINMUX_DATA(IRQ9_MARK, PTI1_FN),
-       PINMUX_DATA(IRQ8_MARK, PTI0_FN),
+       PINMUX_DATA(D15_MARK, PS3_15_FN1, PTI7_FN),
+       PINMUX_DATA(SD_WP_MARK, PS3_15_FN2, PTI7_FN),
+       PINMUX_DATA(D14_MARK, PS3_14_FN1, PTI6_FN),
+       PINMUX_DATA(SD_CD_MARK, PS3_14_FN2, PTI6_FN),
+       PINMUX_DATA(D13_MARK, PS3_13_FN1, PTI5_FN),
+       PINMUX_DATA(SD_CLK_MARK, PS3_13_FN2, PTI5_FN),
+       PINMUX_DATA(D12_MARK, PS3_12_FN1, PTI4_FN),
+       PINMUX_DATA(SD_CMD_MARK, PS3_12_FN2, PTI4_FN),
+       PINMUX_DATA(D11_MARK, PS3_11_FN1, PTI3_FN),
+       PINMUX_DATA(SD_D3_MARK, PS3_11_FN2, PTI3_FN),
+       PINMUX_DATA(D10_MARK, PS3_10_FN1, PTI2_FN),
+       PINMUX_DATA(SD_D2_MARK, PS3_10_FN2, PTI2_FN),
+       PINMUX_DATA(D9_MARK, PS3_9_FN1, PTI1_FN),
+       PINMUX_DATA(SD_D1_MARK, PS3_9_FN2, PTI1_FN),
+       PINMUX_DATA(D8_MARK, PS3_8_FN1, PTI0_FN),
+       PINMUX_DATA(SD_D0_MARK, PS3_8_FN2, PTI0_FN),
 
        /* PTJ FN */
-       PINMUX_DATA(RXD3_MARK, PTJ7_FN),
-       PINMUX_DATA(TXD3_MARK, PTJ6_FN),
-       PINMUX_DATA(RXD2_MARK, PTJ5_FN),
-       PINMUX_DATA(TXD2_MARK, PTJ4_FN),
-       PINMUX_DATA(COM1_TXD_MARK, PTJ3_FN),
-       PINMUX_DATA(COM1_RXD_MARK, PTJ2_FN),
-       PINMUX_DATA(COM1_RTS_MARK, PTJ1_FN),
-       PINMUX_DATA(COM1_CTS_MARK, PTJ0_FN),
+       PINMUX_DATA(RTS3_MARK, PTJ6_FN),
+       PINMUX_DATA(CTS3_MARK, PTJ5_FN),
+       PINMUX_DATA(TXD3_MARK, PTJ4_FN),
+       PINMUX_DATA(RXD3_MARK, PTJ3_FN),
+       PINMUX_DATA(RTS4_MARK, PTJ2_FN),
+       PINMUX_DATA(RXD4_MARK, PTJ1_FN),
+       PINMUX_DATA(TXD4_MARK, PTJ0_FN),
 
        /* PTK FN */
-       PINMUX_DATA(COM2_TXD_MARK, PTK7_FN),
+       PINMUX_DATA(COM2_TXD_MARK, PS3_7_FN1, PTK7_FN),
+       PINMUX_DATA(SCK2_MARK, PS3_7_FN2, PTK7_FN),
        PINMUX_DATA(COM2_RXD_MARK, PTK6_FN),
        PINMUX_DATA(COM2_RTS_MARK, PTK5_FN),
        PINMUX_DATA(COM2_CTS_MARK, PTK4_FN),
        PINMUX_DATA(COM2_DTR_MARK, PTK3_FN),
-       PINMUX_DATA(COM2_DSR_MARK, PTK2_FN),
-       PINMUX_DATA(COM2_DCD_MARK, PTK1_FN),
-       PINMUX_DATA(COM2_RI_MARK, PTK0_FN),
+       PINMUX_DATA(COM2_DSR_MARK, PS3_2_FN1, PTK2_FN),
+       PINMUX_DATA(SCK4_MARK, PS3_2_FN2, PTK2_FN),
+       PINMUX_DATA(COM2_DCD_MARK, PS3_1_FN1, PTK1_FN),
+       PINMUX_DATA(SCK3_MARK, PS3_1_FN2, PTK1_FN),
+       PINMUX_DATA(CLKOUT_MARK, PTK0_FN),
 
        /* PTL FN */
-       PINMUX_DATA(RAC_TXD_MARK, PTL7_FN),
-       PINMUX_DATA(RAC_RXD_MARK, PTL6_FN),
-       PINMUX_DATA(RAC_RTS_MARK, PTL5_FN),
-       PINMUX_DATA(RAC_CTS_MARK, PTL4_FN),
+       PINMUX_DATA(RAC_RXD_MARK, PS4_14_FN1, PTL6_FN),
+       PINMUX_DATA(RXD2_MARK, PS4_14_FN2, PTL6_FN),
+       PINMUX_DATA(RAC_RTS_MARK, PS4_13_FN1, PTL5_FN),
+       PINMUX_DATA(CS5_MARK, PS4_13_FN2, PTL5_FN),
+       PINMUX_DATA(RAC_CTS_MARK, PS4_12_FN1, PTL4_FN),
+       PINMUX_DATA(CS6_MARK, PS4_12_FN2, PTL4_FN),
        PINMUX_DATA(RAC_DTR_MARK, PTL3_FN),
-       PINMUX_DATA(RAC_DSR_MARK, PTL2_FN),
-       PINMUX_DATA(RAC_DCD_MARK, PTL1_FN),
-       PINMUX_DATA(RAC_RI_MARK, PTL0_FN),
+       PINMUX_DATA(RAC_DSR_MARK, PS4_10_FN1, PTL2_FN),
+       PINMUX_DATA(AUDSYNC_MARK, PS4_10_FN2, PTL2_FN),
+       PINMUX_DATA(RAC_DCD_MARK, PS4_9_FN1, PTL1_FN),
+       PINMUX_DATA(AUDCK_MARK, PS4_9_FN2, PTL1_FN),
+       PINMUX_DATA(RAC_TXD_MARK, PS4_8_FN1, PTL0_FN),
+       PINMUX_DATA(TXD2_MARK, PS4_8_FN1, PTL0_FN),
 
        /* PTM FN */
-       PINMUX_DATA(WP_MARK, PTM6_FN),
-       PINMUX_DATA(FMS0_MARK, PTM5_FN),
-       PINMUX_DATA(FMS1_MARK, PTM4_FN),
+       PINMUX_DATA(CS4_MARK, PTM7_FN),
+       PINMUX_DATA(RD_MARK, PTM6_FN),
+       PINMUX_DATA(WE0_MARK, PTM7_FN),
+       PINMUX_DATA(CS0_MARK, PTM4_FN),
        PINMUX_DATA(SDA6_MARK, PTM3_FN),
        PINMUX_DATA(SCL6_MARK, PTM2_FN),
        PINMUX_DATA(SDA7_MARK, PTM1_FN),
        PINMUX_DATA(SCL7_MARK, PTM0_FN),
 
        /* PTN FN */
-       PINMUX_DATA(SCK2_MARK, PS4_15_FN1, PTN7_FN),
-       PINMUX_DATA(EVENT7_MARK, PS4_15_FN2, PTN7_FN),
-       PINMUX_DATA(RTS4_MARK, PS4_14_FN1, PTN6_FN),
-       PINMUX_DATA(EVENT6_MARK, PS4_14_FN2, PTN6_FN),
-       PINMUX_DATA(RTS3_MARK, PS4_13_FN1, PTN5_FN),
-       PINMUX_DATA(EVENT5_MARK, PS4_13_FN2, PTN5_FN),
-       PINMUX_DATA(RTS2_MARK, PS4_12_FN1, PTN4_FN),
-       PINMUX_DATA(EVENT4_MARK, PS4_12_FN2, PTN4_FN),
-       PINMUX_DATA(CTS4_MARK, PS4_11_FN1, PTN3_FN),
-       PINMUX_DATA(EVENT3_MARK, PS4_11_FN2, PTN3_FN),
-       PINMUX_DATA(CTS3_MARK, PS4_10_FN1, PTN2_FN),
-       PINMUX_DATA(EVENT2_MARK, PS4_10_FN2, PTN2_FN),
-       PINMUX_DATA(CTS2_MARK, PS4_9_FN1, PTN1_FN),
-       PINMUX_DATA(EVENT1_MARK, PS4_9_FN2, PTN1_FN),
-       PINMUX_DATA(EVENT0_MARK, PTN0_FN),
+       PINMUX_DATA(VBUS_EN_MARK, PTN6_FN),
+       PINMUX_DATA(VBUS_OC_MARK, PTN5_FN),
+       PINMUX_DATA(JMCTCK_MARK, PS4_4_FN1, PTN4_FN),
+       PINMUX_DATA(SGPIO1_CLK_MARK, PS4_4_FN2, PTN4_FN),
+       PINMUX_DATA(JMCTMS_MARK, PS4_3_FN1, PTN5_FN),
+       PINMUX_DATA(SGPIO1_LOAD_MARK, PS4_3_FN2, PTN5_FN),
+       PINMUX_DATA(JMCTDO_MARK, PS4_2_FN1, PTN2_FN),
+       PINMUX_DATA(SGPIO1_DO_MARK, PS4_2_FN2, PTN2_FN),
+       PINMUX_DATA(JMCTDI_MARK, PS4_1_FN1, PTN1_FN),
+       PINMUX_DATA(SGPIO1_DI_MARK, PS4_1_FN2, PTN1_FN),
+       PINMUX_DATA(JMCTRST_MARK, PS4_0_FN1, PTN0_FN),
+       PINMUX_DATA(SUB_CLKIN_MARK, PS4_0_FN2, PTN0_FN),
 
        /* PTO FN */
        PINMUX_DATA(SGPIO0_CLK_MARK, PTO7_FN),
        PINMUX_DATA(SGPIO0_LOAD_MARK, PTO6_FN),
        PINMUX_DATA(SGPIO0_DI_MARK, PTO5_FN),
        PINMUX_DATA(SGPIO0_DO_MARK, PTO4_FN),
-       PINMUX_DATA(SGPIO1_CLK_MARK, PTO3_FN),
-       PINMUX_DATA(SGPIO1_LOAD_MARK, PTO2_FN),
-       PINMUX_DATA(SGPIO1_DI_MARK, PTO1_FN),
-       PINMUX_DATA(SGPIO1_DO_MARK, PTO0_FN),
+       PINMUX_DATA(SGPIO2_CLK_MARK, PS5_11_FN1, PTO3_FN),
+       PINMUX_DATA(COM1_TXD_MARK, PS5_11_FN2, PTO3_FN),
+       PINMUX_DATA(SGPIO2_LOAD_MARK, PS5_10_FN1, PTO2_FN),
+       PINMUX_DATA(COM1_RXD_MARK, PS5_10_FN2, PTO2_FN),
+       PINMUX_DATA(SGPIO2_DI_MARK, PS5_9_FN1, PTO1_FN),
+       PINMUX_DATA(COM1_RTS_MARK, PS5_9_FN2, PTO1_FN),
+       PINMUX_DATA(SGPIO2_DO_MARK, PS5_8_FN1, PTO0_FN),
+       PINMUX_DATA(COM1_CTS_MARK, PS5_8_FN2, PTO0_FN),
 
        /* PTP FN */
-       PINMUX_DATA(JMCTCK_MARK, PTP6_FN),
-       PINMUX_DATA(JMCTMS_MARK, PTP5_FN),
-       PINMUX_DATA(JMCTDO_MARK, PTP4_FN),
-       PINMUX_DATA(JMCTDI_MARK, PTP3_FN),
-       PINMUX_DATA(JMCRST_MARK, PTP2_FN),
-       PINMUX_DATA(SCK4_MARK, PTP1_FN),
-       PINMUX_DATA(SCK3_MARK, PTP0_FN),
 
        /* PTQ FN */
        PINMUX_DATA(LAD3_MARK, PTQ6_FN),
@@ -864,8 +977,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(LAD1_MARK, PTQ4_FN),
        PINMUX_DATA(LAD0_MARK, PTQ3_FN),
        PINMUX_DATA(LFRAME_MARK, PTQ2_FN),
-       PINMUX_DATA(SCK4_MARK, PTQ1_FN),
-       PINMUX_DATA(SCK3_MARK, PTQ0_FN),
+       PINMUX_DATA(LRESET_MARK, PTQ1_FN),
+       PINMUX_DATA(LCLK_MARK, PTQ0_FN),
 
        /* PTR FN */
        PINMUX_DATA(SDA8_MARK, PTR7_FN),        /* DDC3? */
@@ -888,58 +1001,84 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(SCL3_MARK, PTS0_FN),
 
        /* PTT FN */
-       PINMUX_DATA(AUDSYNC_MARK, PTS5_FN),
-       PINMUX_DATA(AUDCK_MARK, PTS4_FN),
-       PINMUX_DATA(AUDATA3_MARK, PS4_3_FN1, PTS3_FN),
-       PINMUX_DATA(PWX7_MARK, PS4_3_FN2, PTS3_FN),
-       PINMUX_DATA(AUDATA2_MARK, PS4_2_FN1, PTS2_FN),
-       PINMUX_DATA(PWX6_MARK, PS4_2_FN2, PTS2_FN),
-       PINMUX_DATA(AUDATA1_MARK, PS4_1_FN1, PTS1_FN),
-       PINMUX_DATA(PWX5_MARK, PS4_1_FN2, PTS1_FN),
-       PINMUX_DATA(AUDATA0_MARK, PS4_0_FN1, PTS0_FN),
-       PINMUX_DATA(PWX4_MARK, PS4_0_FN2, PTS0_FN),
+       PINMUX_DATA(PWMX7_MARK, PS5_7_FN1, PTT7_FN),
+       PINMUX_DATA(AUDATA3_MARK, PS5_7_FN2, PTT7_FN),
+       PINMUX_DATA(PWMX6_MARK, PS5_6_FN1, PTT6_FN),
+       PINMUX_DATA(AUDATA2_MARK, PS5_6_FN2, PTT6_FN),
+       PINMUX_DATA(PWMX5_MARK, PS5_5_FN1, PTT5_FN),
+       PINMUX_DATA(AUDATA1_MARK, PS5_5_FN2, PTT5_FN),
+       PINMUX_DATA(PWMX4_MARK, PS5_4_FN1, PTT4_FN),
+       PINMUX_DATA(AUDATA0_MARK, PS5_4_FN2, PTT4_FN),
+       PINMUX_DATA(PWMX3_MARK, PS5_3_FN1, PTT3_FN),
+       PINMUX_DATA(STATUS1_MARK, PS5_3_FN2, PTT3_FN),
+       PINMUX_DATA(PWMX2_MARK, PS5_2_FN1, PTT2_FN),
+       PINMUX_DATA(STATUS0_MARK, PS5_2_FN2, PTT2_FN),
+       PINMUX_DATA(PWMX1_MARK, PTT1_FN),
+       PINMUX_DATA(PWMX0_MARK, PTT0_FN),
 
        /* PTU FN */
-       PINMUX_DATA(CS6_MARK, PTU7_FN),
-       PINMUX_DATA(CS5_MARK, PTU6_FN),
-       PINMUX_DATA(CS4_MARK, PTU5_FN),
-       PINMUX_DATA(CS0_MARK, PTU4_FN),
-       PINMUX_DATA(RD_MARK, PTU3_FN),
-       PINMUX_DATA(WE0_MARK, PTU2_FN),
-       PINMUX_DATA(A25_MARK, PS5_9_FN1, PTU1_FN),
-       PINMUX_DATA(DREQ0_MARK, PS5_9_FN2, PTU1_FN),
-       PINMUX_DATA(A24_MARK, PS5_8_FN1, PTU0_FN),
-       PINMUX_DATA(DACK0_MARK, PS5_8_FN2, PTU0_FN),
+       PINMUX_DATA(LGPIO7_MARK, PS6_15_FN1, PTU7_FN),
+       PINMUX_DATA(APMONCTL_O_MARK, PS6_15_FN2, PTU7_FN),
+       PINMUX_DATA(LGPIO6_MARK, PS6_14_FN1, PTU6_FN),
+       PINMUX_DATA(APMPWBTOUT_O_MARK, PS6_14_FN2, PTU6_FN),
+       PINMUX_DATA(LGPIO5_MARK, PS6_13_FN1, PTU5_FN),
+       PINMUX_DATA(APMSCI_O_MARK, PS6_13_FN2, PTU5_FN),
+       PINMUX_DATA(LGPIO4_MARK, PS6_12_FN1, PTU4_FN),
+       PINMUX_DATA(APMVDDON_MARK, PS6_12_FN2, PTU4_FN),
+       PINMUX_DATA(LGPIO3_MARK, PS6_11_FN1, PTU3_FN),
+       PINMUX_DATA(APMSLPBTN_MARK, PS6_11_FN2, PTU3_FN),
+       PINMUX_DATA(LGPIO2_MARK, PS6_10_FN1, PTU2_FN),
+       PINMUX_DATA(APMPWRBTN_MARK, PS6_10_FN2, PTU2_FN),
+       PINMUX_DATA(LGPIO1_MARK, PS6_9_FN1, PTU1_FN),
+       PINMUX_DATA(APMS5N_MARK, PS6_9_FN2, PTU1_FN),
+       PINMUX_DATA(LGPIO0_MARK, PS6_8_FN1, PTU0_FN),
+       PINMUX_DATA(APMS3N_MARK, PS6_8_FN2, PTU0_FN),
 
        /* PTV FN */
-       PINMUX_DATA(A23_MARK, PS5_7_FN1, PTV7_FN),
-       PINMUX_DATA(TEND0_MARK, PS5_7_FN2, PTV7_FN),
-       PINMUX_DATA(A22_MARK, PS5_6_FN1, PTV6_FN),
-       PINMUX_DATA(DREQ1_MARK, PS5_6_FN2, PTV6_FN),
-       PINMUX_DATA(A21_MARK, PS5_5_FN1, PTV5_FN),
-       PINMUX_DATA(DACK1_MARK, PS5_5_FN2, PTV5_FN),
-       PINMUX_DATA(A20_MARK, PS5_4_FN1, PTV4_FN),
-       PINMUX_DATA(TEND1_MARK, PS5_4_FN2, PTV4_FN),
-       PINMUX_DATA(A19_MARK, PTV3_FN),
-       PINMUX_DATA(A18_MARK, PTV2_FN),
-       PINMUX_DATA(A17_MARK, PTV1_FN),
-       PINMUX_DATA(A16_MARK, PTV0_FN),
+       PINMUX_DATA(A23_MARK, PS6_7_FN1, PTV7_FN),
+       PINMUX_DATA(COM2_RI_MARK, PS6_7_FN2, PTV7_FN),
+       PINMUX_DATA(A22_MARK, PS6_6_FN1, PTV6_FN),
+       PINMUX_DATA(R_SPI_MOSI_MARK, PS6_6_FN2, PTV6_FN),
+       PINMUX_DATA(A21_MARK, PS6_5_FN1, PTV5_FN),
+       PINMUX_DATA(R_SPI_MISO_MARK, PS6_5_FN2, PTV5_FN),
+       PINMUX_DATA(A20_MARK, PS6_4_FN1, PTV4_FN),
+       PINMUX_DATA(R_SPI_RSPCK_MARK, PS6_4_FN2, PTV4_FN),
+       PINMUX_DATA(A19_MARK, PS6_3_FN1, PTV3_FN),
+       PINMUX_DATA(R_SPI_SSL0_MARK, PS6_3_FN2, PTV3_FN),
+       PINMUX_DATA(A18_MARK, PS6_2_FN1, PTV2_FN),
+       PINMUX_DATA(R_SPI_SSL1_MARK, PS6_2_FN2, PTV2_FN),
+       PINMUX_DATA(A17_MARK, PS6_1_FN1, PTV1_FN),
+       PINMUX_DATA(EVENT7_MARK, PS6_1_FN2, PTV1_FN),
+       PINMUX_DATA(A16_MARK, PS6_0_FN1, PTV0_FN),
+       PINMUX_DATA(EVENT6_MARK, PS6_0_FN1, PTV0_FN),
 
        /* PTW FN */
-       PINMUX_DATA(A15_MARK, PTW7_FN),
-       PINMUX_DATA(A14_MARK, PTW6_FN),
-       PINMUX_DATA(A13_MARK, PTW5_FN),
-       PINMUX_DATA(A12_MARK, PTW4_FN),
-       PINMUX_DATA(A11_MARK, PTW3_FN),
-       PINMUX_DATA(A10_MARK, PTW2_FN),
-       PINMUX_DATA(A9_MARK, PTW1_FN),
-       PINMUX_DATA(A8_MARK, PTW0_FN),
+       PINMUX_DATA(A15_MARK, PS7_15_FN1, PTW7_FN),
+       PINMUX_DATA(EVENT5_MARK, PS7_15_FN2, PTW7_FN),
+       PINMUX_DATA(A14_MARK, PS7_14_FN1, PTW6_FN),
+       PINMUX_DATA(EVENT4_MARK, PS7_14_FN2, PTW6_FN),
+       PINMUX_DATA(A13_MARK, PS7_13_FN1, PTW5_FN),
+       PINMUX_DATA(EVENT3_MARK, PS7_13_FN2, PTW5_FN),
+       PINMUX_DATA(A12_MARK, PS7_12_FN1, PTW4_FN),
+       PINMUX_DATA(EVENT2_MARK, PS7_12_FN2, PTW4_FN),
+       PINMUX_DATA(A11_MARK, PS7_11_FN1, PTW3_FN),
+       PINMUX_DATA(EVENT1_MARK, PS7_11_FN2, PTW3_FN),
+       PINMUX_DATA(A10_MARK, PS7_10_FN1, PTW2_FN),
+       PINMUX_DATA(EVENT0_MARK, PS7_10_FN2, PTW2_FN),
+       PINMUX_DATA(A9_MARK, PS7_9_FN1, PTW1_FN),
+       PINMUX_DATA(CTS4_MARK, PS7_9_FN2, PTW1_FN),
+       PINMUX_DATA(A8_MARK, PS7_8_FN1, PTW0_FN),
+       PINMUX_DATA(CTS2_MARK, PS7_8_FN2, PTW0_FN),
 
        /* PTX FN */
-       PINMUX_DATA(A7_MARK, PTX7_FN),
-       PINMUX_DATA(A6_MARK, PTX6_FN),
-       PINMUX_DATA(A5_MARK, PTX5_FN),
-       PINMUX_DATA(A4_MARK, PTX4_FN),
+       PINMUX_DATA(A7_MARK, PS7_7_FN1, PTX7_FN),
+       PINMUX_DATA(RTS2_MARK, PS7_7_FN2, PTX7_FN),
+       PINMUX_DATA(A6_MARK, PS7_6_FN1, PTX6_FN),
+       PINMUX_DATA(SIM_D_MARK, PS7_6_FN2, PTX6_FN),
+       PINMUX_DATA(A5_MARK, PS7_5_FN1, PTX5_FN),
+       PINMUX_DATA(SIM_CLK_MARK, PS7_5_FN2, PTX5_FN),
+       PINMUX_DATA(A4_MARK, PS7_4_FN1, PTX4_FN),
+       PINMUX_DATA(SIM_RST_MARK, PS7_4_FN2, PTX4_FN),
        PINMUX_DATA(A3_MARK, PTX3_FN),
        PINMUX_DATA(A2_MARK, PTX2_FN),
        PINMUX_DATA(A1_MARK, PTX1_FN),
@@ -954,6 +1093,24 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(D2_MARK, PTY2_FN),
        PINMUX_DATA(D1_MARK, PTY1_FN),
        PINMUX_DATA(D0_MARK, PTY0_FN),
+
+       /* PTZ FN */
+       PINMUX_DATA(MMCDAT7_MARK, PS8_15_FN1, PTZ7_FN),
+       PINMUX_DATA(ON_DQ7_MARK, PS8_15_FN2, PTZ7_FN),
+       PINMUX_DATA(MMCDAT6_MARK, PS8_14_FN1, PTZ6_FN),
+       PINMUX_DATA(ON_DQ6_MARK, PS8_14_FN2, PTZ6_FN),
+       PINMUX_DATA(MMCDAT5_MARK, PS8_13_FN1, PTZ5_FN),
+       PINMUX_DATA(ON_DQ5_MARK, PS8_13_FN2, PTZ5_FN),
+       PINMUX_DATA(MMCDAT4_MARK, PS8_12_FN1, PTZ4_FN),
+       PINMUX_DATA(ON_DQ4_MARK, PS8_12_FN2, PTZ4_FN),
+       PINMUX_DATA(MMCDAT3_MARK, PS8_11_FN1, PTZ3_FN),
+       PINMUX_DATA(ON_DQ3_MARK, PS8_11_FN2, PTZ3_FN),
+       PINMUX_DATA(MMCDAT2_MARK, PS8_10_FN1, PTZ2_FN),
+       PINMUX_DATA(ON_DQ2_MARK, PS8_10_FN2, PTZ2_FN),
+       PINMUX_DATA(MMCDAT1_MARK, PS8_9_FN1, PTZ1_FN),
+       PINMUX_DATA(ON_DQ1_MARK, PS8_9_FN2, PTZ1_FN),
+       PINMUX_DATA(MMCDAT0_MARK, PS8_8_FN1, PTZ0_FN),
+       PINMUX_DATA(ON_DQ0_MARK, PS8_8_FN2, PTZ0_FN),
 };
 
 static struct pinmux_gpio pinmux_gpios[] = {
@@ -1048,7 +1205,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTI0, PTI0_DATA),
 
        /* PTJ */
-       PINMUX_GPIO(GPIO_PTJ7, PTJ7_DATA),
        PINMUX_GPIO(GPIO_PTJ6, PTJ6_DATA),
        PINMUX_GPIO(GPIO_PTJ5, PTJ5_DATA),
        PINMUX_GPIO(GPIO_PTJ4, PTJ4_DATA),
@@ -1068,7 +1224,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        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),
@@ -1078,6 +1233,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
        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),
@@ -1087,7 +1243,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        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),
@@ -1107,6 +1262,7 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTO0, PTO0_DATA),
 
        /* PTP */
+       PINMUX_GPIO(GPIO_PTP7, PTP7_DATA),
        PINMUX_GPIO(GPIO_PTP6, PTP6_DATA),
        PINMUX_GPIO(GPIO_PTP5, PTP5_DATA),
        PINMUX_GPIO(GPIO_PTP4, PTP4_DATA),
@@ -1145,6 +1301,8 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTS0, PTS0_DATA),
 
        /* PTT */
+       PINMUX_GPIO(GPIO_PTT7, PTT7_DATA),
+       PINMUX_GPIO(GPIO_PTT6, PTT6_DATA),
        PINMUX_GPIO(GPIO_PTT5, PTT5_DATA),
        PINMUX_GPIO(GPIO_PTT4, PTT4_DATA),
        PINMUX_GPIO(GPIO_PTT3, PTT3_DATA),
@@ -1212,54 +1370,35 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_PTZ1, PTZ1_DATA),
        PINMUX_GPIO(GPIO_PTZ0, PTZ0_DATA),
 
-       /* PTA (mobule: LBSC, CPG, LPC) */
+       /* PTA (mobule: LBSC, RGMII) */
        PINMUX_GPIO(GPIO_FN_BS, BS_MARK),
        PINMUX_GPIO(GPIO_FN_RDWR, RDWR_MARK),
        PINMUX_GPIO(GPIO_FN_WE1, WE1_MARK),
        PINMUX_GPIO(GPIO_FN_RDY, RDY_MARK),
-       PINMUX_GPIO(GPIO_FN_MD10, MD10_MARK),
-       PINMUX_GPIO(GPIO_FN_MD9, MD9_MARK),
-       PINMUX_GPIO(GPIO_FN_MD8, MD8_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK),
-       PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK),
-
-       /* PTB (mobule: LBSC, EtherC, SIM, LPC) */
-       PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
-       PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
-       PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
-       PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
-       PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
-       PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
-       PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
-       PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
        PINMUX_GPIO(GPIO_FN_ET0_MDC, ET0_MDC_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDIO_MARK),
+       PINMUX_GPIO(GPIO_FN_ET0_MDIO, ET0_MDC_MARK),
        PINMUX_GPIO(GPIO_FN_ET1_MDC, ET1_MDC_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDIO_MARK),
-       PINMUX_GPIO(GPIO_FN_WPSZ1, WPSZ1_MARK),
-       PINMUX_GPIO(GPIO_FN_WPSZ0, WPSZ0_MARK),
-       PINMUX_GPIO(GPIO_FN_FWID, FWID_MARK),
-       PINMUX_GPIO(GPIO_FN_FLSHSZ, FLSHSZ_MARK),
-       PINMUX_GPIO(GPIO_FN_LPC_SPIEN, LPC_SPIEN_MARK),
-       PINMUX_GPIO(GPIO_FN_BASEL, BASEL_MARK),
-
-       /* PTC (mobule: SD) */
-       PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK),
-       PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK),
+       PINMUX_GPIO(GPIO_FN_ET1_MDIO, ET1_MDC_MARK),
 
-       /* PTD (mobule: INTC, SPI0, LBSC, CPG, ADC) */
+       /* PTB (mobule: INTC, ONFI, TMU) */
+       PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NRE, ON_NRE_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NWE, ON_NWE_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NWP, ON_NWP_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_NCE0, ON_NCE0_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_R_B0, ON_R_B0_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_ALE, ON_ALE_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_CLE, ON_CLE_MARK),
+       PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK),
+
+       /* PTC (mobule: IRQ, PWMU) */
        PINMUX_GPIO(GPIO_FN_IRQ7, IRQ7_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ6, IRQ6_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ5, IRQ5_MARK),
@@ -1268,80 +1407,102 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_IRQ2, IRQ2_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ1, IRQ1_MARK),
        PINMUX_GPIO(GPIO_FN_IRQ0, IRQ0_MARK),
-       PINMUX_GPIO(GPIO_FN_MD6, MD6_MARK),
-       PINMUX_GPIO(GPIO_FN_MD5, MD5_MARK),
-       PINMUX_GPIO(GPIO_FN_MD3, MD3_MARK),
-       PINMUX_GPIO(GPIO_FN_MD2, MD2_MARK),
-       PINMUX_GPIO(GPIO_FN_MD1, MD1_MARK),
-       PINMUX_GPIO(GPIO_FN_MD0, MD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK),
-       PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU0, PWMU0_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU1, PWMU1_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU2, PWMU2_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU3, PWMU3_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU4, PWMU4_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMU5, PWMU5_MARK),
+
+       /* PTD (mobule: SPI0, DMAC) */
+       PINMUX_GPIO(GPIO_FN_SP0_MOSI, SP0_MOSI_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_MISO, SP0_MISO_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SCK, SP0_SCK_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SCK_FB, SP0_SCK_FB_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS0, SP0_SS0_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS2, SP0_SS2_MARK),
+       PINMUX_GPIO(GPIO_FN_SP0_SS3, SP0_SS3_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
 
-       /* PTE (mobule: EtherC) */
-       PINMUX_GPIO(GPIO_FN_ET0_CRS_DV, ET0_CRS_DV_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_TXD1, ET0_TXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_TXD0, ET0_TXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_TX_EN, ET0_TX_EN_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_REF_CLK, ET0_REF_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_RXD1, ET0_RXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_RXD0, ET0_RXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET0_RX_ER, ET0_RX_ER_MARK),
-
-       /* PTF (mobule: EtherC) */
-       PINMUX_GPIO(GPIO_FN_ET1_CRS_DV, ET1_CRS_DV_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_TXD1, ET1_TXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_TXD0, ET1_TXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_TX_EN, ET1_TX_EN_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_REF_CLK, ET1_REF_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_RXD1, ET1_RXD1_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_RXD0, ET1_RXD0_MARK),
-       PINMUX_GPIO(GPIO_FN_ET1_RX_ER, ET1_RX_ER_MARK),
-
-       /* PTG (mobule: SYSTEM, PWMX, LPC) */
-       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
-       PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX0, PWX0_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX1, PWX1_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX2, PWX2_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX3, PWX3_MARK),
+       /* PTE (mobule: RMII) */
+       PINMUX_GPIO(GPIO_FN_RMII0_CRS_DV, RMII0_CRS_DV_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_TXD1, RMII0_TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_TXD0, RMII0_TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_TXEN, RMII0_TXEN_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_REFCLK, RMII0_REFCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_RXD1, RMII0_RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_RXD0, RMII0_RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII0_RX_ER, RMII0_RX_ER_MARK),
+
+       /* PTF (mobule: RMII, SerMux) */
+       PINMUX_GPIO(GPIO_FN_RMII1_CRS_DV, RMII1_CRS_DV_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_TXD1, RMII1_TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_TXD0, RMII1_TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_TXEN, RMII1_TXEN_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_REFCLK, RMII1_REFCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_RXD1, RMII1_RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_RXD0, RMII1_RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RMII1_RX_ER, RMII1_RX_ER_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK),
+
+       /* PTG (mobule: system, LBSC, LPC, WDT, LPC, eMMC) */
+       PINMUX_GPIO(GPIO_FN_BOOTFMS, BOOTFMS_MARK),
+       PINMUX_GPIO(GPIO_FN_BOOTWP, BOOTWP_MARK),
+       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
+       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
        PINMUX_GPIO(GPIO_FN_SERIRQ, SERIRQ_MARK),
-       PINMUX_GPIO(GPIO_FN_CLKRUN, CLKRUN_MARK),
+       PINMUX_GPIO(GPIO_FN_WDTOVF, WDTOVF_MARK),
        PINMUX_GPIO(GPIO_FN_LPCPD, LPCPD_MARK),
        PINMUX_GPIO(GPIO_FN_LDRQ, LDRQ_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCCLK, MMCCLK_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCCMD, MMCCMD_MARK),
 
-       /* PTH (mobule: TMU, SCIF234, SPI1, SPI0) */
-       PINMUX_GPIO(GPIO_FN_TCLK, TCLK_MARK),
-       PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
-       PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
+       /* PTH (mobule: SPI1, LPC, DMAC, ADC) */
        PINMUX_GPIO(GPIO_FN_SP1_MOSI, SP1_MOSI_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_MISO, SP1_MISO_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SCK, SP1_SCK_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SCK_FB, SP1_SCK_FB_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SS0, SP1_SS0_MARK),
        PINMUX_GPIO(GPIO_FN_SP1_SS1, SP1_SS1_MARK),
-       PINMUX_GPIO(GPIO_FN_SP0_SS1, SP0_SS1_MARK),
+       PINMUX_GPIO(GPIO_FN_WP, WP_MARK),
+       PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK),
+       PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG1, ADTRG1_MARK),
+       PINMUX_GPIO(GPIO_FN_ADTRG0, ADTRG0_MARK),
 
-       /* PTI (mobule: INTC) */
-       PINMUX_GPIO(GPIO_FN_IRQ15, IRQ15_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ14, IRQ14_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ13, IRQ13_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ12, IRQ12_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ11, IRQ11_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ10, IRQ10_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ9, IRQ9_MARK),
-       PINMUX_GPIO(GPIO_FN_IRQ8, IRQ8_MARK),
+       /* PTI (mobule: LBSC, SDHI) */
+       PINMUX_GPIO(GPIO_FN_D15, D15_MARK),
+       PINMUX_GPIO(GPIO_FN_D14, D14_MARK),
+       PINMUX_GPIO(GPIO_FN_D13, D13_MARK),
+       PINMUX_GPIO(GPIO_FN_D12, D12_MARK),
+       PINMUX_GPIO(GPIO_FN_D11, D11_MARK),
+       PINMUX_GPIO(GPIO_FN_D10, D10_MARK),
+       PINMUX_GPIO(GPIO_FN_D9, D9_MARK),
+       PINMUX_GPIO(GPIO_FN_D8, D8_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_WP, SD_WP_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CD, SD_CD_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CLK, SD_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_CMD, SD_CMD_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D3, SD_D3_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D2, SD_D2_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D1, SD_D1_MARK),
+       PINMUX_GPIO(GPIO_FN_SD_D0, SD_D0_MARK),
 
        /* PTJ (mobule: SCIF234, SERMUX) */
-       PINMUX_GPIO(GPIO_FN_RXD3, RXD3_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_RXD2, RXD2_MARK),
-       PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK),
-       PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD3, RXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD4, RXD4_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD4, TXD4_MARK),
 
-       /* PTK (mobule: SERMUX) */
+       /* PTK (mobule: SERMUX, LBSC, SCIF) */
        PINMUX_GPIO(GPIO_FN_COM2_TXD, COM2_TXD_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_RXD, COM2_RXD_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_RTS, COM2_RTS_MARK),
@@ -1349,62 +1510,65 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_COM2_DTR, COM2_DTR_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_DSR, COM2_DSR_MARK),
        PINMUX_GPIO(GPIO_FN_COM2_DCD, COM2_DCD_MARK),
-       PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK),
+       PINMUX_GPIO(GPIO_FN_CLKOUT, CLKOUT_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
 
-       /* PTL (mobule: SERMUX) */
-       PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK),
+       /* PTL (mobule: SERMUX, SCIF, LBSC, AUD) */
        PINMUX_GPIO(GPIO_FN_RAC_RXD, RAC_RXD_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_RTS, RAC_RTS_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_CTS, RAC_CTS_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_DTR, RAC_DTR_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_DSR, RAC_DSR_MARK),
        PINMUX_GPIO(GPIO_FN_RAC_DCD, RAC_DCD_MARK),
-       PINMUX_GPIO(GPIO_FN_RAC_RI, RAC_RI_MARK),
+       PINMUX_GPIO(GPIO_FN_RAC_TXD, RAC_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD2, RXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
+       PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD2, TXD2_MARK),
 
-       /* PTM (mobule: IIC, LPC) */
+       /* PTM (mobule: LBSC, IIC) */
+       PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
+       PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
+       PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK),
+       PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
        PINMUX_GPIO(GPIO_FN_SDA6, SDA6_MARK),
        PINMUX_GPIO(GPIO_FN_SCL6, SCL6_MARK),
        PINMUX_GPIO(GPIO_FN_SDA7, SDA7_MARK),
        PINMUX_GPIO(GPIO_FN_SCL7, SCL7_MARK),
-       PINMUX_GPIO(GPIO_FN_WP, WP_MARK),
-       PINMUX_GPIO(GPIO_FN_FMS0, FMS0_MARK),
-       PINMUX_GPIO(GPIO_FN_FMS1, FMS1_MARK),
 
-       /* PTN (mobule: SCIF234, EVC) */
-       PINMUX_GPIO(GPIO_FN_SCK2, SCK2_MARK),
-       PINMUX_GPIO(GPIO_FN_RTS4, RTS4_MARK),
-       PINMUX_GPIO(GPIO_FN_RTS3, RTS3_MARK),
-       PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK),
-       PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK),
-       PINMUX_GPIO(GPIO_FN_CTS3, CTS3_MARK),
-       PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK),
-       PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK),
+       /* PTN (mobule: USB, JMC, SGPIO, WDT) */
+       PINMUX_GPIO(GPIO_FN_VBUS_EN, VBUS_EN_MARK),
+       PINMUX_GPIO(GPIO_FN_VBUS_OC, VBUS_OC_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK),
+       PINMUX_GPIO(GPIO_FN_JMCTRST, JMCTRST_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_SUB_CLKIN, SUB_CLKIN_MARK),
 
-       /* PTO (mobule: SGPIO) */
+       /* PTO (mobule: SGPIO, SerMux) */
        PINMUX_GPIO(GPIO_FN_SGPIO0_CLK, SGPIO0_CLK_MARK),
        PINMUX_GPIO(GPIO_FN_SGPIO0_LOAD, SGPIO0_LOAD_MARK),
        PINMUX_GPIO(GPIO_FN_SGPIO0_DI, SGPIO0_DI_MARK),
        PINMUX_GPIO(GPIO_FN_SGPIO0_DO, SGPIO0_DO_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_CLK, SGPIO1_CLK_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_LOAD, SGPIO1_LOAD_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_DI, SGPIO1_DI_MARK),
-       PINMUX_GPIO(GPIO_FN_SGPIO1_DO, SGPIO1_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_CLK, SGPIO2_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_LOAD, SGPIO2_LOAD_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_DI, SGPIO2_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_SGPIO2_DO, SGPIO2_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_TXD, COM1_TXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_RXD, COM1_RXD_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_RTS, COM1_RTS_MARK),
+       PINMUX_GPIO(GPIO_FN_COM1_CTS, COM1_CTS_MARK),
 
-       /* PTP (mobule: JMC, SCIF234) */
-       PINMUX_GPIO(GPIO_FN_JMCTCK, JMCTCK_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCTMS, JMCTMS_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCTDO, JMCTDO_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCTDI, JMCTDI_MARK),
-       PINMUX_GPIO(GPIO_FN_JMCRST, JMCRST_MARK),
-       PINMUX_GPIO(GPIO_FN_SCK4, SCK4_MARK),
-       PINMUX_GPIO(GPIO_FN_SCK3, SCK3_MARK),
+       /* PTP (mobule: EVC, ADC) */
 
        /* PTQ (mobule: LPC) */
        PINMUX_GPIO(GPIO_FN_LAD3, LAD3_MARK),
@@ -1439,31 +1603,41 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_SDA3, SDA3_MARK),
        PINMUX_GPIO(GPIO_FN_SCL3, SCL3_MARK),
 
-       /* PTT (mobule: SYSTEM, PWMX) */
-       PINMUX_GPIO(GPIO_FN_AUDSYNC, AUDSYNC_MARK),
-       PINMUX_GPIO(GPIO_FN_AUDCK, AUDCK_MARK),
+       /* PTT (mobule: PWMX, AUD) */
+       PINMUX_GPIO(GPIO_FN_PWMX7, PWMX7_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX6, PWMX6_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX5, PWMX5_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX4, PWMX4_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX3, PWMX3_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX2, PWMX2_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX1, PWMX1_MARK),
+       PINMUX_GPIO(GPIO_FN_PWMX0, PWMX0_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),
-       PINMUX_GPIO(GPIO_FN_PWX7, PWX7_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX6, PWX6_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX5, PWX5_MARK),
-       PINMUX_GPIO(GPIO_FN_PWX4, PWX4_MARK),
-
-       /* PTU (mobule: LBSC, DMAC) */
-       PINMUX_GPIO(GPIO_FN_CS6, CS6_MARK),
-       PINMUX_GPIO(GPIO_FN_CS5, CS5_MARK),
-       PINMUX_GPIO(GPIO_FN_CS4, CS4_MARK),
-       PINMUX_GPIO(GPIO_FN_CS0, CS0_MARK),
-       PINMUX_GPIO(GPIO_FN_RD, RD_MARK),
-       PINMUX_GPIO(GPIO_FN_WE0, WE0_MARK),
-       PINMUX_GPIO(GPIO_FN_A25, A25_MARK),
-       PINMUX_GPIO(GPIO_FN_A24, A24_MARK),
-       PINMUX_GPIO(GPIO_FN_DREQ0, DREQ0_MARK),
-       PINMUX_GPIO(GPIO_FN_DACK0, DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS1, STATUS1_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS0, STATUS0_MARK),
 
-       /* PTV (mobule: LBSC, DMAC) */
+       /* PTU (mobule: LPC, APM) */
+       PINMUX_GPIO(GPIO_FN_LGPIO7, LGPIO7_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO6, LGPIO6_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO5, LGPIO5_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO4, LGPIO4_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO3, LGPIO3_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO2, LGPIO2_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO1, LGPIO1_MARK),
+       PINMUX_GPIO(GPIO_FN_LGPIO0, LGPIO0_MARK),
+       PINMUX_GPIO(GPIO_FN_APMONCTL_O, APMONCTL_O_MARK),
+       PINMUX_GPIO(GPIO_FN_APMPWBTOUT_O, APMPWBTOUT_O_MARK),
+       PINMUX_GPIO(GPIO_FN_APMSCI_O, APMSCI_O_MARK),
+       PINMUX_GPIO(GPIO_FN_APMVDDON, APMVDDON_MARK),
+       PINMUX_GPIO(GPIO_FN_APMSLPBTN, APMSLPBTN_MARK),
+       PINMUX_GPIO(GPIO_FN_APMPWRBTN, APMPWRBTN_MARK),
+       PINMUX_GPIO(GPIO_FN_APMS5N, APMS5N_MARK),
+       PINMUX_GPIO(GPIO_FN_APMS3N, APMS3N_MARK),
+
+       /* PTV (mobule: LBSC, SerMux, R-SPI, EVC, GRA) */
        PINMUX_GPIO(GPIO_FN_A23, A23_MARK),
        PINMUX_GPIO(GPIO_FN_A22, A22_MARK),
        PINMUX_GPIO(GPIO_FN_A21, A21_MARK),
@@ -1472,12 +1646,20 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_A18, A18_MARK),
        PINMUX_GPIO(GPIO_FN_A17, A17_MARK),
        PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
-       PINMUX_GPIO(GPIO_FN_TEND0, TEND0_MARK),
-       PINMUX_GPIO(GPIO_FN_DREQ1, DREQ1_MARK),
-       PINMUX_GPIO(GPIO_FN_DACK1, DACK1_MARK),
-       PINMUX_GPIO(GPIO_FN_TEND1, TEND1_MARK),
+       PINMUX_GPIO(GPIO_FN_COM2_RI, COM2_RI_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_MOSI, R_SPI_MOSI_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_MISO, R_SPI_MISO_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_RSPCK, R_SPI_RSPCK_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_SSL0, R_SPI_SSL0_MARK),
+       PINMUX_GPIO(GPIO_FN_R_SPI_SSL1, R_SPI_SSL1_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT7, EVENT7_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT6, EVENT6_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_DI, VBIOS_DI_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_DO, VBIOS_DO_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_CLK, VBIOS_CLK_MARK),
+       PINMUX_GPIO(GPIO_FN_VBIOS_CS, VBIOS_CS_MARK),
 
-       /* PTW (mobule: LBSC) */
+       /* PTW (mobule: LBSC, EVC, SCIF) */
        PINMUX_GPIO(GPIO_FN_A16, A16_MARK),
        PINMUX_GPIO(GPIO_FN_A15, A15_MARK),
        PINMUX_GPIO(GPIO_FN_A14, A14_MARK),
@@ -1487,6 +1669,14 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_A10, A10_MARK),
        PINMUX_GPIO(GPIO_FN_A9, A9_MARK),
        PINMUX_GPIO(GPIO_FN_A8, A8_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT5, EVENT5_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT4, EVENT4_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT3, EVENT3_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT2, EVENT2_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT1, EVENT1_MARK),
+       PINMUX_GPIO(GPIO_FN_EVENT0, EVENT0_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS4, CTS4_MARK),
+       PINMUX_GPIO(GPIO_FN_CTS2, CTS2_MARK),
 
        /* PTX (mobule: LBSC) */
        PINMUX_GPIO(GPIO_FN_A7, A7_MARK),
@@ -1497,6 +1687,10 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_A2, A2_MARK),
        PINMUX_GPIO(GPIO_FN_A1, A1_MARK),
        PINMUX_GPIO(GPIO_FN_A0, A0_MARK),
+       PINMUX_GPIO(GPIO_FN_RTS2, RTS2_MARK),
+       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),
 
        /* PTY (mobule: LBSC) */
        PINMUX_GPIO(GPIO_FN_D7, D7_MARK),
@@ -1507,18 +1701,36 @@ static struct pinmux_gpio pinmux_gpios[] = {
        PINMUX_GPIO(GPIO_FN_D2, D2_MARK),
        PINMUX_GPIO(GPIO_FN_D1, D1_MARK),
        PINMUX_GPIO(GPIO_FN_D0, D0_MARK),
+
+       /* PTZ (mobule: eMMC, ONFI) */
+       PINMUX_GPIO(GPIO_FN_MMCDAT7, MMCDAT7_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT6, MMCDAT6_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT5, MMCDAT5_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT4, MMCDAT4_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT3, MMCDAT3_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT2, MMCDAT2_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT1, MMCDAT1_MARK),
+       PINMUX_GPIO(GPIO_FN_MMCDAT0, MMCDAT0_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ7, ON_DQ7_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ6, ON_DQ6_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ5, ON_DQ5_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ4, ON_DQ4_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ3, ON_DQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ2, ON_DQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ1, ON_DQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_ON_DQ0, ON_DQ0_MARK),
  };
 
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        { PINMUX_CFG_REG("PACR", 0xffec0000, 16, 2) {
-               PTA7_FN, PTA7_OUT, PTA7_IN, 0,
-               PTA6_FN, PTA6_OUT, PTA6_IN, 0,
-               PTA5_FN, PTA5_OUT, PTA5_IN, 0,
-               PTA4_FN, PTA4_OUT, PTA4_IN, 0,
-               PTA3_FN, PTA3_OUT, PTA3_IN, 0,
-               PTA2_FN, PTA2_OUT, PTA2_IN, 0,
-               PTA1_FN, PTA1_OUT, PTA1_IN, 0,
-               PTA0_FN, PTA0_OUT, PTA0_IN, 0 }
+               PTA7_FN, PTA7_OUT, PTA7_IN, PTA7_IN_PU,
+               PTA6_FN, PTA6_OUT, PTA6_IN, PTA6_IN_PU,
+               PTA5_FN, PTA5_OUT, PTA5_IN, PTA5_IN_PU,
+               PTA4_FN, PTA4_OUT, PTA4_IN, PTA4_IN_PU,
+               PTA3_FN, PTA3_OUT, PTA3_IN, PTA3_IN_PU,
+               PTA2_FN, PTA2_OUT, PTA2_IN, PTA2_IN_PU,
+               PTA1_FN, PTA1_OUT, PTA1_IN, PTA1_IN_PU,
+               PTA0_FN, PTA0_OUT, PTA0_IN, PTA0_IN_PU }
        },
        { PINMUX_CFG_REG("PBCR", 0xffec0002, 16, 2) {
                PTB7_FN, PTB7_OUT, PTB7_IN, 0,
@@ -1541,125 +1753,126 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTC0_FN, PTC0_OUT, PTC0_IN, 0 }
        },
        { PINMUX_CFG_REG("PDCR", 0xffec0006, 16, 2) {
-               PTD7_FN, PTD7_OUT, PTD7_IN, 0,
-               PTD6_FN, PTD6_OUT, PTD6_IN, 0,
-               PTD5_FN, PTD5_OUT, PTD5_IN, 0,
-               PTD4_FN, PTD4_OUT, PTD4_IN, 0,
-               PTD3_FN, PTD3_OUT, PTD3_IN, 0,
-               PTD2_FN, PTD2_OUT, PTD2_IN, 0,
-               PTD1_FN, PTD1_OUT, PTD1_IN, 0,
-               PTD0_FN, PTD0_OUT, PTD0_IN, 0 }
+               PTD7_FN, PTD7_OUT, PTD7_IN, PTD7_IN_PU,
+               PTD6_FN, PTD6_OUT, PTD6_IN, PTD6_IN_PU,
+               PTD5_FN, PTD5_OUT, PTD5_IN, PTD5_IN_PU,
+               PTD4_FN, PTD4_OUT, PTD4_IN, PTD4_IN_PU,
+               PTD3_FN, PTD3_OUT, PTD3_IN, PTD3_IN_PU,
+               PTD2_FN, PTD2_OUT, PTD2_IN, PTD2_IN_PU,
+               PTD1_FN, PTD1_OUT, PTD1_IN, PTD1_IN_PU,
+               PTD0_FN, PTD0_OUT, PTD0_IN, PTD0_IN_PU }
        },
        { PINMUX_CFG_REG("PECR", 0xffec0008, 16, 2) {
-               PTE7_FN, PTE7_OUT, PTE7_IN, 0,
-               PTE6_FN, PTE6_OUT, PTE6_IN, 0,
-               PTE5_FN, PTE5_OUT, PTE5_IN, 0,
-               PTE4_FN, PTE4_OUT, PTE4_IN, 0,
-               PTE3_FN, PTE3_OUT, PTE3_IN, 0,
-               PTE2_FN, PTE2_OUT, PTE2_IN, 0,
-               PTE1_FN, PTE1_OUT, PTE1_IN, 0,
-               PTE0_FN, PTE0_OUT, PTE0_IN, 0 }
+               PTE7_FN, PTE7_OUT, PTE7_IN, PTE7_IN_PU,
+               PTE6_FN, PTE6_OUT, PTE6_IN, PTE6_IN_PU,
+               PTE5_FN, PTE5_OUT, PTE5_IN, PTE5_IN_PU,
+               PTE4_FN, PTE4_OUT, PTE4_IN, PTE4_IN_PU,
+               PTE3_FN, PTE3_OUT, PTE3_IN, PTE3_IN_PU,
+               PTE2_FN, PTE2_OUT, PTE2_IN, PTE2_IN_PU,
+               PTE1_FN, PTE1_OUT, PTE1_IN, PTE1_IN_PU,
+               PTE0_FN, PTE0_OUT, PTE0_IN, PTE0_IN_PU }
        },
        { PINMUX_CFG_REG("PFCR", 0xffec000a, 16, 2) {
-               PTF7_FN, PTF7_OUT, PTF7_IN, 0,
-               PTF6_FN, PTF6_OUT, PTF6_IN, 0,
-               PTF5_FN, PTF5_OUT, PTF5_IN, 0,
-               PTF4_FN, PTF4_OUT, PTF4_IN, 0,
-               PTF3_FN, PTF3_OUT, PTF3_IN, 0,
-               PTF2_FN, PTF2_OUT, PTF2_IN, 0,
-               PTF1_FN, PTF1_OUT, PTF1_IN, 0,
-               PTF0_FN, PTF0_OUT, PTF0_IN, 0 }
+               PTF7_FN, PTF7_OUT, PTF7_IN, PTF7_IN_PU,
+               PTF6_FN, PTF6_OUT, PTF6_IN, PTF6_IN_PU,
+               PTF5_FN, PTF5_OUT, PTF5_IN, PTF5_IN_PU,
+               PTF4_FN, PTF4_OUT, PTF4_IN, PTF4_IN_PU,
+               PTF3_FN, PTF3_OUT, PTF3_IN, PTF3_IN_PU,
+               PTF2_FN, PTF2_OUT, PTF2_IN, PTF2_IN_PU,
+               PTF1_FN, PTF1_OUT, PTF1_IN, PTF1_IN_PU,
+               PTF0_FN, PTF0_OUT, PTF0_IN, PTF0_IN_PU }
        },
        { PINMUX_CFG_REG("PGCR", 0xffec000c, 16, 2) {
-               PTG7_FN, PTG7_OUT, PTG7_IN, 0,
-               PTG6_FN, PTG6_OUT, PTG6_IN, 0,
+               PTG7_FN, PTG7_OUT, PTG7_IN, PTG7_IN_PU ,
+               PTG6_FN, PTG6_OUT, PTG6_IN, PTG6_IN_PU ,
                PTG5_FN, PTG5_OUT, PTG5_IN, 0,
-               PTG4_FN, PTG4_OUT, PTG4_IN, 0,
+               PTG4_FN, PTG4_OUT, PTG4_IN, PTG4_IN_PU ,
                PTG3_FN, PTG3_OUT, PTG3_IN, 0,
                PTG2_FN, PTG2_OUT, PTG2_IN, 0,
                PTG1_FN, PTG1_OUT, PTG1_IN, 0,
                PTG0_FN, PTG0_OUT, PTG0_IN, 0 }
        },
        { PINMUX_CFG_REG("PHCR", 0xffec000e, 16, 2) {
-               PTH7_FN, PTH7_OUT, PTH7_IN, 0,
-               PTH6_FN, PTH6_OUT, PTH6_IN, 0,
-               PTH5_FN, PTH5_OUT, PTH5_IN, 0,
-               PTH4_FN, PTH4_OUT, PTH4_IN, 0,
-               PTH3_FN, PTH3_OUT, PTH3_IN, 0,
-               PTH2_FN, PTH2_OUT, PTH2_IN, 0,
-               PTH1_FN, PTH1_OUT, PTH1_IN, 0,
-               PTH0_FN, PTH0_OUT, PTH0_IN, 0 }
+               PTH7_FN, PTH7_OUT, PTH7_IN, PTH7_IN_PU,
+               PTH6_FN, PTH6_OUT, PTH6_IN, PTH6_IN_PU,
+               PTH5_FN, PTH5_OUT, PTH5_IN, PTH5_IN_PU,
+               PTH4_FN, PTH4_OUT, PTH4_IN, PTH4_IN_PU,
+               PTH3_FN, PTH3_OUT, PTH3_IN, PTH3_IN_PU,
+               PTH2_FN, PTH2_OUT, PTH2_IN, PTH2_IN_PU,
+               PTH1_FN, PTH1_OUT, PTH1_IN, PTH1_IN_PU,
+               PTH0_FN, PTH0_OUT, PTH0_IN, PTH0_IN_PU }
        },
        { PINMUX_CFG_REG("PICR", 0xffec0010, 16, 2) {
-               PTI7_FN, PTI7_OUT, PTI7_IN, 0,
-               PTI6_FN, PTI6_OUT, PTI6_IN, 0,
+               PTI7_FN, PTI7_OUT, PTI7_IN, PTI7_IN_PU,
+               PTI6_FN, PTI6_OUT, PTI6_IN, PTI6_IN_PU,
                PTI5_FN, PTI5_OUT, PTI5_IN, 0,
-               PTI4_FN, PTI4_OUT, PTI4_IN, 0,
-               PTI3_FN, PTI3_OUT, PTI3_IN, 0,
-               PTI2_FN, PTI2_OUT, PTI2_IN, 0,
-               PTI1_FN, PTI1_OUT, PTI1_IN, 0,
-               PTI0_FN, PTI0_OUT, PTI0_IN, 0 }
+               PTI4_FN, PTI4_OUT, PTI4_IN, PTI4_IN_PU,
+               PTI3_FN, PTI3_OUT, PTI3_IN, PTI3_IN_PU,
+               PTI2_FN, PTI2_OUT, PTI2_IN, PTI2_IN_PU,
+               PTI1_FN, PTI1_OUT, PTI1_IN, PTI1_IN_PU,
+               PTI0_FN, PTI0_OUT, PTI0_IN, PTI0_IN_PU }
        },
        { PINMUX_CFG_REG("PJCR", 0xffec0012, 16, 2) {
-               PTJ7_FN, PTJ7_OUT, PTJ7_IN, 0,
-               PTJ6_FN, PTJ6_OUT, PTJ6_IN, 0,
-               PTJ5_FN, PTJ5_OUT, PTJ5_IN, 0,
-               PTJ4_FN, PTJ4_OUT, PTJ4_IN, 0,
-               PTJ3_FN, PTJ3_OUT, PTJ3_IN, 0,
-               PTJ2_FN, PTJ2_OUT, PTJ2_IN, 0,
-               PTJ1_FN, PTJ1_OUT, PTJ1_IN, 0,
-               PTJ0_FN, PTJ0_OUT, PTJ0_IN, 0 }
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTJ6_FN, PTJ6_OUT, PTJ6_IN, PTJ6_IN_PU,
+               PTJ5_FN, PTJ5_OUT, PTJ5_IN, PTJ5_IN_PU,
+               PTJ4_FN, PTJ4_OUT, PTJ4_IN, PTJ4_IN_PU,
+               PTJ3_FN, PTJ3_OUT, PTJ3_IN, PTJ3_IN_PU,
+               PTJ2_FN, PTJ2_OUT, PTJ2_IN, PTJ2_IN_PU,
+               PTJ1_FN, PTJ1_OUT, PTJ1_IN, PTJ1_IN_PU,
+               PTJ0_FN, PTJ0_OUT, PTJ0_IN, PTJ0_IN_PU }
        },
        { PINMUX_CFG_REG("PKCR", 0xffec0014, 16, 2) {
-               PTK7_FN, PTK7_OUT, PTK7_IN, 0,
-               PTK6_FN, PTK6_OUT, PTK6_IN, 0,
-               PTK5_FN, PTK5_OUT, PTK5_IN, 0,
-               PTK4_FN, PTK4_OUT, PTK4_IN, 0,
-               PTK3_FN, PTK3_OUT, PTK3_IN, 0,
-               PTK2_FN, PTK2_OUT, PTK2_IN, 0,
-               PTK1_FN, PTK1_OUT, PTK1_IN, 0,
-               PTK0_FN, PTK0_OUT, PTK0_IN, 0 }
+               PTK7_FN, PTK7_OUT, PTK7_IN, PTK7_IN_PU,
+               PTK6_FN, PTK6_OUT, PTK6_IN, PTK6_IN_PU,
+               PTK5_FN, PTK5_OUT, PTK5_IN, PTK5_IN_PU,
+               PTK4_FN, PTK4_OUT, PTK4_IN, PTK4_IN_PU,
+               PTK3_FN, PTK3_OUT, PTK3_IN, PTK3_IN_PU,
+               PTK2_FN, PTK2_OUT, PTK2_IN, PTK2_IN_PU,
+               PTK1_FN, PTK1_OUT, PTK1_IN, PTK1_IN_PU,
+               PTK0_FN, PTK0_OUT, PTK0_IN, PTK0_IN_PU }
        },
        { PINMUX_CFG_REG("PLCR", 0xffec0016, 16, 2) {
-               PTL7_FN, PTL7_OUT, PTL7_IN, 0,
-               PTL6_FN, PTL6_OUT, PTL6_IN, 0,
-               PTL5_FN, PTL5_OUT, PTL5_IN, 0,
-               PTL4_FN, PTL4_OUT, PTL4_IN, 0,
-               PTL3_FN, PTL3_OUT, PTL3_IN, 0,
-               PTL2_FN, PTL2_OUT, PTL2_IN, 0,
-               PTL1_FN, PTL1_OUT, PTL1_IN, 0,
-               PTL0_FN, PTL0_OUT, PTL0_IN, 0 }
+               0, 0, 0, 0,     /* reserved: always set 1 */
+               PTL6_FN, PTL6_OUT, PTL6_IN, PTL6_IN_PU,
+               PTL5_FN, PTL5_OUT, PTL5_IN, PTL5_IN_PU,
+               PTL4_FN, PTL4_OUT, PTL4_IN, PTL4_IN_PU,
+               PTL3_FN, PTL3_OUT, PTL3_IN, PTL3_IN_PU,
+               PTL2_FN, PTL2_OUT, PTL2_IN, PTL2_IN_PU,
+               PTL1_FN, PTL1_OUT, PTL1_IN, PTL1_IN_PU,
+               PTL0_FN, PTL0_OUT, PTL0_IN, PTL0_IN_PU }
        },
        { PINMUX_CFG_REG("PMCR", 0xffec0018, 16, 2) {
-               0, 0, 0, 0,     /* reserved: always set 1 */
-               PTM6_FN, PTM6_OUT, PTM6_IN, 0,
-               PTM5_FN, PTM5_OUT, PTM5_IN, 0,
-               PTM4_FN, PTM4_OUT, PTM4_IN, 0,
+               PTM7_FN, PTM7_OUT, PTM7_IN, PTM7_IN_PU,
+               PTM6_FN, PTM6_OUT, PTM6_IN, PTM6_IN_PU,
+               PTM5_FN, PTM5_OUT, PTM5_IN, PTM5_IN_PU,
+               PTM4_FN, PTM4_OUT, PTM4_IN, PTM4_IN_PU,
                PTM3_FN, PTM3_OUT, PTM3_IN, 0,
                PTM2_FN, PTM2_OUT, PTM2_IN, 0,
                PTM1_FN, PTM1_OUT, PTM1_IN, 0,
                PTM0_FN, PTM0_OUT, PTM0_IN, 0 }
        },
        { PINMUX_CFG_REG("PNCR", 0xffec001a, 16, 2) {
-               PTN7_FN, PTN7_OUT, PTN7_IN, 0,
+               0, 0, 0, 0,     /* reserved: always set 1 */
                PTN6_FN, PTN6_OUT, PTN6_IN, 0,
                PTN5_FN, PTN5_OUT, PTN5_IN, 0,
-               PTN4_FN, PTN4_OUT, PTN4_IN, 0,
-               PTN3_FN, PTN3_OUT, PTN3_IN, 0,
-               PTN2_FN, PTN2_OUT, PTN2_IN, 0,
-               PTN1_FN, PTN1_OUT, PTN1_IN, 0,
-               PTN0_FN, PTN0_OUT, PTN0_IN, 0 }
+               PTN4_FN, PTN4_OUT, PTN4_IN, PTN4_IN_PU,
+               PTN3_FN, PTN3_OUT, PTN3_IN, PTN3_IN_PU,
+               PTN2_FN, PTN2_OUT, PTN2_IN, PTN2_IN_PU,
+               PTN1_FN, PTN1_OUT, PTN1_IN, PTN1_IN_PU,
+               PTN0_FN, PTN0_OUT, PTN0_IN, PTN0_IN_PU }
        },
        { PINMUX_CFG_REG("POCR", 0xffec001c, 16, 2) {
-               PTO7_FN, PTO7_OUT, PTO7_IN, 0,
-               PTO6_FN, PTO6_OUT, PTO6_IN, 0,
-               PTO5_FN, PTO5_OUT, PTO5_IN, 0,
-               PTO4_FN, PTO4_OUT, PTO4_IN, 0,
-               PTO3_FN, PTO3_OUT, PTO3_IN, 0,
-               PTO2_FN, PTO2_OUT, PTO2_IN, 0,
-               PTO1_FN, PTO1_OUT, PTO1_IN, 0,
-               PTO0_FN, PTO0_OUT, PTO0_IN, 0 }
+               PTO7_FN, PTO7_OUT, PTO7_IN, PTO7_IN_PU,
+               PTO6_FN, PTO6_OUT, PTO6_IN, PTO6_IN_PU,
+               PTO5_FN, PTO5_OUT, PTO5_IN, PTO5_IN_PU,
+               PTO4_FN, PTO4_OUT, PTO4_IN, PTO4_IN_PU,
+               PTO3_FN, PTO3_OUT, PTO3_IN, PTO3_IN_PU,
+               PTO2_FN, PTO2_OUT, PTO2_IN, PTO2_IN_PU,
+               PTO1_FN, PTO1_OUT, PTO1_IN, PTO1_IN_PU,
+               PTO0_FN, PTO0_OUT, PTO0_IN, PTO0_IN_PU }
        },
+#if 0  /* FIXME: Remove it? */
        { PINMUX_CFG_REG("PPCR", 0xffec001e, 16, 2) {
                0, 0, 0, 0,     /* reserved: always set 1 */
                PTP6_FN, PTP6_OUT, PTP6_IN, 0,
@@ -1670,6 +1883,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTP1_FN, PTP1_OUT, PTP1_IN, 0,
                PTP0_FN, PTP0_OUT, PTP0_IN, 0 }
        },
+#endif
        { PINMUX_CFG_REG("PQCR", 0xffec0020, 16, 2) {
                0, 0, 0, 0,     /* reserved: always set 1 */
                PTQ6_FN, PTQ6_OUT, PTQ6_IN, 0,
@@ -1701,14 +1915,14 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTS0_FN, PTS0_OUT, PTS0_IN, 0 }
        },
        { PINMUX_CFG_REG("PTCR", 0xffec0026, 16, 2) {
-               0, 0, 0, 0,     /* reserved: always set 1 */
-               0, 0, 0, 0,     /* reserved: always set 1 */
-               PTT5_FN, PTT5_OUT, PTT5_IN, 0,
-               PTT4_FN, PTT4_OUT, PTT4_IN, 0,
-               PTT3_FN, PTT3_OUT, PTT3_IN, 0,
-               PTT2_FN, PTT2_OUT, PTT2_IN, 0,
-               PTT1_FN, PTT1_OUT, PTT1_IN, 0,
-               PTT0_FN, PTT0_OUT, PTT0_IN, 0 }
+               PTT7_FN, PTT7_OUT, PTT7_IN, PTO7_IN_PU,
+               PTT6_FN, PTT6_OUT, PTT6_IN, PTO6_IN_PU,
+               PTT5_FN, PTT5_OUT, PTT5_IN, PTO5_IN_PU,
+               PTT4_FN, PTT4_OUT, PTT4_IN, PTO4_IN_PU,
+               PTT3_FN, PTT3_OUT, PTT3_IN, PTO3_IN_PU,
+               PTT2_FN, PTT2_OUT, PTT2_IN, PTO2_IN_PU,
+               PTT1_FN, PTT1_OUT, PTT1_IN, PTO1_IN_PU,
+               PTT0_FN, PTT0_OUT, PTT0_IN, PTO0_IN_PU }
        },
        { PINMUX_CFG_REG("PUCR", 0xffec0028, 16, 2) {
                PTU7_FN, PTU7_OUT, PTU7_IN, PTU7_IN_PU,
@@ -1727,16 +1941,16 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTV4_FN, PTV4_OUT, PTV4_IN, PTV4_IN_PU,
                PTV3_FN, PTV3_OUT, PTV3_IN, PTV3_IN_PU,
                PTV2_FN, PTV2_OUT, PTV2_IN, PTV2_IN_PU,
-               PTV1_FN, PTV1_OUT, PTV1_IN, PTV1_IN_PU,
-               PTV0_FN, PTV0_OUT, PTV0_IN, PTV0_IN_PU }
+               PTV1_FN, PTV1_OUT, PTV1_IN, 0,
+               PTV0_FN, PTV0_OUT, PTV0_IN, 0 }
        },
        { PINMUX_CFG_REG("PWCR", 0xffec002c, 16, 2) {
-               PTW7_FN, PTW7_OUT, PTW7_IN, PTW7_IN_PU,
-               PTW6_FN, PTW6_OUT, PTW6_IN, PTW6_IN_PU,
-               PTW5_FN, PTW5_OUT, PTW5_IN, PTW5_IN_PU,
-               PTW4_FN, PTW4_OUT, PTW4_IN, PTW4_IN_PU,
-               PTW3_FN, PTW3_OUT, PTW3_IN, PTW3_IN_PU,
-               PTW2_FN, PTW2_OUT, PTW2_IN, PTW2_IN_PU,
+               PTW7_FN, PTW7_OUT, PTW7_IN, 0,
+               PTW6_FN, PTW6_OUT, PTW6_IN, 0,
+               PTW5_FN, PTW5_OUT, PTW5_IN, 0,
+               PTW4_FN, PTW4_OUT, PTW4_IN, 0,
+               PTW3_FN, PTW3_OUT, PTW3_IN, 0,
+               PTW2_FN, PTW2_OUT, PTW2_IN, 0,
                PTW1_FN, PTW1_OUT, PTW1_IN, PTW1_IN_PU,
                PTW0_FN, PTW0_OUT, PTW0_IN, PTW0_IN_PU }
        },
@@ -1761,32 +1975,32 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                PTY0_FN, PTY0_OUT, PTY0_IN, PTY0_IN_PU }
        },
        { PINMUX_CFG_REG("PZCR", 0xffec0032, 16, 2) {
-               0, PTZ7_OUT, PTZ7_IN, 0,
-               0, PTZ6_OUT, PTZ6_IN, 0,
-               0, PTZ5_OUT, PTZ5_IN, 0,
-               0, PTZ4_OUT, PTZ4_IN, 0,
-               0, PTZ3_OUT, PTZ3_IN, 0,
-               0, PTZ2_OUT, PTZ2_IN, 0,
-               0, PTZ1_OUT, PTZ1_IN, 0,
-               0, PTZ0_OUT, PTZ0_IN, 0 }
+               PTZ7_FN, PTZ7_OUT, PTZ7_IN, 0,
+               PTZ6_FN, PTZ6_OUT, PTZ6_IN, 0,
+               PTZ5_FN, PTZ5_OUT, PTZ5_IN, 0,
+               PTZ4_FN, PTZ4_OUT, PTZ4_IN, 0,
+               PTZ3_FN, PTZ3_OUT, PTZ3_IN, 0,
+               PTZ2_FN, PTZ2_OUT, PTZ2_IN, 0,
+               PTZ1_FN, PTZ1_OUT, PTZ1_IN, 0,
+               PTZ0_FN, PTZ0_OUT, PTZ0_IN, 0 }
        },
 
        { PINMUX_CFG_REG("PSEL0", 0xffec0070, 16, 1) {
-               PS0_15_FN3, PS0_15_FN1,
-               PS0_14_FN3, PS0_14_FN1,
-               PS0_13_FN3, PS0_13_FN1,
-               PS0_12_FN3, PS0_12_FN1,
-               0, 0,
-               0, 0,
+               PS0_15_FN1, PS0_15_FN2,
+               PS0_14_FN1, PS0_14_FN2,
+               PS0_13_FN1, PS0_13_FN2,
+               PS0_12_FN1, PS0_12_FN2,
+               PS0_11_FN1, PS0_11_FN2,
+               PS0_10_FN1, PS0_10_FN2,
+               PS0_9_FN1, PS0_9_FN2,
+               PS0_8_FN1, PS0_8_FN2,
+               PS0_7_FN1, PS0_7_FN2,
+               PS0_6_FN1, PS0_6_FN2,
+               PS0_5_FN1, PS0_5_FN2,
+               PS0_4_FN1, PS0_4_FN2,
+               PS0_3_FN1, PS0_3_FN2,
+               PS0_2_FN1, PS0_2_FN2,
                0, 0,
-               0, 0,
-               PS0_7_FN2, PS0_7_FN1,
-               PS0_6_FN2, PS0_6_FN1,
-               PS0_5_FN2, PS0_5_FN1,
-               PS0_4_FN2, PS0_4_FN1,
-               PS0_3_FN2, PS0_3_FN1,
-               PS0_2_FN2, PS0_2_FN1,
-               PS0_1_FN2, PS0_1_FN1,
                0, 0, }
        },
        { PINMUX_CFG_REG("PSEL1", 0xffec0072, 16, 1) {
@@ -1795,73 +2009,136 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                0, 0,
                0, 0,
                0, 0,
+               PS1_10_FN1, PS1_10_FN2,
+               PS1_9_FN1, PS1_9_FN2,
+               PS1_8_FN1, PS1_8_FN2,
                0, 0,
                0, 0,
                0, 0,
-               PS1_7_FN1, PS1_7_FN3,
-               PS1_6_FN1, PS1_6_FN3,
-               0, 0,
-               0, 0,
                0, 0,
                0, 0,
+               PS1_2_FN1, PS1_2_FN2,
                0, 0,
                0, 0, }
        },
        { PINMUX_CFG_REG("PSEL2", 0xffec0074, 16, 1) {
                0, 0,
                0, 0,
-               PS2_13_FN3, PS2_13_FN1,
-               PS2_12_FN3, PS2_12_FN1,
+               PS2_13_FN1, PS2_13_FN2,
+               PS2_12_FN1, PS2_12_FN2,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
+               PS2_7_FN1, PS2_7_FN2,
+               PS2_6_FN1, PS2_6_FN2,
+               PS2_5_FN1, PS2_5_FN2,
+               PS2_4_FN1, PS2_4_FN2,
                0, 0,
+               PS2_2_FN1, PS2_2_FN2,
                0, 0,
+               0, 0, }
+       },
+       { PINMUX_CFG_REG("PSEL3", 0xffec0076, 16, 1) {
+               PS3_15_FN1, PS3_15_FN2,
+               PS3_14_FN1, PS3_14_FN2,
+               PS3_13_FN1, PS3_13_FN2,
+               PS3_12_FN1, PS3_12_FN2,
+               PS3_11_FN1, PS3_11_FN2,
+               PS3_10_FN1, PS3_10_FN2,
+               PS3_9_FN1, PS3_9_FN2,
+               PS3_8_FN1, PS3_8_FN2,
+               PS3_7_FN1, PS3_7_FN2,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
-               PS2_1_FN1, PS2_1_FN2,
-               PS2_0_FN1, PS2_0_FN2, }
+               PS3_2_FN1, PS3_2_FN2,
+               PS3_1_FN1, PS3_1_FN2,
+               0, 0, }
        },
+
        { PINMUX_CFG_REG("PSEL4", 0xffec0078, 16, 1) {
-               PS4_15_FN2, PS4_15_FN1,
-               PS4_14_FN2, PS4_14_FN1,
-               PS4_13_FN2, PS4_13_FN1,
-               PS4_12_FN2, PS4_12_FN1,
-               PS4_11_FN2, PS4_11_FN1,
-               PS4_10_FN2, PS4_10_FN1,
-               PS4_9_FN2, PS4_9_FN1,
                0, 0,
+               PS4_14_FN1, PS4_14_FN2,
+               PS4_13_FN1, PS4_13_FN2,
+               PS4_12_FN1, PS4_12_FN2,
                0, 0,
+               PS4_10_FN1, PS4_10_FN2,
+               PS4_9_FN1, PS4_9_FN2,
+               PS4_8_FN1, PS4_8_FN2,
                0, 0,
                0, 0,
                0, 0,
-               PS4_3_FN2, PS4_3_FN1,
-               PS4_2_FN2, PS4_2_FN1,
-               PS4_1_FN2, PS4_1_FN1,
-               PS4_0_FN2, PS4_0_FN1, }
+               PS4_4_FN1, PS4_4_FN2,
+               PS4_3_FN1, PS4_3_FN2,
+               PS4_2_FN1, PS4_2_FN2,
+               PS4_1_FN1, PS4_1_FN2,
+               PS4_0_FN1, PS4_0_FN2, }
        },
        { PINMUX_CFG_REG("PSEL5", 0xffec007a, 16, 1) {
                0, 0,
                0, 0,
                0, 0,
                0, 0,
-               0, 0,
-               0, 0,
+               PS5_11_FN1, PS5_11_FN2,
+               PS5_10_FN1, PS5_10_FN2,
                PS5_9_FN1, PS5_9_FN2,
                PS5_8_FN1, PS5_8_FN2,
                PS5_7_FN1, PS5_7_FN2,
                PS5_6_FN1, PS5_6_FN2,
                PS5_5_FN1, PS5_5_FN2,
+               PS5_4_FN1, PS5_4_FN2,
+               PS5_3_FN1, PS5_3_FN2,
+               PS5_2_FN1, PS5_2_FN2,
+               0, 0,
+               0, 0, }
+       },
+       { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1) {
+               PS6_15_FN1, PS6_15_FN2,
+               PS6_14_FN1, PS6_14_FN2,
+               PS6_13_FN1, PS6_13_FN2,
+               PS6_12_FN1, PS6_12_FN2,
+               PS6_11_FN1, PS6_11_FN2,
+               PS6_10_FN1, PS6_10_FN2,
+               PS6_9_FN1, PS6_9_FN2,
+               PS6_8_FN1, PS6_8_FN2,
+               PS6_7_FN1, PS6_7_FN2,
+               PS6_6_FN1, PS6_6_FN2,
+               PS6_5_FN1, PS6_5_FN2,
+               PS6_4_FN1, PS6_4_FN2,
+               PS6_3_FN1, PS6_3_FN2,
+               PS6_2_FN1, PS6_2_FN2,
+               PS6_1_FN1, PS6_1_FN2,
+               PS6_0_FN1, PS6_0_FN2, }
+       },
+       { PINMUX_CFG_REG("PSEL7", 0xffec0082, 16, 1) {
+               PS7_15_FN1, PS7_15_FN2,
+               PS7_14_FN1, PS7_14_FN2,
+               PS7_13_FN1, PS7_13_FN2,
+               PS7_12_FN1, PS7_12_FN2,
+               PS7_11_FN1, PS7_11_FN2,
+               PS7_10_FN1, PS7_10_FN2,
+               PS7_9_FN1, PS7_9_FN2,
+               PS7_8_FN1, PS7_8_FN2,
+               PS7_7_FN1, PS7_7_FN2,
+               PS7_6_FN1, PS7_6_FN2,
+               PS7_5_FN1, PS7_5_FN2,
                0, 0,
                0, 0,
                0, 0,
                0, 0,
                0, 0, }
        },
-       { PINMUX_CFG_REG("PSEL6", 0xffec007c, 16, 1) {
+       { PINMUX_CFG_REG("PSEL8", 0xffec0084, 16, 1) {
+               PS8_15_FN1, PS8_15_FN2,
+               PS8_14_FN1, PS8_14_FN2,
+               PS8_13_FN1, PS8_13_FN2,
+               PS8_12_FN1, PS8_12_FN2,
+               PS8_11_FN1, PS8_11_FN2,
+               PS8_10_FN1, PS8_10_FN2,
+               PS8_9_FN1, PS8_9_FN2,
+               PS8_8_FN1, PS8_8_FN2,
                0, 0,
                0, 0,
                0, 0,
@@ -1869,15 +2146,7 @@ static struct pinmux_cfg_reg pinmux_config_regs[] = {
                0, 0,
                0, 0,
                0, 0,
-               0, 0,
-               PS6_7_FN_AN, PS6_7_FN_EV,
-               PS6_6_FN_AN, PS6_6_FN_EV,
-               PS6_5_FN_AN, PS6_5_FN_EV,
-               PS6_4_FN_AN, PS6_4_FN_EV,
-               PS6_3_FN_AN, PS6_3_FN_EV,
-               PS6_2_FN_AN, PS6_2_FN_EV,
-               PS6_1_FN_AN, PS6_1_FN_EV,
-               PS6_0_FN_AN, PS6_0_FN_EV, }
+               0, 0, }
        },
        {}
 };
@@ -1920,7 +2189,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTI3_DATA, PTI2_DATA, PTI1_DATA, PTI0_DATA }
        },
        { PINMUX_DATA_REG("PJDR", 0xffec0046, 8) {
-               PTJ7_DATA, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
+               0, PTJ6_DATA, PTJ5_DATA, PTJ4_DATA,
                PTJ3_DATA, PTJ2_DATA, PTJ1_DATA, PTJ0_DATA }
        },
        { PINMUX_DATA_REG("PKDR", 0xffec0048, 8) {
@@ -1928,15 +2197,15 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTK3_DATA, PTK2_DATA, PTK1_DATA, PTK0_DATA }
        },
        { PINMUX_DATA_REG("PLDR", 0xffec004a, 8) {
-               PTL7_DATA, PTL6_DATA, PTL5_DATA, PTL4_DATA,
+               0, PTL6_DATA, PTL5_DATA, PTL4_DATA,
                PTL3_DATA, PTL2_DATA, PTL1_DATA, PTL0_DATA }
        },
        { PINMUX_DATA_REG("PMDR", 0xffec004c, 8) {
-               0, PTM6_DATA, PTM5_DATA, PTM4_DATA,
+               PTM7_DATA, PTM6_DATA, PTM5_DATA, PTM4_DATA,
                PTM3_DATA, PTM2_DATA, PTM1_DATA, PTM0_DATA }
        },
        { PINMUX_DATA_REG("PNDR", 0xffec004e, 8) {
-               PTN7_DATA, PTN6_DATA, PTN5_DATA, PTN4_DATA,
+               0, PTN6_DATA, PTN5_DATA, PTN4_DATA,
                PTN3_DATA, PTN2_DATA, PTN1_DATA, PTN0_DATA }
        },
        { PINMUX_DATA_REG("PODR", 0xffec0050, 8) {
@@ -1944,7 +2213,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTO3_DATA, PTO2_DATA, PTO1_DATA, PTO0_DATA }
        },
        { PINMUX_DATA_REG("PPDR", 0xffec0052, 8) {
-               0, PTP6_DATA, PTP5_DATA, PTP4_DATA,
+               PTP7_DATA, PTP6_DATA, PTP5_DATA, PTP4_DATA,
                PTP3_DATA, PTP2_DATA, PTP1_DATA, PTP0_DATA }
        },
        { PINMUX_DATA_REG("PQDR", 0xffec0054, 8) {
@@ -1960,7 +2229,7 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
                PTS3_DATA, PTS2_DATA, PTS1_DATA, PTS0_DATA }
        },
        { PINMUX_DATA_REG("PTDR", 0xffec005a, 8) {
-               0, 0, PTT5_DATA, PTT4_DATA,
+               PTT7_DATA, PTT6_DATA, PTT5_DATA, PTT4_DATA,
                PTT3_DATA, PTT2_DATA, PTT1_DATA, PTT0_DATA }
        },
        { PINMUX_DATA_REG("PUDR", 0xffec005c, 8) {
@@ -2000,8 +2269,8 @@ static struct pinmux_info sh7757_pinmux_info = {
        .mark = { PINMUX_MARK_BEGIN, PINMUX_MARK_END },
        .function = { PINMUX_FUNCTION_BEGIN, PINMUX_FUNCTION_END },
 
-       .first_gpio = GPIO_PTA7,
-       .last_gpio = GPIO_FN_D0,
+       .first_gpio = GPIO_PTA0,
+       .last_gpio = GPIO_FN_ON_DQ0,
 
        .gpios = pinmux_gpios,
        .cfg_regs = pinmux_config_regs,
@@ -2015,5 +2284,4 @@ static int __init plat_pinmux_setup(void)
 {
        return register_pinmux(&sh7757_pinmux_info);
 }
-
 arch_initcall(plat_pinmux_setup);
diff --git a/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c b/arch/sh/kernel/cpu/sh4a/pinmux-shx3.c
new file mode 100644 (file)
index 0000000..aaa5338
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ * SH-X3 prototype CPU pinmux
+ *
+ * Copyright (C) 2010  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 <linux/gpio.h>
+#include <cpu/shx3.h>
+
+enum {
+       PINMUX_RESERVED = 0,
+
+       PINMUX_DATA_BEGIN,
+       PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+       PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
+       PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+       PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA,
+       PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+       PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+       PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+       PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA,
+       PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+       PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
+       PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+       PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA,
+       PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+       PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
+
+       PH5_DATA, PH4_DATA,
+       PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA,
+       PINMUX_DATA_END,
+
+       PINMUX_INPUT_BEGIN,
+       PA7_IN, PA6_IN, PA5_IN, PA4_IN,
+       PA3_IN, PA2_IN, PA1_IN, PA0_IN,
+       PB7_IN, PB6_IN, PB5_IN, PB4_IN,
+       PB3_IN, PB2_IN, PB1_IN, PB0_IN,
+       PC7_IN, PC6_IN, PC5_IN, PC4_IN,
+       PC3_IN, PC2_IN, PC1_IN, PC0_IN,
+       PD7_IN, PD6_IN, PD5_IN, PD4_IN,
+       PD3_IN, PD2_IN, PD1_IN, PD0_IN,
+       PE7_IN, PE6_IN, PE5_IN, PE4_IN,
+       PE3_IN, PE2_IN, PE1_IN, PE0_IN,
+       PF7_IN, PF6_IN, PF5_IN, PF4_IN,
+       PF3_IN, PF2_IN, PF1_IN, PF0_IN,
+       PG7_IN, PG6_IN, PG5_IN, PG4_IN,
+       PG3_IN, PG2_IN, PG1_IN, PG0_IN,
+
+       PH5_IN, PH4_IN,
+       PH3_IN, PH2_IN, PH1_IN, PH0_IN,
+       PINMUX_INPUT_END,
+
+       PINMUX_INPUT_PULLUP_BEGIN,
+       PA7_IN_PU, PA6_IN_PU, PA5_IN_PU, PA4_IN_PU,
+       PA3_IN_PU, PA2_IN_PU, PA1_IN_PU, PA0_IN_PU,
+       PB7_IN_PU, PB6_IN_PU, PB5_IN_PU, PB4_IN_PU,
+       PB3_IN_PU, PB2_IN_PU, PB1_IN_PU, PB0_IN_PU,
+       PC7_IN_PU, PC6_IN_PU, PC5_IN_PU, PC4_IN_PU,
+       PC3_IN_PU, PC2_IN_PU, PC1_IN_PU, PC0_IN_PU,
+       PD7_IN_PU, PD6_IN_PU, PD5_IN_PU, PD4_IN_PU,
+       PD3_IN_PU, PD2_IN_PU, PD1_IN_PU, PD0_IN_PU,
+       PE7_IN_PU, PE6_IN_PU, PE5_IN_PU, PE4_IN_PU,
+       PE3_IN_PU, PE2_IN_PU, PE1_IN_PU, PE0_IN_PU,
+       PF7_IN_PU, PF6_IN_PU, PF5_IN_PU, PF4_IN_PU,
+       PF3_IN_PU, PF2_IN_PU, PF1_IN_PU, PF0_IN_PU,
+       PG7_IN_PU, PG6_IN_PU, PG5_IN_PU, PG4_IN_PU,
+       PG3_IN_PU, PG2_IN_PU, PG1_IN_PU, PG0_IN_PU,
+
+       PH5_IN_PU, PH4_IN_PU,
+       PH3_IN_PU, PH2_IN_PU, PH1_IN_PU, PH0_IN_PU,
+       PINMUX_INPUT_PULLUP_END,
+
+       PINMUX_OUTPUT_BEGIN,
+       PA7_OUT, PA6_OUT, PA5_OUT, PA4_OUT,
+       PA3_OUT, PA2_OUT, PA1_OUT, PA0_OUT,
+       PB7_OUT, PB6_OUT, PB5_OUT, PB4_OUT,
+       PB3_OUT, PB2_OUT, PB1_OUT, PB0_OUT,
+       PC7_OUT, PC6_OUT, PC5_OUT, PC4_OUT,
+       PC3_OUT, PC2_OUT, PC1_OUT, PC0_OUT,
+       PD7_OUT, PD6_OUT, PD5_OUT, PD4_OUT,
+       PD3_OUT, PD2_OUT, PD1_OUT, PD0_OUT,
+       PE7_OUT, PE6_OUT, PE5_OUT, PE4_OUT,
+       PE3_OUT, PE2_OUT, PE1_OUT, PE0_OUT,
+       PF7_OUT, PF6_OUT, PF5_OUT, PF4_OUT,
+       PF3_OUT, PF2_OUT, PF1_OUT, PF0_OUT,
+       PG7_OUT, PG6_OUT, PG5_OUT, PG4_OUT,
+       PG3_OUT, PG2_OUT, PG1_OUT, PG0_OUT,
+
+       PH5_OUT, PH4_OUT,
+       PH3_OUT, PH2_OUT, PH1_OUT, PH0_OUT,
+       PINMUX_OUTPUT_END,
+
+       PINMUX_FUNCTION_BEGIN,
+       PA7_FN, PA6_FN, PA5_FN, PA4_FN,
+       PA3_FN, PA2_FN, PA1_FN, PA0_FN,
+       PB7_FN, PB6_FN, PB5_FN, PB4_FN,
+       PB3_FN, PB2_FN, PB1_FN, PB0_FN,
+       PC7_FN, PC6_FN, PC5_FN, PC4_FN,
+       PC3_FN, PC2_FN, PC1_FN, PC0_FN,
+       PD7_FN, PD6_FN, PD5_FN, PD4_FN,
+       PD3_FN, PD2_FN, PD1_FN, PD0_FN,
+       PE7_FN, PE6_FN, PE5_FN, PE4_FN,
+       PE3_FN, PE2_FN, PE1_FN, PE0_FN,
+       PF7_FN, PF6_FN, PF5_FN, PF4_FN,
+       PF3_FN, PF2_FN, PF1_FN, PF0_FN,
+       PG7_FN, PG6_FN, PG5_FN, PG4_FN,
+       PG3_FN, PG2_FN, PG1_FN, PG0_FN,
+
+       PH5_FN, PH4_FN,
+       PH3_FN, PH2_FN, PH1_FN, PH0_FN,
+       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,
+
+       BACK_MARK, BREQ_MARK,
+       WE3_MARK, WE2_MARK,
+       CS6_MARK, CS5_MARK, CS4_MARK,
+       CLKOUTENB_MARK,
+
+       DACK3_MARK, DACK2_MARK, DACK1_MARK, DACK0_MARK,
+       DREQ3_MARK, DREQ2_MARK, DREQ1_MARK, DREQ0_MARK,
+
+       IRQ3_MARK, IRQ2_MARK, IRQ1_MARK, IRQ0_MARK,
+
+       DRAK3_MARK, DRAK2_MARK, DRAK1_MARK, DRAK0_MARK,
+
+       SCK3_MARK, SCK2_MARK, SCK1_MARK, SCK0_MARK,
+       IRL3_MARK, IRL2_MARK, IRL1_MARK, IRL0_MARK,
+       TXD3_MARK, TXD2_MARK, TXD1_MARK, TXD0_MARK,
+       RXD3_MARK, RXD2_MARK, RXD1_MARK, RXD0_MARK,
+
+       CE2B_MARK, CE2A_MARK, IOIS16_MARK,
+       STATUS1_MARK, STATUS0_MARK,
+
+       IRQOUT_MARK,
+
+       PINMUX_MARK_END,
+};
+
+static pinmux_enum_t shx3_pinmux_data[] = {
+
+       /* PA GPIO */
+       PINMUX_DATA(PA7_DATA, PA7_IN, PA7_OUT, PA7_IN_PU),
+       PINMUX_DATA(PA6_DATA, PA6_IN, PA6_OUT, PA6_IN_PU),
+       PINMUX_DATA(PA5_DATA, PA5_IN, PA5_OUT, PA5_IN_PU),
+       PINMUX_DATA(PA4_DATA, PA4_IN, PA4_OUT, PA4_IN_PU),
+       PINMUX_DATA(PA3_DATA, PA3_IN, PA3_OUT, PA3_IN_PU),
+       PINMUX_DATA(PA2_DATA, PA2_IN, PA2_OUT, PA2_IN_PU),
+       PINMUX_DATA(PA1_DATA, PA1_IN, PA1_OUT, PA1_IN_PU),
+       PINMUX_DATA(PA0_DATA, PA0_IN, PA0_OUT, PA0_IN_PU),
+
+       /* PB GPIO */
+       PINMUX_DATA(PB7_DATA, PB7_IN, PB7_OUT, PB7_IN_PU),
+       PINMUX_DATA(PB6_DATA, PB6_IN, PB6_OUT, PB6_IN_PU),
+       PINMUX_DATA(PB5_DATA, PB5_IN, PB5_OUT, PB5_IN_PU),
+       PINMUX_DATA(PB4_DATA, PB4_IN, PB4_OUT, PB4_IN_PU),
+       PINMUX_DATA(PB3_DATA, PB3_IN, PB3_OUT, PB3_IN_PU),
+       PINMUX_DATA(PB2_DATA, PB2_IN, PB2_OUT, PB2_IN_PU),
+       PINMUX_DATA(PB1_DATA, PB1_IN, PB1_OUT, PB1_IN_PU),
+       PINMUX_DATA(PB0_DATA, PB0_IN, PB0_OUT, PB0_IN_PU),
+
+       /* PC GPIO */
+       PINMUX_DATA(PC7_DATA, PC7_IN, PC7_OUT, PC7_IN_PU),
+       PINMUX_DATA(PC6_DATA, PC6_IN, PC6_OUT, PC6_IN_PU),
+       PINMUX_DATA(PC5_DATA, PC5_IN, PC5_OUT, PC5_IN_PU),
+       PINMUX_DATA(PC4_DATA, PC4_IN, PC4_OUT, PC4_IN_PU),
+       PINMUX_DATA(PC3_DATA, PC3_IN, PC3_OUT, PC3_IN_PU),
+       PINMUX_DATA(PC2_DATA, PC2_IN, PC2_OUT, PC2_IN_PU),
+       PINMUX_DATA(PC1_DATA, PC1_IN, PC1_OUT, PC1_IN_PU),
+       PINMUX_DATA(PC0_DATA, PC0_IN, PC0_OUT, PC0_IN_PU),
+
+       /* PD GPIO */
+       PINMUX_DATA(PD7_DATA, PD7_IN, PD7_OUT, PD7_IN_PU),
+       PINMUX_DATA(PD6_DATA, PD6_IN, PD6_OUT, PD6_IN_PU),
+       PINMUX_DATA(PD5_DATA, PD5_IN, PD5_OUT, PD5_IN_PU),
+       PINMUX_DATA(PD4_DATA, PD4_IN, PD4_OUT, PD4_IN_PU),
+       PINMUX_DATA(PD3_DATA, PD3_IN, PD3_OUT, PD3_IN_PU),
+       PINMUX_DATA(PD2_DATA, PD2_IN, PD2_OUT, PD2_IN_PU),
+       PINMUX_DATA(PD1_DATA, PD1_IN, PD1_OUT, PD1_IN_PU),
+       PINMUX_DATA(PD0_DATA, PD0_IN, PD0_OUT, PD0_IN_PU),
+
+       /* PE GPIO */
+       PINMUX_DATA(PE7_DATA, PE7_IN, PE7_OUT, PE7_IN_PU),
+       PINMUX_DATA(PE6_DATA, PE6_IN, PE6_OUT, PE6_IN_PU),
+       PINMUX_DATA(PE5_DATA, PE5_IN, PE5_OUT, PE5_IN_PU),
+       PINMUX_DATA(PE4_DATA, PE4_IN, PE4_OUT, PE4_IN_PU),
+       PINMUX_DATA(PE3_DATA, PE3_IN, PE3_OUT, PE3_IN_PU),
+       PINMUX_DATA(PE2_DATA, PE2_IN, PE2_OUT, PE2_IN_PU),
+       PINMUX_DATA(PE1_DATA, PE1_IN, PE1_OUT, PE1_IN_PU),
+       PINMUX_DATA(PE0_DATA, PE0_IN, PE0_OUT, PE0_IN_PU),
+
+       /* PF GPIO */
+       PINMUX_DATA(PF7_DATA, PF7_IN, PF7_OUT, PF7_IN_PU),
+       PINMUX_DATA(PF6_DATA, PF6_IN, PF6_OUT, PF6_IN_PU),
+       PINMUX_DATA(PF5_DATA, PF5_IN, PF5_OUT, PF5_IN_PU),
+       PINMUX_DATA(PF4_DATA, PF4_IN, PF4_OUT, PF4_IN_PU),
+       PINMUX_DATA(PF3_DATA, PF3_IN, PF3_OUT, PF3_IN_PU),
+       PINMUX_DATA(PF2_DATA, PF2_IN, PF2_OUT, PF2_IN_PU),
+       PINMUX_DATA(PF1_DATA, PF1_IN, PF1_OUT, PF1_IN_PU),
+       PINMUX_DATA(PF0_DATA, PF0_IN, PF0_OUT, PF0_IN_PU),
+
+       /* PG GPIO */
+       PINMUX_DATA(PG7_DATA, PG7_IN, PG7_OUT, PG7_IN_PU),
+       PINMUX_DATA(PG6_DATA, PG6_IN, PG6_OUT, PG6_IN_PU),
+       PINMUX_DATA(PG5_DATA, PG5_IN, PG5_OUT, PG5_IN_PU),
+       PINMUX_DATA(PG4_DATA, PG4_IN, PG4_OUT, PG4_IN_PU),
+       PINMUX_DATA(PG3_DATA, PG3_IN, PG3_OUT, PG3_IN_PU),
+       PINMUX_DATA(PG2_DATA, PG2_IN, PG2_OUT, PG2_IN_PU),
+       PINMUX_DATA(PG1_DATA, PG1_IN, PG1_OUT, PG1_IN_PU),
+       PINMUX_DATA(PG0_DATA, PG0_IN, PG0_OUT, PG0_IN_PU),
+
+       /* PH GPIO */
+       PINMUX_DATA(PH5_DATA, PH5_IN, PH5_OUT, PH5_IN_PU),
+       PINMUX_DATA(PH4_DATA, PH4_IN, PH4_OUT, PH4_IN_PU),
+       PINMUX_DATA(PH3_DATA, PH3_IN, PH3_OUT, PH3_IN_PU),
+       PINMUX_DATA(PH2_DATA, PH2_IN, PH2_OUT, PH2_IN_PU),
+       PINMUX_DATA(PH1_DATA, PH1_IN, PH1_OUT, PH1_IN_PU),
+       PINMUX_DATA(PH0_DATA, PH0_IN, PH0_OUT, PH0_IN_PU),
+
+       /* PA FN */
+       PINMUX_DATA(D31_MARK, PA7_FN),
+       PINMUX_DATA(D30_MARK, PA6_FN),
+       PINMUX_DATA(D29_MARK, PA5_FN),
+       PINMUX_DATA(D28_MARK, PA4_FN),
+       PINMUX_DATA(D27_MARK, PA3_FN),
+       PINMUX_DATA(D26_MARK, PA2_FN),
+       PINMUX_DATA(D25_MARK, PA1_FN),
+       PINMUX_DATA(D24_MARK, PA0_FN),
+
+       /* PB FN */
+       PINMUX_DATA(D23_MARK, PB7_FN),
+       PINMUX_DATA(D22_MARK, PB6_FN),
+       PINMUX_DATA(D21_MARK, PB5_FN),
+       PINMUX_DATA(D20_MARK, PB4_FN),
+       PINMUX_DATA(D19_MARK, PB3_FN),
+       PINMUX_DATA(D18_MARK, PB2_FN),
+       PINMUX_DATA(D17_MARK, PB1_FN),
+       PINMUX_DATA(D16_MARK, PB0_FN),
+
+       /* PC FN */
+       PINMUX_DATA(BACK_MARK,          PC7_FN),
+       PINMUX_DATA(BREQ_MARK,          PC6_FN),
+       PINMUX_DATA(WE3_MARK,           PC5_FN),
+       PINMUX_DATA(WE2_MARK,           PC4_FN),
+       PINMUX_DATA(CS6_MARK,           PC3_FN),
+       PINMUX_DATA(CS5_MARK,           PC2_FN),
+       PINMUX_DATA(CS4_MARK,           PC1_FN),
+       PINMUX_DATA(CLKOUTENB_MARK,     PC0_FN),
+
+       /* PD FN */
+       PINMUX_DATA(DACK3_MARK, PD7_FN),
+       PINMUX_DATA(DACK2_MARK, PD6_FN),
+       PINMUX_DATA(DACK1_MARK, PD5_FN),
+       PINMUX_DATA(DACK0_MARK, PD4_FN),
+       PINMUX_DATA(DREQ3_MARK, PD3_FN),
+       PINMUX_DATA(DREQ2_MARK, PD2_FN),
+       PINMUX_DATA(DREQ1_MARK, PD1_FN),
+       PINMUX_DATA(DREQ0_MARK, PD0_FN),
+
+       /* PE FN */
+       PINMUX_DATA(IRQ3_MARK,  PE7_FN),
+       PINMUX_DATA(IRQ2_MARK,  PE6_FN),
+       PINMUX_DATA(IRQ1_MARK,  PE5_FN),
+       PINMUX_DATA(IRQ0_MARK,  PE4_FN),
+       PINMUX_DATA(DRAK3_MARK, PE3_FN),
+       PINMUX_DATA(DRAK2_MARK, PE2_FN),
+       PINMUX_DATA(DRAK1_MARK, PE1_FN),
+       PINMUX_DATA(DRAK0_MARK, PE0_FN),
+
+       /* PF FN */
+       PINMUX_DATA(SCK3_MARK, PF7_FN),
+       PINMUX_DATA(SCK2_MARK, PF6_FN),
+       PINMUX_DATA(SCK1_MARK, PF5_FN),
+       PINMUX_DATA(SCK0_MARK, PF4_FN),
+       PINMUX_DATA(IRL3_MARK, PF3_FN),
+       PINMUX_DATA(IRL2_MARK, PF2_FN),
+       PINMUX_DATA(IRL1_MARK, PF1_FN),
+       PINMUX_DATA(IRL0_MARK, PF0_FN),
+
+       /* PG FN */
+       PINMUX_DATA(TXD3_MARK, PG7_FN),
+       PINMUX_DATA(TXD2_MARK, PG6_FN),
+       PINMUX_DATA(TXD1_MARK, PG5_FN),
+       PINMUX_DATA(TXD0_MARK, PG4_FN),
+       PINMUX_DATA(RXD3_MARK, PG3_FN),
+       PINMUX_DATA(RXD2_MARK, PG2_FN),
+       PINMUX_DATA(RXD1_MARK, PG1_FN),
+       PINMUX_DATA(RXD0_MARK, PG0_FN),
+
+       /* PH FN */
+       PINMUX_DATA(CE2B_MARK,          PH5_FN),
+       PINMUX_DATA(CE2A_MARK,          PH4_FN),
+       PINMUX_DATA(IOIS16_MARK,        PH3_FN),
+       PINMUX_DATA(STATUS1_MARK,       PH2_FN),
+       PINMUX_DATA(STATUS0_MARK,       PH1_FN),
+       PINMUX_DATA(IRQOUT_MARK,        PH0_FN),
+};
+
+static struct pinmux_gpio shx3_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_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_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_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_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_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),
+
+       /* PG */
+       PINMUX_GPIO(GPIO_PG7, PG7_DATA),
+       PINMUX_GPIO(GPIO_PG6, PG6_DATA),
+       PINMUX_GPIO(GPIO_PG5, PG5_DATA),
+       PINMUX_GPIO(GPIO_PG4, PG4_DATA),
+       PINMUX_GPIO(GPIO_PG3, PG3_DATA),
+       PINMUX_GPIO(GPIO_PG2, PG2_DATA),
+       PINMUX_GPIO(GPIO_PG1, PG1_DATA),
+       PINMUX_GPIO(GPIO_PG0, PG0_DATA),
+
+       /* PH */
+       PINMUX_GPIO(GPIO_PH5, PH5_DATA),
+       PINMUX_GPIO(GPIO_PH4, PH4_DATA),
+       PINMUX_GPIO(GPIO_PH3, PH3_DATA),
+       PINMUX_GPIO(GPIO_PH2, PH2_DATA),
+       PINMUX_GPIO(GPIO_PH1, PH1_DATA),
+       PINMUX_GPIO(GPIO_PH0, PH0_DATA),
+
+       /* FN */
+       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_BACK,       BACK_MARK),
+       PINMUX_GPIO(GPIO_FN_BREQ,       BREQ_MARK),
+       PINMUX_GPIO(GPIO_FN_WE3,        WE3_MARK),
+       PINMUX_GPIO(GPIO_FN_WE2,        WE2_MARK),
+       PINMUX_GPIO(GPIO_FN_CS6,        CS6_MARK),
+       PINMUX_GPIO(GPIO_FN_CS5,        CS5_MARK),
+       PINMUX_GPIO(GPIO_FN_CS4,        CS4_MARK),
+       PINMUX_GPIO(GPIO_FN_CLKOUTENB,  CLKOUTENB_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK3,      DACK3_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK2,      DACK2_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK1,      DACK1_MARK),
+       PINMUX_GPIO(GPIO_FN_DACK0,      DACK0_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ3,      DREQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ2,      DREQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ1,      DREQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_DREQ0,      DREQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ3,       IRQ3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ2,       IRQ2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ1,       IRQ1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQ0,       IRQ0_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK3,      DRAK3_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK2,      DRAK2_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK1,      DRAK1_MARK),
+       PINMUX_GPIO(GPIO_FN_DRAK0,      DRAK0_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK3,       SCK3_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK2,       SCK2_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK1,       SCK1_MARK),
+       PINMUX_GPIO(GPIO_FN_SCK0,       SCK0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL3,       IRL3_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL2,       IRL2_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL1,       IRL1_MARK),
+       PINMUX_GPIO(GPIO_FN_IRL0,       IRL0_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD3,       TXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD2,       TXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD1,       TXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_TXD0,       TXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD3,       RXD3_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD2,       RXD2_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD1,       RXD1_MARK),
+       PINMUX_GPIO(GPIO_FN_RXD0,       RXD0_MARK),
+       PINMUX_GPIO(GPIO_FN_CE2B,       CE2B_MARK),
+       PINMUX_GPIO(GPIO_FN_CE2A,       CE2A_MARK),
+       PINMUX_GPIO(GPIO_FN_IOIS16,     IOIS16_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS1,    STATUS1_MARK),
+       PINMUX_GPIO(GPIO_FN_STATUS0,    STATUS0_MARK),
+       PINMUX_GPIO(GPIO_FN_IRQOUT,     IRQOUT_MARK),
+};
+
+static struct pinmux_cfg_reg shx3_pinmux_config_regs[] = {
+       { PINMUX_CFG_REG("PABCR", 0xffc70000, 32, 2) {
+               PA7_FN, PA7_OUT, PA7_IN, PA7_IN_PU,
+               PA6_FN, PA6_OUT, PA6_IN, PA6_IN_PU,
+               PA5_FN, PA5_OUT, PA5_IN, PA5_IN_PU,
+               PA4_FN, PA4_OUT, PA4_IN, PA4_IN_PU,
+               PA3_FN, PA3_OUT, PA3_IN, PA3_IN_PU,
+               PA2_FN, PA2_OUT, PA2_IN, PA2_IN_PU,
+               PA1_FN, PA1_OUT, PA1_IN, PA1_IN_PU,
+               PA0_FN, PA0_OUT, PA0_IN, PA0_IN_PU,
+               PB7_FN, PB7_OUT, PB7_IN, PB7_IN_PU,
+               PB6_FN, PB6_OUT, PB6_IN, PB6_IN_PU,
+               PB5_FN, PB5_OUT, PB5_IN, PB5_IN_PU,
+               PB4_FN, PB4_OUT, PB4_IN, PB4_IN_PU,
+               PB3_FN, PB3_OUT, PB3_IN, PB3_IN_PU,
+               PB2_FN, PB2_OUT, PB2_IN, PB2_IN_PU,
+               PB1_FN, PB1_OUT, PB1_IN, PB1_IN_PU,
+               PB0_FN, PB0_OUT, PB0_IN, PB0_IN_PU, },
+       },
+       { PINMUX_CFG_REG("PCDCR", 0xffc70004, 32, 2) {
+               PC7_FN, PC7_OUT, PC7_IN, PC7_IN_PU,
+               PC6_FN, PC6_OUT, PC6_IN, PC6_IN_PU,
+               PC5_FN, PC5_OUT, PC5_IN, PC5_IN_PU,
+               PC4_FN, PC4_OUT, PC4_IN, PC4_IN_PU,
+               PC3_FN, PC3_OUT, PC3_IN, PC3_IN_PU,
+               PC2_FN, PC2_OUT, PC2_IN, PC2_IN_PU,
+               PC1_FN, PC1_OUT, PC1_IN, PC1_IN_PU,
+               PC0_FN, PC0_OUT, PC0_IN, PC0_IN_PU,
+               PD7_FN, PD7_OUT, PD7_IN, PD7_IN_PU,
+               PD6_FN, PD6_OUT, PD6_IN, PD6_IN_PU,
+               PD5_FN, PD5_OUT, PD5_IN, PD5_IN_PU,
+               PD4_FN, PD4_OUT, PD4_IN, PD4_IN_PU,
+               PD3_FN, PD3_OUT, PD3_IN, PD3_IN_PU,
+               PD2_FN, PD2_OUT, PD2_IN, PD2_IN_PU,
+               PD1_FN, PD1_OUT, PD1_IN, PD1_IN_PU,
+               PD0_FN, PD0_OUT, PD0_IN, PD0_IN_PU, },
+       },
+       { PINMUX_CFG_REG("PEFCR", 0xffc70008, 32, 2) {
+               PE7_FN, PE7_OUT, PE7_IN, PE7_IN_PU,
+               PE6_FN, PE6_OUT, PE6_IN, PE6_IN_PU,
+               PE5_FN, PE5_OUT, PE5_IN, PE5_IN_PU,
+               PE4_FN, PE4_OUT, PE4_IN, PE4_IN_PU,
+               PE3_FN, PE3_OUT, PE3_IN, PE3_IN_PU,
+               PE2_FN, PE2_OUT, PE2_IN, PE2_IN_PU,
+               PE1_FN, PE1_OUT, PE1_IN, PE1_IN_PU,
+               PE0_FN, PE0_OUT, PE0_IN, PE0_IN_PU,
+               PF7_FN, PF7_OUT, PF7_IN, PF7_IN_PU,
+               PF6_FN, PF6_OUT, PF6_IN, PF6_IN_PU,
+               PF5_FN, PF5_OUT, PF5_IN, PF5_IN_PU,
+               PF4_FN, PF4_OUT, PF4_IN, PF4_IN_PU,
+               PF3_FN, PF3_OUT, PF3_IN, PF3_IN_PU,
+               PF2_FN, PF2_OUT, PF2_IN, PF2_IN_PU,
+               PF1_FN, PF1_OUT, PF1_IN, PF1_IN_PU,
+               PF0_FN, PF0_OUT, PF0_IN, PF0_IN_PU, },
+       },
+       { PINMUX_CFG_REG("PGHCR", 0xffc7000c, 32, 2) {
+               PG7_FN, PG7_OUT, PG7_IN, PG7_IN_PU,
+               PG6_FN, PG6_OUT, PG6_IN, PG6_IN_PU,
+               PG5_FN, PG5_OUT, PG5_IN, PG5_IN_PU,
+               PG4_FN, PG4_OUT, PG4_IN, PG4_IN_PU,
+               PG3_FN, PG3_OUT, PG3_IN, PG3_IN_PU,
+               PG2_FN, PG2_OUT, PG2_IN, PG2_IN_PU,
+               PG1_FN, PG1_OUT, PG1_IN, PG1_IN_PU,
+               PG0_FN, PG0_OUT, PG0_IN, PG0_IN_PU,
+               0, 0, 0, 0,
+               0, 0, 0, 0,
+               PH5_FN, PH5_OUT, PH5_IN, PH5_IN_PU,
+               PH4_FN, PH4_OUT, PH4_IN, PH4_IN_PU,
+               PH3_FN, PH3_OUT, PH3_IN, PH3_IN_PU,
+               PH2_FN, PH2_OUT, PH2_IN, PH2_IN_PU,
+               PH1_FN, PH1_OUT, PH1_IN, PH1_IN_PU,
+               PH0_FN, PH0_OUT, PH0_IN, PH0_IN_PU, },
+       },
+       { },
+};
+
+static struct pinmux_data_reg shx3_pinmux_data_regs[] = {
+       { PINMUX_DATA_REG("PABDR", 0xffc70010, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PA7_DATA, PA6_DATA, PA5_DATA, PA4_DATA,
+               PA3_DATA, PA2_DATA, PA1_DATA, PA0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PB7_DATA, PB6_DATA, PB5_DATA, PB4_DATA,
+               PB3_DATA, PB2_DATA, PB1_DATA, PB0_DATA, },
+       },
+       { PINMUX_DATA_REG("PCDDR", 0xffc70014, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PC7_DATA, PC6_DATA, PC5_DATA, PC4_DATA,
+               PC3_DATA, PC2_DATA, PC1_DATA, PC0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PD7_DATA, PD6_DATA, PD5_DATA, PD4_DATA,
+               PD3_DATA, PD2_DATA, PD1_DATA, PD0_DATA, },
+       },
+       { PINMUX_DATA_REG("PEFDR", 0xffc70018, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PE7_DATA, PE6_DATA, PE5_DATA, PE4_DATA,
+               PE3_DATA, PE2_DATA, PE1_DATA, PE0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PF7_DATA, PF6_DATA, PF5_DATA, PF4_DATA,
+               PF3_DATA, PF2_DATA, PF1_DATA, PF0_DATA, },
+       },
+       { PINMUX_DATA_REG("PGHDR", 0xffc7001c, 32) {
+               0, 0, 0, 0, 0, 0, 0, 0,
+               PG7_DATA, PG6_DATA, PG5_DATA, PG4_DATA,
+               PG3_DATA, PG2_DATA, PG1_DATA, PG0_DATA,
+               0, 0, 0, 0, 0, 0, 0, 0,
+               0, 0, PH5_DATA, PH4_DATA,
+               PH3_DATA, PH2_DATA, PH1_DATA, PH0_DATA, },
+       },
+       { },
+};
+
+static struct pinmux_info shx3_pinmux_info = {
+       .name           = "shx3_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_PA7,
+       .last_gpio      = GPIO_FN_IRQOUT,
+       .gpios          = shx3_pinmux_gpios,
+       .gpio_data      = shx3_pinmux_data,
+       .gpio_data_size = ARRAY_SIZE(shx3_pinmux_data),
+       .cfg_regs       = shx3_pinmux_config_regs,
+       .data_regs      = shx3_pinmux_data_regs,
+};
+
+static int __init shx3_pinmux_setup(void)
+{
+       return register_pinmux(&shx3_pinmux_info);
+}
+arch_initcall(shx3_pinmux_setup);
index 79c556e..828c965 100644 (file)
@@ -524,6 +524,70 @@ static struct platform_device veu1_device = {
        },
 };
 
+/* BEU0 */
+static struct uio_info beu0_platform_data = {
+       .name = "BEU0",
+       .version = "0",
+       .irq = evt2irq(0x8A0),
+};
+
+static struct resource beu0_resources[] = {
+       [0] = {
+               .name   = "BEU0",
+               .start  = 0xfe930000,
+               .end    = 0xfe933400,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device beu0_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 6,
+       .dev = {
+               .platform_data  = &beu0_platform_data,
+       },
+       .resource       = beu0_resources,
+       .num_resources  = ARRAY_SIZE(beu0_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_BEU0,
+       },
+};
+
+/* BEU1 */
+static struct uio_info beu1_platform_data = {
+       .name = "BEU1",
+       .version = "0",
+       .irq = evt2irq(0xA00),
+};
+
+static struct resource beu1_resources[] = {
+       [0] = {
+               .name   = "BEU1",
+               .start  = 0xfe940000,
+               .end    = 0xfe943400,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               /* place holder for contiguous memory */
+       },
+};
+
+static struct platform_device beu1_device = {
+       .name           = "uio_pdrv_genirq",
+       .id             = 7,
+       .dev = {
+               .platform_data  = &beu1_platform_data,
+       },
+       .resource       = beu1_resources,
+       .num_resources  = ARRAY_SIZE(beu1_resources),
+       .archdata = {
+               .hwblk_id = HWBLK_BEU1,
+       },
+};
+
 static struct sh_timer_config cmt_platform_data = {
        .channel_offset = 0x60,
        .timer_bit = 5,
@@ -857,6 +921,8 @@ static struct platform_device *sh7724_devices[] __initdata = {
        &vpu_device,
        &veu0_device,
        &veu1_device,
+       &beu0_device,
+       &beu1_device,
        &jpu_device,
        &spu0_device,
        &spu1_device,
index 444aca9..749c638 100644 (file)
@@ -26,7 +26,7 @@ static struct plat_sci_port scif2_platform_data = {
 
 static struct platform_device scif2_device = {
        .name           = "sh-sci",
-       .id             = 2,
+       .id             = 0,
        .dev            = {
                .platform_data  = &scif2_platform_data,
        },
@@ -41,7 +41,7 @@ static struct plat_sci_port scif3_platform_data = {
 
 static struct platform_device scif3_device = {
        .name           = "sh-sci",
-       .id             = 3,
+       .id             = 1,
        .dev            = {
                .platform_data  = &scif3_platform_data,
        },
@@ -56,7 +56,7 @@ static struct plat_sci_port scif4_platform_data = {
 
 static struct platform_device scif4_device = {
        .name           = "sh-sci",
-       .id             = 4,
+       .id             = 2,
        .dev            = {
                .platform_data  = &scif4_platform_data,
        },
@@ -163,39 +163,23 @@ enum {
        IRL4_HHLL, IRL4_HHLH, IRL4_HHHL,
        IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
 
-       SDHI,
-       DVC,
-       IRQ8, IRQ9, IRQ10,
-       WDT0,
-       TMU0, TMU1, TMU2, TMU2_TICPI,
+       SDHI, DVC,
+       IRQ8, IRQ9, IRQ11, IRQ10, IRQ12, IRQ13, IRQ14, IRQ15,
+       TMU0, TMU1, TMU2, TMU2_TICPI, TMU3, TMU4, TMU5,
        HUDI,
-
        ARC4,
-       DMAC0,
-       IRQ11,
-       SCIF2,
-       DMAC1_6,
-       USB0,
-       IRQ12,
+       DMAC0_5, DMAC6_7, DMAC8_11,
+       SCIF0, SCIF1, SCIF2, SCIF3, SCIF4,
+       USB0, USB1,
        JMC,
-       SPI1,
-       IRQ13, IRQ14,
-       USB1,
+       SPI0, SPI1,
        TMR01, TMR23, TMR45,
-       WDT1,
        FRT,
-       LPC,
-       SCIF0, SCIF1, SCIF3,
-       PECI0I, PECI1I, PECI2I,
-       IRQ15,
+       LPC, LPC5, LPC6, LPC7, LPC8,
+       PECI0, PECI1, PECI2, PECI3, PECI4, PECI5,
        ETHERC,
-       SPI0,
-       ADC1,
-       DMAC1_8,
+       ADC0, ADC1,
        SIM,
-       TMU3, TMU4, TMU5,
-       ADC0,
-       SCIF4,
        IIC0_0, IIC0_1, IIC0_2, IIC0_3,
        IIC1_0, IIC1_1, IIC1_2, IIC1_3,
        IIC2_0, IIC2_1, IIC2_2, IIC2_3,
@@ -206,9 +190,23 @@ enum {
        IIC7_0, IIC7_1, IIC7_2, IIC7_3,
        IIC8_0, IIC8_1, IIC8_2, IIC8_3,
        IIC9_0, IIC9_1, IIC9_2, IIC9_3,
-       PCIINTA,
-       PCIE,
+       ONFICTL,
+       MMC1, MMC2,
+       ECCU,
+       PCIC,
+       G200,
+       RSPI,
        SGPIO,
+       DMINT12, DMINT13, DMINT14, DMINT15, DMINT16, DMINT17, DMINT18, DMINT19,
+       DMINT20, DMINT21, DMINT22, DMINT23,
+       DDRECC,
+       TSIP,
+       PCIE_BRIDGE,
+       WDT0B, WDT1B, WDT2B, WDT3B, WDT4B, WDT5B, WDT6B, WDT7B, WDT8B,
+       GETHER0, GETHER1, GETHER2,
+       PBIA, PBIB, PBIC,
+       DMAE2, DMAE3,
+       SERMUX2, SERMUX3,
 
        /* interrupt groups */
 
@@ -221,19 +219,18 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(DVC, 0x4e0),
        INTC_VECT(IRQ8, 0x500), INTC_VECT(IRQ9, 0x520),
        INTC_VECT(IRQ10, 0x540),
-       INTC_VECT(WDT0, 0x560),
        INTC_VECT(TMU0, 0x580), INTC_VECT(TMU1, 0x5a0),
        INTC_VECT(TMU2, 0x5c0), INTC_VECT(TMU2_TICPI, 0x5e0),
        INTC_VECT(HUDI, 0x600),
        INTC_VECT(ARC4, 0x620),
-       INTC_VECT(DMAC0, 0x640), INTC_VECT(DMAC0, 0x660),
-       INTC_VECT(DMAC0, 0x680), INTC_VECT(DMAC0, 0x6a0),
-       INTC_VECT(DMAC0, 0x6c0),
+       INTC_VECT(DMAC0_5, 0x640), INTC_VECT(DMAC0_5, 0x660),
+       INTC_VECT(DMAC0_5, 0x680), INTC_VECT(DMAC0_5, 0x6a0),
+       INTC_VECT(DMAC0_5, 0x6c0),
        INTC_VECT(IRQ11, 0x6e0),
        INTC_VECT(SCIF2, 0x700), INTC_VECT(SCIF2, 0x720),
        INTC_VECT(SCIF2, 0x740), INTC_VECT(SCIF2, 0x760),
-       INTC_VECT(DMAC0, 0x780), INTC_VECT(DMAC0, 0x7a0),
-       INTC_VECT(DMAC1_6, 0x7c0), INTC_VECT(DMAC1_6, 0x7e0),
+       INTC_VECT(DMAC0_5, 0x780), INTC_VECT(DMAC0_5, 0x7a0),
+       INTC_VECT(DMAC6_7, 0x7c0), INTC_VECT(DMAC6_7, 0x7e0),
        INTC_VECT(USB0, 0x840),
        INTC_VECT(IRQ12, 0x880),
        INTC_VECT(JMC, 0x8a0),
@@ -242,7 +239,6 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(USB1, 0x920),
        INTC_VECT(TMR01, 0xa00), INTC_VECT(TMR23, 0xa20),
        INTC_VECT(TMR45, 0xa40),
-       INTC_VECT(WDT1, 0xa60),
        INTC_VECT(FRT, 0xa80),
        INTC_VECT(LPC, 0xaa0), INTC_VECT(LPC, 0xac0),
        INTC_VECT(LPC, 0xae0), INTC_VECT(LPC, 0xb00),
@@ -250,14 +246,14 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(SCIF0, 0xb40), INTC_VECT(SCIF1, 0xb60),
        INTC_VECT(SCIF3, 0xb80), INTC_VECT(SCIF3, 0xba0),
        INTC_VECT(SCIF3, 0xbc0), INTC_VECT(SCIF3, 0xbe0),
-       INTC_VECT(PECI0I, 0xc00), INTC_VECT(PECI1I, 0xc20),
-       INTC_VECT(PECI2I, 0xc40),
+       INTC_VECT(PECI0, 0xc00), INTC_VECT(PECI1, 0xc20),
+       INTC_VECT(PECI2, 0xc40),
        INTC_VECT(IRQ15, 0xc60),
        INTC_VECT(ETHERC, 0xc80), INTC_VECT(ETHERC, 0xca0),
        INTC_VECT(SPI0, 0xcc0),
        INTC_VECT(ADC1, 0xce0),
-       INTC_VECT(DMAC1_8, 0xd00), INTC_VECT(DMAC1_8, 0xd20),
-       INTC_VECT(DMAC1_8, 0xd40), INTC_VECT(DMAC1_8, 0xd60),
+       INTC_VECT(DMAC8_11, 0xd00), INTC_VECT(DMAC8_11, 0xd20),
+       INTC_VECT(DMAC8_11, 0xd40), INTC_VECT(DMAC8_11, 0xd60),
        INTC_VECT(SIM, 0xd80), INTC_VECT(SIM, 0xda0),
        INTC_VECT(SIM, 0xdc0), INTC_VECT(SIM, 0xde0),
        INTC_VECT(TMU3, 0xe00), INTC_VECT(TMU4, 0xe20),
@@ -278,17 +274,47 @@ static struct intc_vect vectors[] __initdata = {
        INTC_VECT(IIC5_0, 0x1860), INTC_VECT(IIC5_1, 0x1880),
        INTC_VECT(IIC5_2, 0x18a0), INTC_VECT(IIC5_3, 0x18c0),
        INTC_VECT(IIC6_0, 0x18e0), INTC_VECT(IIC6_1, 0x1900),
-       INTC_VECT(IIC6_2, 0x1920), INTC_VECT(IIC6_3, 0x1980),
+       INTC_VECT(IIC6_2, 0x1920),
+       INTC_VECT(ONFICTL, 0x1960),
+       INTC_VECT(IIC6_3, 0x1980),
        INTC_VECT(IIC7_0, 0x19a0), INTC_VECT(IIC7_1, 0x1a00),
        INTC_VECT(IIC7_2, 0x1a20), INTC_VECT(IIC7_3, 0x1a40),
        INTC_VECT(IIC8_0, 0x1a60), INTC_VECT(IIC8_1, 0x1a80),
        INTC_VECT(IIC8_2, 0x1aa0), INTC_VECT(IIC8_3, 0x1b40),
        INTC_VECT(IIC9_0, 0x1b60), INTC_VECT(IIC9_1, 0x1b80),
        INTC_VECT(IIC9_2, 0x1c00), INTC_VECT(IIC9_3, 0x1c20),
-       INTC_VECT(PCIINTA, 0x1ce0),
-       INTC_VECT(PCIE, 0x1e00),
-       INTC_VECT(SGPIO, 0x1f80),
-       INTC_VECT(SGPIO, 0x1fa0),
+       INTC_VECT(MMC1, 0x1c60), INTC_VECT(MMC2, 0x1c80),
+       INTC_VECT(ECCU, 0x1cc0),
+       INTC_VECT(PCIC, 0x1ce0),
+       INTC_VECT(G200, 0x1d00),
+       INTC_VECT(RSPI, 0x1d80), INTC_VECT(RSPI, 0x1da0),
+       INTC_VECT(RSPI, 0x1dc0), INTC_VECT(RSPI, 0x1de0),
+       INTC_VECT(PECI3, 0x1ec0), INTC_VECT(PECI4, 0x1ee0),
+       INTC_VECT(PECI5, 0x1f00),
+       INTC_VECT(SGPIO, 0x1f80), INTC_VECT(SGPIO, 0x1fa0),
+       INTC_VECT(SGPIO, 0x1fc0),
+       INTC_VECT(DMINT12, 0x2400), INTC_VECT(DMINT13, 0x2420),
+       INTC_VECT(DMINT14, 0x2440), INTC_VECT(DMINT15, 0x2460),
+       INTC_VECT(DMINT16, 0x2480), INTC_VECT(DMINT17, 0x24e0),
+       INTC_VECT(DMINT18, 0x2500), INTC_VECT(DMINT19, 0x2520),
+       INTC_VECT(DMINT20, 0x2540), INTC_VECT(DMINT21, 0x2560),
+       INTC_VECT(DMINT22, 0x2580), INTC_VECT(DMINT23, 0x2600),
+       INTC_VECT(DDRECC, 0x2620),
+       INTC_VECT(TSIP, 0x2640),
+       INTC_VECT(PCIE_BRIDGE, 0x27c0),
+       INTC_VECT(WDT0B, 0x2800), INTC_VECT(WDT1B, 0x2820),
+       INTC_VECT(WDT2B, 0x2840), INTC_VECT(WDT3B, 0x2860),
+       INTC_VECT(WDT4B, 0x2880), INTC_VECT(WDT5B, 0x28a0),
+       INTC_VECT(WDT6B, 0x28c0), INTC_VECT(WDT7B, 0x28e0),
+       INTC_VECT(WDT8B, 0x2900),
+       INTC_VECT(GETHER0, 0x2960), INTC_VECT(GETHER1, 0x2980),
+       INTC_VECT(GETHER2, 0x29a0),
+       INTC_VECT(PBIA, 0x2a00), INTC_VECT(PBIB, 0x2a20),
+       INTC_VECT(PBIC, 0x2a40),
+       INTC_VECT(DMAE2, 0x2a60), INTC_VECT(DMAE3, 0x2a80),
+       INTC_VECT(SERMUX2, 0x2aa0), INTC_VECT(SERMUX3, 0x2b40),
+       INTC_VECT(LPC5, 0x2b60), INTC_VECT(LPC6, 0x2b80),
+       INTC_VECT(LPC7, 0x2c00), INTC_VECT(LPC8, 0x2c20),
 };
 
 static struct intc_group groups[] __initdata = {
@@ -312,31 +338,45 @@ static struct intc_mask_reg mask_registers[] __initdata = {
 
        { 0xffd40038, 0xffd4003c, 32, /* INT2MSKR / INT2MSKCR */
          { 0, 0, 0, 0, 0, 0, 0, 0,
-           0, DMAC1_8, 0, PECI0I, LPC, FRT, WDT1, TMR45,
-           TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0,
-           HUDI, 0, WDT0, SCIF3, SCIF2, SDHI, TMU345, TMU012
+           0, DMAC8_11, 0, PECI0, LPC, FRT, 0, TMR45,
+           TMR23, TMR01, 0, 0, 0, 0, 0, DMAC0_5,
+           HUDI, 0, 0, SCIF3, SCIF2, SDHI, TMU345, TMU012
             } },
 
        { 0xffd400d0, 0xffd400d4, 32, /* INT2MSKR1 / INT2MSKCR1 */
          { IRQ15, IRQ14, IRQ13, IRQ12, IRQ11, IRQ10, SCIF4, ETHERC,
            IRQ9, IRQ8, SCIF1, SCIF0, USB0, 0, 0, USB1,
-           ADC1, 0, DMAC1_6, ADC0, SPI0, SIM, PECI2I, PECI1I,
+           ADC1, 0, DMAC6_7, ADC0, SPI0, SIM, PECI2, PECI1,
            ARC4, 0, SPI1, JMC, 0, 0, 0, DVC
             } },
 
        { 0xffd10038, 0xffd1003c, 32, /* INT2MSKR2 / INT2MSKCR2 */
-         { IIC4_1, IIC4_2, IIC5_0, 0, 0, 0, SGPIO, 0,
-           0, 0, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3,
+         { IIC4_1, IIC4_2, IIC5_0, ONFICTL, 0, 0, SGPIO, 0,
+           0, G200, 0, IIC9_2, IIC8_2, IIC8_1, IIC8_0, IIC7_3,
            IIC7_2, IIC7_1, IIC6_3, IIC0_0, IIC0_1, IIC0_2, IIC0_3, IIC3_1,
-           IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, PCIE, IIC2_2
+           IIC2_3, 0, IIC2_1, IIC9_1, IIC3_3, IIC1_0, 0, IIC2_2
             } },
 
-       { 0xffd100d0, 0xff1400d4, 32, /* INT2MSKR3 / INT2MSKCR4 */
-         { 0, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, 0, 0,
+       { 0xffd100d0, 0xffd100d4, 32, /* INT2MSKR3 / INT2MSKCR3 */
+         { MMC1, IIC6_1, IIC6_0, IIC5_1, IIC3_2, IIC2_0, PECI5, MMC2,
            IIC1_3, IIC1_2, IIC9_0, IIC8_3, IIC4_3, IIC7_0, 0, IIC6_2,
-           PCIINTA, 0, IIC4_0, 0, 0, 0, 0, IIC9_3,
+           PCIC, 0, IIC4_0, 0, ECCU, RSPI, 0, IIC9_3,
            IIC3_0, 0, IIC5_3, IIC5_2, 0, 0, 0, IIC1_1
             } },
+
+       { 0xffd20038, 0xffd2003c, 32, /* INT2MSKR4 / INT2MSKCR4 */
+         { WDT0B, WDT1B, WDT3B, GETHER0, 0, 0, 0, 0,
+           0, 0, 0, LPC7, SERMUX2, DMAE3, DMAE2, PBIC,
+           PBIB, PBIA, GETHER1, DMINT12, DMINT13, DMINT14, DMINT15, TSIP,
+           DMINT23, 0, DMINT21, LPC6, 0, DMINT16, 0, DMINT22
+            } },
+
+       { 0xffd200d0, 0xffd200d4, 32, /* INT2MSKR5 / INT2MSKCR5 */
+         { 0, WDT8B, WDT7B, WDT4B, 0, DMINT20, 0, 0,
+           DMINT19, DMINT18, LPC5, SERMUX3, WDT2B, GETHER2, 0, 0,
+           0, 0, PCIE_BRIDGE, 0, 0, 0, 0, LPC8,
+           DDRECC, 0, WDT6B, WDT5B, 0, 0, 0, DMINT17
+            } },
 };
 
 #define INTPRI         0xffd00010
@@ -372,6 +412,22 @@ static struct intc_mask_reg mask_registers[] __initdata = {
 #define INT2PRI29      0xffd100b4
 #define INT2PRI30      0xffd100b8
 #define INT2PRI31      0xffd100bc
+#define INT2PRI32      0xffd20000
+#define INT2PRI33      0xffd20004
+#define INT2PRI34      0xffd20008
+#define INT2PRI35      0xffd2000c
+#define INT2PRI36      0xffd20010
+#define INT2PRI37      0xffd20014
+#define INT2PRI38      0xffd20018
+#define INT2PRI39      0xffd2001c
+#define INT2PRI40      0xffd200a0
+#define INT2PRI41      0xffd200a4
+#define INT2PRI42      0xffd200a8
+#define INT2PRI43      0xffd200ac
+#define INT2PRI44      0xffd200b0
+#define INT2PRI45      0xffd200b4
+#define INT2PRI46      0xffd200b8
+#define INT2PRI47      0xffd200bc
 
 static struct intc_prio_reg prio_registers[] __initdata = {
        { INTPRI, 0, 32, 4, { IRQ0, IRQ1, IRQ2, IRQ3,
@@ -379,39 +435,61 @@ static struct intc_prio_reg prio_registers[] __initdata = {
 
        { INT2PRI0, 0, 32, 8, { TMU0, TMU1, TMU2, TMU2_TICPI } },
        { INT2PRI1, 0, 32, 8, { TMU3, TMU4, TMU5, SDHI } },
-       { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, WDT0, IRQ8 } },
-       { INT2PRI3, 0, 32, 8, { HUDI, DMAC0, ADC0, IRQ9 } },
+       { INT2PRI2, 0, 32, 8, { SCIF2, SCIF3, 0, IRQ8 } },
+       { INT2PRI3, 0, 32, 8, { HUDI, DMAC0_5, ADC0, IRQ9 } },
        { INT2PRI4, 0, 32, 8, { IRQ10, 0, TMR01, TMR23 } },
-       { INT2PRI5, 0, 32, 8, { TMR45, WDT1, FRT, LPC } },
-       { INT2PRI6, 0, 32, 8, { PECI0I, ETHERC, DMAC1_8, 0 } },
+       { INT2PRI5, 0, 32, 8, { TMR45, 0, FRT, LPC } },
+       { INT2PRI6, 0, 32, 8, { PECI0, ETHERC, DMAC8_11, 0 } },
        { INT2PRI7, 0, 32, 8, { SCIF4, 0, IRQ11, IRQ12 } },
        { INT2PRI8, 0, 32, 8, { 0, 0, 0, DVC } },
        { INT2PRI9, 0, 32, 8, { ARC4, 0, SPI1, JMC } },
-       { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2I, PECI1I } },
-       { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC1_6, IRQ14 } },
+       { INT2PRI10, 0, 32, 8, { SPI0, SIM, PECI2, PECI1 } },
+       { INT2PRI11, 0, 32, 8, { ADC1, IRQ13, DMAC6_7, IRQ14 } },
        { INT2PRI12, 0, 32, 8, { USB0, 0, IRQ15, USB1 } },
        { INT2PRI13, 0, 32, 8, { 0, 0, SCIF1, SCIF0 } },
 
        { INT2PRI16, 0, 32, 8, { IIC2_2, 0, 0, 0 } },
-       { INT2PRI17, 0, 32, 8, { PCIE, 0, 0, IIC1_0 } },
+       { INT2PRI17, 0, 32, 8, { 0, 0, 0, IIC1_0 } },
        { INT2PRI18, 0, 32, 8, { IIC3_3, IIC9_1, IIC2_1, IIC1_2 } },
        { INT2PRI19, 0, 32, 8, { IIC2_3, IIC3_1, 0, IIC1_3 } },
        { INT2PRI20, 0, 32, 8, { IIC2_0, IIC6_3, IIC7_1, IIC7_2 } },
        { INT2PRI21, 0, 32, 8, { IIC7_3, IIC8_0, IIC8_1, IIC8_2 } },
-       { INT2PRI22, 0, 32, 8, { IIC9_2, 0, 0, 0 } },
-       { INT2PRI23, 0, 32, 8, { 0, SGPIO, IIC3_2, IIC5_1 } },
-       { INT2PRI24, 0, 32, 8, { 0, 0, 0, IIC1_1 } },
+       { INT2PRI22, 0, 32, 8, { IIC9_2, MMC2, G200, 0 } },
+       { INT2PRI23, 0, 32, 8, { PECI5, SGPIO, IIC3_2, IIC5_1 } },
+       { INT2PRI24, 0, 32, 8, { PECI4, PECI3, 0, IIC1_1 } },
        { INT2PRI25, 0, 32, 8, { IIC3_0, 0, IIC5_3, IIC5_2 } },
-       { INT2PRI26, 0, 32, 8, { 0, 0, 0, IIC9_3 } },
-       { INT2PRI27, 0, 32, 8, { PCIINTA, IIC6_0, IIC4_0, IIC6_1 } },
-       { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, 0, IIC6_2 } },
+       { INT2PRI26, 0, 32, 8, { ECCU, RSPI, 0, IIC9_3 } },
+       { INT2PRI27, 0, 32, 8, { PCIC, IIC6_0, IIC4_0, IIC6_1 } },
+       { INT2PRI28, 0, 32, 8, { IIC4_3, IIC7_0, MMC1, IIC6_2 } },
        { INT2PRI29, 0, 32, 8, { 0, 0, IIC9_0, IIC8_3 } },
-       { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, 0 } },
+       { INT2PRI30, 0, 32, 8, { IIC4_1, IIC4_2, IIC5_0, ONFICTL } },
        { INT2PRI31, 0, 32, 8, { IIC0_0, IIC0_1, IIC0_2, IIC0_3 } },
+       { INT2PRI32, 0, 32, 8, { DMINT22, 0, 0, 0 } },
+       { INT2PRI33, 0, 32, 8, { 0, 0, 0, DMINT16 } },
+       { INT2PRI34, 0, 32, 8, { 0, LPC6, DMINT21, DMINT18 } },
+       { INT2PRI35, 0, 32, 8, { DMINT23, TSIP, 0, DMINT19 } },
+       { INT2PRI36, 0, 32, 8, { DMINT20, GETHER1, PBIA, PBIB } },
+       { INT2PRI37, 0, 32, 8, { PBIC, DMAE2, DMAE3, SERMUX2 } },
+       { INT2PRI38, 0, 32, 8, { LPC7, 0, 0, 0 } },
+       { INT2PRI39, 0, 32, 8, { 0, 0, 0, WDT4B } },
+       { INT2PRI40, 0, 32, 8, { 0, 0, 0, DMINT17 } },
+       { INT2PRI41, 0, 32, 8, { DDRECC, 0, WDT6B, WDT5B } },
+       { INT2PRI42, 0, 32, 8, { 0, 0, 0, LPC8 } },
+       { INT2PRI43, 0, 32, 8, { 0, WDT7B, PCIE_BRIDGE, WDT8B } },
+       { INT2PRI44, 0, 32, 8, { WDT2B, GETHER2, 0, 0 } },
+       { INT2PRI45, 0, 32, 8, { 0, 0, LPC5, SERMUX3 } },
+       { INT2PRI46, 0, 32, 8, { WDT0B, WDT1B, WDT3B, GETHER0 } },
+       { INT2PRI47, 0, 32, 8, { DMINT12, DMINT13, DMINT14, DMINT15 } },
+};
+
+static struct intc_sense_reg sense_registers_irq8to15[] __initdata = {
+       { 0xffd100f8, 32, 2, /* ICR2 */   { IRQ15, IRQ14, IRQ13, IRQ12,
+                                           IRQ11, IRQ10, IRQ9, IRQ8 } },
 };
 
 static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups,
-                        mask_registers, prio_registers, NULL);
+                        mask_registers, prio_registers,
+                        sense_registers_irq8to15);
 
 /* Support for external interrupt pins in IRQ mode */
 static struct intc_vect vectors_irq0123[] __initdata = {
index 8797723..c016c00 100644 (file)
@@ -629,33 +629,10 @@ static void __init sh7786_usb_setup(void)
        }
 }
 
-static int __init sh7786_devices_setup(void)
-{
-       int ret;
-
-       sh7786_usb_setup();
-
-       ret = platform_add_devices(sh7786_early_devices,
-                                  ARRAY_SIZE(sh7786_early_devices));
-       if (unlikely(ret != 0))
-               return ret;
-
-       return platform_add_devices(sh7786_devices,
-                                   ARRAY_SIZE(sh7786_devices));
-}
-arch_initcall(sh7786_devices_setup);
-
-void __init plat_early_device_setup(void)
-{
-       early_platform_add_devices(sh7786_early_devices,
-                                  ARRAY_SIZE(sh7786_early_devices));
-}
-
 enum {
        UNUSED = 0,
 
        /* interrupt sources */
-
        IRL0_LLLL, IRL0_LLLH, IRL0_LLHL, IRL0_LLHH,
        IRL0_LHLL, IRL0_LHLH, IRL0_LHHL, IRL0_LHHH,
        IRL0_HLLL, IRL0_HLLH, IRL0_HLHL, IRL0_HLHH,
@@ -693,9 +670,12 @@ enum {
        Thermal,
        INTICI0, INTICI1, INTICI2, INTICI3,
        INTICI4, INTICI5, INTICI6, INTICI7,
+
+       /* Muxed sub-events */
+       TXI1, BRI1, RXI1, ERI1,
 };
 
-static struct intc_vect vectors[] __initdata = {
+static struct intc_vect sh7786_vectors[] __initdata = {
        INTC_VECT(WDT, 0x3e0),
        INTC_VECT(TMU0_0, 0x400), INTC_VECT(TMU0_1, 0x420),
        INTC_VECT(TMU0_2, 0x440), INTC_VECT(TMU0_3, 0x460),
@@ -756,14 +736,12 @@ static struct intc_vect vectors[] __initdata = {
 
 #define INTDISTCR0     0xfe4100b0
 #define INTDISTCR1     0xfe4100b4
-#define INTACK         0xfe4100b8
-#define INTACKCLR      0xfe4100bc
 #define INT2DISTCR0    0xfe410900
 #define INT2DISTCR1    0xfe410904
 #define INT2DISTCR2    0xfe410908
 #define INT2DISTCR3    0xfe41090c
 
-static struct intc_mask_reg mask_registers[] __initdata = {
+static struct intc_mask_reg sh7786_mask_registers[] __initdata = {
        { CnINTMSK0, CnINTMSKCLR0, 32,
          { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 },
            INTC_SMP_BALANCING(INTDISTCR0) },
@@ -807,7 +785,7 @@ static struct intc_mask_reg mask_registers[] __initdata = {
            0, 0, 0, 0, 0, 0, 0, 0 }, INTC_SMP_BALANCING(INT2DISTCR3) },
 };
 
-static struct intc_prio_reg prio_registers[] __initdata = {
+static struct intc_prio_reg sh7786_prio_registers[] __initdata = {
        { 0xfe410010, 0, 32, 4, /* INTPRI */   { IRQ0, IRQ1, IRQ2, IRQ3,
                                                 IRQ4, IRQ5, IRQ6, IRQ7 } },
        { 0xfe410800, 0, 32, 8, /* INT2PRI0 */ { 0, 0, 0, WDT } },
@@ -851,11 +829,27 @@ static struct intc_prio_reg prio_registers[] __initdata = {
            INTICI3, INTICI2, INTICI1, INTICI0 }, INTC_SMP(4, 2) },
 };
 
-static DECLARE_INTC_DESC(intc_desc, "sh7786", vectors, NULL,
-                        mask_registers, prio_registers, NULL);
+static struct intc_subgroup sh7786_subgroups[] __initdata = {
+       { 0xfe410c20, 32, SCIF1,
+         { 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, TXI1, BRI1, RXI1, ERI1 } },
+};
 
-/* Support for external interrupt pins in IRQ mode */
+static struct intc_desc sh7786_intc_desc __initdata = {
+       .name           = "sh7786",
+       .hw             = {
+               .vectors        = sh7786_vectors,
+               .nr_vectors     = ARRAY_SIZE(sh7786_vectors),
+               .mask_regs      = sh7786_mask_registers,
+               .nr_mask_regs   = ARRAY_SIZE(sh7786_mask_registers),
+               .subgroups      = sh7786_subgroups,
+               .nr_subgroups   = ARRAY_SIZE(sh7786_subgroups),
+               .prio_regs      = sh7786_prio_registers,
+               .nr_prio_regs   = ARRAY_SIZE(sh7786_prio_registers),
+       },
+};
 
+/* Support for external interrupt pins in IRQ mode */
 static struct intc_vect vectors_irq0123[] __initdata = {
        INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240),
        INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0),
@@ -866,23 +860,25 @@ static struct intc_vect vectors_irq4567[] __initdata = {
        INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0),
 };
 
-static struct intc_sense_reg sense_registers[] __initdata = {
+static struct intc_sense_reg sh7786_sense_registers[] __initdata = {
        { 0xfe41001c, 32, 2, /* ICR1 */   { IRQ0, IRQ1, IRQ2, IRQ3,
                                            IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
-static struct intc_mask_reg ack_registers[] __initdata = {
+static struct intc_mask_reg sh7786_ack_registers[] __initdata = {
        { 0xfe410024, 0, 32, /* INTREQ */
          { IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7 } },
 };
 
 static DECLARE_INTC_DESC_ACK(intc_desc_irq0123, "sh7786-irq0123",
-                            vectors_irq0123, NULL, mask_registers,
-                            prio_registers, sense_registers, ack_registers);
+                            vectors_irq0123, NULL, sh7786_mask_registers,
+                            sh7786_prio_registers, sh7786_sense_registers,
+                            sh7786_ack_registers);
 
 static DECLARE_INTC_DESC_ACK(intc_desc_irq4567, "sh7786-irq4567",
-                            vectors_irq4567, NULL, mask_registers,
-                            prio_registers, sense_registers, ack_registers);
+                            vectors_irq4567, NULL, sh7786_mask_registers,
+                            sh7786_prio_registers, sh7786_sense_registers,
+                            sh7786_ack_registers);
 
 /* External interrupt pins in IRL mode */
 
@@ -909,10 +905,10 @@ static struct intc_vect vectors_irl4567[] __initdata = {
 };
 
 static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7786-irl0123", vectors_irl0123,
-                        NULL, mask_registers, NULL, NULL);
+                        NULL, sh7786_mask_registers, NULL, NULL);
 
 static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567,
-                        NULL, mask_registers, NULL, NULL);
+                        NULL, sh7786_mask_registers, NULL, NULL);
 
 #define INTC_ICR0      0xfe410000
 #define INTC_INTMSK0   CnINTMSK0
@@ -920,19 +916,6 @@ static DECLARE_INTC_DESC(intc_desc_irl4567, "sh7786-irl4567", vectors_irl4567,
 #define INTC_INTMSK2   INTMSK2
 #define INTC_INTMSKCLR1        CnINTMSKCLR1
 #define INTC_INTMSKCLR2        INTMSKCLR2
-#define INTC_USERIMASK 0xfe411000
-
-#ifdef CONFIG_INTC_BALANCING
-unsigned int irq_lookup(unsigned int irq)
-{
-       return __raw_readl(INTACK) & 1 ? irq : NO_IRQ_IGNORE;
-}
-
-void irq_finish(unsigned int irq)
-{
-       __raw_writel(irq2evt(irq), INTACKCLR);
-}
-#endif
 
 void __init plat_irq_setup(void)
 {
@@ -946,8 +929,7 @@ void __init plat_irq_setup(void)
        /* select IRL mode for IRL3-0 + IRL7-4 */
        __raw_writel(__raw_readl(INTC_ICR0) & ~0x00c00000, INTC_ICR0);
 
-       register_intc_controller(&intc_desc);
-       register_intc_userimask(INTC_USERIMASK);
+       register_intc_controller(&sh7786_intc_desc);
 }
 
 void __init plat_irq_setup_pins(int mode)
@@ -991,3 +973,39 @@ void __init plat_irq_setup_pins(int mode)
 void __init plat_mem_setup(void)
 {
 }
+
+static int __init sh7786_devices_setup(void)
+{
+       int ret, irq;
+
+       sh7786_usb_setup();
+
+       /*
+        * De-mux SCIF1 IRQs if possible
+        */
+       irq = intc_irq_lookup(sh7786_intc_desc.name, TXI1);
+       if (irq > 0) {
+               scif1_platform_data.irqs[SCIx_TXI_IRQ] = irq;
+               scif1_platform_data.irqs[SCIx_ERI_IRQ] =
+                       intc_irq_lookup(sh7786_intc_desc.name, ERI1);
+               scif1_platform_data.irqs[SCIx_BRI_IRQ] =
+                       intc_irq_lookup(sh7786_intc_desc.name, BRI1);
+               scif1_platform_data.irqs[SCIx_RXI_IRQ] =
+                       intc_irq_lookup(sh7786_intc_desc.name, RXI1);
+       }
+
+       ret = platform_add_devices(sh7786_early_devices,
+                                  ARRAY_SIZE(sh7786_early_devices));
+       if (unlikely(ret != 0))
+               return ret;
+
+       return platform_add_devices(sh7786_devices,
+                                   ARRAY_SIZE(sh7786_devices));
+}
+arch_initcall(sh7786_devices_setup);
+
+void __init plat_early_device_setup(void)
+{
+       early_platform_add_devices(sh7786_early_devices,
+                                  ARRAY_SIZE(sh7786_early_devices));
+}
index 9158bc5..013f0b1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * SH-X3 Prototype Setup
  *
- *  Copyright (C) 2007 - 2009  Paul Mundt
+ *  Copyright (C) 2007 - 2010  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
@@ -12,7 +12,9 @@
 #include <linux/serial.h>
 #include <linux/serial_sci.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 #include <linux/sh_timer.h>
+#include <cpu/shx3.h>
 #include <asm/mmzone.h>
 
 /*
@@ -354,6 +356,10 @@ static struct intc_group groups[] __initdata = {
                   DMAC1_DMINT9, DMAC1_DMINT10, DMAC1_DMINT11),
 };
 
+#define INT2DISTCR0    0xfe4108a0
+#define INT2DISTCR1    0xfe4108a4
+#define INT2DISTCR2    0xfe4108a8
+
 static struct intc_mask_reg mask_registers[] __initdata = {
        { 0xfe410030, 0xfe410050, 32, /* CnINTMSK0 / CnINTMSKCLR0 */
          { IRQ0, IRQ1, IRQ2, IRQ3 } },
@@ -363,20 +369,23 @@ static struct intc_mask_reg mask_registers[] __initdata = {
          { FE1, FE0, 0, ATAPI, VCORE0, VIN1, VIN0, IIC,
            DU, GPIO3, GPIO2, GPIO1, GPIO0, PAM, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, /* HUDI bits ignored */
-           0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, } },
+           0, TMU5, TMU4, TMU3, TMU2, TMU1, TMU0, 0, },
+           INTC_SMP_BALANCING(INT2DISTCR0) },
        { 0xfe410830, 0xfe410860, 32, /* CnINT2MSK1 / CnINT2MSKCLR1 */
          { 0, 0, 0, 0, DTU3, DTU2, DTU1, DTU0, /* IRM bits ignored */
            PCII9, PCII8, PCII7, PCII6, PCII5, PCII4, PCII3, PCII2,
            PCII1, PCII0, DMAC1_DMAE, DMAC1_DMINT11,
            DMAC1_DMINT10, DMAC1_DMINT9, DMAC1_DMINT8, DMAC1_DMINT7,
            DMAC1_DMINT6, DMAC0_DMAE, DMAC0_DMINT5, DMAC0_DMINT4,
-           DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 } },
+           DMAC0_DMINT3, DMAC0_DMINT2, DMAC0_DMINT1, DMAC0_DMINT0 },
+           INTC_SMP_BALANCING(INT2DISTCR1) },
        { 0xfe410840, 0xfe410870, 32, /* CnINT2MSK2 / CnINT2MSKCLR2 */
          { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            SCIF3_TXI, SCIF3_BRI, SCIF3_RXI, SCIF3_ERI,
            SCIF2_TXI, SCIF2_BRI, SCIF2_RXI, SCIF2_ERI,
            SCIF1_TXI, SCIF1_BRI, SCIF1_RXI, SCIF1_ERI,
-           SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI } },
+           SCIF0_TXI, SCIF0_BRI, SCIF0_RXI, SCIF0_ERI },
+           INTC_SMP_BALANCING(INT2DISTCR2) },
 };
 
 static struct intc_prio_reg prio_registers[] __initdata = {
@@ -433,11 +442,33 @@ static DECLARE_INTC_DESC(intc_desc_irl, "shx3-irl", vectors_irl, groups,
 
 void __init plat_irq_setup_pins(int mode)
 {
+       int ret = 0;
+
        switch (mode) {
        case IRQ_MODE_IRQ:
+               ret |= gpio_request(GPIO_FN_IRQ3, intc_desc_irq.name);
+               ret |= gpio_request(GPIO_FN_IRQ2, intc_desc_irq.name);
+               ret |= gpio_request(GPIO_FN_IRQ1, intc_desc_irq.name);
+               ret |= gpio_request(GPIO_FN_IRQ0, intc_desc_irq.name);
+
+               if (unlikely(ret)) {
+                       pr_err("Failed to set IRQ mode\n");
+                       return;
+               }
+
                register_intc_controller(&intc_desc_irq);
                break;
        case IRQ_MODE_IRL3210:
+               ret |= gpio_request(GPIO_FN_IRL3, intc_desc_irl.name);
+               ret |= gpio_request(GPIO_FN_IRL2, intc_desc_irl.name);
+               ret |= gpio_request(GPIO_FN_IRL1, intc_desc_irl.name);
+               ret |= gpio_request(GPIO_FN_IRL0, intc_desc_irl.name);
+
+               if (unlikely(ret)) {
+                       pr_err("Failed to set IRL mode\n");
+                       return;
+               }
+
                register_intc_controller(&intc_desc_irl);
                break;
        default:
@@ -447,6 +478,9 @@ void __init plat_irq_setup_pins(int mode)
 
 void __init plat_irq_setup(void)
 {
+       reserve_intc_vectors(vectors_irq, ARRAY_SIZE(vectors_irq));
+       reserve_intc_vectors(vectors_irl, ARRAY_SIZE(vectors_irl));
+
        register_intc_controller(&intc_desc);
 }
 
index 6e35f01..7db2489 100644 (file)
@@ -330,7 +330,7 @@ ENTRY(_stext)
 #if defined(CONFIG_CPU_SH2)
 1:     .long   0x000000F0              ! IMASK=0xF
 #else
-1:     .long   0x400080F0              ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF
+1:     .long   0x500080F0              ! MD=1, RB=0, BL=1, FD=1, IMASK=0xF
 #endif
 ENTRY(stack_start)
 2:     .long   init_thread_union+THREAD_SIZE
index 2947d2b..32c385e 100644 (file)
@@ -291,7 +291,7 @@ int handle_trapped_io(struct pt_regs *regs, unsigned long address)
        }
 
        tmp = handle_unaligned_access(instruction, regs,
-                                     &trapped_io_access, 1);
+                                     &trapped_io_access, 1, address);
        set_fs(oldfs);
        return tmp == 0;
 }
index ae5bac3..9dc447d 100644 (file)
@@ -283,6 +283,8 @@ void __init init_IRQ(void)
        if (sh_mv.mv_init_irq)
                sh_mv.mv_init_irq();
 
+       intc_finalize();
+
        irq_ctx_init(smp_processor_id());
 }
 
diff --git a/arch/sh/kernel/kdebugfs.c b/arch/sh/kernel/kdebugfs.c
new file mode 100644 (file)
index 0000000..e11c30b
--- /dev/null
@@ -0,0 +1,16 @@
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/debugfs.h>
+
+struct dentry *arch_debugfs_dir;
+EXPORT_SYMBOL(arch_debugfs_dir);
+
+static int __init arch_kdebugfs_init(void)
+{
+       arch_debugfs_dir = debugfs_create_dir("sh", NULL);
+       if (!arch_debugfs_dir)
+               return -ENOMEM;
+
+       return 0;
+}
+arch_initcall(arch_kdebugfs_init);
index 4049d99..1208b09 100644 (file)
@@ -20,9 +20,9 @@
 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;
+static DEFINE_PER_CPU(struct kprobe, saved_current_opcode);
+static DEFINE_PER_CPU(struct kprobe, saved_next_opcode);
+static DEFINE_PER_CPU(struct kprobe, saved_next_opcode2);
 
 #define OPCODE_JMP(x)  (((x) & 0xF0FF) == 0x402b)
 #define OPCODE_JSR(x)  (((x) & 0xF0FF) == 0x400b)
@@ -102,16 +102,21 @@ int __kprobes kprobe_handle_illslot(unsigned long pc)
 
 void __kprobes arch_remove_kprobe(struct kprobe *p)
 {
-       if (saved_next_opcode.addr != 0x0) {
+       struct kprobe *saved = &__get_cpu_var(saved_next_opcode);
+
+       if (saved->addr) {
                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;
+               arch_disarm_kprobe(saved);
+
+               saved->addr = NULL;
+               saved->opcode = 0;
+
+               saved = &__get_cpu_var(saved_next_opcode2);
+               if (saved->addr) {
+                       arch_disarm_kprobe(saved);
+
+                       saved->addr = NULL;
+                       saved->opcode = 0;
                }
        }
 }
@@ -141,57 +146,59 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
  */
 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;
+       __get_cpu_var(saved_current_opcode).addr = (kprobe_opcode_t *)regs->pc;
 
        if (p != NULL) {
+               struct kprobe *op1, *op2;
+
                arch_disarm_kprobe(p);
 
+               op1 = &__get_cpu_var(saved_next_opcode);
+               op2 = &__get_cpu_var(saved_next_opcode2);
+
                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];
+                       op1->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 =
+                       op1->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 =
+                       op1->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;
+                       op1->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;
+                       op1->addr = p->addr + 1;
                        /* case 2 */
-                       saved_next_opcode2.addr =
+                       op2->addr =
                            (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
-                       saved_next_opcode2.opcode = *(saved_next_opcode2.addr);
-                       arch_arm_kprobe(&saved_next_opcode2);
+                       op2->opcode = *(op2->addr);
+                       arch_arm_kprobe(op2);
 
                } 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;
+                       op1->addr = p->addr + 2;
                        /* case 2 */
-                       saved_next_opcode2.addr =
+                       op2->addr =
                            (kprobe_opcode_t *) (regs->pc + 4 + disp * 2);
-                       saved_next_opcode2.opcode = *(saved_next_opcode2.addr);
-                       arch_arm_kprobe(&saved_next_opcode2);
+                       op2->opcode = *(op2->addr);
+                       arch_arm_kprobe(op2);
 
                } else {
-                       saved_next_opcode.addr = p->addr + 1;
+                       op1->addr = p->addr + 1;
                }
 
-               saved_next_opcode.opcode = *(saved_next_opcode.addr);
-               arch_arm_kprobe(&saved_next_opcode);
+               op1->opcode = *(op1->addr);
+               arch_arm_kprobe(op1);
        }
 }
 
@@ -376,21 +383,23 @@ static int __kprobes post_kprobe_handler(struct pt_regs *regs)
                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;
+       p = &__get_cpu_var(saved_next_opcode);
+       if (p->addr) {
+               arch_disarm_kprobe(p);
+               p->addr = NULL;
+               p->opcode = 0;
 
-               addr = saved_current_opcode.addr;
-               saved_current_opcode.addr = 0x0;
+               addr = __get_cpu_var(saved_current_opcode).addr;
+               __get_cpu_var(saved_current_opcode).addr = NULL;
 
                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;
+               p = &__get_cpu_var(saved_next_opcode2);
+               if (p->addr) {
+                       arch_disarm_kprobe(p);
+                       p->addr = NULL;
+                       p->opcode = 0;
                }
        }
 
@@ -572,14 +581,5 @@ static struct kprobe trampoline_p = {
 
 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);
 }
diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
new file mode 100644 (file)
index 0000000..0a05983
--- /dev/null
@@ -0,0 +1,33 @@
+#include <linux/ptrace.h>
+
+/**
+ * regs_query_register_offset() - query register offset from its name
+ * @name:      the name of a register
+ *
+ * regs_query_register_offset() returns the offset of a register in struct
+ * pt_regs from its name. If the name is invalid, this returns -EINVAL;
+ */
+int regs_query_register_offset(const char *name)
+{
+       const struct pt_regs_offset *roff;
+       for (roff = regoffset_table; roff->name != NULL; roff++)
+               if (!strcmp(roff->name, name))
+                       return roff->offset;
+       return -EINVAL;
+}
+
+/**
+ * regs_query_register_name() - query register name from its offset
+ * @offset:    the offset of a register in struct pt_regs.
+ *
+ * regs_query_register_name() returns the name of a register from its
+ * offset in struct pt_regs. If the @offset is invalid, this returns NULL;
+ */
+const char *regs_query_register_name(unsigned int offset)
+{
+       const struct pt_regs_offset *roff;
+       for (roff = regoffset_table; roff->name != NULL; roff++)
+               if (roff->offset == offset)
+                       return roff->name;
+       return NULL;
+}
index 6c4bbba..2cd42b5 100644 (file)
@@ -274,6 +274,33 @@ static int dspregs_active(struct task_struct *target,
 }
 #endif
 
+const struct pt_regs_offset regoffset_table[] = {
+       REGS_OFFSET_NAME(0),
+       REGS_OFFSET_NAME(1),
+       REGS_OFFSET_NAME(2),
+       REGS_OFFSET_NAME(3),
+       REGS_OFFSET_NAME(4),
+       REGS_OFFSET_NAME(5),
+       REGS_OFFSET_NAME(6),
+       REGS_OFFSET_NAME(7),
+       REGS_OFFSET_NAME(8),
+       REGS_OFFSET_NAME(9),
+       REGS_OFFSET_NAME(10),
+       REGS_OFFSET_NAME(11),
+       REGS_OFFSET_NAME(12),
+       REGS_OFFSET_NAME(13),
+       REGS_OFFSET_NAME(14),
+       REGS_OFFSET_NAME(15),
+       REG_OFFSET_NAME(pc),
+       REG_OFFSET_NAME(pr),
+       REG_OFFSET_NAME(sr),
+       REG_OFFSET_NAME(gbr),
+       REG_OFFSET_NAME(mach),
+       REG_OFFSET_NAME(macl),
+       REG_OFFSET_NAME(tra),
+       REG_OFFSET_END,
+};
+
 /*
  * These are our native regset flavours.
  */
index 5fd644d..e0fb065 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
+#include <linux/bitops.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
@@ -252,6 +252,85 @@ static int fpregs_active(struct task_struct *target,
 }
 #endif
 
+const struct pt_regs_offset regoffset_table[] = {
+       REG_OFFSET_NAME(pc),
+       REG_OFFSET_NAME(sr),
+       REG_OFFSET_NAME(syscall_nr),
+       REGS_OFFSET_NAME(0),
+       REGS_OFFSET_NAME(1),
+       REGS_OFFSET_NAME(2),
+       REGS_OFFSET_NAME(3),
+       REGS_OFFSET_NAME(4),
+       REGS_OFFSET_NAME(5),
+       REGS_OFFSET_NAME(6),
+       REGS_OFFSET_NAME(7),
+       REGS_OFFSET_NAME(8),
+       REGS_OFFSET_NAME(9),
+       REGS_OFFSET_NAME(10),
+       REGS_OFFSET_NAME(11),
+       REGS_OFFSET_NAME(12),
+       REGS_OFFSET_NAME(13),
+       REGS_OFFSET_NAME(14),
+       REGS_OFFSET_NAME(15),
+       REGS_OFFSET_NAME(16),
+       REGS_OFFSET_NAME(17),
+       REGS_OFFSET_NAME(18),
+       REGS_OFFSET_NAME(19),
+       REGS_OFFSET_NAME(20),
+       REGS_OFFSET_NAME(21),
+       REGS_OFFSET_NAME(22),
+       REGS_OFFSET_NAME(23),
+       REGS_OFFSET_NAME(24),
+       REGS_OFFSET_NAME(25),
+       REGS_OFFSET_NAME(26),
+       REGS_OFFSET_NAME(27),
+       REGS_OFFSET_NAME(28),
+       REGS_OFFSET_NAME(29),
+       REGS_OFFSET_NAME(30),
+       REGS_OFFSET_NAME(31),
+       REGS_OFFSET_NAME(32),
+       REGS_OFFSET_NAME(33),
+       REGS_OFFSET_NAME(34),
+       REGS_OFFSET_NAME(35),
+       REGS_OFFSET_NAME(36),
+       REGS_OFFSET_NAME(37),
+       REGS_OFFSET_NAME(38),
+       REGS_OFFSET_NAME(39),
+       REGS_OFFSET_NAME(40),
+       REGS_OFFSET_NAME(41),
+       REGS_OFFSET_NAME(42),
+       REGS_OFFSET_NAME(43),
+       REGS_OFFSET_NAME(44),
+       REGS_OFFSET_NAME(45),
+       REGS_OFFSET_NAME(46),
+       REGS_OFFSET_NAME(47),
+       REGS_OFFSET_NAME(48),
+       REGS_OFFSET_NAME(49),
+       REGS_OFFSET_NAME(50),
+       REGS_OFFSET_NAME(51),
+       REGS_OFFSET_NAME(52),
+       REGS_OFFSET_NAME(53),
+       REGS_OFFSET_NAME(54),
+       REGS_OFFSET_NAME(55),
+       REGS_OFFSET_NAME(56),
+       REGS_OFFSET_NAME(57),
+       REGS_OFFSET_NAME(58),
+       REGS_OFFSET_NAME(59),
+       REGS_OFFSET_NAME(60),
+       REGS_OFFSET_NAME(61),
+       REGS_OFFSET_NAME(62),
+       REGS_OFFSET_NAME(63),
+       TREGS_OFFSET_NAME(0),
+       TREGS_OFFSET_NAME(1),
+       TREGS_OFFSET_NAME(2),
+       TREGS_OFFSET_NAME(3),
+       TREGS_OFFSET_NAME(4),
+       TREGS_OFFSET_NAME(5),
+       TREGS_OFFSET_NAME(6),
+       TREGS_OFFSET_NAME(7),
+       REG_OFFSET_END,
+};
+
 /*
  * These are our native regset flavours.
  */
@@ -395,10 +474,9 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
 asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
 {
 #define WPC_DBRMODE 0x0d104008
-       static int first_call = 1;
+       static unsigned long first_call;
 
-       lock_kernel();
-       if (first_call) {
+       if (!test_and_set_bit(0, &first_call)) {
                /* Set WPC.DBRMODE to 0.  This makes all debug events get
                 * delivered through RESVEC, i.e. into the handlers in entry.S.
                 * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
@@ -408,9 +486,7 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data)
                 * the remote gdb.) */
                printk("DBRMODE set to 0 to permit native debugging\n");
                poke_real_address_q(WPC_DBRMODE, 0);
-               first_call = 0;
        }
-       unlock_kernel();
 
        return sys_ptrace(request, pid, addr, data);
 }
index b1fca66..ca6a5ca 100644 (file)
@@ -9,6 +9,7 @@
 #include <asm/addrspace.h>
 #include <asm/reboot.h>
 #include <asm/system.h>
+#include <asm/tlbflush.h>
 
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
@@ -25,6 +26,9 @@ static void native_machine_restart(char * __unused)
 {
        local_irq_disable();
 
+       /* Destroy all of the TLBs in preparation for reset by MMU */
+       __flush_tlb_global();
+
        /* Address error with SR.BL=1 first. */
        trigger_address_error();
 
index e769401..4e27846 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/err.h>
-#include <linux/debugfs.h>
 #include <linux/crash_dump.h>
 #include <linux/mmzone.h>
 #include <linux/clk.h>
@@ -136,8 +135,9 @@ void __init check_for_initrd(void)
                goto disable;
        }
 
-       if (unlikely(start < PAGE_OFFSET)) {
-               pr_err("initrd start < PAGE_OFFSET\n");
+       if (unlikely(start < __MEMORY_START)) {
+               pr_err("initrd start (%08lx) < __MEMORY_START(%x)\n",
+                       start, __MEMORY_START);
                goto disable;
        }
 
@@ -158,7 +158,7 @@ void __init check_for_initrd(void)
        /*
         * Address sanitization
         */
-       initrd_start = (unsigned long)__va(__pa(start));
+       initrd_start = (unsigned long)__va(start);
        initrd_end = initrd_start + INITRD_SIZE;
 
        memblock_reserve(__pa(initrd_start), INITRD_SIZE);
@@ -458,17 +458,3 @@ const struct seq_operations cpuinfo_op = {
        .show   = show_cpuinfo,
 };
 #endif /* CONFIG_PROC_FS */
-
-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);
-
-       return 0;
-}
-arch_initcall(sh_debugfs_init);
index 19fd11d..e872e81 100644 (file)
@@ -353,3 +353,25 @@ ENTRY(sys_call_table)
        .long sys_pwritev
        .long sys_rt_tgsigqueueinfo     /* 335 */
        .long sys_perf_event_open
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
+       /* Broken-out socket family */
+       .long sys_socket                /* 340 */
+       .long sys_bind
+       .long sys_connect
+       .long sys_listen
+       .long sys_accept
+       .long sys_getsockname   /* 345 */
+       .long sys_getpeername
+       .long sys_socketpair
+       .long sys_send
+       .long sys_sendto
+       .long sys_recv                  /* 350 */
+       .long sys_recvfrom
+       .long sys_shutdown
+       .long sys_setsockopt
+       .long sys_getsockopt
+       .long sys_sendmsg               /* 355 */
+       .long sys_recvmsg
+       .long sys_recvmmsg
index 2048a20..6658570 100644 (file)
@@ -393,3 +393,6 @@ sys_call_table:
        .long sys_perf_event_open
        .long sys_recvmmsg              /* 365 */
        .long sys_accept4
+       .long sys_fanotify_init
+       .long sys_fanotify_mark
+       .long sys_prlimit64
index c3d86fa..3484c2f 100644 (file)
@@ -5,7 +5,7 @@
  *  SuperH version: Copyright (C) 1999 Niibe Yutaka
  *                  Copyright (C) 2000 Philipp Rumpf
  *                  Copyright (C) 2000 David Howells
- *                  Copyright (C) 2002 - 2007 Paul Mundt
+ *                  Copyright (C) 2002 - 2010 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
@@ -26,6 +26,7 @@
 #include <linux/limits.h>
 #include <linux/sysfs.h>
 #include <linux/uaccess.h>
+#include <linux/perf_event.h>
 #include <asm/system.h>
 #include <asm/alignment.h>
 #include <asm/fpu.h>
@@ -369,7 +370,8 @@ static inline int handle_delayslot(struct pt_regs *regs,
 #define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4)
 
 int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
-                           struct mem_access *ma, int expected)
+                           struct mem_access *ma, int expected,
+                           unsigned long address)
 {
        u_int rm;
        int ret, index;
@@ -383,9 +385,18 @@ int handle_unaligned_access(insn_size_t instruction, struct pt_regs *regs,
        index = (instruction>>8)&15;    /* 0x0F00 */
        rm = regs->regs[index];
 
-       /* shout about fixups */
-       if (!expected)
+       /*
+        * Log the unexpected fixups, and then pass them on to perf.
+        *
+        * We intentionally don't report the expected cases to perf as
+        * otherwise the trapped I/O case will skew the results too much
+        * to be useful.
+        */
+       if (!expected) {
                unaligned_fixups_notify(current, instruction, regs);
+               perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0,
+                             regs, address);
+       }
 
        ret = -EFAULT;
        switch (instruction&0xF000) {
@@ -574,7 +585,8 @@ fixup:
 
                set_fs(USER_DS);
                tmp = handle_unaligned_access(instruction, regs,
-                                             &user_mem_access, 0);
+                                             &user_mem_access, 0,
+                                             address);
                set_fs(oldfs);
 
                if (tmp == 0)
@@ -607,8 +619,8 @@ uspace_segv:
 
                unaligned_fixups_notify(current, instruction, regs);
 
-               handle_unaligned_access(instruction, regs,
-                                       &user_mem_access, 0);
+               handle_unaligned_access(instruction, regs, &user_mem_access,
+                                       0, address);
                set_fs(oldfs);
        }
 }
@@ -802,6 +814,9 @@ void __cpuinit per_cpu_trap_init(void)
                     : /* no output */
                     : "r" (&vbr_base)
                     : "memory");
+
+       /* disable exception blocking now when the vbr has been setup */
+       clear_bl_bit();
 }
 
 void *set_exception_table_vec(unsigned int vec, void *handler)
index e67e140..6713ca9 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
 #include <linux/module.h>
+#include <linux/perf_event.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
@@ -50,7 +51,7 @@ asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \
        do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \
 }
 
-spinlock_t die_lock;
+static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
@@ -433,6 +434,8 @@ static int misaligned_load(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+
        destreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
@@ -509,6 +512,8 @@ static int misaligned_store(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, 0, regs, address);
+
        srcreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
@@ -583,6 +588,8 @@ static int misaligned_fpu_load(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+
        destreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
@@ -658,6 +665,8 @@ static int misaligned_fpu_store(struct pt_regs *regs,
                return error;
        }
 
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, address);
+
        srcreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
                __u64 buffer;
index dab4d21..7b95f29 100644 (file)
@@ -30,4 +30,4 @@ lib-$(CONFIG_MMU)             += copy_page.o __clear_user.o
 lib-$(CONFIG_MCOUNT)           += mcount.o
 lib-y                          += $(memcpy-y) $(memset-y) $(udivsi3-y)
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index 1fcdb12..f76a509 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
+#include <linux/perf_event.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -619,6 +620,8 @@ int do_fpu_inst(unsigned short inst, struct pt_regs *regs)
        struct task_struct *tsk = current;
        struct sh_fpu_soft_struct *fpu = &(tsk->thread.xstate->softfpu);
 
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, 0);
+
        if (!(task_thread_info(tsk)->status & TS_USEDFPU)) {
                /* initialize once. */
                fpu_init(fpu);
index 1445ca6..0937039 100644 (file)
@@ -168,6 +168,10 @@ config IOREMAP_FIXED
 config UNCACHED_MAPPING
        bool
 
+config HAVE_SRAM_POOL
+       bool
+       select GENERIC_ALLOCATOR
+
 choice
        prompt "Kernel page size"
        default PAGE_SIZE_4KB
index 53f7c68..ab89ea4 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_PMB)             += pmb.o
 obj-$(CONFIG_NUMA)             += numa.o
 obj-$(CONFIG_IOREMAP_FIXED)    += ioremap_fixed.o
 obj-$(CONFIG_UNCACHED_MAPPING) += uncached.o
+obj-$(CONFIG_HAVE_SRAM_POOL)   += sram.o
 
 # Special flags for fault_64.o.  This puts restrictions on the number of
 # caller-save registers that the compiler can target when building this file.
@@ -66,4 +67,4 @@ CFLAGS_fault_64.o += -ffixed-r7 \
        -ffixed-r60 -ffixed-r61 -ffixed-r62 \
        -fomit-frame-pointer
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
index cd8c3bf..74c03ec 100644 (file)
@@ -63,7 +63,7 @@ static int __init asids_debugfs_init(void)
 {
        struct dentry *asids_dentry;
 
-       asids_dentry = debugfs_create_file("asids", S_IRUSR, sh_debugfs_root,
+       asids_dentry = debugfs_create_file("asids", S_IRUSR, arch_debugfs_dir,
                                           NULL, &asids_debugfs_fops);
        if (!asids_dentry)
                return -ENOMEM;
index 690ed01..5241146 100644 (file)
@@ -126,25 +126,19 @@ static int __init cache_debugfs_init(void)
 {
        struct dentry *dcache_dentry, *icache_dentry;
 
-       dcache_dentry = debugfs_create_file("dcache", S_IRUSR, sh_debugfs_root,
+       dcache_dentry = debugfs_create_file("dcache", S_IRUSR, arch_debugfs_dir,
                                            (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,
+       icache_dentry = debugfs_create_file("icache", S_IRUSR, arch_debugfs_dir,
                                            (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);
-       }
 
        return 0;
 }
index c86a085..0387932 100644 (file)
@@ -38,11 +38,12 @@ void *dma_generic_alloc_coherent(struct device *dev, size_t size,
        void *ret, *ret_nocache;
        int order = get_order(size);
 
+       gfp |= __GFP_ZERO;
+
        ret = (void *)__get_free_pages(gfp, order);
        if (!ret)
                return NULL;
 
-       memset(ret, 0, size);
        /*
         * Pages from the page allocator may have data present in
         * cache. So flush the cache before using uncached memory.
index 552bea5..3385b28 100644 (file)
@@ -47,7 +47,6 @@ static pte_t *__get_pte_phys(unsigned long addr)
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
-       pte_t *pte;
 
        pgd = pgd_offset_k(addr);
        if (pgd_none(*pgd)) {
@@ -67,8 +66,7 @@ static pte_t *__get_pte_phys(unsigned long addr)
                return NULL;
        }
 
-       pte = pte_offset_kernel(pmd, addr);
-       return pte;
+       return pte_offset_kernel(pmd, addr);
 }
 
 static void set_pte_phys(unsigned long addr, unsigned long phys, pgprot_t prot)
@@ -125,13 +123,45 @@ void __clear_fixmap(enum fixed_addresses idx, pgprot_t prot)
        clear_pte_phys(address, prot);
 }
 
+static pmd_t * __init one_md_table_init(pud_t *pud)
+{
+       if (pud_none(*pud)) {
+               pmd_t *pmd;
+
+               pmd = alloc_bootmem_pages(PAGE_SIZE);
+               pud_populate(&init_mm, pud, pmd);
+               BUG_ON(pmd != pmd_offset(pud, 0));
+       }
+
+       return pmd_offset(pud, 0);
+}
+
+static pte_t * __init one_page_table_init(pmd_t *pmd)
+{
+       if (pmd_none(*pmd)) {
+               pte_t *pte;
+
+               pte = alloc_bootmem_pages(PAGE_SIZE);
+               pmd_populate_kernel(&init_mm, pmd, pte);
+               BUG_ON(pte != pte_offset_kernel(pmd, 0));
+       }
+
+       return pte_offset_kernel(pmd, 0);
+}
+
+static pte_t * __init page_table_kmap_check(pte_t *pte, pmd_t *pmd,
+                                           unsigned long vaddr, pte_t *lastpte)
+{
+       return pte;
+}
+
 void __init page_table_range_init(unsigned long start, unsigned long end,
                                         pgd_t *pgd_base)
 {
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
-       pte_t *pte;
+       pte_t *pte = NULL;
        int i, j, k;
        unsigned long vaddr;
 
@@ -144,19 +174,13 @@ void __init page_table_range_init(unsigned long start, unsigned long end,
        for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
                pud = (pud_t *)pgd;
                for ( ; (j < PTRS_PER_PUD) && (vaddr != end); pud++, j++) {
-#ifdef __PAGETABLE_PMD_FOLDED
-                       pmd = (pmd_t *)pud;
-#else
-                       pmd = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE);
-                       pud_populate(&init_mm, pud, pmd);
+                       pmd = one_md_table_init(pud);
+#ifndef __PAGETABLE_PMD_FOLDED
                        pmd += k;
 #endif
                        for (; (k < PTRS_PER_PMD) && (vaddr != end); pmd++, k++) {
-                               if (pmd_none(*pmd)) {
-                                       pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-                                       pmd_populate_kernel(&init_mm, pmd, pte);
-                                       BUG_ON(pte != pte_offset_kernel(pmd, 0));
-                               }
+                               pte = page_table_kmap_check(one_page_table_init(pmd),
+                                                           pmd, vaddr, pte);
                                vaddr += PMD_SIZE;
                        }
                        k = 0;
index 7694f50..36312d2 100644 (file)
@@ -67,6 +67,10 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
        BUG();
 }
 
+void __flush_tlb_global(void)
+{
+}
+
 void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
 }
index 6379091..b20b1b3 100644 (file)
@@ -40,7 +40,7 @@ struct pmb_entry {
        unsigned long flags;
        unsigned long size;
 
-       spinlock_t lock;
+       raw_spinlock_t lock;
 
        /*
         * 0 .. NR_PMB_ENTRIES for specific entry selection, or
@@ -265,7 +265,7 @@ static struct pmb_entry *pmb_alloc(unsigned long vpn, unsigned long ppn,
 
        memset(pmbe, 0, sizeof(struct pmb_entry));
 
-       spin_lock_init(&pmbe->lock);
+       raw_spin_lock_init(&pmbe->lock);
 
        pmbe->vpn       = vpn;
        pmbe->ppn       = ppn;
@@ -327,9 +327,9 @@ static void set_pmb_entry(struct pmb_entry *pmbe)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&pmbe->lock, flags);
+       raw_spin_lock_irqsave(&pmbe->lock, flags);
        __set_pmb_entry(pmbe);
-       spin_unlock_irqrestore(&pmbe->lock, flags);
+       raw_spin_unlock_irqrestore(&pmbe->lock, flags);
 }
 #endif /* CONFIG_PM */
 
@@ -368,7 +368,7 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
                                return PTR_ERR(pmbe);
                        }
 
-                       spin_lock_irqsave(&pmbe->lock, flags);
+                       raw_spin_lock_irqsave(&pmbe->lock, flags);
 
                        pmbe->size = pmb_sizes[i].size;
 
@@ -383,9 +383,10 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
                         * entries for easier tear-down.
                         */
                        if (likely(pmbp)) {
-                               spin_lock(&pmbp->lock);
+                               raw_spin_lock_nested(&pmbp->lock,
+                                                    SINGLE_DEPTH_NESTING);
                                pmbp->link = pmbe;
-                               spin_unlock(&pmbp->lock);
+                               raw_spin_unlock(&pmbp->lock);
                        }
 
                        pmbp = pmbe;
@@ -398,7 +399,7 @@ int pmb_bolt_mapping(unsigned long vaddr, phys_addr_t phys,
                        i--;
                        mapped++;
 
-                       spin_unlock_irqrestore(&pmbe->lock, flags);
+                       raw_spin_unlock_irqrestore(&pmbe->lock, flags);
                }
        } while (size >= SZ_16M);
 
@@ -627,15 +628,14 @@ static void __init pmb_synchronize(void)
                        continue;
                }
 
-               spin_lock_irqsave(&pmbe->lock, irqflags);
+               raw_spin_lock_irqsave(&pmbe->lock, irqflags);
 
                for (j = 0; j < ARRAY_SIZE(pmb_sizes); j++)
                        if (pmb_sizes[j].flag == size)
                                pmbe->size = pmb_sizes[j].size;
 
                if (pmbp) {
-                       spin_lock(&pmbp->lock);
-
+                       raw_spin_lock_nested(&pmbp->lock, SINGLE_DEPTH_NESTING);
                        /*
                         * Compare the previous entry against the current one to
                         * see if the entries span a contiguous mapping. If so,
@@ -644,13 +644,12 @@ static void __init pmb_synchronize(void)
                         */
                        if (pmb_can_merge(pmbp, pmbe))
                                pmbp->link = pmbe;
-
-                       spin_unlock(&pmbp->lock);
+                       raw_spin_unlock(&pmbp->lock);
                }
 
                pmbp = pmbe;
 
-               spin_unlock_irqrestore(&pmbe->lock, irqflags);
+               raw_spin_unlock_irqrestore(&pmbe->lock, irqflags);
        }
 }
 
@@ -757,7 +756,7 @@ static void __init pmb_resize(void)
                /*
                 * Found it, now resize it.
                 */
-               spin_lock_irqsave(&pmbe->lock, flags);
+               raw_spin_lock_irqsave(&pmbe->lock, flags);
 
                pmbe->size = SZ_16M;
                pmbe->flags &= ~PMB_SZ_MASK;
@@ -767,7 +766,7 @@ static void __init pmb_resize(void)
 
                __set_pmb_entry(pmbe);
 
-               spin_unlock_irqrestore(&pmbe->lock, flags);
+               raw_spin_unlock_irqrestore(&pmbe->lock, flags);
        }
 
        read_unlock(&pmb_rwlock);
@@ -866,11 +865,9 @@ static int __init pmb_debugfs_init(void)
        struct dentry *dentry;
 
        dentry = debugfs_create_file("pmb", S_IFREG | S_IRUGO,
-                                    sh_debugfs_root, NULL, &pmb_debugfs_fops);
+                                    arch_debugfs_dir, NULL, &pmb_debugfs_fops);
        if (!dentry)
                return -ENOMEM;
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
 
        return 0;
 }
diff --git a/arch/sh/mm/sram.c b/arch/sh/mm/sram.c
new file mode 100644 (file)
index 0000000..bc156ec
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * SRAM pool for tiny memories not otherwise managed.
+ *
+ * Copyright (C) 2010  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/sram.h>
+
+/*
+ * This provides a standard SRAM pool for tiny memories that can be
+ * added either by the CPU or the platform code. Typical SRAM sizes
+ * to be inserted in to the pool will generally be less than the page
+ * size, with anything more reasonably sized handled as a NUMA memory
+ * node.
+ */
+struct gen_pool *sram_pool;
+
+static int __init sram_pool_init(void)
+{
+       /*
+        * This is a global pool, we don't care about node locality.
+        */
+       sram_pool = gen_pool_create(1, -1);
+       if (unlikely(!sram_pool))
+               return -ENOMEM;
+
+       return 0;
+}
+core_initcall(sram_pool_init);
index 229bf75..dea637a 100644 (file)
@@ -151,15 +151,13 @@ static int __init tlb_debugfs_init(void)
 {
        struct dentry *itlb, *utlb;
 
-       itlb = debugfs_create_file("itlb", S_IRUSR, sh_debugfs_root,
+       itlb = debugfs_create_file("itlb", S_IRUSR, arch_debugfs_dir,
                                   (unsigned int *)TLB_TYPE_ITLB,
                                   &tlb_debugfs_fops);
        if (unlikely(!itlb))
                return -ENOMEM;
-       if (IS_ERR(itlb))
-               return PTR_ERR(itlb);
 
-       utlb = debugfs_create_file("utlb", S_IRUSR, sh_debugfs_root,
+       utlb = debugfs_create_file("utlb", S_IRUSR, arch_debugfs_dir,
                                   (unsigned int *)TLB_TYPE_UTLB,
                                   &tlb_debugfs_fops);
        if (unlikely(!utlb)) {
@@ -167,11 +165,6 @@ static int __init tlb_debugfs_init(void)
                return -ENOMEM;
        }
 
-       if (IS_ERR(utlb)) {
-               debugfs_remove(itlb);
-               return PTR_ERR(utlb);
-       }
-
        return 0;
 }
 module_init(tlb_debugfs_init);
index 3fbe03c..a6a20d6 100644 (file)
@@ -119,3 +119,19 @@ void local_flush_tlb_mm(struct mm_struct *mm)
                local_irq_restore(flags);
        }
 }
+
+void __flush_tlb_global(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       /*
+        * This is the most destructive of the TLB flushing options,
+        * and will tear down all of the UTLB/ITLB mappings, including
+        * wired entries.
+        */
+       __raw_writel(__raw_readl(MMUCR) | MMUCR_TI, MMUCR);
+
+       local_irq_restore(flags);
+}
index 03db41c..7f5810f 100644 (file)
@@ -455,6 +455,11 @@ void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
         flush_tlb_all();
 }
 
+void __flush_tlb_global(void)
+{
+       flush_tlb_all();
+}
+
 void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
 }
index b25aa55..9f56eb9 100644 (file)
@@ -52,6 +52,8 @@ MIGOR                 SH_MIGOR
 RSK7201                        SH_RSK7201
 RSK7203                        SH_RSK7203
 AP325RXA               SH_AP325RXA
+SH2007                 SH_SH2007
+SH7757LCR              SH_SH7757LCR
 SH7763RDP              SH_SH7763RDP
 SH7785LCR              SH_SH7785LCR
 SH7785LCR_PT           SH_SH7785LCR_PT
index 3e9d314..8e7bafc 100644 (file)
@@ -19,6 +19,7 @@ config SPARC
        bool
        default y
        select OF
+       select OF_PROMTREE
        select HAVE_IDE
        select HAVE_OPROFILE
        select HAVE_ARCH_KGDB if !SMP || SPARC64
index deeb0fb..3c93f08 100644 (file)
@@ -7,7 +7,6 @@ header-y += display7seg.h
 header-y += envctrl.h
 header-y += fbio.h
 header-y += jsflash.h
-header-y += openprom.h
 header-y += openpromio.h
 header-y += perfctr.h
 header-y += psrcompat.h
index c792830..86666f7 100644 (file)
@@ -304,7 +304,8 @@ static struct linux_prom_registers fd_regs[2];
 static int sun_floppy_init(void)
 {
        char state[128];
-       int tnode, fd_node, num_regs;
+       phandle tnode, fd_node;
+       int num_regs;
        struct resource r;
 
        use_virtual_dma = 1;
index 963e1a4..81cd434 100644 (file)
@@ -11,6 +11,8 @@
 #define LINUX_OPPROM_MAGIC      0x10010407
 
 #ifndef __ASSEMBLY__
+#include <linux/of.h>
+
 /* V0 prom device operations. */
 struct linux_dev_v0_funcs {
        int (*v0_devopen)(char *device_str);
@@ -26,7 +28,7 @@ struct linux_dev_v0_funcs {
 
 /* V2 and later prom device operations. */
 struct linux_dev_v2_funcs {
-       int (*v2_inst2pkg)(int d);      /* Convert ihandle to phandle */
+       phandle (*v2_inst2pkg)(int d);  /* Convert ihandle to phandle */
        char * (*v2_dumb_mem_alloc)(char *va, unsigned sz);
        void (*v2_dumb_mem_free)(char *va, unsigned sz);
 
@@ -168,12 +170,12 @@ struct linux_romvec {
 
 /* Routines for traversing the prom device tree. */
 struct linux_nodeops {
-       int (*no_nextnode)(int node);
-       int (*no_child)(int node);
-       int (*no_proplen)(int node, const char *name);
-       int (*no_getprop)(int node, const char *name, char *val);
-       int (*no_setprop)(int node, const char *name, char *val, int len);
-       char * (*no_nextprop)(int node, char *name);
+       phandle (*no_nextnode)(phandle node);
+       phandle (*no_child)(phandle node);
+       int (*no_proplen)(phandle node, const char *name);
+       int (*no_getprop)(phandle node, const char *name, char *val);
+       int (*no_setprop)(phandle node, const char *name, char *val, int len);
+       char * (*no_nextprop)(phandle node, char *name);
 };
 
 /* More fun PROM structures for device probing. */
index 33e31ce..51296a6 100644 (file)
@@ -30,7 +30,7 @@ extern unsigned int prom_rev, prom_prev;
 /* Root node of the prom device tree, this stays constant after
  * initialization is complete.
  */
-extern int prom_root_node;
+extern phandle prom_root_node;
 
 /* Pointer to prom structure containing the device tree traversal
  * and usage utility functions.  Only prom-lib should use these,
@@ -178,68 +178,68 @@ extern void prom_putsegment(int context, unsigned long virt_addr,
 /* PROM device tree traversal functions... */
 
 /* Get the child node of the given node, or zero if no child exists. */
-extern int prom_getchild(int parent_node);
+extern phandle prom_getchild(phandle parent_node);
 
 /* Get the next sibling node of the given node, or zero if no further
  * siblings exist.
  */
-extern int prom_getsibling(int node);
+extern phandle prom_getsibling(phandle node);
 
 /* Get the length, at the passed node, of the given property type.
  * Returns -1 on error (ie. no such property at this node).
  */
-extern int prom_getproplen(int thisnode, const char *property);
+extern int prom_getproplen(phandle thisnode, const char *property);
 
 /* Fetch the requested property using the given buffer.  Returns
  * the number of bytes the prom put into your buffer or -1 on error.
  */
-extern int __must_check prom_getproperty(int thisnode, const char *property,
+extern int __must_check prom_getproperty(phandle thisnode, const char *property,
                                         char *prop_buffer, int propbuf_size);
 
 /* Acquire an integer property. */
-extern int prom_getint(int node, char *property);
+extern int prom_getint(phandle node, char *property);
 
 /* Acquire an integer property, with a default value. */
-extern int prom_getintdefault(int node, char *property, int defval);
+extern int prom_getintdefault(phandle node, char *property, int defval);
 
 /* Acquire a boolean property, 0=FALSE 1=TRUE. */
-extern int prom_getbool(int node, char *prop);
+extern int prom_getbool(phandle node, char *prop);
 
 /* Acquire a string property, null string on error. */
-extern void prom_getstring(int node, char *prop, char *buf, int bufsize);
+extern void prom_getstring(phandle node, char *prop, char *buf, int bufsize);
 
 /* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(int thisnode, char *name);
+extern int prom_nodematch(phandle thisnode, char *name);
 
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
-extern int prom_searchsiblings(int node_start, char *name);
+extern phandle prom_searchsiblings(phandle node_start, char *name);
 
 /* Return the first property type, as a string, for the given node.
  * Returns a null string on error.
  */
-extern char *prom_firstprop(int node, char *buffer);
+extern char *prom_firstprop(phandle node, char *buffer);
 
 /* Returns the next property after the passed property for the given
  * node.  Returns null string on failure.
  */
-extern char *prom_nextprop(int node, char *prev_property, char *buffer);
+extern char *prom_nextprop(phandle node, char *prev_property, char *buffer);
 
 /* Returns phandle of the path specified */
-extern int prom_finddevice(char *name);
+extern phandle prom_finddevice(char *name);
 
 /* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(int node, char *property);
+extern int prom_node_has_property(phandle node, char *property);
 
 /* Set the indicated property at the given node with the passed value.
  * Returns the number of bytes of your value that the prom took.
  */
-extern int prom_setprop(int node, const char *prop_name, char *prop_value,
+extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern int prom_pathtoinode(char *path);
-extern int prom_inst2pkg(int);
+extern phandle prom_pathtoinode(char *path);
+extern phandle prom_inst2pkg(int);
 
 /* Dorking with Bus ranges... */
 
@@ -247,13 +247,13 @@ extern int prom_inst2pkg(int);
 extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
 
 /* Apply ranges of any prom node (and optionally parent node as well) to registers. */
-extern void prom_apply_generic_ranges(int node, int parent,
+extern void prom_apply_generic_ranges(phandle node, phandle parent,
                                      struct linux_prom_registers *sbusregs, int nregs);
 
 /* CPU probing helpers.  */
-int cpu_find_by_instance(int instance, int *prom_node, int *mid);
-int cpu_find_by_mid(int mid, int *prom_node);
-int cpu_get_hwmid(int prom_node);
+int cpu_find_by_instance(int instance, phandle *prom_node, int *mid);
+int cpu_find_by_mid(int mid, phandle *prom_node);
+int cpu_get_hwmid(phandle prom_node);
 
 extern spinlock_t prom_lock;
 
index 3e0b2d6..c9cc078 100644 (file)
@@ -16,7 +16,7 @@ extern char prom_version[];
 /* Root node of the prom device tree, this stays constant after
  * initialization is complete.
  */
-extern int prom_root_node;
+extern phandle prom_root_node;
 
 /* PROM stdin and stdout */
 extern int prom_stdin, prom_stdout;
@@ -24,7 +24,7 @@ extern int prom_stdin, prom_stdout;
 /* /chosen node of the prom device tree, this stays constant after
  * initialization is complete.
  */
-extern int prom_chosen_node;
+extern phandle prom_chosen_node;
 
 /* Helper values and strings in arch/sparc64/kernel/head.S */
 extern const char prom_peer_name[];
@@ -218,68 +218,69 @@ extern void prom_unmap(unsigned long size, unsigned long vaddr);
 /* PROM device tree traversal functions... */
 
 /* Get the child node of the given node, or zero if no child exists. */
-extern int prom_getchild(int parent_node);
+extern phandle prom_getchild(phandle parent_node);
 
 /* Get the next sibling node of the given node, or zero if no further
  * siblings exist.
  */
-extern int prom_getsibling(int node);
+extern phandle prom_getsibling(phandle node);
 
 /* Get the length, at the passed node, of the given property type.
  * Returns -1 on error (ie. no such property at this node).
  */
-extern int prom_getproplen(int thisnode, const char *property);
+extern int prom_getproplen(phandle thisnode, const char *property);
 
 /* Fetch the requested property using the given buffer.  Returns
  * the number of bytes the prom put into your buffer or -1 on error.
  */
-extern int prom_getproperty(int thisnode, const char *property,
+extern int prom_getproperty(phandle thisnode, const char *property,
                            char *prop_buffer, int propbuf_size);
 
 /* Acquire an integer property. */
-extern int prom_getint(int node, const char *property);
+extern int prom_getint(phandle node, const char *property);
 
 /* Acquire an integer property, with a default value. */
-extern int prom_getintdefault(int node, const char *property, int defval);
+extern int prom_getintdefault(phandle node, const char *property, int defval);
 
 /* Acquire a boolean property, 0=FALSE 1=TRUE. */
-extern int prom_getbool(int node, const char *prop);
+extern int prom_getbool(phandle node, const char *prop);
 
 /* Acquire a string property, null string on error. */
-extern void prom_getstring(int node, const char *prop, char *buf, int bufsize);
+extern void prom_getstring(phandle node, const char *prop, char *buf,
+                          int bufsize);
 
 /* Does the passed node have the given "name"? YES=1 NO=0 */
-extern int prom_nodematch(int thisnode, const char *name);
+extern int prom_nodematch(phandle thisnode, const char *name);
 
 /* Search all siblings starting at the passed node for "name" matching
  * the given string.  Returns the node on success, zero on failure.
  */
-extern int prom_searchsiblings(int node_start, const char *name);
+extern phandle prom_searchsiblings(phandle node_start, const char *name);
 
 /* Return the first property type, as a string, for the given node.
  * Returns a null string on error. Buffer should be at least 32B long.
  */
-extern char *prom_firstprop(int node, char *buffer);
+extern char *prom_firstprop(phandle node, char *buffer);
 
 /* Returns the next property after the passed property for the given
  * node.  Returns null string on failure. Buffer should be at least 32B long.
  */
-extern char *prom_nextprop(int node, const char *prev_property, char *buffer);
+extern char *prom_nextprop(phandle node, const char *prev_property, char *buf);
 
 /* Returns 1 if the specified node has given property. */
-extern int prom_node_has_property(int node, const char *property);
+extern int prom_node_has_property(phandle node, const char *property);
 
 /* Returns phandle of the path specified */
-extern int prom_finddevice(const char *name);
+extern phandle prom_finddevice(const char *name);
 
 /* Set the indicated property at the given node with the passed value.
  * Returns the number of bytes of your value that the prom took.
  */
-extern int prom_setprop(int node, const char *prop_name, char *prop_value,
+extern int prom_setprop(phandle node, const char *prop_name, char *prop_value,
                        int value_size);
 
-extern int prom_pathtoinode(const char *path);
-extern int prom_inst2pkg(int);
+extern phandle prom_pathtoinode(const char *path);
+extern phandle prom_inst2pkg(int);
 extern int prom_service_exists(const char *service_name);
 extern void prom_sun4v_guest_soft_state(void);
 
index 291f125..56bbaad 100644 (file)
@@ -18,6 +18,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 #include <linux/types.h>
+#include <linux/of_pdt.h>
 #include <linux/proc_fs.h>
 #include <linux/mutex.h>
 #include <asm/atomic.h>
@@ -67,8 +68,8 @@ extern struct device_node *of_console_device;
 extern char *of_console_path;
 extern char *of_console_options;
 
-extern void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp);
-extern char *build_full_name(struct device_node *dp);
+extern void irq_trans_init(struct device_node *dp);
+extern char *build_path_component(struct device_node *dp);
 
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
index ee8d214..35f4883 100644 (file)
@@ -23,7 +23,7 @@ static DEFINE_SPINLOCK(auxio_lock);
 
 void __init auxio_probe(void)
 {
-       int node, auxio_nd;
+       phandle node, auxio_nd;
        struct linux_prom_registers auxregs[1];
        struct resource r;
 
@@ -113,7 +113,7 @@ volatile unsigned char * auxio_power_register = NULL;
 void __init auxio_power_probe(void)
 {
        struct linux_prom_registers regs;
-       int node;
+       phandle node;
        struct resource r;
 
        /* Attempt to find the sun4m power control node. */
index 8cc2d56..89aa4eb 100644 (file)
@@ -40,7 +40,7 @@ static unsigned char *dispDeviceBase __force_data;
 
 static unsigned char vga_font[cmapsz];
 
-static int __init btext_initialize(unsigned int node)
+static int __init btext_initialize(phandle node)
 {
        unsigned int width, height, depth, pitch;
        unsigned long address = 0;
@@ -309,7 +309,7 @@ static struct console btext_console = {
 
 int __init btext_find_display(void)
 {
-       unsigned int node;
+       phandle node;
        char type[32];
        int ret;
 
index 62dc7a0..d2eddd6 100644 (file)
@@ -31,9 +31,9 @@ static char *cpu_mid_prop(void)
        return "mid";
 }
 
-static int check_cpu_node(int nd, int *cur_inst,
-                         int (*compare)(int, int, void *), void *compare_arg,
-                         int *prom_node, int *mid)
+static int check_cpu_node(phandle nd, int *cur_inst,
+               int (*compare)(phandle, int, void *), void *compare_arg,
+               phandle *prom_node, int *mid)
 {
        if (!compare(nd, *cur_inst, compare_arg)) {
                if (prom_node)
@@ -51,8 +51,8 @@ static int check_cpu_node(int nd, int *cur_inst,
        return -ENODEV;
 }
 
-static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
-                        int *prom_node, int *mid)
+static int __cpu_find_by(int (*compare)(phandle, int, void *),
+               void *compare_arg, phandle *prom_node, int *mid)
 {
        struct device_node *dp;
        int cur_inst;
@@ -71,7 +71,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
        return -ENODEV;
 }
 
-static int cpu_instance_compare(int nd, int instance, void *_arg)
+static int cpu_instance_compare(phandle nd, int instance, void *_arg)
 {
        int desired_instance = (int) _arg;
 
@@ -80,13 +80,13 @@ static int cpu_instance_compare(int nd, int instance, void *_arg)
        return -ENODEV;
 }
 
-int cpu_find_by_instance(int instance, int *prom_node, int *mid)
+int cpu_find_by_instance(int instance, phandle *prom_node, int *mid)
 {
        return __cpu_find_by(cpu_instance_compare, (void *)instance,
                             prom_node, mid);
 }
 
-static int cpu_mid_compare(int nd, int instance, void *_arg)
+static int cpu_mid_compare(phandle nd, int instance, void *_arg)
 {
        int desired_mid = (int) _arg;
        int this_mid;
@@ -98,7 +98,7 @@ static int cpu_mid_compare(int nd, int instance, void *_arg)
        return -ENODEV;
 }
 
-int cpu_find_by_mid(int mid, int *prom_node)
+int cpu_find_by_mid(int mid, phandle *prom_node)
 {
        return __cpu_find_by(cpu_mid_compare, (void *)mid,
                             prom_node, NULL);
@@ -108,7 +108,7 @@ int cpu_find_by_mid(int mid, int *prom_node)
  * address (0-3).  This gives us the true hardware mid, which might have
  * some other bits set.  On 4d hardware and software mids are the same.
  */
-int cpu_get_hwmid(int prom_node)
+int cpu_get_hwmid(phandle prom_node)
 {
        return prom_getintdefault(prom_node, cpu_mid_prop(), -ENODEV);
 }
@@ -119,7 +119,8 @@ void __init device_scan(void)
 
 #ifndef CONFIG_SMP
        {
-               int err, cpu_node;
+               phandle cpu_node;
+               int err;
                err = cpu_find_by_instance(0, &cpu_node, NULL);
                if (err) {
                        /* Probably a sun4e, Sun is trying to trick us ;-) */
index 6a7b4db..2d51527 100644 (file)
@@ -282,5 +282,5 @@ void __init leon_init_IRQ(void)
 
 void __init leon_init(void)
 {
-       prom_build_more = &leon_node_init;
+       of_pdt_build_more = &leon_node_init;
 }
index d36a8d3..aeaa09a 100644 (file)
@@ -284,7 +284,7 @@ int __init pcic_probe(void)
        struct linux_prom_registers regs[PROMREG_MAX];
        struct linux_pbm_info* pbm;
        char namebuf[64];
-       int node;
+       phandle node;
        int err;
 
        if (pcic0_up) {
@@ -440,7 +440,7 @@ static int __devinit pdev_to_pnode(struct linux_pbm_info *pbm,
 {
        struct linux_prom_pci_registers regs[PROMREG_MAX];
        int err;
-       int node = prom_getchild(pbm->prom_node);
+       phandle node = prom_getchild(pbm->prom_node);
 
        while(node) {
                err = prom_getproperty(node, "reg", 
index eeb04a7..cf5fe1c 100644 (file)
@@ -4,12 +4,6 @@
 #include <linux/spinlock.h>
 #include <asm/prom.h>
 
-extern void * prom_early_alloc(unsigned long size);
-extern void irq_trans_init(struct device_node *dp);
-
-extern unsigned int prom_unique_id;
-
-extern char *build_path_component(struct device_node *dp);
 extern void of_console_init(void);
 
 extern unsigned int prom_early_allocated;
index 1f830da..ed25834 100644 (file)
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/of_pdt.h>
 #include <asm/prom.h>
 #include <asm/oplib.h>
 #include <asm/leon.h>
 
 #include "prom.h"
 
-void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp);
-
 struct device_node *of_console_device;
 EXPORT_SYMBOL(of_console_device);
 
@@ -119,192 +118,47 @@ int of_find_in_proplist(const char *list, const char *match, int len)
 }
 EXPORT_SYMBOL(of_find_in_proplist);
 
-unsigned int prom_unique_id;
-
-static struct property * __init build_one_prop(phandle node, char *prev,
-                                              char *special_name,
-                                              void *special_val,
-                                              int special_len)
+/*
+ * SPARC32 and SPARC64's prom_nextprop() do things differently
+ * here, despite sharing the same interface.  SPARC32 doesn't fill in 'buf',
+ * returning NULL on an error.  SPARC64 fills in 'buf', but sets it to an
+ * empty string upon error.
+ */
+static int __init handle_nextprop_quirks(char *buf, const char *name)
 {
-       static struct property *tmp = NULL;
-       struct property *p;
-       const char *name;
-
-       if (tmp) {
-               p = tmp;
-               memset(p, 0, sizeof(*p) + 32);
-               tmp = NULL;
-       } else {
-               p = prom_early_alloc(sizeof(struct property) + 32);
-               p->unique_id = prom_unique_id++;
-       }
-
-       p->name = (char *) (p + 1);
-       if (special_name) {
-               strcpy(p->name, special_name);
-               p->length = special_len;
-               p->value = prom_early_alloc(special_len);
-               memcpy(p->value, special_val, special_len);
-       } else {
-               if (prev == NULL) {
-                       name = prom_firstprop(node, p->name);
-               } else {
-                       name = prom_nextprop(node, prev, p->name);
-               }
+       if (!name || strlen(name) == 0)
+               return -1;
 
-               if (!name || strlen(name) == 0) {
-                       tmp = p;
-                       return NULL;
-               }
 #ifdef CONFIG_SPARC32
-               strcpy(p->name, name);
+       strcpy(buf, name);
 #endif
-               p->length = prom_getproplen(node, p->name);
-               if (p->length <= 0) {
-                       p->length = 0;
-               } else {
-                       int len;
-
-                       p->value = prom_early_alloc(p->length + 1);
-                       len = prom_getproperty(node, p->name, p->value,
-                                              p->length);
-                       if (len <= 0)
-                               p->length = 0;
-                       ((unsigned char *)p->value)[p->length] = '\0';
-               }
-       }
-       return p;
-}
-
-static struct property * __init build_prop_list(phandle node)
-{
-       struct property *head, *tail;
-
-       head = tail = build_one_prop(node, NULL,
-                                    ".node", &node, sizeof(node));
-
-       tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
-       tail = tail->next;
-       while(tail) {
-               tail->next = build_one_prop(node, tail->name,
-                                           NULL, NULL, 0);
-               tail = tail->next;
-       }
-
-       return head;
-}
-
-static char * __init get_one_property(phandle node, const char *name)
-{
-       char *buf = "<NULL>";
-       int len;
-
-       len = prom_getproplen(node, name);
-       if (len > 0) {
-               buf = prom_early_alloc(len);
-               len = prom_getproperty(node, name, buf, len);
-       }
-
-       return buf;
-}
-
-static struct device_node * __init prom_create_node(phandle node,
-                                                   struct device_node *parent)
-{
-       struct device_node *dp;
-
-       if (!node)
-               return NULL;
-
-       dp = prom_early_alloc(sizeof(*dp));
-       dp->unique_id = prom_unique_id++;
-       dp->parent = parent;
-
-       kref_init(&dp->kref);
-
-       dp->name = get_one_property(node, "name");
-       dp->type = get_one_property(node, "device_type");
-       dp->phandle = node;
-
-       dp->properties = build_prop_list(node);
-
-       irq_trans_init(dp);
-
-       return dp;
-}
-
-char * __init build_full_name(struct device_node *dp)
-{
-       int len, ourlen, plen;
-       char *n;
-
-       plen = strlen(dp->parent->full_name);
-       ourlen = strlen(dp->path_component_name);
-       len = ourlen + plen + 2;
-
-       n = prom_early_alloc(len);
-       strcpy(n, dp->parent->full_name);
-       if (!of_node_is_root(dp->parent)) {
-               strcpy(n + plen, "/");
-               plen++;
-       }
-       strcpy(n + plen, dp->path_component_name);
-
-       return n;
+       return 0;
 }
 
-static struct device_node * __init prom_build_tree(struct device_node *parent,
-                                                  phandle node,
-                                                  struct device_node ***nextp)
+static int __init prom_common_nextprop(phandle node, char *prev, char *buf)
 {
-       struct device_node *ret = NULL, *prev_sibling = NULL;
-       struct device_node *dp;
-
-       while (1) {
-               dp = prom_create_node(node, parent);
-               if (!dp)
-                       break;
-
-               if (prev_sibling)
-                       prev_sibling->sibling = dp;
-
-               if (!ret)
-                       ret = dp;
-               prev_sibling = dp;
-
-               *(*nextp) = dp;
-               *nextp = &dp->allnext;
-
-               dp->path_component_name = build_path_component(dp);
-               dp->full_name = build_full_name(dp);
-
-               dp->child = prom_build_tree(dp, prom_getchild(node), nextp);
-
-               if (prom_build_more)
-                       prom_build_more(dp, nextp);
-
-               node = prom_getsibling(node);
-       }
+       const char *name;
 
-       return ret;
+       buf[0] = '\0';
+       name = prom_nextprop(node, prev, buf);
+       return handle_nextprop_quirks(buf, name);
 }
 
 unsigned int prom_early_allocated __initdata;
 
+static struct of_pdt_ops prom_sparc_ops __initdata = {
+       .nextprop = prom_common_nextprop,
+       .getproplen = prom_getproplen,
+       .getproperty = prom_getproperty,
+       .getchild = prom_getchild,
+       .getsibling = prom_getsibling,
+};
+
 void __init prom_build_devicetree(void)
 {
-       struct device_node **nextp;
-
-       allnodes = prom_create_node(prom_root_node, NULL);
-       allnodes->path_component_name = "";
-       allnodes->full_name = "/";
-
-       nextp = &allnodes->allnext;
-       allnodes->child = prom_build_tree(allnodes,
-                                         prom_getchild(allnodes->phandle),
-                                         &nextp);
+       of_pdt_build_devicetree(prom_root_node, &prom_sparc_ops);
        of_console_init();
 
-       printk("PROM: Built device tree with %u bytes of memory.\n",
-              prom_early_allocated);
+       pr_info("PROM: Built device tree with %u bytes of memory.\n",
+                       prom_early_allocated);
 }
index 5f72de6..29bafe0 100644 (file)
@@ -315,7 +315,7 @@ void __init setup_arch(char **cmdline_p)
 
 #ifdef CONFIG_IP_PNP
        if (!ic_set_manually) {
-               int chosen = prom_finddevice ("/chosen");
+               phandle chosen = prom_finddevice("/chosen");
                u32 cl, sv, gw;
                
                cl = prom_getintdefault (chosen, "client-ip", 0);
index 060d0f3..a4446c0 100644 (file)
@@ -23,7 +23,7 @@ int this_is_starfire = 0;
 
 void check_if_starfire(void)
 {
-       int ssnode = prom_finddevice("/ssp-serial");
+       phandle ssnode = prom_finddevice("/ssp-serial");
        if (ssnode != 0 && ssnode != -1)
                this_is_starfire = 1;
 }
index f476a5f..9aba8bd 100644 (file)
@@ -100,7 +100,7 @@ static void swift_clockstop(void)
 
 void __init clock_stop_probe(void)
 {
-       unsigned int node, clk_nd;
+       phandle node, clk_nd;
        char name[20];
     
        prom_getstring(prom_root_node, "name", name, sizeof(name));
index 4c25727..2f6ae1d 100644 (file)
@@ -88,7 +88,7 @@ static void __init read_obp_memory(const char *property,
                                   struct linux_prom64_registers *regs,
                                   int *num_ents)
 {
-       int node = prom_finddevice("/memory");
+       phandle node = prom_finddevice("/memory");
        int prop_size = prom_getproplen(node, property);
        int ents, ret, i;
 
index b0b43aa..92319aa 100644 (file)
@@ -1262,7 +1262,8 @@ extern unsigned long bootmem_init(unsigned long *pages_avail);
 
 void __init srmmu_paging_init(void)
 {
-       int i, cpunode;
+       int i;
+       phandle cpunode;
        char node_str[128];
        pgd_t *pgd;
        pmd_t *pmd;
@@ -1398,7 +1399,8 @@ static void __init srmmu_is_bad(void)
 
 static void __init init_vac_layout(void)
 {
-       int nd, cache_lines;
+       phandle nd;
+       int cache_lines;
        char node_str[128];
 #ifdef CONFIG_SMP
        int cpu = 0;
@@ -2082,7 +2084,7 @@ static void __init get_srmmu_type(void)
 
        /* Next check for Fujitsu Swift. */
        if(psr_typ == 0 && psr_vers == 4) {
-               int cpunode;
+               phandle cpunode;
                char node_str[128];
 
                /* Look if it is not a TurboSparc emulating Swift... */
index 4289f90..ddd0d86 100644 (file)
@@ -420,7 +420,7 @@ volatile unsigned long __iomem *sun4c_memerr_reg = NULL;
 
 void __init sun4c_probe_memerr_reg(void)
 {
-       int node;
+       phandle node;
        struct linux_prom_registers regs[1];
 
        node = prom_getchild(prom_root_node);
index ccb36c7..d342dba 100644 (file)
@@ -20,7 +20,7 @@ enum prom_major_version prom_vers;
 unsigned int prom_rev, prom_prev;
 
 /* The root node of the prom device tree. */
-int prom_root_node;
+phandle prom_root_node;
 EXPORT_SYMBOL(prom_root_node);
 
 /* Pointer to the device tree operations structure. */
index 7b00f89..3ff911e 100644 (file)
@@ -19,7 +19,7 @@ char prom_version[80];
 
 /* The root node of the prom device tree. */
 int prom_stdin, prom_stdout;
-int prom_chosen_node;
+phandle prom_chosen_node;
 
 /* You must call prom_init() before you attempt to use any of the
  * routines in the prom library.  It returns 0 on success, 1 on
@@ -30,7 +30,7 @@ extern void prom_cif_init(void *, void *);
 
 void __init prom_init(void *cif_handler, void *cif_stack)
 {
-       int node;
+       phandle node;
 
        prom_cif_init(cif_handler, cif_stack);
 
index fac7899..3f263a6 100644 (file)
@@ -31,7 +31,8 @@ static int __init prom_meminit_v0(void)
 static int __init prom_meminit_v2(void)
 {
        struct linux_prom_registers reg[64];
-       int node, size, num_ents, i;
+       phandle node;
+       int size, num_ents, i;
 
        node = prom_searchsiblings(prom_getchild(prom_root_node), "memory");
        size = prom_getproperty(node, "available", (char *) reg, sizeof(reg));
index 6cb1581..d24bc44 100644 (file)
@@ -183,7 +183,8 @@ unsigned char prom_get_idprom(char *idbuf, int num_bytes)
 
 int prom_get_mmu_ihandle(void)
 {
-       int node, ret;
+       phandle node;
+       int ret;
 
        if (prom_mmu_ihandle_cache != 0)
                return prom_mmu_ihandle_cache;
@@ -201,7 +202,8 @@ int prom_get_mmu_ihandle(void)
 static int prom_get_memory_ihandle(void)
 {
        static int memory_ihandle_cache;
-       int node, ret;
+       phandle node;
+       int ret;
 
        if (memory_ihandle_cache != 0)
                return memory_ihandle_cache;
index aeff43e..541fc82 100644 (file)
@@ -68,7 +68,7 @@ EXPORT_SYMBOL(prom_apply_obio_ranges);
 
 void __init prom_ranges_init(void)
 {
-       int node, obio_node;
+       phandle node, obio_node;
        int success;
 
        num_obio_ranges = 0;
@@ -89,8 +89,8 @@ void __init prom_ranges_init(void)
                prom_printf("PROMLIB: obio_ranges %d\n", num_obio_ranges);
 }
 
-void
-prom_apply_generic_ranges (int node, int parent, struct linux_prom_registers *regs, int nregs)
+void prom_apply_generic_ranges(phandle node, phandle parent,
+               struct linux_prom_registers *regs, int nregs)
 {
        int success;
        int num_ranges;
index b21592f..63e08e1 100644 (file)
@@ -20,10 +20,10 @@ extern void restore_current(void);
 static char promlib_buf[128];
 
 /* Internal version of prom_getchild that does not alter return values. */
-int __prom_getchild(int node)
+phandle __prom_getchild(phandle node)
 {
        unsigned long flags;
-       int cnode;
+       phandle cnode;
 
        spin_lock_irqsave(&prom_lock, flags);
        cnode = prom_nodeops->no_child(node);
@@ -36,9 +36,9 @@ int __prom_getchild(int node)
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
  */
-int prom_getchild(int node)
+phandle prom_getchild(phandle node)
 {
-       int cnode;
+       phandle cnode;
 
        if (node == -1)
                return 0;
@@ -52,10 +52,10 @@ int prom_getchild(int node)
 EXPORT_SYMBOL(prom_getchild);
 
 /* Internal version of prom_getsibling that does not alter return values. */
-int __prom_getsibling(int node)
+phandle __prom_getsibling(phandle node)
 {
        unsigned long flags;
-       int cnode;
+       phandle cnode;
 
        spin_lock_irqsave(&prom_lock, flags);
        cnode = prom_nodeops->no_nextnode(node);
@@ -68,9 +68,9 @@ int __prom_getsibling(int node)
 /* Return the next sibling of node 'node' or zero if no more siblings
  * at this level of depth in the tree.
  */
-int prom_getsibling(int node)
+phandle prom_getsibling(phandle node)
 {
-       int sibnode;
+       phandle sibnode;
 
        if (node == -1)
                return 0;
@@ -86,7 +86,7 @@ EXPORT_SYMBOL(prom_getsibling);
 /* Return the length in bytes of property 'prop' at node 'node'.
  * Return -1 on error.
  */
-int prom_getproplen(int node, const char *prop)
+int prom_getproplen(phandle node, const char *prop)
 {
        int ret;
        unsigned long flags;
@@ -106,7 +106,7 @@ EXPORT_SYMBOL(prom_getproplen);
  * 'buffer' which has a size of 'bufsize'.  If the acquisition
  * was successful the length will be returned, else -1 is returned.
  */
-int prom_getproperty(int node, const char *prop, char *buffer, int bufsize)
+int prom_getproperty(phandle node, const char *prop, char *buffer, int bufsize)
 {
        int plen, ret;
        unsigned long flags;
@@ -126,7 +126,7 @@ EXPORT_SYMBOL(prom_getproperty);
 /* Acquire an integer property and return its value.  Returns -1
  * on failure.
  */
-int prom_getint(int node, char *prop)
+int prom_getint(phandle node, char *prop)
 {
        static int intprop;
 
@@ -140,7 +140,7 @@ EXPORT_SYMBOL(prom_getint);
 /* Acquire an integer property, upon error return the passed default
  * integer.
  */
-int prom_getintdefault(int node, char *property, int deflt)
+int prom_getintdefault(phandle node, char *property, int deflt)
 {
        int retval;
 
@@ -152,7 +152,7 @@ int prom_getintdefault(int node, char *property, int deflt)
 EXPORT_SYMBOL(prom_getintdefault);
 
 /* Acquire a boolean property, 1=TRUE 0=FALSE. */
-int prom_getbool(int node, char *prop)
+int prom_getbool(phandle node, char *prop)
 {
        int retval;
 
@@ -166,7 +166,7 @@ EXPORT_SYMBOL(prom_getbool);
  * string on error.  The char pointer is the user supplied string
  * buffer.
  */
-void prom_getstring(int node, char *prop, char *user_buf, int ubuf_size)
+void prom_getstring(phandle node, char *prop, char *user_buf, int ubuf_size)
 {
        int len;
 
@@ -180,7 +180,7 @@ EXPORT_SYMBOL(prom_getstring);
 /* Does the device at node 'node' have name 'name'?
  * YES = 1   NO = 0
  */
-int prom_nodematch(int node, char *name)
+int prom_nodematch(phandle node, char *name)
 {
        int error;
 
@@ -194,10 +194,11 @@ int prom_nodematch(int node, char *name)
 /* Search siblings at 'node_start' for a node with name
  * 'nodename'.  Return node if successful, zero if not.
  */
-int prom_searchsiblings(int node_start, char *nodename)
+phandle prom_searchsiblings(phandle node_start, char *nodename)
 {
 
-       int thisnode, error;
+       phandle thisnode;
+       int error;
 
        for(thisnode = node_start; thisnode;
            thisnode=prom_getsibling(thisnode)) {
@@ -213,7 +214,7 @@ int prom_searchsiblings(int node_start, char *nodename)
 EXPORT_SYMBOL(prom_searchsiblings);
 
 /* Interal version of nextprop that does not alter return values. */
-char * __prom_nextprop(int node, char * oprop)
+char *__prom_nextprop(phandle node, char * oprop)
 {
        unsigned long flags;
        char *prop;
@@ -228,7 +229,7 @@ char * __prom_nextprop(int node, char * oprop)
 
 /* Return the first property name for node 'node'. */
 /* buffer is unused argument, but as v9 uses it, we need to have the same interface */
-char * prom_firstprop(int node, char *bufer)
+char *prom_firstprop(phandle node, char *bufer)
 {
        if (node == 0 || node == -1)
                return "";
@@ -241,7 +242,7 @@ EXPORT_SYMBOL(prom_firstprop);
  * at node 'node' .  Returns empty string if no more
  * property types for this node.
  */
-char * prom_nextprop(int node, char *oprop, char *buffer)
+char *prom_nextprop(phandle node, char *oprop, char *buffer)
 {
        if (node == 0 || node == -1)
                return "";
@@ -250,11 +251,11 @@ char * prom_nextprop(int node, char *oprop, char *buffer)
 }
 EXPORT_SYMBOL(prom_nextprop);
 
-int prom_finddevice(char *name)
+phandle prom_finddevice(char *name)
 {
        char nbuf[128];
        char *s = name, *d;
-       int node = prom_root_node, node2;
+       phandle node = prom_root_node, node2;
        unsigned int which_io, phys_addr;
        struct linux_prom_registers reg[PROMREG_MAX];
 
@@ -298,7 +299,7 @@ int prom_finddevice(char *name)
 }
 EXPORT_SYMBOL(prom_finddevice);
 
-int prom_node_has_property(int node, char *prop)
+int prom_node_has_property(phandle node, char *prop)
 {
        char *current_property = "";
 
@@ -314,7 +315,7 @@ EXPORT_SYMBOL(prom_node_has_property);
 /* Set property 'pname' at node 'node' to value 'value' which has a length
  * of 'size' bytes.  Return the number of bytes the prom accepted.
  */
-int prom_setprop(int node, const char *pname, char *value, int size)
+int prom_setprop(phandle node, const char *pname, char *value, int size)
 {
        unsigned long flags;
        int ret;
@@ -329,9 +330,9 @@ int prom_setprop(int node, const char *pname, char *value, int size)
 }
 EXPORT_SYMBOL(prom_setprop);
 
-int prom_inst2pkg(int inst)
+phandle prom_inst2pkg(int inst)
 {
-       int node;
+       phandle node;
        unsigned long flags;
        
        spin_lock_irqsave(&prom_lock, flags);
@@ -345,9 +346,10 @@ int prom_inst2pkg(int inst)
 /* Return 'node' assigned to a particular prom 'path'
  * FIXME: Should work for v0 as well
  */
-int prom_pathtoinode(char *path)
+phandle prom_pathtoinode(char *path)
 {
-       int node, inst;
+       phandle node;
+       int inst;
        
        inst = prom_devopen (path);
        if (inst == -1) return 0;
index 9d3f913..691be68 100644 (file)
@@ -16,7 +16,7 @@
 #include <asm/oplib.h>
 #include <asm/ldc.h>
 
-static int prom_node_to_node(const char *type, int node)
+static phandle prom_node_to_node(const char *type, phandle node)
 {
        unsigned long args[5];
 
@@ -28,20 +28,20 @@ static int prom_node_to_node(const char *type, int node)
 
        p1275_cmd_direct(args);
 
-       return (int) args[4];
+       return (phandle) args[4];
 }
 
 /* Return the child of node 'node' or zero if no this node has no
  * direct descendent.
  */
-inline int __prom_getchild(int node)
+inline phandle __prom_getchild(phandle node)
 {
        return prom_node_to_node("child", node);
 }
 
-inline int prom_getchild(int node)
+inline phandle prom_getchild(phandle node)
 {
-       int cnode;
+       phandle cnode;
 
        if (node == -1)
                return 0;
@@ -52,9 +52,9 @@ inline int prom_getchild(int node)
 }
 EXPORT_SYMBOL(prom_getchild);
 
-inline int prom_getparent(int node)
+inline phandle prom_getparent(phandle node)
 {
-       int cnode;
+       phandle cnode;
 
        if (node == -1)
                return 0;
@@ -67,14 +67,14 @@ inline int prom_getparent(int node)
 /* Return the next sibling of node 'node' or zero if no more siblings
  * at this level of depth in the tree.
  */
-inline int __prom_getsibling(int node)
+inline phandle __prom_getsibling(phandle node)
 {
        return prom_node_to_node(prom_peer_name, node);
 }
 
-inline int prom_getsibling(int node)
+inline phandle prom_getsibling(phandle node)
 {
-       int sibnode;
+       phandle sibnode;
 
        if (node == -1)
                return 0;
@@ -89,7 +89,7 @@ EXPORT_SYMBOL(prom_getsibling);
 /* Return the length in bytes of property 'prop' at node 'node'.
  * Return -1 on error.
  */
-inline int prom_getproplen(int node, const char *prop)
+inline int prom_getproplen(phandle node, const char *prop)
 {
        unsigned long args[6];
 
@@ -113,7 +113,7 @@ EXPORT_SYMBOL(prom_getproplen);
  * 'buffer' which has a size of 'bufsize'.  If the acquisition
  * was successful the length will be returned, else -1 is returned.
  */
-inline int prom_getproperty(int node, const char *prop,
+inline int prom_getproperty(phandle node, const char *prop,
                            char *buffer, int bufsize)
 {
        unsigned long args[8];
@@ -141,7 +141,7 @@ EXPORT_SYMBOL(prom_getproperty);
 /* Acquire an integer property and return its value.  Returns -1
  * on failure.
  */
-inline int prom_getint(int node, const char *prop)
+inline int prom_getint(phandle node, const char *prop)
 {
        int intprop;
 
@@ -156,7 +156,7 @@ EXPORT_SYMBOL(prom_getint);
  * integer.
  */
 
-int prom_getintdefault(int node, const char *property, int deflt)
+int prom_getintdefault(phandle node, const char *property, int deflt)
 {
        int retval;
 
@@ -169,7 +169,7 @@ int prom_getintdefault(int node, const char *property, int deflt)
 EXPORT_SYMBOL(prom_getintdefault);
 
 /* Acquire a boolean property, 1=TRUE 0=FALSE. */
-int prom_getbool(int node, const char *prop)
+int prom_getbool(phandle node, const char *prop)
 {
        int retval;
 
@@ -184,7 +184,8 @@ EXPORT_SYMBOL(prom_getbool);
  * string on error.  The char pointer is the user supplied string
  * buffer.
  */
-void prom_getstring(int node, const char *prop, char *user_buf, int ubuf_size)
+void prom_getstring(phandle node, const char *prop, char *user_buf,
+               int ubuf_size)
 {
        int len;
 
@@ -198,7 +199,7 @@ EXPORT_SYMBOL(prom_getstring);
 /* Does the device at node 'node' have name 'name'?
  * YES = 1   NO = 0
  */
-int prom_nodematch(int node, const char *name)
+int prom_nodematch(phandle node, const char *name)
 {
        char namebuf[128];
        prom_getproperty(node, "name", namebuf, sizeof(namebuf));
@@ -210,10 +211,10 @@ int prom_nodematch(int node, const char *name)
 /* Search siblings at 'node_start' for a node with name
  * 'nodename'.  Return node if successful, zero if not.
  */
-int prom_searchsiblings(int node_start, const char *nodename)
+phandle prom_searchsiblings(phandle node_start, const char *nodename)
 {
-
-       int thisnode, error;
+       phandle thisnode;
+       int error;
        char promlib_buf[128];
 
        for(thisnode = node_start; thisnode;
@@ -234,7 +235,7 @@ static const char *prom_nextprop_name = "nextprop";
 /* Return the first property type for node 'node'.
  * buffer should be at least 32B in length
  */
-inline char *prom_firstprop(int node, char *buffer)
+inline char *prom_firstprop(phandle node, char *buffer)
 {
        unsigned long args[7];
 
@@ -260,7 +261,7 @@ EXPORT_SYMBOL(prom_firstprop);
  * at node 'node' .  Returns NULL string if no more
  * property types for this node.
  */
-inline char *prom_nextprop(int node, const char *oprop, char *buffer)
+inline char *prom_nextprop(phandle node, const char *oprop, char *buffer)
 {
        unsigned long args[7];
        char buf[32];
@@ -288,8 +289,7 @@ inline char *prom_nextprop(int node, const char *oprop, char *buffer)
 }
 EXPORT_SYMBOL(prom_nextprop);
 
-int
-prom_finddevice(const char *name)
+phandle prom_finddevice(const char *name)
 {
        unsigned long args[5];
 
@@ -307,7 +307,7 @@ prom_finddevice(const char *name)
 }
 EXPORT_SYMBOL(prom_finddevice);
 
-int prom_node_has_property(int node, const char *prop)
+int prom_node_has_property(phandle node, const char *prop)
 {
        char buf [32];
         
@@ -325,7 +325,7 @@ EXPORT_SYMBOL(prom_node_has_property);
  * of 'size' bytes.  Return the number of bytes the prom accepted.
  */
 int
-prom_setprop(int node, const char *pname, char *value, int size)
+prom_setprop(phandle node, const char *pname, char *value, int size)
 {
        unsigned long args[8];
 
@@ -355,10 +355,10 @@ prom_setprop(int node, const char *pname, char *value, int size)
 }
 EXPORT_SYMBOL(prom_setprop);
 
-inline int prom_inst2pkg(int inst)
+inline phandle prom_inst2pkg(int inst)
 {
        unsigned long args[5];
-       int node;
+       phandle node;
        
        args[0] = (unsigned long) "instance-to-package";
        args[1] = 1;
@@ -377,10 +377,10 @@ inline int prom_inst2pkg(int inst)
 /* Return 'node' assigned to a particular prom 'path'
  * FIXME: Should work for v0 as well
  */
-int
-prom_pathtoinode(const char *path)
+phandle prom_pathtoinode(const char *path)
 {
-       int node, inst;
+       phandle node;
+       int inst;
 
        inst = prom_devopen (path);
        if (inst == 0)
index 101229b..42a978c 100644 (file)
@@ -89,6 +89,8 @@ extern int olpc_ec_mask_unset(uint8_t bits);
 /* EC commands */
 
 #define EC_FIRMWARE_REV                0x08
+#define EC_WLAN_ENTER_RESET    0x35
+#define EC_WLAN_LEAVE_RESET    0x25
 
 /* SCI source values */
 
index 881fe44..f0834e2 100644 (file)
@@ -64,15 +64,13 @@ static void drive_stat_acct(struct request *rq, int new_io)
                return;
 
        cpu = part_stat_lock();
+       part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
 
-       if (!new_io) {
-               part = rq->part;
+       if (!new_io)
                part_stat_inc(cpu, part, merges[rw]);
-       } else {
-               part = disk_map_sector_rcu(rq->rq_disk, blk_rq_pos(rq));
+       else {
                part_round_stats(cpu, part);
                part_inc_in_flight(part, rw);
-               rq->part = part;
        }
 
        part_stat_unlock();
@@ -130,7 +128,6 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
        rq->ref_count = 1;
        rq->start_time = jiffies;
        set_start_time_ns(rq);
-       rq->part = NULL;
 }
 EXPORT_SYMBOL(blk_rq_init);
 
@@ -805,16 +802,11 @@ static struct request *get_request(struct request_queue *q, int rw_flags,
        rl->starved[is_sync] = 0;
 
        priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-       if (priv) {
+       if (priv)
                rl->elvpriv++;
 
-               /*
-                * Don't do stats for non-priv requests
-                */
-               if (blk_queue_io_stat(q))
-                       rw_flags |= REQ_IO_STAT;
-       }
-
+       if (blk_queue_io_stat(q))
+               rw_flags |= REQ_IO_STAT;
        spin_unlock_irq(q->queue_lock);
 
        rq = blk_alloc_request(q, rw_flags, priv, gfp_mask);
@@ -1791,7 +1783,7 @@ static void blk_account_io_completion(struct request *req, unsigned int bytes)
                int cpu;
 
                cpu = part_stat_lock();
-               part = req->part;
+               part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
                part_stat_add(cpu, part, sectors[rw], bytes >> 9);
                part_stat_unlock();
        }
@@ -1811,7 +1803,7 @@ static void blk_account_io_done(struct request *req)
                int cpu;
 
                cpu = part_stat_lock();
-               part = req->part;
+               part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 
                part_stat_inc(cpu, part, ios[rw]);
                part_stat_add(cpu, part, ticks[rw], duration);
index 0a2fd8a..77b7c26 100644 (file)
@@ -351,7 +351,7 @@ static void blk_account_io_merge(struct request *req)
                int cpu;
 
                cpu = part_stat_lock();
-               part = req->part;
+               part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
 
                part_round_stats(cpu, part);
                part_dec_in_flight(part, rq_data_dir(req));
index 1e675e5..2db8f32 100644 (file)
@@ -116,6 +116,10 @@ void blk_queue_congestion_threshold(struct request_queue *q);
 
 int blk_dev_init(void);
 
+void elv_quiesce_start(struct request_queue *q);
+void elv_quiesce_end(struct request_queue *q);
+
+
 /*
  * Return the threshold (number of used requests) at which the queue is
  * considered to be congested.  It include a little hysteresis to keep the
index a8adf96..5fa2b44 100644 (file)
@@ -929,15 +929,8 @@ static void disk_free_ptbl_rcu_cb(struct rcu_head *head)
 {
        struct disk_part_tbl *ptbl =
                container_of(head, struct disk_part_tbl, rcu_head);
-       struct gendisk *disk = ptbl->disk;
-       struct request_queue *q = disk->queue;
-       unsigned long flags;
 
        kfree(ptbl);
-
-       spin_lock_irqsave(q->queue_lock, flags);
-       elv_quiesce_end(q);
-       spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 /**
@@ -955,17 +948,11 @@ static void disk_replace_part_tbl(struct gendisk *disk,
                                  struct disk_part_tbl *new_ptbl)
 {
        struct disk_part_tbl *old_ptbl = disk->part_tbl;
-       struct request_queue *q = disk->queue;
 
        rcu_assign_pointer(disk->part_tbl, new_ptbl);
 
        if (old_ptbl) {
                rcu_assign_pointer(old_ptbl->last_lookup, NULL);
-
-               spin_lock_irq(q->queue_lock);
-               elv_quiesce_start(q);
-               spin_unlock_irq(q->queue_lock);
-
                call_rcu(&old_ptbl->rcu_head, disk_free_ptbl_rcu_cb);
        }
 }
@@ -1006,7 +993,6 @@ int disk_expand_part_tbl(struct gendisk *disk, int partno)
                return -ENOMEM;
 
        new_ptbl->len = target;
-       new_ptbl->disk = disk;
 
        for (i = 0; i < len; i++)
                rcu_assign_pointer(new_ptbl->part[i], old_ptbl->part[i]);
index a2aea53..14cf907 100644 (file)
@@ -51,7 +51,6 @@ obj-y                         += net/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_FUSION)           += message/
 obj-y                          += firewire/
-obj-y                          += ieee1394/
 obj-$(CONFIG_UIO)              += uio/
 obj-y                          += cdrom/
 obj-y                          += auxdisplay/
@@ -92,6 +91,7 @@ obj-$(CONFIG_EISA)            += eisa/
 obj-y                          += lguest/
 obj-$(CONFIG_CPU_FREQ)         += cpufreq/
 obj-$(CONFIG_CPU_IDLE)         += cpuidle/
+obj-$(CONFIG_DMA_ENGINE)       += dma/
 obj-$(CONFIG_MMC)              += mmc/
 obj-$(CONFIG_MEMSTICK)         += memstick/
 obj-$(CONFIG_NEW_LEDS)         += leds/
@@ -104,7 +104,6 @@ obj-$(CONFIG_ARCH_SHMOBILE) += sh/
 ifndef CONFIG_ARCH_USES_GETTIMEOFFSET
 obj-y                          += clocksource/
 endif
-obj-$(CONFIG_DMA_ENGINE)       += dma/
 obj-$(CONFIG_DCA)              += dca/
 obj-$(CONFIG_HID)              += hid/
 obj-$(CONFIG_PPC_PS3)          += ps3/
index 3966e62..f051cff 100644 (file)
@@ -147,6 +147,7 @@ static void platform_device_release(struct device *dev)
        struct platform_object *pa = container_of(dev, struct platform_object,
                                                  pdev.dev);
 
+       of_device_node_put(&pa->pdev.dev);
        kfree(pa->pdev.dev.platform_data);
        kfree(pa->pdev.resource);
        kfree(pa);
index 6e968cd..829161e 100644 (file)
@@ -1225,7 +1225,8 @@ ace_of_probe(struct platform_device *op, const struct of_device_id *match)
                bus_width = ACE_BUS_WIDTH_8;
 
        /* Call the bus-independant setup code */
-       return ace_alloc(&op->dev, id ? *id : 0, physaddr, irq, bus_width);
+       return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0,
+                                               physaddr, irq, bus_width);
 }
 
 static int __devexit ace_of_remove(struct platform_device *op)
index a7ca752..e95d787 100644 (file)
@@ -175,8 +175,7 @@ EXPORT_SYMBOL_GPL(unregister_keyboard_notifier);
  */
 
 struct getset_keycode_data {
-       unsigned int scancode;
-       unsigned int keycode;
+       struct input_keymap_entry ke;
        int error;
 };
 
@@ -184,32 +183,50 @@ static int getkeycode_helper(struct input_handle *handle, void *data)
 {
        struct getset_keycode_data *d = data;
 
-       d->error = input_get_keycode(handle->dev, d->scancode, &d->keycode);
+       d->error = input_get_keycode(handle->dev, &d->ke);
 
        return d->error == 0; /* stop as soon as we successfully get one */
 }
 
 int getkeycode(unsigned int scancode)
 {
-       struct getset_keycode_data d = { scancode, 0, -ENODEV };
+       struct getset_keycode_data d = {
+               .ke     = {
+                       .flags          = 0,
+                       .len            = sizeof(scancode),
+                       .keycode        = 0,
+               },
+               .error  = -ENODEV,
+       };
+
+       memcpy(d.ke.scancode, &scancode, sizeof(scancode));
 
        input_handler_for_each_handle(&kbd_handler, &d, getkeycode_helper);
 
-       return d.error ?: d.keycode;
+       return d.error ?: d.ke.keycode;
 }
 
 static int setkeycode_helper(struct input_handle *handle, void *data)
 {
        struct getset_keycode_data *d = data;
 
-       d->error = input_set_keycode(handle->dev, d->scancode, d->keycode);
+       d->error = input_set_keycode(handle->dev, &d->ke);
 
        return d->error == 0; /* stop as soon as we successfully set one */
 }
 
 int setkeycode(unsigned int scancode, unsigned int keycode)
 {
-       struct getset_keycode_data d = { scancode, keycode, -ENODEV };
+       struct getset_keycode_data d = {
+               .ke     = {
+                       .flags          = 0,
+                       .len            = sizeof(scancode),
+                       .keycode        = keycode,
+               },
+               .error  = -ENODEV,
+       };
+
+       memcpy(d.ke.scancode, &scancode, sizeof(scancode));
 
        input_handler_for_each_handle(&kbd_handler, &d, setkeycode_helper);
 
index f3019f5..eaa5d3e 100644 (file)
@@ -566,10 +566,16 @@ static const unsigned char sysrq_xlate[KEY_MAX + 1] =
 static bool sysrq_down;
 static int sysrq_alt_use;
 static int sysrq_alt;
+static DEFINE_SPINLOCK(sysrq_event_lock);
 
 static bool sysrq_filter(struct input_handle *handle, unsigned int type,
                         unsigned int code, int value)
 {
+       bool suppress;
+
+       /* We are called with interrupts disabled, just take the lock */
+       spin_lock(&sysrq_event_lock);
+
        if (type != EV_KEY)
                goto out;
 
@@ -601,7 +607,10 @@ static bool sysrq_filter(struct input_handle *handle, unsigned int type,
        }
 
 out:
-       return sysrq_down;
+       suppress = sysrq_down;
+       spin_unlock(&sysrq_event_lock);
+
+       return suppress;
 }
 
 static int sysrq_connect(struct input_handler *handler,
@@ -652,8 +661,8 @@ static void sysrq_disconnect(struct input_handle *handle)
 }
 
 /*
- * We are matching on KEY_LEFTALT insteard of KEY_SYSRQ because not all
- * keyboards have SysRq ikey predefined and so user may add it to keymap
+ * We are matching on KEY_LEFTALT instead of KEY_SYSRQ because not all
+ * keyboards have SysRq key predefined and so user may add it to keymap
  * later, but we expect all such keyboards to have left alt.
  */
 static const struct input_device_id sysrq_ids[] = {
index 717305d..a446116 100644 (file)
@@ -308,7 +308,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
         * isr before we end up here.
         */
        if (p->flags & FLAG_CLOCKSOURCE)
-               p->total_cycles += p->match_value;
+               p->total_cycles += p->match_value + 1;
 
        if (!(p->flags & FLAG_REPROGRAM))
                p->next_match_value = p->max_match_value;
@@ -403,7 +403,7 @@ static cycle_t sh_cmt_clocksource_read(struct clocksource *cs)
        raw = sh_cmt_get_counter(p, &has_wrapped);
 
        if (unlikely(has_wrapped))
-               raw += p->match_value;
+               raw += p->match_value + 1;
        spin_unlock_irqrestore(&p->lock, flags);
 
        return value + raw;
@@ -445,7 +445,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p,
 
        /* clk_get_rate() needs an enabled clock */
        clk_enable(p->clk);
-       p->rate = clk_get_rate(p->clk) / (p->width == 16) ? 512 : 8;
+       p->rate = clk_get_rate(p->clk) / ((p->width == 16) ? 512 : 8);
        clk_disable(p->clk);
 
        /* TODO: calculate good shift from rate and counter bit width */
@@ -478,7 +478,7 @@ static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic)
        ced->min_delta_ns = clockevent_delta2ns(0x1f, ced);
 
        if (periodic)
-               sh_cmt_set_next(p, (p->rate + HZ/2) / HZ);
+               sh_cmt_set_next(p, ((p->rate + HZ/2) / HZ) - 1);
        else
                sh_cmt_set_next(p, p->max_match_value);
 }
@@ -523,9 +523,9 @@ static int sh_cmt_clock_event_next(unsigned long delta,
 
        BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT);
        if (likely(p->flags & FLAG_IRQCONTEXT))
-               p->next_match_value = delta;
+               p->next_match_value = delta - 1;
        else
-               sh_cmt_set_next(p, delta);
+               sh_cmt_set_next(p, delta - 1);
 
        return 0;
 }
index fcf3ea2..40a222e 100644 (file)
@@ -3,9 +3,6 @@ menu "IEEE 1394 (FireWire) support"
        # firewire-core does not depend on PCI but is
        # not useful without PCI controller driver
 
-comment "You can enable one or both FireWire driver stacks."
-comment "The newer stack is recommended."
-
 config FIREWIRE
        tristate "FireWire driver stack"
        select CRC_ITU_T
@@ -64,8 +61,6 @@ config FIREWIRE_NET
          To compile this driver as a module, say M here:  The module will be
          called firewire-net.
 
-source "drivers/ieee1394/Kconfig"
-
 config FIREWIRE_NOSY
        tristate "Nosy - a FireWire traffic sniffer for PCILynx cards"
        depends on PCI
index 3c6a7fb..e3870d5 100644 (file)
@@ -13,3 +13,4 @@ obj-$(CONFIG_FIREWIRE_OHCI) += firewire-ohci.o
 obj-$(CONFIG_FIREWIRE_SBP2) += firewire-sbp2.o
 obj-$(CONFIG_FIREWIRE_NET)  += firewire-net.o
 obj-$(CONFIG_FIREWIRE_NOSY) += nosy.o
+obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
diff --git a/drivers/firewire/init_ohci1394_dma.c b/drivers/firewire/init_ohci1394_dma.c
new file mode 100644 (file)
index 0000000..a9a347a
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * init_ohci1394_dma.c - Initializes physical DMA on all OHCI 1394 controllers
+ *
+ * Copyright (C) 2006-2007      Bernhard Kaindl <bk@suse.de>
+ *
+ * Derived from drivers/ieee1394/ohci1394.c and arch/x86/kernel/early-quirks.c
+ * this file has functions to:
+ * - scan the PCI very early on boot for all OHCI 1394-compliant controllers
+ * - reset and initialize them and make them join the IEEE1394 bus and
+ * - enable physical DMA on them to allow remote debugging
+ *
+ * All code and data is marked as __init and __initdata, respective as
+ * during boot, all OHCI1394 controllers may be claimed by the firewire
+ * stack and at this point, this code should not touch them anymore.
+ *
+ * To use physical DMA after the initialization of the firewire stack,
+ * be sure that the stack enables it and (re-)attach after the bus reset
+ * which may be caused by the firewire stack initialization.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>         /* for PCI defines */
+#include <linux/string.h>
+
+#include <asm/pci-direct.h>    /* for direct PCI config space access */
+#include <asm/fixmap.h>
+
+#include <linux/init_ohci1394_dma.h>
+#include "ohci.h"
+
+int __initdata init_ohci1394_dma_early;
+
+struct ohci {
+       void __iomem *registers;
+};
+
+static inline void reg_write(const struct ohci *ohci, int offset, u32 data)
+{
+       writel(data, ohci->registers + offset);
+}
+
+static inline u32 reg_read(const struct ohci *ohci, int offset)
+{
+       return readl(ohci->registers + offset);
+}
+
+#define OHCI_LOOP_COUNT                100     /* Number of loops for reg read waits */
+
+/* Reads a PHY register of an OHCI-1394 controller */
+static inline u8 __init get_phy_reg(struct ohci *ohci, u8 addr)
+{
+       int i;
+       u32 r;
+
+       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
+
+       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
+               if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
+                       break;
+               mdelay(1);
+       }
+       r = reg_read(ohci, OHCI1394_PhyControl);
+
+       return (r & 0x00ff0000) >> 16;
+}
+
+/* Writes to a PHY register of an OHCI-1394 controller */
+static inline void __init set_phy_reg(struct ohci *ohci, u8 addr, u8 data)
+{
+       int i;
+
+       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
+
+       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
+               if (!(reg_read(ohci, OHCI1394_PhyControl) & 0x00004000))
+                       break;
+               mdelay(1);
+       }
+}
+
+/* Resets an OHCI-1394 controller (for sane state before initialization) */
+static inline void __init init_ohci1394_soft_reset(struct ohci *ohci)
+{
+       int i;
+
+       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
+
+       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
+               if (!(reg_read(ohci, OHCI1394_HCControlSet)
+                                  & OHCI1394_HCControl_softReset))
+                       break;
+               mdelay(1);
+       }
+}
+
+#define OHCI1394_MAX_AT_REQ_RETRIES    0xf
+#define OHCI1394_MAX_AT_RESP_RETRIES   0x2
+#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
+
+/* Basic OHCI-1394 register and port inititalization */
+static inline void __init init_ohci1394_initialize(struct ohci *ohci)
+{
+       u32 bus_options;
+       int num_ports, i;
+
+       /* Put some defaults to these undefined bus options */
+       bus_options = reg_read(ohci, OHCI1394_BusOptions);
+       bus_options |=  0x60000000; /* Enable CMC and ISC */
+       bus_options &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
+       bus_options &= ~0x18000000; /* Disable PMC and BMC */
+       reg_write(ohci, OHCI1394_BusOptions, bus_options);
+
+       /* Set the bus number */
+       reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
+
+       /* Enable posted writes */
+       reg_write(ohci, OHCI1394_HCControlSet,
+                       OHCI1394_HCControl_postedWriteEnable);
+
+       /* Clear link control register */
+       reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
+
+       /* enable phys */
+       reg_write(ohci, OHCI1394_LinkControlSet,
+                       OHCI1394_LinkControl_rcvPhyPkt);
+
+       /* Don't accept phy packets into AR request context */
+       reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
+
+       /* Clear the Isochonouys interrupt masks */
+       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
+
+       /* Accept asyncronous transfer requests from all nodes for now */
+       reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
+
+       /* Specify asyncronous transfer retries */
+       reg_write(ohci, OHCI1394_ATRetries,
+                 OHCI1394_MAX_AT_REQ_RETRIES |
+                 (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
+                 (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
+
+       /* We don't want hardware swapping */
+       reg_write(ohci, OHCI1394_HCControlClear,
+                 OHCI1394_HCControl_noByteSwapData);
+
+       /* Enable link */
+       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
+
+       /* If anything is connected to a port, make sure it is enabled */
+       num_ports = get_phy_reg(ohci, 2) & 0xf;
+       for (i = 0; i < num_ports; i++) {
+               unsigned int status;
+
+               set_phy_reg(ohci, 7, i);
+               status = get_phy_reg(ohci, 8);
+
+               if (status & 0x20)
+                       set_phy_reg(ohci, 8, status & ~1);
+       }
+}
+
+/**
+ * init_ohci1394_wait_for_busresets - wait until bus resets are completed
+ *
+ * OHCI1394 initialization itself and any device going on- or offline
+ * and any cable issue cause a IEEE1394 bus reset. The OHCI1394 spec
+ * specifies that physical DMA is disabled on each bus reset and it
+ * has to be enabled after each bus reset when needed. We resort
+ * to polling here because on early boot, we have no interrupts.
+ */
+static inline void __init init_ohci1394_wait_for_busresets(struct ohci *ohci)
+{
+       int i, events;
+
+       for (i = 0; i < 9; i++) {
+               mdelay(200);
+               events = reg_read(ohci, OHCI1394_IntEventSet);
+               if (events & OHCI1394_busReset)
+                       reg_write(ohci, OHCI1394_IntEventClear,
+                                       OHCI1394_busReset);
+       }
+}
+
+/**
+ * init_ohci1394_enable_physical_dma - Enable physical DMA for remote debugging
+ * This enables remote DMA access over IEEE1394 from every host for the low
+ * 4GB of address space. DMA accesses above 4GB are not available currently.
+ */
+static inline void __init init_ohci1394_enable_physical_dma(struct ohci *ohci)
+{
+       reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
+       reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
+       reg_write(ohci, OHCI1394_PhyUpperBound, 0xffff0000);
+}
+
+/**
+ * init_ohci1394_reset_and_init_dma - init controller and enable DMA
+ * This initializes the given controller and enables physical DMA engine in it.
+ */
+static inline void __init init_ohci1394_reset_and_init_dma(struct ohci *ohci)
+{
+       /* Start off with a soft reset, clears everything to a sane state. */
+       init_ohci1394_soft_reset(ohci);
+
+       /* Accessing some registers without LPS enabled may cause lock up */
+       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
+
+       /* Disable and clear interrupts */
+       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
+       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
+
+       mdelay(50); /* Wait 50msec to make sure we have full link enabled */
+
+       init_ohci1394_initialize(ohci);
+       /*
+        * The initialization causes at least one IEEE1394 bus reset. Enabling
+        * physical DMA only works *after* *all* bus resets have calmed down:
+        */
+       init_ohci1394_wait_for_busresets(ohci);
+
+       /* We had to wait and do this now if we want to debug early problems */
+       init_ohci1394_enable_physical_dma(ohci);
+}
+
+/**
+ * init_ohci1394_controller - Map the registers of the controller and init DMA
+ * This maps the registers of the specified controller and initializes it
+ */
+static inline void __init init_ohci1394_controller(int num, int slot, int func)
+{
+       unsigned long ohci_base;
+       struct ohci ohci;
+
+       printk(KERN_INFO "init_ohci1394_dma: initializing OHCI-1394"
+                        " at %02x:%02x.%x\n", num, slot, func);
+
+       ohci_base = read_pci_config(num, slot, func, PCI_BASE_ADDRESS_0+(0<<2))
+                                                  & PCI_BASE_ADDRESS_MEM_MASK;
+
+       set_fixmap_nocache(FIX_OHCI1394_BASE, ohci_base);
+
+       ohci.registers = (void __iomem *)fix_to_virt(FIX_OHCI1394_BASE);
+
+       init_ohci1394_reset_and_init_dma(&ohci);
+}
+
+/**
+ * debug_init_ohci1394_dma - scan for OHCI1394 controllers and init DMA on them
+ * Scans the whole PCI space for OHCI1394 controllers and inits DMA on them
+ */
+void __init init_ohci1394_dma_on_all_controllers(void)
+{
+       int num, slot, func;
+       u32 class;
+
+       if (!early_pci_allowed())
+               return;
+
+       /* Poor man's PCI discovery, the only thing we can do at early boot */
+       for (num = 0; num < 32; num++) {
+               for (slot = 0; slot < 32; slot++) {
+                       for (func = 0; func < 8; func++) {
+                               class = read_pci_config(num, slot, func,
+                                                       PCI_CLASS_REVISION);
+                               if (class == 0xffffffff)
+                                       continue; /* No device at this func */
+
+                               if (class>>8 != PCI_CLASS_SERIAL_FIREWIRE_OHCI)
+                                       continue; /* Not an OHCI-1394 device */
+
+                               init_ohci1394_controller(num, slot, func);
+                               break; /* Assume one controller per device */
+                       }
+               }
+       }
+       printk(KERN_INFO "init_ohci1394_dma: finished initializing OHCI DMA\n");
+}
+
+/**
+ * setup_init_ohci1394_early - enables early OHCI1394 DMA initialization
+ */
+static int __init setup_ohci1394_dma(char *opt)
+{
+       if (!strcmp(opt, "early"))
+               init_ohci1394_dma_early = 1;
+       return 0;
+}
+
+/* passing ohci1394_dma=early on boot causes early OHCI1394 DMA initialization */
+early_param("ohci1394_dma", setup_ohci1394_dma);
index 7096909..846fbd5 100644 (file)
@@ -171,13 +171,13 @@ static int __devinit xgpio_of_probe(struct device_node *np)
        /* Update GPIO state shadow register with default value */
        tree_info = of_get_property(np, "xlnx,dout-default", NULL);
        if (tree_info)
-               chip->gpio_state = *tree_info;
+               chip->gpio_state = be32_to_cpup(tree_info);
 
        /* Update GPIO direction shadow register with default value */
        chip->gpio_dir = 0xFFFFFFFF; /* By default, all pins are inputs */
        tree_info = of_get_property(np, "xlnx,tri-default", NULL);
        if (tree_info)
-               chip->gpio_dir = *tree_info;
+               chip->gpio_dir = be32_to_cpup(tree_info);
 
        /* Check device node and parent device node for device width */
        chip->mmchip.gc.ngpio = 32; /* By default assume full GPIO controller */
@@ -186,7 +186,7 @@ static int __devinit xgpio_of_probe(struct device_node *np)
                tree_info = of_get_property(np->parent,
                                            "xlnx,gpio-width", NULL);
        if (tree_info)
-               chip->mmchip.gc.ngpio = *tree_info;
+               chip->mmchip.gc.ngpio = be32_to_cpup(tree_info);
 
        spin_lock_init(&chip->gpio_lock);
 
index 7832b6e..515345b 100644 (file)
@@ -1780,6 +1780,11 @@ static bool hid_ignore(struct hid_device *hdev)
                    hdev->product <= USB_DEVICE_ID_SOUNDGRAPH_IMON_LAST)
                        return true;
                break;
+       case USB_VENDOR_ID_HANWANG:
+               if (hdev->product >= USB_DEVICE_ID_HANWANG_TABLET_FIRST &&
+                   hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST)
+                       return true;
+               break;
        }
 
        if (hdev->type == HID_TYPE_USBMOUSE &&
index 3ee999d..3341baa 100644 (file)
 #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003
 #define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008
 
+#define USB_VENDOR_ID_HANWANG          0x0b57
+#define USB_DEVICE_ID_HANWANG_TABLET_FIRST     0x5000
+#define USB_DEVICE_ID_HANWANG_TABLET_LAST      0x8fff
+
 #define USB_VENDOR_ID_HAPP             0x078b
 #define USB_DEVICE_ID_UGCI_DRIVING     0x0010
 #define USB_DEVICE_ID_UGCI_FLYING      0x0020
index 834ef47..bb0b365 100644 (file)
@@ -68,39 +68,52 @@ static const struct {
 #define map_key_clear(c)       hid_map_usage_clear(hidinput, usage, &bit, \
                &max, EV_KEY, (c))
 
-static inline int match_scancode(unsigned int code, unsigned int scancode)
+static bool match_scancode(struct hid_usage *usage,
+                          unsigned int cur_idx, unsigned int scancode)
 {
-       if (scancode == 0)
-               return 1;
-
-       return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
+       return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
 }
 
-static inline int match_keycode(unsigned int code, unsigned int keycode)
+static bool match_keycode(struct hid_usage *usage,
+                         unsigned int cur_idx, unsigned int keycode)
 {
-       if (keycode == 0)
-               return 1;
+       /*
+        * We should exclude unmapped usages when doing lookup by keycode.
+        */
+       return (usage->type == EV_KEY && usage->code == keycode);
+}
 
-       return code == keycode;
+static bool match_index(struct hid_usage *usage,
+                       unsigned int cur_idx, unsigned int idx)
+{
+       return cur_idx == idx;
 }
 
+typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
+                               unsigned int cur_idx, unsigned int val);
+
 static struct hid_usage *hidinput_find_key(struct hid_device *hid,
-                                          unsigned int scancode,
-                                          unsigned int keycode)
+                                          hid_usage_cmp_t match,
+                                          unsigned int value,
+                                          unsigned int *usage_idx)
 {
-       int i, j, k;
+       unsigned int i, j, k, cur_idx = 0;
        struct hid_report *report;
        struct hid_usage *usage;
 
        for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
                list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
                        for (i = 0; i < report->maxfield; i++) {
-                               for ( j = 0; j < report->field[i]->maxusage; j++) {
+                               for (j = 0; j < report->field[i]->maxusage; j++) {
                                        usage = report->field[i]->usage + j;
-                                       if (usage->type == EV_KEY &&
-                                               match_scancode(usage->hid, scancode) &&
-                                               match_keycode(usage->code, keycode))
-                                               return usage;
+                                       if (usage->type == EV_KEY || usage->type == 0) {
+                                               if (match(usage, cur_idx, value)) {
+                                                       if (usage_idx)
+                                                               *usage_idx = cur_idx;
+                                                       return usage;
+                                               }
+                                               cur_idx++;
+                                       }
                                }
                        }
                }
@@ -108,39 +121,68 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid,
        return NULL;
 }
 
+static struct hid_usage *hidinput_locate_usage(struct hid_device *hid,
+                                       const struct input_keymap_entry *ke,
+                                       unsigned int *index)
+{
+       struct hid_usage *usage;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX)
+               usage = hidinput_find_key(hid, match_index, ke->index, index);
+       else if (input_scancode_to_scalar(ke, &scancode) == 0)
+               usage = hidinput_find_key(hid, match_scancode, scancode, index);
+       else
+               usage = NULL;
+
+       return usage;
+}
+
 static int hidinput_getkeycode(struct input_dev *dev,
-                              unsigned int scancode, unsigned int *keycode)
+                              struct input_keymap_entry *ke)
 {
        struct hid_device *hid = input_get_drvdata(dev);
        struct hid_usage *usage;
+       unsigned int scancode, index;
 
-       usage = hidinput_find_key(hid, scancode, 0);
+       usage = hidinput_locate_usage(hid, ke, &index);
        if (usage) {
-               *keycode = usage->code;
+               ke->keycode = usage->type == EV_KEY ?
+                               usage->code : KEY_RESERVED;
+               ke->index = index;
+               scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE);
+               ke->len = sizeof(scancode);
+               memcpy(ke->scancode, &scancode, sizeof(scancode));
                return 0;
        }
+
        return -EINVAL;
 }
 
 static int hidinput_setkeycode(struct input_dev *dev,
-                              unsigned int scancode, unsigned int keycode)
+                              const struct input_keymap_entry *ke,
+                              unsigned int *old_keycode)
 {
        struct hid_device *hid = input_get_drvdata(dev);
        struct hid_usage *usage;
-       int old_keycode;
 
-       usage = hidinput_find_key(hid, scancode, 0);
+       usage = hidinput_locate_usage(hid, ke, NULL);
        if (usage) {
-               old_keycode = usage->code;
-               usage->code = keycode;
+               *old_keycode = usage->type == EV_KEY ?
+                               usage->code : KEY_RESERVED;
+               usage->code = ke->keycode;
 
-               clear_bit(old_keycode, dev->keybit);
+               clear_bit(*old_keycode, dev->keybit);
                set_bit(usage->code, dev->keybit);
-               dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode);
-               /* Set the keybit for the old keycode if the old keycode is used
-                * by another key */
-               if (hidinput_find_key (hid, 0, old_keycode))
-                       set_bit(old_keycode, dev->keybit);
+               dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n",
+                       usage->code, usage->hid);
+
+               /*
+                * Set the keybit for the old keycode if the old keycode is used
+                * by another key
+                */
+               if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL))
+                       set_bit(*old_keycode, dev->keybit);
 
                return 0;
        }
@@ -835,8 +877,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
                                        hid->ll_driver->hidinput_input_event;
                                input_dev->open = hidinput_open;
                                input_dev->close = hidinput_close;
-                               input_dev->setkeycode = hidinput_setkeycode;
-                               input_dev->getkeycode = hidinput_getkeycode;
+                               input_dev->setkeycode_new = hidinput_setkeycode;
+                               input_dev->getkeycode_new = hidinput_getkeycode;
 
                                input_dev->name = hid->name;
                                input_dev->phys = hid->phys;
index 97499d0..e382da3 100644 (file)
@@ -1088,26 +1088,6 @@ config SENSORS_ULTRA45
          This driver provides support for the Ultra45 workstation environmental
          sensors.
 
-config SENSORS_HDAPS
-       tristate "IBM Hard Drive Active Protection System (hdaps)"
-       depends on INPUT && X86
-       select INPUT_POLLDEV
-       default n
-       help
-         This driver provides support for the IBM Hard Drive Active Protection
-         System (hdaps), which provides an accelerometer and other misc. data.
-         ThinkPads starting with the R50, T41, and X40 are supported.  The
-         accelerometer data is readable via sysfs.
-
-         This driver also provides an absolute input class device, allowing
-         the laptop to act as a pinball machine-esque joystick.
-
-         If your ThinkPad is not recognized by the driver, please update to latest
-         BIOS. This is especially the case for some R52 ThinkPads.
-
-         Say Y here if you have an applicable laptop and want to experience
-         the awesome power of hdaps.
-
 config SENSORS_LIS3_SPI
        tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
        depends on !ACPI && SPI_MASTER && INPUT
index e3c2484..ec9cb73 100644 (file)
@@ -52,7 +52,6 @@ obj-$(CONFIG_SENSORS_G760A)   += g760a.o
 obj-$(CONFIG_SENSORS_GL518SM)  += gl518sm.o
 obj-$(CONFIG_SENSORS_GL520SM)  += gl520sm.o
 obj-$(CONFIG_SENSORS_ULTRA45)  += ultra45_env.o
-obj-$(CONFIG_SENSORS_HDAPS)    += hdaps.o
 obj-$(CONFIG_SENSORS_I5K_AMB)  += i5k_amb.o
 obj-$(CONFIG_SENSORS_IBMAEM)   += ibmaem.o
 obj-$(CONFIG_SENSORS_IBMPEX)   += ibmpex.o
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
deleted file mode 100644 (file)
index bfd42f1..0000000
+++ /dev/null
@@ -1,637 +0,0 @@
-/*
- * drivers/hwmon/hdaps.c - driver for IBM's Hard Drive Active Protection System
- *
- * Copyright (C) 2005 Robert Love <rml@novell.com>
- * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
- *
- * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads
- * starting with the R40, T41, and X40.  It provides a basic two-axis
- * accelerometer and other data, such as the device's temperature.
- *
- * This driver is based on the document by Mark A. Smith available at
- * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
- * and error.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License v2 as published by the
- * Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
- */
-
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/input-polldev.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/dmi.h>
-#include <linux/jiffies.h>
-#include <linux/io.h>
-
-#define HDAPS_LOW_PORT         0x1600  /* first port used by hdaps */
-#define HDAPS_NR_PORTS         0x30    /* number of ports: 0x1600 - 0x162f */
-
-#define HDAPS_PORT_STATE       0x1611  /* device state */
-#define HDAPS_PORT_YPOS                0x1612  /* y-axis position */
-#define        HDAPS_PORT_XPOS         0x1614  /* x-axis position */
-#define HDAPS_PORT_TEMP1       0x1616  /* device temperature, in Celsius */
-#define HDAPS_PORT_YVAR                0x1617  /* y-axis variance (what is this?) */
-#define HDAPS_PORT_XVAR                0x1619  /* x-axis variance (what is this?) */
-#define HDAPS_PORT_TEMP2       0x161b  /* device temperature (again?) */
-#define HDAPS_PORT_UNKNOWN     0x161c  /* what is this? */
-#define HDAPS_PORT_KMACT       0x161d  /* keyboard or mouse activity */
-
-#define STATE_FRESH            0x50    /* accelerometer data is fresh */
-
-#define KEYBD_MASK             0x20    /* set if keyboard activity */
-#define MOUSE_MASK             0x40    /* set if mouse activity */
-#define KEYBD_ISSET(n)         (!! (n & KEYBD_MASK))   /* keyboard used? */
-#define MOUSE_ISSET(n)         (!! (n & MOUSE_MASK))   /* mouse used? */
-
-#define INIT_TIMEOUT_MSECS     4000    /* wait up to 4s for device init ... */
-#define INIT_WAIT_MSECS                200     /* ... in 200ms increments */
-
-#define HDAPS_POLL_INTERVAL    50      /* poll for input every 1/20s (50 ms)*/
-#define HDAPS_INPUT_FUZZ       4       /* input event threshold */
-#define HDAPS_INPUT_FLAT       4
-
-#define HDAPS_X_AXIS           (1 << 0)
-#define HDAPS_Y_AXIS           (1 << 1)
-#define HDAPS_BOTH_AXES                (HDAPS_X_AXIS | HDAPS_Y_AXIS)
-
-static struct platform_device *pdev;
-static struct input_polled_dev *hdaps_idev;
-static unsigned int hdaps_invert;
-static u8 km_activity;
-static int rest_x;
-static int rest_y;
-
-static DEFINE_MUTEX(hdaps_mtx);
-
-/*
- * __get_latch - Get the value from a given port.  Callers must hold hdaps_mtx.
- */
-static inline u8 __get_latch(u16 port)
-{
-       return inb(port) & 0xff;
-}
-
-/*
- * __check_latch - Check a port latch for a given value.  Returns zero if the
- * port contains the given value.  Callers must hold hdaps_mtx.
- */
-static inline int __check_latch(u16 port, u8 val)
-{
-       if (__get_latch(port) == val)
-               return 0;
-       return -EINVAL;
-}
-
-/*
- * __wait_latch - Wait up to 100us for a port latch to get a certain value,
- * returning zero if the value is obtained.  Callers must hold hdaps_mtx.
- */
-static int __wait_latch(u16 port, u8 val)
-{
-       unsigned int i;
-
-       for (i = 0; i < 20; i++) {
-               if (!__check_latch(port, val))
-                       return 0;
-               udelay(5);
-       }
-
-       return -EIO;
-}
-
-/*
- * __device_refresh - request a refresh from the accelerometer.  Does not wait
- * for refresh to complete.  Callers must hold hdaps_mtx.
- */
-static void __device_refresh(void)
-{
-       udelay(200);
-       if (inb(0x1604) != STATE_FRESH) {
-               outb(0x11, 0x1610);
-               outb(0x01, 0x161f);
-       }
-}
-
-/*
- * __device_refresh_sync - request a synchronous refresh from the
- * accelerometer.  We wait for the refresh to complete.  Returns zero if
- * successful and nonzero on error.  Callers must hold hdaps_mtx.
- */
-static int __device_refresh_sync(void)
-{
-       __device_refresh();
-       return __wait_latch(0x1604, STATE_FRESH);
-}
-
-/*
- * __device_complete - indicate to the accelerometer that we are done reading
- * data, and then initiate an async refresh.  Callers must hold hdaps_mtx.
- */
-static inline void __device_complete(void)
-{
-       inb(0x161f);
-       inb(0x1604);
-       __device_refresh();
-}
-
-/*
- * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
- * the given pointer.  Returns zero on success or a negative error on failure.
- * Can sleep.
- */
-static int hdaps_readb_one(unsigned int port, u8 *val)
-{
-       int ret;
-
-       mutex_lock(&hdaps_mtx);
-
-       /* do a sync refresh -- we need to be sure that we read fresh data */
-       ret = __device_refresh_sync();
-       if (ret)
-               goto out;
-
-       *val = inb(port);
-       __device_complete();
-
-out:
-       mutex_unlock(&hdaps_mtx);
-       return ret;
-}
-
-/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
-static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
-                            int *x, int *y)
-{
-       /* do a sync refresh -- we need to be sure that we read fresh data */
-       if (__device_refresh_sync())
-               return -EIO;
-
-       *y = inw(port2);
-       *x = inw(port1);
-       km_activity = inb(HDAPS_PORT_KMACT);
-       __device_complete();
-
-       /* hdaps_invert is a bitvector to negate the axes */
-       if (hdaps_invert & HDAPS_X_AXIS)
-               *x = -*x;
-       if (hdaps_invert & HDAPS_Y_AXIS)
-               *y = -*y;
-
-       return 0;
-}
-
-/*
- * hdaps_read_pair - reads the values from a pair of ports, placing the values
- * in the given pointers.  Returns zero on success.  Can sleep.
- */
-static int hdaps_read_pair(unsigned int port1, unsigned int port2,
-                          int *val1, int *val2)
-{
-       int ret;
-
-       mutex_lock(&hdaps_mtx);
-       ret = __hdaps_read_pair(port1, port2, val1, val2);
-       mutex_unlock(&hdaps_mtx);
-
-       return ret;
-}
-
-/*
- * hdaps_device_init - initialize the accelerometer.  Returns zero on success
- * and negative error code on failure.  Can sleep.
- */
-static int hdaps_device_init(void)
-{
-       int total, ret = -ENXIO;
-
-       mutex_lock(&hdaps_mtx);
-
-       outb(0x13, 0x1610);
-       outb(0x01, 0x161f);
-       if (__wait_latch(0x161f, 0x00))
-               goto out;
-
-       /*
-        * Most ThinkPads return 0x01.
-        *
-        * Others--namely the R50p, T41p, and T42p--return 0x03.  These laptops
-        * have "inverted" axises.
-        *
-        * The 0x02 value occurs when the chip has been previously initialized.
-        */
-       if (__check_latch(0x1611, 0x03) &&
-                    __check_latch(0x1611, 0x02) &&
-                    __check_latch(0x1611, 0x01))
-               goto out;
-
-       printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n",
-              __get_latch(0x1611));
-
-       outb(0x17, 0x1610);
-       outb(0x81, 0x1611);
-       outb(0x01, 0x161f);
-       if (__wait_latch(0x161f, 0x00))
-               goto out;
-       if (__wait_latch(0x1611, 0x00))
-               goto out;
-       if (__wait_latch(0x1612, 0x60))
-               goto out;
-       if (__wait_latch(0x1613, 0x00))
-               goto out;
-       outb(0x14, 0x1610);
-       outb(0x01, 0x1611);
-       outb(0x01, 0x161f);
-       if (__wait_latch(0x161f, 0x00))
-               goto out;
-       outb(0x10, 0x1610);
-       outb(0xc8, 0x1611);
-       outb(0x00, 0x1612);
-       outb(0x02, 0x1613);
-       outb(0x01, 0x161f);
-       if (__wait_latch(0x161f, 0x00))
-               goto out;
-       if (__device_refresh_sync())
-               goto out;
-       if (__wait_latch(0x1611, 0x00))
-               goto out;
-
-       /* we have done our dance, now let's wait for the applause */
-       for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
-               int x, y;
-
-               /* a read of the device helps push it into action */
-               __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
-               if (!__wait_latch(0x1611, 0x02)) {
-                       ret = 0;
-                       break;
-               }
-
-               msleep(INIT_WAIT_MSECS);
-       }
-
-out:
-       mutex_unlock(&hdaps_mtx);
-       return ret;
-}
-
-
-/* Device model stuff */
-
-static int hdaps_probe(struct platform_device *dev)
-{
-       int ret;
-
-       ret = hdaps_device_init();
-       if (ret)
-               return ret;
-
-       printk(KERN_INFO "hdaps: device successfully initialized.\n");
-       return 0;
-}
-
-static int hdaps_resume(struct platform_device *dev)
-{
-       return hdaps_device_init();
-}
-
-static struct platform_driver hdaps_driver = {
-       .probe = hdaps_probe,
-       .resume = hdaps_resume,
-       .driver = {
-               .name = "hdaps",
-               .owner = THIS_MODULE,
-       },
-};
-
-/*
- * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_mtx.
- */
-static void hdaps_calibrate(void)
-{
-       __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
-}
-
-static void hdaps_mousedev_poll(struct input_polled_dev *dev)
-{
-       struct input_dev *input_dev = dev->input;
-       int x, y;
-
-       mutex_lock(&hdaps_mtx);
-
-       if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
-               goto out;
-
-       input_report_abs(input_dev, ABS_X, x - rest_x);
-       input_report_abs(input_dev, ABS_Y, y - rest_y);
-       input_sync(input_dev);
-
-out:
-       mutex_unlock(&hdaps_mtx);
-}
-
-
-/* Sysfs Files */
-
-static ssize_t hdaps_position_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       int ret, x, y;
-
-       ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
-       if (ret)
-               return ret;
-
-       return sprintf(buf, "(%d,%d)\n", x, y);
-}
-
-static ssize_t hdaps_variance_show(struct device *dev,
-                                  struct device_attribute *attr, char *buf)
-{
-       int ret, x, y;
-
-       ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
-       if (ret)
-               return ret;
-
-       return sprintf(buf, "(%d,%d)\n", x, y);
-}
-
-static ssize_t hdaps_temp1_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       u8 temp;
-       int ret;
-
-       ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
-       if (ret < 0)
-               return ret;
-
-       return sprintf(buf, "%u\n", temp);
-}
-
-static ssize_t hdaps_temp2_show(struct device *dev,
-                               struct device_attribute *attr, char *buf)
-{
-       u8 temp;
-       int ret;
-
-       ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
-       if (ret < 0)
-               return ret;
-
-       return sprintf(buf, "%u\n", temp);
-}
-
-static ssize_t hdaps_keyboard_activity_show(struct device *dev,
-                                           struct device_attribute *attr,
-                                           char *buf)
-{
-       return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
-}
-
-static ssize_t hdaps_mouse_activity_show(struct device *dev,
-                                        struct device_attribute *attr,
-                                        char *buf)
-{
-       return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
-}
-
-static ssize_t hdaps_calibrate_show(struct device *dev,
-                                   struct device_attribute *attr, char *buf)
-{
-       return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
-}
-
-static ssize_t hdaps_calibrate_store(struct device *dev,
-                                    struct device_attribute *attr,
-                                    const char *buf, size_t count)
-{
-       mutex_lock(&hdaps_mtx);
-       hdaps_calibrate();
-       mutex_unlock(&hdaps_mtx);
-
-       return count;
-}
-
-static ssize_t hdaps_invert_show(struct device *dev,
-                                struct device_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%u\n", hdaps_invert);
-}
-
-static ssize_t hdaps_invert_store(struct device *dev,
-                                 struct device_attribute *attr,
-                                 const char *buf, size_t count)
-{
-       int invert;
-
-       if (sscanf(buf, "%d", &invert) != 1 ||
-           invert < 0 || invert > HDAPS_BOTH_AXES)
-               return -EINVAL;
-
-       hdaps_invert = invert;
-       hdaps_calibrate();
-
-       return count;
-}
-
-static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
-static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
-static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
-static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
-static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
-static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
-static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
-static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
-
-static struct attribute *hdaps_attributes[] = {
-       &dev_attr_position.attr,
-       &dev_attr_variance.attr,
-       &dev_attr_temp1.attr,
-       &dev_attr_temp2.attr,
-       &dev_attr_keyboard_activity.attr,
-       &dev_attr_mouse_activity.attr,
-       &dev_attr_calibrate.attr,
-       &dev_attr_invert.attr,
-       NULL,
-};
-
-static struct attribute_group hdaps_attribute_group = {
-       .attrs = hdaps_attributes,
-};
-
-
-/* Module stuff */
-
-/* hdaps_dmi_match - found a match.  return one, short-circuiting the hunt. */
-static int __init hdaps_dmi_match(const struct dmi_system_id *id)
-{
-       printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
-       return 1;
-}
-
-/* hdaps_dmi_match_invert - found an inverted match. */
-static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id)
-{
-       hdaps_invert = (unsigned long)id->driver_data;
-       printk(KERN_INFO "hdaps: inverting axis (%u) readings.\n",
-              hdaps_invert);
-       return hdaps_dmi_match(id);
-}
-
-#define HDAPS_DMI_MATCH_INVERT(vendor, model, axes) {  \
-       .ident = vendor " " model,                      \
-       .callback = hdaps_dmi_match_invert,             \
-       .driver_data = (void *)axes,                    \
-       .matches = {                                    \
-               DMI_MATCH(DMI_BOARD_VENDOR, vendor),    \
-               DMI_MATCH(DMI_PRODUCT_VERSION, model)   \
-       }                                               \
-}
-
-#define HDAPS_DMI_MATCH_NORMAL(vendor, model)          \
-       HDAPS_DMI_MATCH_INVERT(vendor, model, 0)
-
-/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
-   "ThinkPad T42p", so the order of the entries matters.
-   If your ThinkPad is not recognized, please update to latest
-   BIOS. This is especially the case for some R52 ThinkPads. */
-static struct dmi_system_id __initdata hdaps_whitelist[] = {
-       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
-       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T400", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
-       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad X41", HDAPS_Y_AXIS),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m", HDAPS_BOTH_AXES),
-       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p", HDAPS_BOTH_AXES),
-       { .ident = NULL }
-};
-
-static int __init hdaps_init(void)
-{
-       struct input_dev *idev;
-       int ret;
-
-       if (!dmi_check_system(hdaps_whitelist)) {
-               printk(KERN_WARNING "hdaps: supported laptop not found!\n");
-               ret = -ENODEV;
-               goto out;
-       }
-
-       if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
-               ret = -ENXIO;
-               goto out;
-       }
-
-       ret = platform_driver_register(&hdaps_driver);
-       if (ret)
-               goto out_region;
-
-       pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
-       if (IS_ERR(pdev)) {
-               ret = PTR_ERR(pdev);
-               goto out_driver;
-       }
-
-       ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
-       if (ret)
-               goto out_device;
-
-       hdaps_idev = input_allocate_polled_device();
-       if (!hdaps_idev) {
-               ret = -ENOMEM;
-               goto out_group;
-       }
-
-       hdaps_idev->poll = hdaps_mousedev_poll;
-       hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL;
-
-       /* initial calibrate for the input device */
-       hdaps_calibrate();
-
-       /* initialize the input class */
-       idev = hdaps_idev->input;
-       idev->name = "hdaps";
-       idev->phys = "isa1600/input0";
-       idev->id.bustype = BUS_ISA;
-       idev->dev.parent = &pdev->dev;
-       idev->evbit[0] = BIT_MASK(EV_ABS);
-       input_set_abs_params(idev, ABS_X,
-                       -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
-       input_set_abs_params(idev, ABS_Y,
-                       -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
-
-       ret = input_register_polled_device(hdaps_idev);
-       if (ret)
-               goto out_idev;
-
-       printk(KERN_INFO "hdaps: driver successfully loaded.\n");
-       return 0;
-
-out_idev:
-       input_free_polled_device(hdaps_idev);
-out_group:
-       sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
-out_device:
-       platform_device_unregister(pdev);
-out_driver:
-       platform_driver_unregister(&hdaps_driver);
-out_region:
-       release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
-out:
-       printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret);
-       return ret;
-}
-
-static void __exit hdaps_exit(void)
-{
-       input_unregister_polled_device(hdaps_idev);
-       input_free_polled_device(hdaps_idev);
-       sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
-       platform_device_unregister(pdev);
-       platform_driver_unregister(&hdaps_driver);
-       release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
-
-       printk(KERN_INFO "hdaps: driver unloaded.\n");
-}
-
-module_init(hdaps_init);
-module_exit(hdaps_exit);
-
-module_param_named(invert, hdaps_invert, int, 0);
-MODULE_PARM_DESC(invert, "invert data along each axis. 1 invert x-axis, "
-                "2 invert y-axis, 3 invert both axes.");
-
-MODULE_AUTHOR("Robert Love");
-MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
-MODULE_LICENSE("GPL v2");
index 4f93da3..3cad8fe 100644 (file)
@@ -101,12 +101,12 @@ struct cami2c {
 
 static inline void OUT32(struct cami2c *cam, int reg, unsigned long val)
 {
-       ctrl_outl(val, (unsigned long)cam->iobase + reg);
+       __raw_writel(val, (unsigned long)cam->iobase + reg);
 }
 
 static inline unsigned long IN32(struct cami2c *cam, int reg)
 {
-       return ctrl_inl((unsigned long)cam->iobase + reg);
+       return __raw_readl((unsigned long)cam->iobase + reg);
 }
 
 static irqreturn_t sh7760_i2c_irq(int irq, void *ptr)
index 598c49a..2707f5e 100644 (file)
@@ -538,15 +538,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
 {
        struct resource *res;
        int ret = -ENXIO;
-       int q, m;
-       int k = 0;
-       int n = 0;
+       int n, k = 0;
 
        while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) {
                for (n = res->start; hook && n <= res->end; n++) {
                        if (request_irq(n, sh_mobile_i2c_isr, IRQF_DISABLED,
-                                       dev_name(&dev->dev), dev))
+                                       dev_name(&dev->dev), dev)) {
+                               for (n--; n >= res->start; n--)
+                                       free_irq(n, dev);
+
                                goto rollback;
+                       }
                }
                k++;
        }
@@ -554,16 +556,17 @@ static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook)
        if (hook)
                return k > 0 ? 0 : -ENOENT;
 
-       k--;
        ret = 0;
 
  rollback:
-       for (q = k; k >= 0; k--) {
-               for (m = n; m >= res->start; m--)
-                       free_irq(m, dev);
+       k--;
+
+       while (k >= 0) {
+               res = platform_get_resource(dev, IORESOURCE_IRQ, k);
+               for (n = res->start; n <= res->end; n++)
+                       free_irq(n, dev);
 
-               res = platform_get_resource(dev, IORESOURCE_IRQ, k - 1);
-               m = res->end;
+               k--;
        }
 
        return ret;
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
deleted file mode 100644 (file)
index e02096c..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-config IEEE1394
-       tristate "Legacy alternative FireWire driver stack"
-       depends on PCI || BROKEN
-       help
-         IEEE 1394 describes a high performance serial bus, which is also
-         known as FireWire(tm) or i.Link(tm) and is used for connecting all
-         sorts of devices (most notably digital video cameras) to your
-         computer.
-
-         If you have FireWire hardware and want to use it, say Y here.  This
-         is the core support only, you will also need to select a driver for
-         your IEEE 1394 adapter.
-
-         To compile this driver as a module, say M here: the module will be
-         called ieee1394.
-
-         NOTE:
-         ieee1394 is superseded by the newer firewire-core driver.  See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_OHCI1394
-       tristate "OHCI-1394 controllers"
-       depends on PCI && IEEE1394
-       help
-         Enable this driver if you have an IEEE 1394 controller based on the
-         OHCI-1394 specification. The current driver is only tested with OHCI
-         chipsets made by Texas Instruments and NEC. Most third-party vendors
-         use one of these chipsets.  It should work with any OHCI-1394
-         compliant card, however.
-
-         To compile this driver as a module, say M here: the module will be
-         called ohci1394.
-
-         NOTE:
-         ohci1394 is superseded by the newer firewire-ohci driver.  See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-         If you want to install firewire-ohci and ohci1394 together, you
-         should configure them only as modules and blacklist the driver(s)
-         which you don't want to have auto-loaded.  Add either
-
-             blacklist ohci1394
-             blacklist video1394
-             blacklist dv1394
-         or
-             blacklist firewire-ohci
-
-         to /etc/modprobe.conf or /etc/modprobe.d/* and update modprobe.conf
-         depending on your distribution.
-
-comment "PCILynx controller requires I2C"
-       depends on IEEE1394 && I2C=n
-
-config IEEE1394_PCILYNX
-       tristate "PCILynx controller"
-       depends on PCI && IEEE1394 && I2C
-       select I2C_ALGOBIT
-       help
-         Say Y here if you have an IEEE-1394 controller with the Texas
-         Instruments PCILynx chip.  Note: this driver is written for revision
-         2 of this chip and may not work with revision 0.
-
-         To compile this driver as a module, say M here: the module will be
-         called pcilynx.
-
-         Only some old and now very rare PCI and CardBus cards and
-         PowerMacs G3 B&W contain the PCILynx controller.  Therefore
-         almost everybody can say N here.
-
-comment "SBP-2 support (for storage devices) requires SCSI"
-       depends on IEEE1394 && SCSI=n
-
-config IEEE1394_SBP2
-       tristate "Storage devices (SBP-2 protocol)"
-       depends on IEEE1394 && SCSI
-       help
-         This option enables you to use SBP-2 devices connected to an IEEE
-         1394 bus.  SBP-2 devices include storage devices like harddisks and
-         DVD drives, also some other FireWire devices like scanners.
-
-         You should also enable support for disks, CD-ROMs, etc. in the SCSI
-         configuration section.
-
-         To compile this driver as a module, say M here: the module will be
-         called sbp2.
-
-         NOTE:
-         sbp2 is superseded by the newer firewire-sbp2 driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_SBP2_PHYS_DMA
-       bool "Enable replacement for physical DMA in SBP2"
-       depends on IEEE1394_SBP2 && VIRT_TO_BUS && EXPERIMENTAL
-       help
-         This builds sbp2 for use with non-OHCI host adapters which do not
-         support physical DMA or for when ohci1394 is run with phys_dma=0.
-         Physical DMA is data movement without assistance of the drivers'
-         interrupt handlers.  This option includes the interrupt handlers
-         that are required in absence of this hardware feature.
-
-         This option is buggy and currently broken on some architectures.
-         If unsure, say N.
-
-config IEEE1394_ETH1394_ROM_ENTRY
-       depends on IEEE1394
-       bool
-       default n
-
-config IEEE1394_ETH1394
-       tristate "IP networking over 1394 (experimental)"
-       depends on IEEE1394 && EXPERIMENTAL && INET
-       select IEEE1394_ETH1394_ROM_ENTRY
-       help
-         This driver implements a functional majority of RFC 2734: IPv4 over
-         1394.  It will provide IP connectivity with implementations of RFC
-         2734 found on other operating systems.  It will not communicate with
-         older versions of this driver found in stock kernels prior to 2.6.3.
-         This driver is still considered experimental.  It does not yet support
-         MCAP, therefore multicast support is significantly limited.
-
-         The module is called eth1394 although it does not emulate Ethernet.
-
-         NOTE:
-         eth1394 is superseded by the newer firewire-net driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_RAWIO
-       tristate "raw1394 userspace interface"
-       depends on IEEE1394
-       help
-         This option adds support for the raw1394 device file which enables
-         direct communication of user programs with IEEE 1394 devices
-         (isochronous and asynchronous).  Almost all application programs
-         which access FireWire require this option.
-
-         To compile this driver as a module, say M here: the module will be
-         called raw1394.
-
-         NOTE:
-         raw1394 is superseded by the newer firewire-core driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_VIDEO1394
-       tristate "video1394 userspace interface"
-       depends on IEEE1394 && IEEE1394_OHCI1394
-       help
-         This option adds support for the video1394 device files which enable
-         isochronous communication of user programs with IEEE 1394 devices,
-         especially video capture or export.  This interface is used by all
-         libdc1394 based programs and by several other programs, in addition to
-         the raw1394 interface.  It is generally not required for DV capture.
-
-         To compile this driver as a module, say M here: the module will be
-         called video1394.
-
-         NOTE:
-         video1394 is superseded by the newer firewire-core driver. See
-         http://ieee1394.wiki.kernel.org/index.php/Juju_Migration for
-         further information on how to switch to the new FireWire drivers.
-
-config IEEE1394_DV1394
-       tristate "dv1394 userspace interface (deprecated)"
-       depends on IEEE1394 && IEEE1394_OHCI1394
-       help
-         The dv1394 driver is unsupported and may be removed from Linux in a
-         future release.  Its functionality is now provided by either
-         raw1394 or firewire-core together with libraries such as libiec61883.
-
-config IEEE1394_VERBOSEDEBUG
-       bool "Excessive debugging output"
-       depends on IEEE1394
-       help
-         If you say Y here, you will get very verbose debugging logs from the
-         ieee1394 drivers, including sent and received packet headers.  This
-         will quickly result in large amounts of data sent to the system log.
-
-         Say Y if you really need the debugging output.  Everyone else says N.
diff --git a/drivers/ieee1394/Makefile b/drivers/ieee1394/Makefile
deleted file mode 100644 (file)
index 1f8153b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#
-# Makefile for the Linux IEEE 1394 implementation
-#
-
-ieee1394-objs := ieee1394_core.o ieee1394_transactions.o hosts.o \
-                highlevel.o csr.o nodemgr.o dma.o iso.o \
-                csr1212.o config_roms.o
-
-obj-$(CONFIG_IEEE1394) += ieee1394.o
-obj-$(CONFIG_IEEE1394_PCILYNX) += pcilynx.o
-obj-$(CONFIG_IEEE1394_OHCI1394) += ohci1394.o
-obj-$(CONFIG_IEEE1394_VIDEO1394) += video1394.o
-obj-$(CONFIG_IEEE1394_RAWIO) += raw1394.o
-obj-$(CONFIG_IEEE1394_SBP2) += sbp2.o
-obj-$(CONFIG_IEEE1394_DV1394) += dv1394.o
-obj-$(CONFIG_IEEE1394_ETH1394) += eth1394.o
-
-obj-$(CONFIG_PROVIDE_OHCI1394_DMA_INIT) += init_ohci1394_dma.o
diff --git a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c
deleted file mode 100644 (file)
index 1b98120..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * ConfigROM  entries
- *
- * Copyright (C) 2004 Ben Collins
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/types.h>
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "csr.h"
-#include "config_roms.h"
-
-struct hpsb_config_rom_entry {
-       const char *name;
-
-       /* Base initialization, called at module load */
-       int (*init)(void);
-
-       /* Cleanup called at module exit */
-       void (*cleanup)(void);
-
-       /* The flag added to host->config_roms */
-       unsigned int flag;
-};
-
-/* The default host entry. This must succeed. */
-int hpsb_default_host_entry(struct hpsb_host *host)
-{
-       struct csr1212_keyval *root;
-       struct csr1212_keyval *vend_id = NULL;
-       struct csr1212_keyval *text = NULL;
-       char csr_name[128];
-       int ret;
-
-       sprintf(csr_name, "Linux - %s", host->driver->name);
-       root = host->csr.rom->root_kv;
-
-       vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8);
-       text = csr1212_new_string_descriptor_leaf(csr_name);
-
-       if (!vend_id || !text) {
-               if (vend_id)
-                       csr1212_release_keyval(vend_id);
-               if (text)
-                       csr1212_release_keyval(text);
-               csr1212_destroy_csr(host->csr.rom);
-               return -ENOMEM;
-       }
-
-       csr1212_associate_keyval(vend_id, text);
-       csr1212_release_keyval(text);
-       ret = csr1212_attach_keyval_to_directory(root, vend_id);
-       csr1212_release_keyval(vend_id);
-       if (ret != CSR1212_SUCCESS) {
-               csr1212_destroy_csr(host->csr.rom);
-               return -ENOMEM;
-       }
-
-       host->update_config_rom = 1;
-
-       return 0;
-}
-
-
-#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
-#include "eth1394.h"
-
-static struct csr1212_keyval *ip1394_ud;
-
-static int config_rom_ip1394_init(void)
-{
-       struct csr1212_keyval *spec_id = NULL;
-       struct csr1212_keyval *spec_desc = NULL;
-       struct csr1212_keyval *ver = NULL;
-       struct csr1212_keyval *ver_desc = NULL;
-       int ret = -ENOMEM;
-
-       ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);
-
-       spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
-                                       ETHER1394_GASP_SPECIFIER_ID);
-       spec_desc = csr1212_new_string_descriptor_leaf("IANA");
-       ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
-                                   ETHER1394_GASP_VERSION);
-       ver_desc = csr1212_new_string_descriptor_leaf("IPv4");
-
-       if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
-               goto ip1394_fail;
-
-       csr1212_associate_keyval(spec_id, spec_desc);
-       csr1212_associate_keyval(ver, ver_desc);
-       if (csr1212_attach_keyval_to_directory(ip1394_ud, spec_id)
-                       == CSR1212_SUCCESS &&
-           csr1212_attach_keyval_to_directory(ip1394_ud, ver)
-                       == CSR1212_SUCCESS)
-               ret = 0;
-
-ip1394_fail:
-       if (ret && ip1394_ud) {
-               csr1212_release_keyval(ip1394_ud);
-               ip1394_ud = NULL;
-       }
-
-       if (spec_id)
-               csr1212_release_keyval(spec_id);
-       if (spec_desc)
-               csr1212_release_keyval(spec_desc);
-       if (ver)
-               csr1212_release_keyval(ver);
-       if (ver_desc)
-               csr1212_release_keyval(ver_desc);
-
-       return ret;
-}
-
-static void config_rom_ip1394_cleanup(void)
-{
-       if (ip1394_ud) {
-               csr1212_release_keyval(ip1394_ud);
-               ip1394_ud = NULL;
-       }
-}
-
-int hpsb_config_rom_ip1394_add(struct hpsb_host *host)
-{
-       if (!ip1394_ud)
-               return -ENODEV;
-
-       if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
-                                              ip1394_ud) != CSR1212_SUCCESS)
-               return -ENOMEM;
-
-       host->config_roms |= HPSB_CONFIG_ROM_ENTRY_IP1394;
-       host->update_config_rom = 1;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_add);
-
-void hpsb_config_rom_ip1394_remove(struct hpsb_host *host)
-{
-       csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud);
-       host->config_roms &= ~HPSB_CONFIG_ROM_ENTRY_IP1394;
-       host->update_config_rom = 1;
-}
-EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_remove);
-
-static struct hpsb_config_rom_entry ip1394_entry = {
-       .name           = "ip1394",
-       .init           = config_rom_ip1394_init,
-       .cleanup        = config_rom_ip1394_cleanup,
-       .flag           = HPSB_CONFIG_ROM_ENTRY_IP1394,
-};
-
-#endif /* CONFIG_IEEE1394_ETH1394_ROM_ENTRY */
-
-static struct hpsb_config_rom_entry *const config_rom_entries[] = {
-#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
-       &ip1394_entry,
-#endif
-};
-
-/* Initialize all config roms */
-int hpsb_init_config_roms(void)
-{
-       int i, error = 0;
-
-       for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
-               if (config_rom_entries[i]->init()) {
-                       HPSB_ERR("Failed to initialize config rom entry `%s'",
-                                config_rom_entries[i]->name);
-                       error = -1;
-               }
-
-       return error;
-}
-
-/* Cleanup all config roms */
-void hpsb_cleanup_config_roms(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
-               config_rom_entries[i]->cleanup();
-}
diff --git a/drivers/ieee1394/config_roms.h b/drivers/ieee1394/config_roms.h
deleted file mode 100644 (file)
index 1f5cd1f..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _IEEE1394_CONFIG_ROMS_H
-#define _IEEE1394_CONFIG_ROMS_H
-
-struct hpsb_host;
-
-int hpsb_default_host_entry(struct hpsb_host *host);
-int hpsb_init_config_roms(void);
-void hpsb_cleanup_config_roms(void);
-
-/* List of flags to check if a host contains a certain extra config rom
- * entry. Available in the host->config_roms member. */
-#define HPSB_CONFIG_ROM_ENTRY_IP1394           0x00000001
-
-#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
-int hpsb_config_rom_ip1394_add(struct hpsb_host *host);
-void hpsb_config_rom_ip1394_remove(struct hpsb_host *host);
-#endif
-
-#endif /* _IEEE1394_CONFIG_ROMS_H */
diff --git a/drivers/ieee1394/csr.c b/drivers/ieee1394/csr.c
deleted file mode 100644 (file)
index d696f69..0000000
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * CSR implementation, iso/bus manager implementation.
- *
- * Copyright (C) 1999 Andreas E. Bombe
- *               2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        configuration ROM manipulation
- *
- */
-
-#include <linux/jiffies.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/param.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-
-#include "csr1212.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "highlevel.h"
-#include "ieee1394_core.h"
-
-/* Module Parameters */
-/* this module parameter can be used to disable mapping of the FCP registers */
-
-static int fcp = 1;
-module_param(fcp, int, 0444);
-MODULE_PARM_DESC(fcp, "Map FCP registers (default = 1, disable = 0).");
-
-static struct csr1212_keyval *node_cap = NULL;
-
-static void add_host(struct hpsb_host *host);
-static void remove_host(struct hpsb_host *host);
-static void host_reset(struct hpsb_host *host);
-static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                    u64 addr, size_t length, u16 fl);
-static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
-                    quadlet_t *data, u64 addr, size_t length, u16 flags);
-static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
-                    u64 addr, size_t length, u16 flags);
-static int write_regs(struct hpsb_host *host, int nodeid, int destid,
-                     quadlet_t *data, u64 addr, size_t length, u16 flags);
-static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                    u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl);
-static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
-                      u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl);
-static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                          u64 addr, size_t length, u16 fl);
-static u64 allocate_addr_range(u64 size, u32 alignment, void *__host);
-static void release_addr_range(u64 addr, void *__host);
-
-static struct hpsb_highlevel csr_highlevel = {
-       .name =         "standard registers",
-       .add_host =     add_host,
-       .remove_host =  remove_host,
-       .host_reset =   host_reset,
-};
-
-static const struct hpsb_address_ops map_ops = {
-       .read = read_maps,
-};
-
-static const struct hpsb_address_ops fcp_ops = {
-       .write = write_fcp,
-};
-
-static const struct hpsb_address_ops reg_ops = {
-       .read = read_regs,
-       .write = write_regs,
-       .lock = lock_regs,
-       .lock64 = lock64_regs,
-};
-
-static const struct hpsb_address_ops config_rom_ops = {
-       .read = read_config_rom,
-};
-
-struct csr1212_bus_ops csr_bus_ops = {
-       .allocate_addr_range =  allocate_addr_range,
-       .release_addr =         release_addr_range,
-};
-
-
-static u16 csr_crc16(unsigned *data, int length)
-{
-        int check=0, i;
-        int shift, sum, next=0;
-
-        for (i = length; i; i--) {
-                for (next = check, shift = 28; shift >= 0; shift -= 4 ) {
-                        sum = ((next >> 12) ^ (be32_to_cpu(*data) >> shift)) & 0xf;
-                        next = (next << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
-                }
-                check = next & 0xffff;
-                data++;
-        }
-
-        return check;
-}
-
-static void host_reset(struct hpsb_host *host)
-{
-        host->csr.state &= 0x300;
-
-        host->csr.bus_manager_id = 0x3f;
-        host->csr.bandwidth_available = 4915;
-       host->csr.channels_available_hi = 0xfffffffe;   /* pre-alloc ch 31 per 1394a-2000 */
-        host->csr.channels_available_lo = ~0;
-       host->csr.broadcast_channel = 0x80000000 | 31;
-
-       if (host->is_irm) {
-               if (host->driver->hw_csr_reg) {
-                       host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
-               }
-       }
-
-        host->csr.node_ids = host->node_id << 16;
-
-        if (!host->is_root) {
-                /* clear cmstr bit */
-                host->csr.state &= ~0x100;
-        }
-
-       be32_add_cpu(&host->csr.topology_map[1], 1);
-        host->csr.topology_map[2] = cpu_to_be32(host->node_count << 16
-                                                | host->selfid_count);
-        host->csr.topology_map[0] =
-                cpu_to_be32((host->selfid_count + 2) << 16
-                            | csr_crc16(host->csr.topology_map + 1,
-                                        host->selfid_count + 2));
-
-       be32_add_cpu(&host->csr.speed_map[1], 1);
-        host->csr.speed_map[0] = cpu_to_be32(0x3f1 << 16
-                                             | csr_crc16(host->csr.speed_map+1,
-                                                         0x3f1));
-}
-
-/*
- * HI == seconds (bits 0:2)
- * LO == fractions of a second in units of 125usec (bits 19:31)
- *
- * Convert SPLIT_TIMEOUT to jiffies.
- * The default and minimum as per 1394a-2000 clause 8.3.2.2.6 is 100ms.
- */
-static inline void calculate_expire(struct csr_control *csr)
-{
-       unsigned int usecs = (csr->split_timeout_hi & 7) * 1000000 +
-                            (csr->split_timeout_lo >> 19) * 125;
-
-       csr->expire = usecs_to_jiffies(usecs > 100000 ? usecs : 100000);
-       HPSB_VERBOSE("CSR: setting expire to %lu, HZ=%u", csr->expire, HZ);
-}
-
-
-static void add_host(struct hpsb_host *host)
-{
-       struct csr1212_keyval *root;
-       quadlet_t bus_info[CSR_BUS_INFO_SIZE];
-
-       hpsb_register_addrspace(&csr_highlevel, host, &reg_ops,
-                               CSR_REGISTER_BASE,
-                               CSR_REGISTER_BASE + CSR_CONFIG_ROM);
-       hpsb_register_addrspace(&csr_highlevel, host, &config_rom_ops,
-                               CSR_REGISTER_BASE + CSR_CONFIG_ROM,
-                               CSR_REGISTER_BASE + CSR_CONFIG_ROM_END);
-       if (fcp) {
-               hpsb_register_addrspace(&csr_highlevel, host, &fcp_ops,
-                                       CSR_REGISTER_BASE + CSR_FCP_COMMAND,
-                                       CSR_REGISTER_BASE + CSR_FCP_END);
-       }
-       hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
-                               CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP,
-                               CSR_REGISTER_BASE + CSR_TOPOLOGY_MAP_END);
-       hpsb_register_addrspace(&csr_highlevel, host, &map_ops,
-                               CSR_REGISTER_BASE + CSR_SPEED_MAP,
-                               CSR_REGISTER_BASE + CSR_SPEED_MAP_END);
-
-        spin_lock_init(&host->csr.lock);
-
-        host->csr.state                 = 0;
-        host->csr.node_ids              = 0;
-        host->csr.split_timeout_hi      = 0;
-        host->csr.split_timeout_lo      = 800 << 19;
-       calculate_expire(&host->csr);
-        host->csr.cycle_time            = 0;
-        host->csr.bus_time              = 0;
-        host->csr.bus_manager_id        = 0x3f;
-        host->csr.bandwidth_available   = 4915;
-       host->csr.channels_available_hi = 0xfffffffe;   /* pre-alloc ch 31 per 1394a-2000 */
-        host->csr.channels_available_lo = ~0;
-       host->csr.broadcast_channel = 0x80000000 | 31;
-
-       if (host->is_irm) {
-               if (host->driver->hw_csr_reg) {
-                       host->driver->hw_csr_reg(host, 2, 0xfffffffe, ~0);
-               }
-       }
-
-       if (host->csr.max_rec >= 9)
-               host->csr.max_rom = 2;
-       else if (host->csr.max_rec >= 5)
-               host->csr.max_rom = 1;
-       else
-               host->csr.max_rom = 0;
-
-       host->csr.generation = 2;
-
-       bus_info[1] = IEEE1394_BUSID_MAGIC;
-       bus_info[2] = cpu_to_be32((hpsb_disable_irm ? 0 : 1 << CSR_IRMC_SHIFT) |
-                                 (1 << CSR_CMC_SHIFT) |
-                                 (1 << CSR_ISC_SHIFT) |
-                                 (0 << CSR_BMC_SHIFT) |
-                                 (0 << CSR_PMC_SHIFT) |
-                                 (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
-                                 (host->csr.max_rec << CSR_MAX_REC_SHIFT) |
-                                 (host->csr.max_rom << CSR_MAX_ROM_SHIFT) |
-                                 (host->csr.generation << CSR_GENERATION_SHIFT) |
-                                 host->csr.lnk_spd);
-
-       bus_info[3] = cpu_to_be32(host->csr.guid_hi);
-       bus_info[4] = cpu_to_be32(host->csr.guid_lo);
-
-       /* The hardware copy of the bus info block will be set later when a
-        * bus reset is issued. */
-
-       csr1212_init_local_csr(host->csr.rom, bus_info, host->csr.max_rom);
-
-       root = host->csr.rom->root_kv;
-
-       if(csr1212_attach_keyval_to_directory(root, node_cap) != CSR1212_SUCCESS) {
-               HPSB_ERR("Failed to attach Node Capabilities to root directory");
-       }
-
-       host->update_config_rom = 1;
-}
-
-static void remove_host(struct hpsb_host *host)
-{
-       quadlet_t bus_info[CSR_BUS_INFO_SIZE];
-
-       bus_info[1] = IEEE1394_BUSID_MAGIC;
-       bus_info[2] = cpu_to_be32((0 << CSR_IRMC_SHIFT) |
-                                 (0 << CSR_CMC_SHIFT) |
-                                 (0 << CSR_ISC_SHIFT) |
-                                 (0 << CSR_BMC_SHIFT) |
-                                 (0 << CSR_PMC_SHIFT) |
-                                 (host->csr.cyc_clk_acc << CSR_CYC_CLK_ACC_SHIFT) |
-                                 (host->csr.max_rec << CSR_MAX_REC_SHIFT) |
-                                 (0 << CSR_MAX_ROM_SHIFT) |
-                                 (0 << CSR_GENERATION_SHIFT) |
-                                 host->csr.lnk_spd);
-
-       bus_info[3] = cpu_to_be32(host->csr.guid_hi);
-       bus_info[4] = cpu_to_be32(host->csr.guid_lo);
-
-       csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, node_cap);
-
-       csr1212_init_local_csr(host->csr.rom, bus_info, 0);
-       host->update_config_rom = 1;
-}
-
-
-int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
-       size_t buffersize, unsigned char rom_version)
-{
-       unsigned long flags;
-       int ret;
-
-       HPSB_NOTICE("hpsb_update_config_rom() is deprecated");
-
-        spin_lock_irqsave(&host->csr.lock, flags);
-       if (rom_version != host->csr.generation)
-                ret = -1;
-       else if (buffersize > host->csr.rom->cache_head->size)
-               ret = -2;
-        else {
-               /* Just overwrite the generated ConfigROM image with new data,
-                * it can be regenerated later. */
-               memcpy(host->csr.rom->cache_head->data, new_rom, buffersize);
-               host->csr.rom->cache_head->len = buffersize;
-
-               if (host->driver->set_hw_config_rom)
-                       host->driver->set_hw_config_rom(host, host->csr.rom->bus_info_data);
-               /* Increment the generation number to keep some sort of sync
-                * with the newer ConfigROM manipulation method. */
-               host->csr.generation++;
-               if (host->csr.generation > 0xf || host->csr.generation < 2)
-                       host->csr.generation = 2;
-               ret=0;
-        }
-        spin_unlock_irqrestore(&host->csr.lock, flags);
-        return ret;
-}
-
-
-/* Read topology / speed maps and configuration ROM */
-static int read_maps(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                     u64 addr, size_t length, u16 fl)
-{
-       unsigned long flags;
-        int csraddr = addr - CSR_REGISTER_BASE;
-        const char *src;
-
-        spin_lock_irqsave(&host->csr.lock, flags);
-
-       if (csraddr < CSR_SPEED_MAP) {
-                src = ((char *)host->csr.topology_map) + csraddr
-                        - CSR_TOPOLOGY_MAP;
-        } else {
-                src = ((char *)host->csr.speed_map) + csraddr - CSR_SPEED_MAP;
-        }
-
-        memcpy(buffer, src, length);
-        spin_unlock_irqrestore(&host->csr.lock, flags);
-        return RCODE_COMPLETE;
-}
-
-
-#define out if (--length == 0) break
-
-static int read_regs(struct hpsb_host *host, int nodeid, quadlet_t *buf,
-                     u64 addr, size_t length, u16 flags)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-        int oldcycle;
-        quadlet_t ret;
-
-        if ((csraddr | length) & 0x3)
-                return RCODE_TYPE_ERROR;
-
-        length /= 4;
-
-        switch (csraddr) {
-        case CSR_STATE_CLEAR:
-                *(buf++) = cpu_to_be32(host->csr.state);
-                out;
-        case CSR_STATE_SET:
-                *(buf++) = cpu_to_be32(host->csr.state);
-                out;
-        case CSR_NODE_IDS:
-                *(buf++) = cpu_to_be32(host->csr.node_ids);
-                out;
-
-        case CSR_RESET_START:
-                return RCODE_TYPE_ERROR;
-
-                /* address gap - handled by default below */
-
-        case CSR_SPLIT_TIMEOUT_HI:
-                *(buf++) = cpu_to_be32(host->csr.split_timeout_hi);
-                out;
-        case CSR_SPLIT_TIMEOUT_LO:
-                *(buf++) = cpu_to_be32(host->csr.split_timeout_lo);
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_CYCLE_TIME:
-                oldcycle = host->csr.cycle_time;
-                host->csr.cycle_time =
-                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
-
-                if (oldcycle > host->csr.cycle_time) {
-                        /* cycle time wrapped around */
-                        host->csr.bus_time += 1 << 7;
-                }
-                *(buf++) = cpu_to_be32(host->csr.cycle_time);
-                out;
-        case CSR_BUS_TIME:
-                oldcycle = host->csr.cycle_time;
-                host->csr.cycle_time =
-                        host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
-
-                if (oldcycle > host->csr.cycle_time) {
-                        /* cycle time wrapped around */
-                        host->csr.bus_time += (1 << 7);
-                }
-                *(buf++) = cpu_to_be32(host->csr.bus_time
-                                       | (host->csr.cycle_time >> 25));
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUSY_TIMEOUT:
-                /* not yet implemented */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUS_MANAGER_ID:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 0, 0, 0);
-                else
-                        ret = host->csr.bus_manager_id;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-        case CSR_BANDWIDTH_AVAILABLE:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 1, 0, 0);
-                else
-                        ret = host->csr.bandwidth_available;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-        case CSR_CHANNELS_AVAILABLE_HI:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 2, 0, 0);
-                else
-                        ret = host->csr.channels_available_hi;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-        case CSR_CHANNELS_AVAILABLE_LO:
-                if (host->driver->hw_csr_reg)
-                        ret = host->driver->hw_csr_reg(host, 3, 0, 0);
-                else
-                        ret = host->csr.channels_available_lo;
-
-                *(buf++) = cpu_to_be32(ret);
-                out;
-
-       case CSR_BROADCAST_CHANNEL:
-               *(buf++) = cpu_to_be32(host->csr.broadcast_channel);
-               out;
-
-                /* address gap to end - fall through to default */
-        default:
-                return RCODE_ADDRESS_ERROR;
-        }
-
-        return RCODE_COMPLETE;
-}
-
-static int write_regs(struct hpsb_host *host, int nodeid, int destid,
-                     quadlet_t *data, u64 addr, size_t length, u16 flags)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-
-        if ((csraddr | length) & 0x3)
-                return RCODE_TYPE_ERROR;
-
-        length /= 4;
-
-        switch (csraddr) {
-        case CSR_STATE_CLEAR:
-                /* FIXME FIXME FIXME */
-                printk("doh, someone wants to mess with state clear\n");
-                out;
-        case CSR_STATE_SET:
-                printk("doh, someone wants to mess with state set\n");
-                out;
-
-        case CSR_NODE_IDS:
-                host->csr.node_ids &= NODE_MASK << 16;
-                host->csr.node_ids |= be32_to_cpu(*(data++)) & (BUS_MASK << 16);
-                host->node_id = host->csr.node_ids >> 16;
-                host->driver->devctl(host, SET_BUS_ID, host->node_id >> 6);
-                out;
-
-        case CSR_RESET_START:
-                /* FIXME - perform command reset */
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_SPLIT_TIMEOUT_HI:
-                host->csr.split_timeout_hi =
-                        be32_to_cpu(*(data++)) & 0x00000007;
-               calculate_expire(&host->csr);
-                out;
-        case CSR_SPLIT_TIMEOUT_LO:
-                host->csr.split_timeout_lo =
-                        be32_to_cpu(*(data++)) & 0xfff80000;
-               calculate_expire(&host->csr);
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_CYCLE_TIME:
-                /* should only be set by cycle start packet, automatically */
-                host->csr.cycle_time = be32_to_cpu(*data);
-                host->driver->devctl(host, SET_CYCLE_COUNTER,
-                                       be32_to_cpu(*(data++)));
-                out;
-        case CSR_BUS_TIME:
-                host->csr.bus_time = be32_to_cpu(*(data++)) & 0xffffff80;
-                out;
-
-                /* address gap */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUSY_TIMEOUT:
-                /* not yet implemented */
-                return RCODE_ADDRESS_ERROR;
-
-        case CSR_BUS_MANAGER_ID:
-        case CSR_BANDWIDTH_AVAILABLE:
-        case CSR_CHANNELS_AVAILABLE_HI:
-        case CSR_CHANNELS_AVAILABLE_LO:
-                /* these are not writable, only lockable */
-                return RCODE_TYPE_ERROR;
-
-       case CSR_BROADCAST_CHANNEL:
-               /* only the valid bit can be written */
-               host->csr.broadcast_channel = (host->csr.broadcast_channel & ~0x40000000)
-                        | (be32_to_cpu(*data) & 0x40000000);
-               out;
-
-                /* address gap to end - fall through */
-        default:
-                return RCODE_ADDRESS_ERROR;
-        }
-
-        return RCODE_COMPLETE;
-}
-
-#undef out
-
-
-static int lock_regs(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                     u64 addr, quadlet_t data, quadlet_t arg, int extcode, u16 fl)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-        unsigned long flags;
-        quadlet_t *regptr = NULL;
-
-        if (csraddr & 0x3)
-               return RCODE_TYPE_ERROR;
-
-        if (csraddr < CSR_BUS_MANAGER_ID || csraddr > CSR_CHANNELS_AVAILABLE_LO
-            || extcode != EXTCODE_COMPARE_SWAP)
-                goto unsupported_lockreq;
-
-        data = be32_to_cpu(data);
-        arg = be32_to_cpu(arg);
-
-       /* Is somebody releasing the broadcast_channel on us? */
-       if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x1)) {
-               /* Note: this is may not be the right way to handle
-                * the problem, so we should look into the proper way
-                * eventually. */
-               HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
-                         "broadcast channel 31.  Ignoring.",
-                         NODE_BUS_ARGS(host, nodeid));
-
-               data &= ~0x1;   /* keep broadcast channel allocated */
-       }
-
-        if (host->driver->hw_csr_reg) {
-                quadlet_t old;
-
-                old = host->driver->
-                        hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
-                                   data, arg);
-
-                *store = cpu_to_be32(old);
-                return RCODE_COMPLETE;
-        }
-
-        spin_lock_irqsave(&host->csr.lock, flags);
-
-        switch (csraddr) {
-        case CSR_BUS_MANAGER_ID:
-                regptr = &host->csr.bus_manager_id;
-               *store = cpu_to_be32(*regptr);
-               if (*regptr == arg)
-                       *regptr = data;
-                break;
-
-        case CSR_BANDWIDTH_AVAILABLE:
-        {
-                quadlet_t bandwidth;
-                quadlet_t old;
-                quadlet_t new;
-
-                regptr = &host->csr.bandwidth_available;
-                old = *regptr;
-
-                /* bandwidth available algorithm adapted from IEEE 1394a-2000 spec */
-                if (arg > 0x1fff) {
-                        *store = cpu_to_be32(old);     /* change nothing */
-                       break;
-                }
-                data &= 0x1fff;
-                if (arg >= data) {
-                        /* allocate bandwidth */
-                        bandwidth = arg - data;
-                        if (old >= bandwidth) {
-                                new = old - bandwidth;
-                                *store = cpu_to_be32(arg);
-                                *regptr = new;
-                        } else {
-                                *store = cpu_to_be32(old);
-                        }
-                } else {
-                        /* deallocate bandwidth */
-                        bandwidth = data - arg;
-                        if (old + bandwidth < 0x2000) {
-                                new = old + bandwidth;
-                                *store = cpu_to_be32(arg);
-                                *regptr = new;
-                        } else {
-                                *store = cpu_to_be32(old);
-                        }
-                }
-                break;
-        }
-
-        case CSR_CHANNELS_AVAILABLE_HI:
-        {
-                /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */
-                quadlet_t affected_channels = arg ^ data;
-
-                regptr = &host->csr.channels_available_hi;
-
-                if ((arg & affected_channels) == (*regptr & affected_channels)) {
-                        *regptr ^= affected_channels;
-                        *store = cpu_to_be32(arg);
-                } else {
-                        *store = cpu_to_be32(*regptr);
-                }
-
-                break;
-        }
-
-        case CSR_CHANNELS_AVAILABLE_LO:
-        {
-                /* Lock algorithm for CHANNELS_AVAILABLE as recommended by 1394a-2000 */
-                quadlet_t affected_channels = arg ^ data;
-
-                regptr = &host->csr.channels_available_lo;
-
-                if ((arg & affected_channels) == (*regptr & affected_channels)) {
-                        *regptr ^= affected_channels;
-                        *store = cpu_to_be32(arg);
-                } else {
-                        *store = cpu_to_be32(*regptr);
-                }
-                break;
-        }
-        }
-
-        spin_unlock_irqrestore(&host->csr.lock, flags);
-
-        return RCODE_COMPLETE;
-
- unsupported_lockreq:
-        switch (csraddr) {
-        case CSR_STATE_CLEAR:
-        case CSR_STATE_SET:
-        case CSR_RESET_START:
-        case CSR_NODE_IDS:
-        case CSR_SPLIT_TIMEOUT_HI:
-        case CSR_SPLIT_TIMEOUT_LO:
-        case CSR_CYCLE_TIME:
-        case CSR_BUS_TIME:
-       case CSR_BROADCAST_CHANNEL:
-                return RCODE_TYPE_ERROR;
-
-        case CSR_BUSY_TIMEOUT:
-                /* not yet implemented - fall through */
-        default:
-                return RCODE_ADDRESS_ERROR;
-        }
-}
-
-static int lock64_regs(struct hpsb_host *host, int nodeid, octlet_t * store,
-                      u64 addr, octlet_t data, octlet_t arg, int extcode, u16 fl)
-{
-       int csraddr = addr - CSR_REGISTER_BASE;
-       unsigned long flags;
-
-       data = be64_to_cpu(data);
-       arg = be64_to_cpu(arg);
-
-       if (csraddr & 0x3)
-               return RCODE_TYPE_ERROR;
-
-       if (csraddr != CSR_CHANNELS_AVAILABLE
-           || extcode != EXTCODE_COMPARE_SWAP)
-               goto unsupported_lock64req;
-
-       /* Is somebody releasing the broadcast_channel on us? */
-       if (csraddr == CSR_CHANNELS_AVAILABLE_HI && (data & 0x100000000ULL)) {
-               /* Note: this is may not be the right way to handle
-                * the problem, so we should look into the proper way
-                 * eventually. */
-               HPSB_WARN("Node [" NODE_BUS_FMT "] wants to release "
-                         "broadcast channel 31.  Ignoring.",
-                         NODE_BUS_ARGS(host, nodeid));
-
-               data &= ~0x100000000ULL;        /* keep broadcast channel allocated */
-       }
-
-       if (host->driver->hw_csr_reg) {
-               quadlet_t data_hi, data_lo;
-               quadlet_t arg_hi, arg_lo;
-               quadlet_t old_hi, old_lo;
-
-               data_hi = data >> 32;
-               data_lo = data & 0xFFFFFFFF;
-               arg_hi = arg >> 32;
-               arg_lo = arg & 0xFFFFFFFF;
-
-               old_hi = host->driver->hw_csr_reg(host, (csraddr - CSR_BUS_MANAGER_ID) >> 2,
-                                                  data_hi, arg_hi);
-
-               old_lo = host->driver->hw_csr_reg(host, ((csraddr + 4) - CSR_BUS_MANAGER_ID) >> 2,
-                                                  data_lo, arg_lo);
-
-               *store = cpu_to_be64(((octlet_t)old_hi << 32) | old_lo);
-       } else {
-               octlet_t old;
-               octlet_t affected_channels = arg ^ data;
-
-               spin_lock_irqsave(&host->csr.lock, flags);
-
-               old = ((octlet_t)host->csr.channels_available_hi << 32) | host->csr.channels_available_lo;
-
-               if ((arg & affected_channels) == (old & affected_channels)) {
-                       host->csr.channels_available_hi ^= (affected_channels >> 32);
-                       host->csr.channels_available_lo ^= (affected_channels & 0xffffffff);
-                       *store = cpu_to_be64(arg);
-               } else {
-                       *store = cpu_to_be64(old);
-               }
-
-               spin_unlock_irqrestore(&host->csr.lock, flags);
-       }
-
-       /* Is somebody erroneously releasing the broadcast_channel on us? */
-       if (host->csr.channels_available_hi & 0x1)
-               host->csr.channels_available_hi &= ~0x1;
-
-       return RCODE_COMPLETE;
-
- unsupported_lock64req:
-       switch (csraddr) {
-       case CSR_STATE_CLEAR:
-       case CSR_STATE_SET:
-       case CSR_RESET_START:
-       case CSR_NODE_IDS:
-       case CSR_SPLIT_TIMEOUT_HI:
-       case CSR_SPLIT_TIMEOUT_LO:
-       case CSR_CYCLE_TIME:
-       case CSR_BUS_TIME:
-       case CSR_BUS_MANAGER_ID:
-       case CSR_BROADCAST_CHANNEL:
-       case CSR_BUSY_TIMEOUT:
-       case CSR_BANDWIDTH_AVAILABLE:
-               return RCODE_TYPE_ERROR;
-
-       default:
-               return RCODE_ADDRESS_ERROR;
-       }
-}
-
-static int write_fcp(struct hpsb_host *host, int nodeid, int dest,
-                    quadlet_t *data, u64 addr, size_t length, u16 flags)
-{
-        int csraddr = addr - CSR_REGISTER_BASE;
-
-        if (length > 512)
-                return RCODE_TYPE_ERROR;
-
-        switch (csraddr) {
-        case CSR_FCP_COMMAND:
-                highlevel_fcp_request(host, nodeid, 0, (u8 *)data, length);
-                break;
-        case CSR_FCP_RESPONSE:
-                highlevel_fcp_request(host, nodeid, 1, (u8 *)data, length);
-                break;
-        default:
-                return RCODE_TYPE_ERROR;
-        }
-
-        return RCODE_COMPLETE;
-}
-
-static int read_config_rom(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                          u64 addr, size_t length, u16 fl)
-{
-       u32 offset = addr - CSR1212_REGISTER_SPACE_BASE;
-
-       if (csr1212_read(host->csr.rom, offset, buffer, length) == CSR1212_SUCCESS)
-               return RCODE_COMPLETE;
-       else
-               return RCODE_ADDRESS_ERROR;
-}
-
-static u64 allocate_addr_range(u64 size, u32 alignment, void *__host)
-{
-       struct hpsb_host *host = (struct hpsb_host*)__host;
-
-       return hpsb_allocate_and_register_addrspace(&csr_highlevel,
-                                                   host,
-                                                   &config_rom_ops,
-                                                   size, alignment,
-                                                   CSR1212_UNITS_SPACE_BASE,
-                                                   CSR1212_UNITS_SPACE_END);
-}
-
-static void release_addr_range(u64 addr, void *__host)
-{
-       struct hpsb_host *host = (struct hpsb_host*)__host;
-       hpsb_unregister_addrspace(&csr_highlevel, host, addr);
-}
-
-
-int init_csr(void)
-{
-       node_cap = csr1212_new_immediate(CSR1212_KV_ID_NODE_CAPABILITIES, 0x0083c0);
-       if (!node_cap) {
-               HPSB_ERR("Failed to allocate memory for Node Capabilties ConfigROM entry!");
-               return -ENOMEM;
-       }
-
-       hpsb_register_highlevel(&csr_highlevel);
-
-       return 0;
-}
-
-void cleanup_csr(void)
-{
-       if (node_cap)
-               csr1212_release_keyval(node_cap);
-        hpsb_unregister_highlevel(&csr_highlevel);
-}
diff --git a/drivers/ieee1394/csr.h b/drivers/ieee1394/csr.h
deleted file mode 100644 (file)
index 90fb3f2..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef _IEEE1394_CSR_H
-#define _IEEE1394_CSR_H
-
-#include <linux/spinlock_types.h>
-
-#include "csr1212.h"
-#include "ieee1394_types.h"
-
-#define CSR_REGISTER_BASE              0xfffff0000000ULL
-
-/* register offsets relative to CSR_REGISTER_BASE */
-#define CSR_STATE_CLEAR                        0x0
-#define CSR_STATE_SET                  0x4
-#define CSR_NODE_IDS                   0x8
-#define CSR_RESET_START                        0xc
-#define CSR_SPLIT_TIMEOUT_HI           0x18
-#define CSR_SPLIT_TIMEOUT_LO           0x1c
-#define CSR_CYCLE_TIME                 0x200
-#define CSR_BUS_TIME                   0x204
-#define CSR_BUSY_TIMEOUT               0x210
-#define CSR_BUS_MANAGER_ID             0x21c
-#define CSR_BANDWIDTH_AVAILABLE                0x220
-#define CSR_CHANNELS_AVAILABLE         0x224
-#define CSR_CHANNELS_AVAILABLE_HI      0x224
-#define CSR_CHANNELS_AVAILABLE_LO      0x228
-#define CSR_BROADCAST_CHANNEL          0x234
-#define CSR_CONFIG_ROM                 0x400
-#define CSR_CONFIG_ROM_END             0x800
-#define CSR_FCP_COMMAND                        0xB00
-#define CSR_FCP_RESPONSE               0xD00
-#define CSR_FCP_END                    0xF00
-#define CSR_TOPOLOGY_MAP               0x1000
-#define CSR_TOPOLOGY_MAP_END           0x1400
-#define CSR_SPEED_MAP                  0x2000
-#define CSR_SPEED_MAP_END              0x3000
-
-/* IEEE 1394 bus specific Configuration ROM Key IDs */
-#define IEEE1394_KV_ID_POWER_REQUIREMENTS (0x30)
-
-/* IEEE 1394 Bus Information Block specifics */
-#define CSR_BUS_INFO_SIZE (5 * sizeof(quadlet_t))
-
-#define CSR_IRMC_SHIFT                 31
-#define CSR_CMC_SHIFT                  30
-#define CSR_ISC_SHIFT                  29
-#define CSR_BMC_SHIFT                  28
-#define CSR_PMC_SHIFT                  27
-#define CSR_CYC_CLK_ACC_SHIFT          16
-#define CSR_MAX_REC_SHIFT              12
-#define CSR_MAX_ROM_SHIFT              8
-#define CSR_GENERATION_SHIFT           4
-
-static inline void csr_set_bus_info_generation(struct csr1212_csr *csr, u8 gen)
-{
-       csr->bus_info_data[2] &= ~cpu_to_be32(0xf << CSR_GENERATION_SHIFT);
-       csr->bus_info_data[2] |= cpu_to_be32((u32)gen << CSR_GENERATION_SHIFT);
-}
-
-struct csr_control {
-       spinlock_t lock;
-
-       quadlet_t state;
-       quadlet_t node_ids;
-       quadlet_t split_timeout_hi, split_timeout_lo;
-       unsigned long expire;   /* Calculated from split_timeout */
-       quadlet_t cycle_time;
-       quadlet_t bus_time;
-       quadlet_t bus_manager_id;
-       quadlet_t bandwidth_available;
-       quadlet_t channels_available_hi, channels_available_lo;
-       quadlet_t broadcast_channel;
-
-       /* Bus Info */
-       quadlet_t guid_hi, guid_lo;
-       u8 cyc_clk_acc;
-       u8 max_rec;
-       u8 max_rom;
-       u8 generation;  /* Only use values between 0x2 and 0xf */
-       u8 lnk_spd;
-
-       unsigned long gen_timestamp[16];
-
-       struct csr1212_csr *rom;
-
-       quadlet_t topology_map[256];
-       quadlet_t speed_map[1024];
-};
-
-extern struct csr1212_bus_ops csr_bus_ops;
-
-int init_csr(void);
-void cleanup_csr(void);
-
-/* hpsb_update_config_rom() is deprecated */
-struct hpsb_host;
-int hpsb_update_config_rom(struct hpsb_host *host, const quadlet_t *new_rom,
-                          size_t size, unsigned char rom_version);
-
-#endif /* _IEEE1394_CSR_H */
diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
deleted file mode 100644 (file)
index e76cac6..0000000
+++ /dev/null
@@ -1,1467 +0,0 @@
-/*
- * csr1212.c -- IEEE 1212 Control and Status Register support for Linux
- *
- * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
- *                    Steve Kinneberg <kinnebergsteve@acmsystems.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *    1. Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *    2. Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *    3. The name of the author may not be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-
-/* TODO List:
- * - Verify interface consistency: i.e., public functions that take a size
- *   parameter expect size to be in bytes.
- */
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/kmemcheck.h>
-#include <linux/string.h>
-#include <asm/bug.h>
-#include <asm/byteorder.h>
-
-#include "csr1212.h"
-
-
-/* Permitted key type for each key id */
-#define __I (1 << CSR1212_KV_TYPE_IMMEDIATE)
-#define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET)
-#define __D (1 << CSR1212_KV_TYPE_DIRECTORY)
-#define __L (1 << CSR1212_KV_TYPE_LEAF)
-static const u8 csr1212_key_id_type_map[0x30] = {
-       __C,                    /* used by Apple iSight */
-       __D | __L,              /* Descriptor */
-       __I | __D | __L,        /* Bus_Dependent_Info */
-       __I | __D | __L,        /* Vendor */
-       __I,                    /* Hardware_Version */
-       0, 0,                   /* Reserved */
-       __D | __L | __I,        /* Module */
-       __I, 0, 0, 0,           /* used by Apple iSight, Reserved */
-       __I,                    /* Node_Capabilities */
-       __L,                    /* EUI_64 */
-       0, 0, 0,                /* Reserved */
-       __D,                    /* Unit */
-       __I,                    /* Specifier_ID */
-       __I,                    /* Version */
-       __I | __C | __D | __L,  /* Dependent_Info */
-       __L,                    /* Unit_Location */
-       0,                      /* Reserved */
-       __I,                    /* Model */
-       __D,                    /* Instance */
-       __L,                    /* Keyword */
-       __D,                    /* Feature */
-       __L,                    /* Extended_ROM */
-       __I,                    /* Extended_Key_Specifier_ID */
-       __I,                    /* Extended_Key */
-       __I | __C | __D | __L,  /* Extended_Data */
-       __L,                    /* Modifiable_Descriptor */
-       __I,                    /* Directory_ID */
-       __I,                    /* Revision */
-};
-#undef __I
-#undef __C
-#undef __D
-#undef __L
-
-
-#define quads_to_bytes(_q) ((_q) * sizeof(u32))
-#define bytes_to_quads(_b) DIV_ROUND_UP(_b, sizeof(u32))
-
-static void free_keyval(struct csr1212_keyval *kv)
-{
-       if ((kv->key.type == CSR1212_KV_TYPE_LEAF) &&
-           (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM))
-               CSR1212_FREE(kv->value.leaf.data);
-
-       CSR1212_FREE(kv);
-}
-
-static u16 csr1212_crc16(const u32 *buffer, size_t length)
-{
-       int shift;
-       u32 data;
-       u16 sum, crc = 0;
-
-       for (; length; length--) {
-               data = be32_to_cpu(*buffer);
-               buffer++;
-               for (shift = 28; shift >= 0; shift -= 4 ) {
-                       sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
-                       crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
-               }
-               crc &= 0xffff;
-       }
-
-       return cpu_to_be16(crc);
-}
-
-/* Microsoft computes the CRC with the bytes in reverse order. */
-static u16 csr1212_msft_crc16(const u32 *buffer, size_t length)
-{
-       int shift;
-       u32 data;
-       u16 sum, crc = 0;
-
-       for (; length; length--) {
-               data = le32_to_cpu(*buffer);
-               buffer++;
-               for (shift = 28; shift >= 0; shift -= 4 ) {
-                       sum = ((crc >> 12) ^ (data >> shift)) & 0xf;
-                       crc = (crc << 4) ^ (sum << 12) ^ (sum << 5) ^ (sum);
-               }
-               crc &= 0xffff;
-       }
-
-       return cpu_to_be16(crc);
-}
-
-static struct csr1212_dentry *
-csr1212_find_keyval(struct csr1212_keyval *dir, struct csr1212_keyval *kv)
-{
-       struct csr1212_dentry *pos;
-
-       for (pos = dir->value.directory.dentries_head;
-            pos != NULL; pos = pos->next)
-               if (pos->kv == kv)
-                       return pos;
-       return NULL;
-}
-
-static struct csr1212_keyval *
-csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, u32 offset)
-{
-       struct csr1212_keyval *kv;
-
-       for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next)
-               if (kv->offset == offset)
-                       return kv;
-       return NULL;
-}
-
-
-/* Creation Routines */
-
-struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
-                                      size_t bus_info_size, void *private)
-{
-       struct csr1212_csr *csr;
-
-       csr = CSR1212_MALLOC(sizeof(*csr));
-       if (!csr)
-               return NULL;
-
-       csr->cache_head =
-               csr1212_rom_cache_malloc(CSR1212_CONFIG_ROM_SPACE_OFFSET,
-                                        CSR1212_CONFIG_ROM_SPACE_SIZE);
-       if (!csr->cache_head) {
-               CSR1212_FREE(csr);
-               return NULL;
-       }
-
-       /* The keyval key id is not used for the root node, but a valid key id
-        * that can be used for a directory needs to be passed to
-        * csr1212_new_directory(). */
-       csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
-       if (!csr->root_kv) {
-               CSR1212_FREE(csr->cache_head);
-               CSR1212_FREE(csr);
-               return NULL;
-       }
-
-       csr->bus_info_data = csr->cache_head->data;
-       csr->bus_info_len = bus_info_size;
-       csr->crc_len = bus_info_size;
-       csr->ops = ops;
-       csr->private = private;
-       csr->cache_tail = csr->cache_head;
-
-       return csr;
-}
-
-void csr1212_init_local_csr(struct csr1212_csr *csr,
-                           const u32 *bus_info_data, int max_rom)
-{
-       static const int mr_map[] = { 4, 64, 1024, 0 };
-
-       BUG_ON(max_rom & ~0x3);
-       csr->max_rom = mr_map[max_rom];
-       memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len);
-}
-
-static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key)
-{
-       struct csr1212_keyval *kv;
-
-       if (key < 0x30 && ((csr1212_key_id_type_map[key] & (1 << type)) == 0))
-               return NULL;
-
-       kv = CSR1212_MALLOC(sizeof(*kv));
-       if (!kv)
-               return NULL;
-
-       atomic_set(&kv->refcnt, 1);
-       kv->key.type = type;
-       kv->key.id = key;
-       kv->associate = NULL;
-       kv->next = NULL;
-       kv->prev = NULL;
-       kv->offset = 0;
-       kv->valid = 0;
-       return kv;
-}
-
-struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key);
-       if (!kv)
-               return NULL;
-
-       kv->value.immediate = value;
-       kv->valid = 1;
-       return kv;
-}
-
-static struct csr1212_keyval *
-csr1212_new_leaf(u8 key, const void *data, size_t data_len)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key);
-       if (!kv)
-               return NULL;
-
-       if (data_len > 0) {
-               kv->value.leaf.data = CSR1212_MALLOC(data_len);
-               if (!kv->value.leaf.data) {
-                       CSR1212_FREE(kv);
-                       return NULL;
-               }
-
-               if (data)
-                       memcpy(kv->value.leaf.data, data, data_len);
-       } else {
-               kv->value.leaf.data = NULL;
-       }
-
-       kv->value.leaf.len = bytes_to_quads(data_len);
-       kv->offset = 0;
-       kv->valid = 1;
-
-       return kv;
-}
-
-static struct csr1212_keyval *
-csr1212_new_csr_offset(u8 key, u32 csr_offset)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key);
-       if (!kv)
-               return NULL;
-
-       kv->value.csr_offset = csr_offset;
-
-       kv->offset = 0;
-       kv->valid = 1;
-       return kv;
-}
-
-struct csr1212_keyval *csr1212_new_directory(u8 key)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key);
-       if (!kv)
-               return NULL;
-
-       kv->value.directory.len = 0;
-       kv->offset = 0;
-       kv->value.directory.dentries_head = NULL;
-       kv->value.directory.dentries_tail = NULL;
-       kv->valid = 1;
-       return kv;
-}
-
-void csr1212_associate_keyval(struct csr1212_keyval *kv,
-                             struct csr1212_keyval *associate)
-{
-       BUG_ON(!kv || !associate || kv->key.id == CSR1212_KV_ID_DESCRIPTOR ||
-              (associate->key.id != CSR1212_KV_ID_DESCRIPTOR &&
-               associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_KEY &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_DATA &&
-               associate->key.id < 0x30) ||
-              (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) ||
-              (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
-               associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) ||
-              (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY &&
-               kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) ||
-              (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA &&
-               kv->key.id != CSR1212_KV_ID_EXTENDED_KEY));
-
-       if (kv->associate)
-               csr1212_release_keyval(kv->associate);
-
-       csr1212_keep_keyval(associate);
-       kv->associate = associate;
-}
-
-static int __csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
-                                               struct csr1212_keyval *kv,
-                                               bool keep_keyval)
-{
-       struct csr1212_dentry *dentry;
-
-       BUG_ON(!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY);
-
-       dentry = CSR1212_MALLOC(sizeof(*dentry));
-       if (!dentry)
-               return -ENOMEM;
-
-       if (keep_keyval)
-               csr1212_keep_keyval(kv);
-       dentry->kv = kv;
-
-       dentry->next = NULL;
-       dentry->prev = dir->value.directory.dentries_tail;
-
-       if (!dir->value.directory.dentries_head)
-               dir->value.directory.dentries_head = dentry;
-
-       if (dir->value.directory.dentries_tail)
-               dir->value.directory.dentries_tail->next = dentry;
-       dir->value.directory.dentries_tail = dentry;
-
-       return CSR1212_SUCCESS;
-}
-
-int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
-                                      struct csr1212_keyval *kv)
-{
-       return __csr1212_attach_keyval_to_directory(dir, kv, true);
-}
-
-#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \
-       (&((kv)->value.leaf.data[1]))
-
-#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \
-       ((kv)->value.leaf.data[0] = \
-        cpu_to_be32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \
-                    ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)))
-#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \
-       ((kv)->value.leaf.data[0] = \
-        cpu_to_be32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \
-                     CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \
-                    ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)))
-
-static struct csr1212_keyval *
-csr1212_new_descriptor_leaf(u8 dtype, u32 specifier_id,
-                           const void *data, size_t data_len)
-{
-       struct csr1212_keyval *kv;
-
-       kv = csr1212_new_leaf(CSR1212_KV_ID_DESCRIPTOR, NULL,
-                             data_len + CSR1212_DESCRIPTOR_LEAF_OVERHEAD);
-       if (!kv)
-               return NULL;
-
-       kmemcheck_annotate_variable(kv->value.leaf.data[0]);
-       CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype);
-       CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id);
-
-       if (data)
-               memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len);
-
-       return kv;
-}
-
-/* Check if string conforms to minimal ASCII as per IEEE 1212 clause 7.4 */
-static int csr1212_check_minimal_ascii(const char *s)
-{
-       static const char minimal_ascii_table[] = {
-                                       /*  1   2   4   8  16  32  64  128 */
-               128,                    /* --, --, --, --, --, --, --, 07, */
-               4 + 16 + 32,            /* --, --, 0a, --, 0C, 0D, --, --, */
-               0,                      /* --, --, --, --, --, --, --, --, */
-               0,                      /* --, --, --, --, --, --, --, --, */
-               255 - 8 - 16,           /* 20, 21, 22, --, --, 25, 26, 27, */
-               255,                    /* 28, 29, 2a, 2b, 2c, 2d, 2e, 2f, */
-               255,                    /* 30, 31, 32, 33, 34, 35, 36, 37, */
-               255,                    /* 38, 39, 3a, 3b, 3c, 3d, 3e, 3f, */
-               255,                    /* 40, 41, 42, 43, 44, 45, 46, 47, */
-               255,                    /* 48, 49, 4a, 4b, 4c, 4d, 4e, 4f, */
-               255,                    /* 50, 51, 52, 53, 54, 55, 56, 57, */
-               1 + 2 + 4 + 128,        /* 58, 59, 5a, --, --, --, --, 5f, */
-               255 - 1,                /* --, 61, 62, 63, 64, 65, 66, 67, */
-               255,                    /* 68, 69, 6a, 6b, 6c, 6d, 6e, 6f, */
-               255,                    /* 70, 71, 72, 73, 74, 75, 76, 77, */
-               1 + 2 + 4,              /* 78, 79, 7a, --, --, --, --, --, */
-       };
-       int i, j;
-
-       for (; *s; s++) {
-               i = *s >> 3;            /*  i = *s / 8;         */
-               j = 1 << (*s & 3);      /*  j = 1 << (*s % 8);  */
-
-               if (i >= ARRAY_SIZE(minimal_ascii_table) ||
-                   !(minimal_ascii_table[i] & j))
-                       return -EINVAL;
-       }
-       return 0;
-}
-
-/* IEEE 1212 clause 7.5.4.1 textual descriptors (English, minimal ASCII) */
-struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s)
-{
-       struct csr1212_keyval *kv;
-       u32 *text;
-       size_t str_len, quads;
-
-       if (!s || !*s || csr1212_check_minimal_ascii(s))
-               return NULL;
-
-       str_len = strlen(s);
-       quads = bytes_to_quads(str_len);
-       kv = csr1212_new_descriptor_leaf(0, 0, NULL, quads_to_bytes(quads) +
-                                     CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD);
-       if (!kv)
-               return NULL;
-
-       kv->value.leaf.data[1] = 0;     /* width, character_set, language */
-       text = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv);
-       text[quads - 1] = 0;            /* padding */
-       memcpy(text, s, str_len);
-
-       return kv;
-}
-
-
-/* Destruction Routines */
-
-void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
-                                         struct csr1212_keyval *kv)
-{
-       struct csr1212_dentry *dentry;
-
-       if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)
-               return;
-
-       dentry = csr1212_find_keyval(dir, kv);
-
-       if (!dentry)
-               return;
-
-       if (dentry->prev)
-               dentry->prev->next = dentry->next;
-       if (dentry->next)
-               dentry->next->prev = dentry->prev;
-       if (dir->value.directory.dentries_head == dentry)
-               dir->value.directory.dentries_head = dentry->next;
-       if (dir->value.directory.dentries_tail == dentry)
-               dir->value.directory.dentries_tail = dentry->prev;
-
-       CSR1212_FREE(dentry);
-
-       csr1212_release_keyval(kv);
-}
-
-/* This function is used to free the memory taken by a keyval.  If the given
- * keyval is a directory type, then any keyvals contained in that directory
- * will be destroyed as well if noone holds a reference on them.  By means of
- * list manipulation, this routine will descend a directory structure in a
- * non-recursive manner. */
-void csr1212_release_keyval(struct csr1212_keyval *kv)
-{
-       struct csr1212_keyval *k, *a;
-       struct csr1212_dentry dentry;
-       struct csr1212_dentry *head, *tail;
-
-       if (!atomic_dec_and_test(&kv->refcnt))
-               return;
-
-       dentry.kv = kv;
-       dentry.next = NULL;
-       dentry.prev = NULL;
-
-       head = &dentry;
-       tail = head;
-
-       while (head) {
-               k = head->kv;
-
-               while (k) {
-                       /* must not dec_and_test kv->refcnt again */
-                       if (k != kv && !atomic_dec_and_test(&k->refcnt))
-                               break;
-
-                       a = k->associate;
-
-                       if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {
-                               /* If the current entry is a directory, move all
-                                * the entries to the destruction list. */
-                               if (k->value.directory.dentries_head) {
-                                       tail->next =
-                                           k->value.directory.dentries_head;
-                                       k->value.directory.dentries_head->prev =
-                                           tail;
-                                       tail = k->value.directory.dentries_tail;
-                               }
-                       }
-                       free_keyval(k);
-                       k = a;
-               }
-
-               head = head->next;
-               if (head) {
-                       if (head->prev && head->prev != &dentry)
-                               CSR1212_FREE(head->prev);
-                       head->prev = NULL;
-               } else if (tail != &dentry) {
-                       CSR1212_FREE(tail);
-               }
-       }
-}
-
-void csr1212_destroy_csr(struct csr1212_csr *csr)
-{
-       struct csr1212_csr_rom_cache *c, *oc;
-       struct csr1212_cache_region *cr, *ocr;
-
-       csr1212_release_keyval(csr->root_kv);
-
-       c = csr->cache_head;
-       while (c) {
-               oc = c;
-               cr = c->filled_head;
-               while (cr) {
-                       ocr = cr;
-                       cr = cr->next;
-                       CSR1212_FREE(ocr);
-               }
-               c = c->next;
-               CSR1212_FREE(oc);
-       }
-
-       CSR1212_FREE(csr);
-}
-
-
-/* CSR Image Creation */
-
-static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize)
-{
-       struct csr1212_csr_rom_cache *cache;
-       u64 csr_addr;
-
-       BUG_ON(!csr || !csr->ops || !csr->ops->allocate_addr_range ||
-              !csr->ops->release_addr || csr->max_rom < 1);
-
-       /* ROM size must be a multiple of csr->max_rom */
-       romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);
-
-       csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom,
-                                                csr->private);
-       if (csr_addr == CSR1212_INVALID_ADDR_SPACE)
-               return -ENOMEM;
-
-       if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {
-               /* Invalid address returned from allocate_addr_range(). */
-               csr->ops->release_addr(csr_addr, csr->private);
-               return -ENOMEM;
-       }
-
-       cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE,
-                                        romsize);
-       if (!cache) {
-               csr->ops->release_addr(csr_addr, csr->private);
-               return -ENOMEM;
-       }
-
-       cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF,
-                                           CSR1212_KV_ID_EXTENDED_ROM);
-       if (!cache->ext_rom) {
-               csr->ops->release_addr(csr_addr, csr->private);
-               CSR1212_FREE(cache);
-               return -ENOMEM;
-       }
-
-       if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) !=
-           CSR1212_SUCCESS) {
-               csr1212_release_keyval(cache->ext_rom);
-               csr->ops->release_addr(csr_addr, csr->private);
-               CSR1212_FREE(cache);
-               return -ENOMEM;
-       }
-       cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
-       cache->ext_rom->value.leaf.len = -1;
-       cache->ext_rom->value.leaf.data = cache->data;
-
-       /* Add cache to tail of cache list */
-       cache->prev = csr->cache_tail;
-       csr->cache_tail->next = cache;
-       csr->cache_tail = cache;
-       return CSR1212_SUCCESS;
-}
-
-static void csr1212_remove_cache(struct csr1212_csr *csr,
-                                struct csr1212_csr_rom_cache *cache)
-{
-       if (csr->cache_head == cache)
-               csr->cache_head = cache->next;
-       if (csr->cache_tail == cache)
-               csr->cache_tail = cache->prev;
-
-       if (cache->prev)
-               cache->prev->next = cache->next;
-       if (cache->next)
-               cache->next->prev = cache->prev;
-
-       if (cache->ext_rom) {
-               csr1212_detach_keyval_from_directory(csr->root_kv,
-                                                    cache->ext_rom);
-               csr1212_release_keyval(cache->ext_rom);
-       }
-
-       CSR1212_FREE(cache);
-}
-
-static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,
-                                         struct csr1212_keyval **layout_tail)
-{
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *dkv;
-       struct csr1212_keyval *last_extkey_spec = NULL;
-       struct csr1212_keyval *last_extkey = NULL;
-       int num_entries = 0;
-
-       for (dentry = dir->value.directory.dentries_head; dentry;
-            dentry = dentry->next) {
-               for (dkv = dentry->kv; dkv; dkv = dkv->associate) {
-                       /* Special Case: Extended Key Specifier_ID */
-                       if (dkv->key.id ==
-                           CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
-                               if (last_extkey_spec == NULL)
-                                       last_extkey_spec = dkv;
-                               else if (dkv->value.immediate !=
-                                        last_extkey_spec->value.immediate)
-                                       last_extkey_spec = dkv;
-                               else
-                                       continue;
-                       /* Special Case: Extended Key */
-                       } else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
-                               if (last_extkey == NULL)
-                                       last_extkey = dkv;
-                               else if (dkv->value.immediate !=
-                                        last_extkey->value.immediate)
-                                       last_extkey = dkv;
-                               else
-                                       continue;
-                       }
-
-                       num_entries += 1;
-
-                       switch (dkv->key.type) {
-                       default:
-                       case CSR1212_KV_TYPE_IMMEDIATE:
-                       case CSR1212_KV_TYPE_CSR_OFFSET:
-                               break;
-                       case CSR1212_KV_TYPE_LEAF:
-                       case CSR1212_KV_TYPE_DIRECTORY:
-                               /* Remove from list */
-                               if (dkv->prev && (dkv->prev->next == dkv))
-                                       dkv->prev->next = dkv->next;
-                               if (dkv->next && (dkv->next->prev == dkv))
-                                       dkv->next->prev = dkv->prev;
-                               //if (dkv == *layout_tail)
-                               //      *layout_tail = dkv->prev;
-
-                               /* Special case: Extended ROM leafs */
-                               if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
-                                       dkv->value.leaf.len = -1;
-                                       /* Don't add Extended ROM leafs in the
-                                        * layout list, they are handled
-                                        * differently. */
-                                       break;
-                               }
-
-                               /* Add to tail of list */
-                               dkv->next = NULL;
-                               dkv->prev = *layout_tail;
-                               (*layout_tail)->next = dkv;
-                               *layout_tail = dkv;
-                               break;
-                       }
-               }
-       }
-       return num_entries;
-}
-
-static size_t csr1212_generate_layout_order(struct csr1212_keyval *kv)
-{
-       struct csr1212_keyval *ltail = kv;
-       size_t agg_size = 0;
-
-       while (kv) {
-               switch (kv->key.type) {
-               case CSR1212_KV_TYPE_LEAF:
-                       /* Add 1 quadlet for crc/len field */
-                       agg_size += kv->value.leaf.len + 1;
-                       break;
-
-               case CSR1212_KV_TYPE_DIRECTORY:
-                       kv->value.directory.len =
-                               csr1212_generate_layout_subdir(kv, &ltail);
-                       /* Add 1 quadlet for crc/len field */
-                       agg_size += kv->value.directory.len + 1;
-                       break;
-               }
-               kv = kv->next;
-       }
-       return quads_to_bytes(agg_size);
-}
-
-static struct csr1212_keyval *
-csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
-                          struct csr1212_keyval *start_kv, int start_pos)
-{
-       struct csr1212_keyval *kv = start_kv;
-       struct csr1212_keyval *okv = start_kv;
-       int pos = start_pos;
-       int kv_len = 0, okv_len = 0;
-
-       cache->layout_head = kv;
-
-       while (kv && pos < cache->size) {
-               /* Special case: Extended ROM leafs */
-               if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
-                       kv->offset = cache->offset + pos;
-
-               switch (kv->key.type) {
-               case CSR1212_KV_TYPE_LEAF:
-                       kv_len = kv->value.leaf.len;
-                       break;
-
-               case CSR1212_KV_TYPE_DIRECTORY:
-                       kv_len = kv->value.directory.len;
-                       break;
-
-               default:
-                       /* Should never get here */
-                       WARN_ON(1);
-                       break;
-               }
-
-               pos += quads_to_bytes(kv_len + 1);
-
-               if (pos <= cache->size) {
-                       okv = kv;
-                       okv_len = kv_len;
-                       kv = kv->next;
-               }
-       }
-
-       cache->layout_tail = okv;
-       cache->len = okv->offset - cache->offset + quads_to_bytes(okv_len + 1);
-
-       return kv;
-}
-
-#define CSR1212_KV_KEY_SHIFT           24
-#define CSR1212_KV_KEY_TYPE_SHIFT      6
-#define CSR1212_KV_KEY_ID_MASK         0x3f
-#define CSR1212_KV_KEY_TYPE_MASK       0x3     /* after shift */
-
-static void
-csr1212_generate_tree_subdir(struct csr1212_keyval *dir, u32 *data_buffer)
-{
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *last_extkey_spec = NULL;
-       struct csr1212_keyval *last_extkey = NULL;
-       int index = 0;
-
-       for (dentry = dir->value.directory.dentries_head;
-            dentry;
-            dentry = dentry->next) {
-               struct csr1212_keyval *a;
-
-               for (a = dentry->kv; a; a = a->associate) {
-                       u32 value = 0;
-
-                       /* Special Case: Extended Key Specifier_ID */
-                       if (a->key.id ==
-                           CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {
-                               if (last_extkey_spec == NULL)
-                                       last_extkey_spec = a;
-                               else if (a->value.immediate !=
-                                        last_extkey_spec->value.immediate)
-                                       last_extkey_spec = a;
-                               else
-                                       continue;
-
-                       /* Special Case: Extended Key */
-                       } else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {
-                               if (last_extkey == NULL)
-                                       last_extkey = a;
-                               else if (a->value.immediate !=
-                                        last_extkey->value.immediate)
-                                       last_extkey = a;
-                               else
-                                       continue;
-                       }
-
-                       switch (a->key.type) {
-                       case CSR1212_KV_TYPE_IMMEDIATE:
-                               value = a->value.immediate;
-                               break;
-                       case CSR1212_KV_TYPE_CSR_OFFSET:
-                               value = a->value.csr_offset;
-                               break;
-                       case CSR1212_KV_TYPE_LEAF:
-                               value = a->offset;
-                               value -= dir->offset + quads_to_bytes(1+index);
-                               value = bytes_to_quads(value);
-                               break;
-                       case CSR1212_KV_TYPE_DIRECTORY:
-                               value = a->offset;
-                               value -= dir->offset + quads_to_bytes(1+index);
-                               value = bytes_to_quads(value);
-                               break;
-                       default:
-                               /* Should never get here */
-                               WARN_ON(1);
-                               break;
-                       }
-
-                       value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) <<
-                                CSR1212_KV_KEY_SHIFT;
-                       value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<
-                                (CSR1212_KV_KEY_SHIFT +
-                                 CSR1212_KV_KEY_TYPE_SHIFT);
-                       data_buffer[index] = cpu_to_be32(value);
-                       index++;
-               }
-       }
-}
-
-struct csr1212_keyval_img {
-       u16 length;
-       u16 crc;
-
-       /* Must be last */
-       u32 data[0];    /* older gcc can't handle [] which is standard */
-};
-
-static void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache)
-{
-       struct csr1212_keyval *kv, *nkv;
-       struct csr1212_keyval_img *kvi;
-
-       for (kv = cache->layout_head;
-            kv != cache->layout_tail->next;
-            kv = nkv) {
-               kvi = (struct csr1212_keyval_img *)(cache->data +
-                               bytes_to_quads(kv->offset - cache->offset));
-               switch (kv->key.type) {
-               default:
-               case CSR1212_KV_TYPE_IMMEDIATE:
-               case CSR1212_KV_TYPE_CSR_OFFSET:
-                       /* Should never get here */
-                       WARN_ON(1);
-                       break;
-
-               case CSR1212_KV_TYPE_LEAF:
-                       /* Don't copy over Extended ROM areas, they are
-                        * already filled out! */
-                       if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
-                               memcpy(kvi->data, kv->value.leaf.data,
-                                      quads_to_bytes(kv->value.leaf.len));
-
-                       kvi->length = cpu_to_be16(kv->value.leaf.len);
-                       kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);
-                       break;
-
-               case CSR1212_KV_TYPE_DIRECTORY:
-                       csr1212_generate_tree_subdir(kv, kvi->data);
-
-                       kvi->length = cpu_to_be16(kv->value.directory.len);
-                       kvi->crc = csr1212_crc16(kvi->data,
-                                                kv->value.directory.len);
-                       break;
-               }
-
-               nkv = kv->next;
-               if (kv->prev)
-                       kv->prev->next = NULL;
-               if (kv->next)
-                       kv->next->prev = NULL;
-               kv->prev = NULL;
-               kv->next = NULL;
-       }
-}
-
-/* This size is arbitrarily chosen.
- * The struct overhead is subtracted for more economic allocations. */
-#define CSR1212_EXTENDED_ROM_SIZE (2048 - sizeof(struct csr1212_csr_rom_cache))
-
-int csr1212_generate_csr_image(struct csr1212_csr *csr)
-{
-       struct csr1212_bus_info_block_img *bi;
-       struct csr1212_csr_rom_cache *cache;
-       struct csr1212_keyval *kv;
-       size_t agg_size;
-       int ret;
-       int init_offset;
-
-       BUG_ON(!csr);
-
-       cache = csr->cache_head;
-
-       bi = (struct csr1212_bus_info_block_img*)cache->data;
-
-       bi->length = bytes_to_quads(csr->bus_info_len) - 1;
-       bi->crc_length = bi->length;
-       bi->crc = csr1212_crc16(bi->data, bi->crc_length);
-
-       csr->root_kv->next = NULL;
-       csr->root_kv->prev = NULL;
-
-       agg_size = csr1212_generate_layout_order(csr->root_kv);
-
-       init_offset = csr->bus_info_len;
-
-       for (kv = csr->root_kv, cache = csr->cache_head;
-            kv;
-            cache = cache->next) {
-               if (!cache) {
-                       /* Estimate approximate number of additional cache
-                        * regions needed (it assumes that the cache holding
-                        * the first 1K Config ROM space always exists). */
-                       int est_c = agg_size / (CSR1212_EXTENDED_ROM_SIZE -
-                                               (2 * sizeof(u32))) + 1;
-
-                       /* Add additional cache regions, extras will be
-                        * removed later */
-                       for (; est_c; est_c--) {
-                               ret = csr1212_append_new_cache(csr,
-                                               CSR1212_EXTENDED_ROM_SIZE);
-                               if (ret != CSR1212_SUCCESS)
-                                       return ret;
-                       }
-                       /* Need to re-layout for additional cache regions */
-                       agg_size = csr1212_generate_layout_order(csr->root_kv);
-                       kv = csr->root_kv;
-                       cache = csr->cache_head;
-                       init_offset = csr->bus_info_len;
-               }
-               kv = csr1212_generate_positions(cache, kv, init_offset);
-               agg_size -= cache->len;
-               init_offset = sizeof(u32);
-       }
-
-       /* Remove unused, excess cache regions */
-       while (cache) {
-               struct csr1212_csr_rom_cache *oc = cache;
-
-               cache = cache->next;
-               csr1212_remove_cache(csr, oc);
-       }
-
-       /* Go through the list backward so that when done, the correct CRC
-        * will be calculated for the Extended ROM areas. */
-       for (cache = csr->cache_tail; cache; cache = cache->prev) {
-               /* Only Extended ROM caches should have this set. */
-               if (cache->ext_rom) {
-                       int leaf_size;
-
-                       /* Make sure the Extended ROM leaf is a multiple of
-                        * max_rom in size. */
-                       BUG_ON(csr->max_rom < 1);
-                       leaf_size = (cache->len + (csr->max_rom - 1)) &
-                               ~(csr->max_rom - 1);
-
-                       /* Zero out the unused ROM region */
-                       memset(cache->data + bytes_to_quads(cache->len), 0x00,
-                              leaf_size - cache->len);
-
-                       /* Subtract leaf header */
-                       leaf_size -= sizeof(u32);
-
-                       /* Update the Extended ROM leaf length */
-                       cache->ext_rom->value.leaf.len =
-                               bytes_to_quads(leaf_size);
-               } else {
-                       /* Zero out the unused ROM region */
-                       memset(cache->data + bytes_to_quads(cache->len), 0x00,
-                              cache->size - cache->len);
-               }
-
-               /* Copy the data into the cache buffer */
-               csr1212_fill_cache(cache);
-
-               if (cache != csr->cache_head) {
-                       /* Set the length and CRC of the extended ROM. */
-                       struct csr1212_keyval_img *kvi =
-                               (struct csr1212_keyval_img*)cache->data;
-                       u16 len = bytes_to_quads(cache->len) - 1;
-
-                       kvi->length = cpu_to_be16(len);
-                       kvi->crc = csr1212_crc16(kvi->data, len);
-               }
-       }
-
-       return CSR1212_SUCCESS;
-}
-
-int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer, u32 len)
-{
-       struct csr1212_csr_rom_cache *cache;
-
-       for (cache = csr->cache_head; cache; cache = cache->next)
-               if (offset >= cache->offset &&
-                   (offset + len) <= (cache->offset + cache->size)) {
-                       memcpy(buffer, &cache->data[
-                                       bytes_to_quads(offset - cache->offset)],
-                              len);
-                       return CSR1212_SUCCESS;
-               }
-
-       return -ENOENT;
-}
-
-/*
- * Apparently there are many different wrong implementations of the CRC
- * algorithm.  We don't fail, we just warn... approximately once per GUID.
- */
-static void
-csr1212_check_crc(const u32 *buffer, size_t length, u16 crc, __be32 *guid)
-{
-       static u64 last_bad_eui64;
-       u64 eui64 = ((u64)be32_to_cpu(guid[0]) << 32) | be32_to_cpu(guid[1]);
-
-       if (csr1212_crc16(buffer, length) == crc ||
-           csr1212_msft_crc16(buffer, length) == crc ||
-           eui64 == last_bad_eui64)
-               return;
-
-       printk(KERN_DEBUG "ieee1394: config ROM CRC error\n");
-       last_bad_eui64 = eui64;
-}
-
-/* Parse a chunk of data as a Config ROM */
-
-static int csr1212_parse_bus_info_block(struct csr1212_csr *csr)
-{
-       struct csr1212_bus_info_block_img *bi;
-       struct csr1212_cache_region *cr;
-       int i;
-       int ret;
-
-       for (i = 0; i < csr->bus_info_len; i += sizeof(u32)) {
-               ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
-                               &csr->cache_head->data[bytes_to_quads(i)],
-                               csr->private);
-               if (ret != CSR1212_SUCCESS)
-                       return ret;
-
-               /* check ROM header's info_length */
-               if (i == 0 &&
-                   be32_to_cpu(csr->cache_head->data[0]) >> 24 !=
-                   bytes_to_quads(csr->bus_info_len) - 1)
-                       return -EINVAL;
-       }
-
-       bi = (struct csr1212_bus_info_block_img*)csr->cache_head->data;
-       csr->crc_len = quads_to_bytes(bi->crc_length);
-
-       /* IEEE 1212 recommends that crc_len be equal to bus_info_len, but that
-        * is not always the case, so read the rest of the crc area 1 quadlet at
-        * a time. */
-       for (i = csr->bus_info_len; i <= csr->crc_len; i += sizeof(u32)) {
-               ret = csr->ops->bus_read(csr, CSR1212_CONFIG_ROM_SPACE_BASE + i,
-                               &csr->cache_head->data[bytes_to_quads(i)],
-                               csr->private);
-               if (ret != CSR1212_SUCCESS)
-                       return ret;
-       }
-
-       csr1212_check_crc(bi->data, bi->crc_length, bi->crc,
-                         &csr->bus_info_data[3]);
-
-       cr = CSR1212_MALLOC(sizeof(*cr));
-       if (!cr)
-               return -ENOMEM;
-
-       cr->next = NULL;
-       cr->prev = NULL;
-       cr->offset_start = 0;
-       cr->offset_end = csr->crc_len + 4;
-
-       csr->cache_head->filled_head = cr;
-       csr->cache_head->filled_tail = cr;
-
-       return CSR1212_SUCCESS;
-}
-
-#define CSR1212_KV_KEY(q)      (be32_to_cpu(q) >> CSR1212_KV_KEY_SHIFT)
-#define CSR1212_KV_KEY_TYPE(q) (CSR1212_KV_KEY(q) >> CSR1212_KV_KEY_TYPE_SHIFT)
-#define CSR1212_KV_KEY_ID(q)   (CSR1212_KV_KEY(q) & CSR1212_KV_KEY_ID_MASK)
-#define CSR1212_KV_VAL_MASK    0xffffff
-#define CSR1212_KV_VAL(q)      (be32_to_cpu(q) & CSR1212_KV_VAL_MASK)
-
-static int
-csr1212_parse_dir_entry(struct csr1212_keyval *dir, u32 ki, u32 kv_pos)
-{
-       int ret = CSR1212_SUCCESS;
-       struct csr1212_keyval *k = NULL;
-       u32 offset;
-       bool keep_keyval = true;
-
-       switch (CSR1212_KV_KEY_TYPE(ki)) {
-       case CSR1212_KV_TYPE_IMMEDIATE:
-               k = csr1212_new_immediate(CSR1212_KV_KEY_ID(ki),
-                                         CSR1212_KV_VAL(ki));
-               if (!k) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               /* Don't keep local reference when parsing. */
-               keep_keyval = false;
-               break;
-
-       case CSR1212_KV_TYPE_CSR_OFFSET:
-               k = csr1212_new_csr_offset(CSR1212_KV_KEY_ID(ki),
-                                          CSR1212_KV_VAL(ki));
-               if (!k) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               /* Don't keep local reference when parsing. */
-               keep_keyval = false;
-               break;
-
-       default:
-               /* Compute the offset from 0xffff f000 0000. */
-               offset = quads_to_bytes(CSR1212_KV_VAL(ki)) + kv_pos;
-               if (offset == kv_pos) {
-                       /* Uh-oh.  Can't have a relative offset of 0 for Leaves
-                        * or Directories.  The Config ROM image is most likely
-                        * messed up, so we'll just abort here. */
-                       ret = -EIO;
-                       goto out;
-               }
-
-               k = csr1212_find_keyval_offset(dir, offset);
-
-               if (k)
-                       break;          /* Found it. */
-
-               if (CSR1212_KV_KEY_TYPE(ki) == CSR1212_KV_TYPE_DIRECTORY)
-                       k = csr1212_new_directory(CSR1212_KV_KEY_ID(ki));
-               else
-                       k = csr1212_new_leaf(CSR1212_KV_KEY_ID(ki), NULL, 0);
-
-               if (!k) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
-               /* Don't keep local reference when parsing. */
-               keep_keyval = false;
-               /* Contents not read yet so it's not valid. */
-               k->valid = 0;
-               k->offset = offset;
-
-               k->prev = dir;
-               k->next = dir->next;
-               dir->next->prev = k;
-               dir->next = k;
-       }
-       ret = __csr1212_attach_keyval_to_directory(dir, k, keep_keyval);
-out:
-       if (ret != CSR1212_SUCCESS && k != NULL)
-               free_keyval(k);
-       return ret;
-}
-
-int csr1212_parse_keyval(struct csr1212_keyval *kv,
-                        struct csr1212_csr_rom_cache *cache)
-{
-       struct csr1212_keyval_img *kvi;
-       int i;
-       int ret = CSR1212_SUCCESS;
-       int kvi_len;
-
-       kvi = (struct csr1212_keyval_img*)
-               &cache->data[bytes_to_quads(kv->offset - cache->offset)];
-       kvi_len = be16_to_cpu(kvi->length);
-
-       /* GUID is wrong in here in case of extended ROM.  We don't care. */
-       csr1212_check_crc(kvi->data, kvi_len, kvi->crc, &cache->data[3]);
-
-       switch (kv->key.type) {
-       case CSR1212_KV_TYPE_DIRECTORY:
-               for (i = 0; i < kvi_len; i++) {
-                       u32 ki = kvi->data[i];
-
-                       /* Some devices put null entries in their unit
-                        * directories.  If we come across such an entry,
-                        * then skip it. */
-                       if (ki == 0x0)
-                               continue;
-                       ret = csr1212_parse_dir_entry(kv, ki,
-                                       kv->offset + quads_to_bytes(i + 1));
-               }
-               kv->value.directory.len = kvi_len;
-               break;
-
-       case CSR1212_KV_TYPE_LEAF:
-               if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
-                       size_t size = quads_to_bytes(kvi_len);
-
-                       kv->value.leaf.data = CSR1212_MALLOC(size);
-                       if (!kv->value.leaf.data) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-
-                       kv->value.leaf.len = kvi_len;
-                       memcpy(kv->value.leaf.data, kvi->data, size);
-               }
-               break;
-       }
-
-       kv->valid = 1;
-out:
-       return ret;
-}
-
-static int
-csr1212_read_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
-{
-       struct csr1212_cache_region *cr, *ncr, *newcr = NULL;
-       struct csr1212_keyval_img *kvi = NULL;
-       struct csr1212_csr_rom_cache *cache;
-       int cache_index;
-       u64 addr;
-       u32 *cache_ptr;
-       u16 kv_len = 0;
-
-       BUG_ON(!csr || !kv || csr->max_rom < 1);
-
-       /* First find which cache the data should be in (or go in if not read
-        * yet). */
-       for (cache = csr->cache_head; cache; cache = cache->next)
-               if (kv->offset >= cache->offset &&
-                   kv->offset < (cache->offset + cache->size))
-                       break;
-
-       if (!cache) {
-               u32 q, cache_size;
-
-               /* Only create a new cache for Extended ROM leaves. */
-               if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
-                       return -EINVAL;
-
-               if (csr->ops->bus_read(csr,
-                                      CSR1212_REGISTER_SPACE_BASE + kv->offset,
-                                      &q, csr->private))
-                       return -EIO;
-
-               kv->value.leaf.len = be32_to_cpu(q) >> 16;
-
-               cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
-                             (csr->max_rom - 1)) & ~(csr->max_rom - 1);
-
-               cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
-               if (!cache)
-                       return -ENOMEM;
-
-               kv->value.leaf.data = &cache->data[1];
-               csr->cache_tail->next = cache;
-               cache->prev = csr->cache_tail;
-               cache->next = NULL;
-               csr->cache_tail = cache;
-               cache->filled_head =
-                       CSR1212_MALLOC(sizeof(*cache->filled_head));
-               if (!cache->filled_head)
-                       return -ENOMEM;
-
-               cache->filled_head->offset_start = 0;
-               cache->filled_head->offset_end = sizeof(u32);
-               cache->filled_tail = cache->filled_head;
-               cache->filled_head->next = NULL;
-               cache->filled_head->prev = NULL;
-               cache->data[0] = q;
-
-               /* Don't read the entire extended ROM now.  Pieces of it will
-                * be read when entries inside it are read. */
-               return csr1212_parse_keyval(kv, cache);
-       }
-
-       cache_index = kv->offset - cache->offset;
-
-       /* Now seach read portions of the cache to see if it is there. */
-       for (cr = cache->filled_head; cr; cr = cr->next) {
-               if (cache_index < cr->offset_start) {
-                       newcr = CSR1212_MALLOC(sizeof(*newcr));
-                       if (!newcr)
-                               return -ENOMEM;
-
-                       newcr->offset_start = cache_index & ~(csr->max_rom - 1);
-                       newcr->offset_end = newcr->offset_start;
-                       newcr->next = cr;
-                       newcr->prev = cr->prev;
-                       cr->prev = newcr;
-                       cr = newcr;
-                       break;
-               } else if ((cache_index >= cr->offset_start) &&
-                          (cache_index < cr->offset_end)) {
-                       kvi = (struct csr1212_keyval_img*)
-                               (&cache->data[bytes_to_quads(cache_index)]);
-                       kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1);
-                       break;
-               } else if (cache_index == cr->offset_end) {
-                       break;
-               }
-       }
-
-       if (!cr) {
-               cr = cache->filled_tail;
-               newcr = CSR1212_MALLOC(sizeof(*newcr));
-               if (!newcr)
-                       return -ENOMEM;
-
-               newcr->offset_start = cache_index & ~(csr->max_rom - 1);
-               newcr->offset_end = newcr->offset_start;
-               newcr->prev = cr;
-               newcr->next = cr->next;
-               cr->next = newcr;
-               cr = newcr;
-               cache->filled_tail = newcr;
-       }
-
-       while(!kvi || cr->offset_end < cache_index + kv_len) {
-               cache_ptr = &cache->data[bytes_to_quads(cr->offset_end &
-                                                       ~(csr->max_rom - 1))];
-
-               addr = (CSR1212_CSR_ARCH_REG_SPACE_BASE + cache->offset +
-                       cr->offset_end) & ~(csr->max_rom - 1);
-
-               if (csr->ops->bus_read(csr, addr, cache_ptr, csr->private))
-                       return -EIO;
-
-               cr->offset_end += csr->max_rom - (cr->offset_end &
-                                                 (csr->max_rom - 1));
-
-               if (!kvi && (cr->offset_end > cache_index)) {
-                       kvi = (struct csr1212_keyval_img*)
-                               (&cache->data[bytes_to_quads(cache_index)]);
-                       kv_len = quads_to_bytes(be16_to_cpu(kvi->length) + 1);
-               }
-
-               if ((kv_len + (kv->offset - cache->offset)) > cache->size) {
-                       /* The Leaf or Directory claims its length extends
-                        * beyond the ConfigROM image region and thus beyond the
-                        * end of our cache region.  Therefore, we abort now
-                        * rather than seg faulting later. */
-                       return -EIO;
-               }
-
-               ncr = cr->next;
-
-               if (ncr && (cr->offset_end >= ncr->offset_start)) {
-                       /* consolidate region entries */
-                       ncr->offset_start = cr->offset_start;
-
-                       if (cr->prev)
-                               cr->prev->next = cr->next;
-                       ncr->prev = cr->prev;
-                       if (cache->filled_head == cr)
-                               cache->filled_head = ncr;
-                       CSR1212_FREE(cr);
-                       cr = ncr;
-               }
-       }
-
-       return csr1212_parse_keyval(kv, cache);
-}
-
-struct csr1212_keyval *
-csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv)
-{
-       if (!kv)
-               return NULL;
-       if (!kv->valid)
-               if (csr1212_read_keyval(csr, kv) != CSR1212_SUCCESS)
-                       return NULL;
-       return kv;
-}
-
-int csr1212_parse_csr(struct csr1212_csr *csr)
-{
-       struct csr1212_dentry *dentry;
-       int ret;
-
-       BUG_ON(!csr || !csr->ops || !csr->ops->bus_read);
-
-       ret = csr1212_parse_bus_info_block(csr);
-       if (ret != CSR1212_SUCCESS)
-               return ret;
-
-       /*
-        * There has been a buggy firmware with bus_info_block.max_rom > 0
-        * spotted which actually only supported quadlet read requests to the
-        * config ROM.  Therefore read everything quadlet by quadlet regardless
-        * of what the bus info block says.
-        */
-       csr->max_rom = 4;
-
-       csr->cache_head->layout_head = csr->root_kv;
-       csr->cache_head->layout_tail = csr->root_kv;
-
-       csr->root_kv->offset = (CSR1212_CONFIG_ROM_SPACE_BASE & 0xffff) +
-               csr->bus_info_len;
-
-       csr->root_kv->valid = 0;
-       csr->root_kv->next = csr->root_kv;
-       csr->root_kv->prev = csr->root_kv;
-       ret = csr1212_read_keyval(csr, csr->root_kv);
-       if (ret != CSR1212_SUCCESS)
-               return ret;
-
-       /* Scan through the Root directory finding all extended ROM regions
-        * and make cache regions for them */
-       for (dentry = csr->root_kv->value.directory.dentries_head;
-            dentry; dentry = dentry->next) {
-               if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM &&
-                       !dentry->kv->valid) {
-                       ret = csr1212_read_keyval(csr, dentry->kv);
-                       if (ret != CSR1212_SUCCESS)
-                               return ret;
-               }
-       }
-
-       return CSR1212_SUCCESS;
-}
diff --git a/drivers/ieee1394/csr1212.h b/drivers/ieee1394/csr1212.h
deleted file mode 100644 (file)
index a892d92..0000000
+++ /dev/null
@@ -1,383 +0,0 @@
-/*
- * csr1212.h -- IEEE 1212 Control and Status Register support for Linux
- *
- * Copyright (C) 2003 Francois Retief <fgretief@sun.ac.za>
- *                    Steve Kinneberg <kinnebergsteve@acmsystems.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- *    1. Redistributions of source code must retain the above copyright notice,
- *       this list of conditions and the following disclaimer.
- *    2. Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *    3. The name of the author may not be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef __CSR1212_H__
-#define __CSR1212_H__
-
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <asm/atomic.h>
-
-#define CSR1212_MALLOC(size)   kmalloc((size), GFP_KERNEL)
-#define CSR1212_FREE(ptr)      kfree(ptr)
-
-#define CSR1212_SUCCESS (0)
-
-
-/* CSR 1212 key types */
-#define CSR1212_KV_TYPE_IMMEDIATE              0
-#define CSR1212_KV_TYPE_CSR_OFFSET             1
-#define CSR1212_KV_TYPE_LEAF                   2
-#define CSR1212_KV_TYPE_DIRECTORY              3
-
-
-/* CSR 1212 key ids */
-#define CSR1212_KV_ID_DESCRIPTOR               0x01
-#define CSR1212_KV_ID_BUS_DEPENDENT_INFO       0x02
-#define CSR1212_KV_ID_VENDOR                   0x03
-#define CSR1212_KV_ID_HARDWARE_VERSION         0x04
-#define CSR1212_KV_ID_MODULE                   0x07
-#define CSR1212_KV_ID_NODE_CAPABILITIES                0x0C
-#define CSR1212_KV_ID_EUI_64                   0x0D
-#define CSR1212_KV_ID_UNIT                     0x11
-#define CSR1212_KV_ID_SPECIFIER_ID             0x12
-#define CSR1212_KV_ID_VERSION                  0x13
-#define CSR1212_KV_ID_DEPENDENT_INFO           0x14
-#define CSR1212_KV_ID_UNIT_LOCATION            0x15
-#define CSR1212_KV_ID_MODEL                    0x17
-#define CSR1212_KV_ID_INSTANCE                 0x18
-#define CSR1212_KV_ID_KEYWORD                  0x19
-#define CSR1212_KV_ID_FEATURE                  0x1A
-#define CSR1212_KV_ID_EXTENDED_ROM             0x1B
-#define CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID        0x1C
-#define CSR1212_KV_ID_EXTENDED_KEY             0x1D
-#define CSR1212_KV_ID_EXTENDED_DATA            0x1E
-#define CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR    0x1F
-#define CSR1212_KV_ID_DIRECTORY_ID             0x20
-#define CSR1212_KV_ID_REVISION                 0x21
-
-
-/* IEEE 1212 Address space map */
-#define CSR1212_ALL_SPACE_BASE                 (0x000000000000ULL)
-#define CSR1212_ALL_SPACE_SIZE                 (1ULL << 48)
-#define CSR1212_ALL_SPACE_END                  (CSR1212_ALL_SPACE_BASE + CSR1212_ALL_SPACE_SIZE)
-
-#define  CSR1212_MEMORY_SPACE_BASE             (0x000000000000ULL)
-#define  CSR1212_MEMORY_SPACE_SIZE             ((256ULL * (1ULL << 40)) - (512ULL * (1ULL << 20)))
-#define  CSR1212_MEMORY_SPACE_END              (CSR1212_MEMORY_SPACE_BASE + CSR1212_MEMORY_SPACE_SIZE)
-
-#define  CSR1212_PRIVATE_SPACE_BASE            (0xffffe0000000ULL)
-#define  CSR1212_PRIVATE_SPACE_SIZE            (256ULL * (1ULL << 20))
-#define  CSR1212_PRIVATE_SPACE_END             (CSR1212_PRIVATE_SPACE_BASE + CSR1212_PRIVATE_SPACE_SIZE)
-
-#define  CSR1212_REGISTER_SPACE_BASE           (0xfffff0000000ULL)
-#define  CSR1212_REGISTER_SPACE_SIZE           (256ULL * (1ULL << 20))
-#define  CSR1212_REGISTER_SPACE_END            (CSR1212_REGISTER_SPACE_BASE + CSR1212_REGISTER_SPACE_SIZE)
-
-#define  CSR1212_CSR_ARCH_REG_SPACE_BASE       (0xfffff0000000ULL)
-#define  CSR1212_CSR_ARCH_REG_SPACE_SIZE       (512)
-#define  CSR1212_CSR_ARCH_REG_SPACE_END                (CSR1212_CSR_ARCH_REG_SPACE_BASE + CSR1212_CSR_ARCH_REG_SPACE_SIZE)
-#define  CSR1212_CSR_ARCH_REG_SPACE_OFFSET     (CSR1212_CSR_ARCH_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_BASE    (0xfffff0000200ULL)
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE    (512)
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_END     (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE + CSR1212_CSR_BUS_DEP_REG_SPACE_SIZE)
-#define  CSR1212_CSR_BUS_DEP_REG_SPACE_OFFSET  (CSR1212_CSR_BUS_DEP_REG_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_CONFIG_ROM_SPACE_BASE         (0xfffff0000400ULL)
-#define  CSR1212_CONFIG_ROM_SPACE_SIZE         (1024)
-#define  CSR1212_CONFIG_ROM_SPACE_END          (CSR1212_CONFIG_ROM_SPACE_BASE + CSR1212_CONFIG_ROM_SPACE_SIZE)
-#define  CSR1212_CONFIG_ROM_SPACE_OFFSET       (CSR1212_CONFIG_ROM_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_UNITS_SPACE_BASE              (0xfffff0000800ULL)
-#define  CSR1212_UNITS_SPACE_SIZE              ((256ULL * (1ULL << 20)) - 2048)
-#define  CSR1212_UNITS_SPACE_END               (CSR1212_UNITS_SPACE_BASE + CSR1212_UNITS_SPACE_SIZE)
-#define  CSR1212_UNITS_SPACE_OFFSET            (CSR1212_UNITS_SPACE_BASE - CSR1212_REGISTER_SPACE_BASE)
-
-#define  CSR1212_INVALID_ADDR_SPACE            -1
-
-
-/* Config ROM image structures */
-struct csr1212_bus_info_block_img {
-       u8 length;
-       u8 crc_length;
-       u16 crc;
-
-       /* Must be last */
-       u32 data[0];    /* older gcc can't handle [] which is standard */
-};
-
-struct csr1212_leaf {
-       int len;
-       u32 *data;
-};
-
-struct csr1212_dentry {
-       struct csr1212_dentry *next, *prev;
-       struct csr1212_keyval *kv;
-};
-
-struct csr1212_directory {
-       int len;
-       struct csr1212_dentry *dentries_head, *dentries_tail;
-};
-
-struct csr1212_keyval {
-       struct {
-               u8 type;
-               u8 id;
-       } key;
-       union {
-               u32 immediate;
-               u32 csr_offset;
-               struct csr1212_leaf leaf;
-               struct csr1212_directory directory;
-       } value;
-       struct csr1212_keyval *associate;
-       atomic_t refcnt;
-
-       /* used in generating and/or parsing CSR image */
-       struct csr1212_keyval *next, *prev;     /* flat list of CSR elements */
-       u32 offset;     /* position in CSR from 0xffff f000 0000 */
-       u8 valid;       /* flag indicating keyval has valid data*/
-};
-
-
-struct csr1212_cache_region {
-       struct csr1212_cache_region *next, *prev;
-       u32 offset_start;       /* inclusive */
-       u32 offset_end;         /* exclusive */
-};
-
-struct csr1212_csr_rom_cache {
-       struct csr1212_csr_rom_cache *next, *prev;
-       struct csr1212_cache_region *filled_head, *filled_tail;
-       struct csr1212_keyval *layout_head, *layout_tail;
-       size_t size;
-       u32 offset;
-       struct csr1212_keyval *ext_rom;
-       size_t len;
-
-       /* Must be last */
-       u32 data[0];    /* older gcc can't handle [] which is standard */
-};
-
-struct csr1212_csr {
-       size_t bus_info_len;    /* bus info block length in bytes */
-       size_t crc_len;         /* crc length in bytes */
-       __be32 *bus_info_data;  /* bus info data incl bus name and EUI */
-
-       void *private;          /* private, bus specific data */
-       struct csr1212_bus_ops *ops;
-
-       struct csr1212_keyval *root_kv;
-
-       int max_rom;            /* max bytes readable in Config ROM region */
-
-       /* Items below used for image parsing and generation */
-       struct csr1212_csr_rom_cache *cache_head, *cache_tail;
-};
-
-struct csr1212_bus_ops {
-       /* This function is used by csr1212 to read additional information
-        * from remote nodes when parsing a Config ROM (i.e., read Config ROM
-        * entries located in the Units Space.  Must return 0 on success
-        * anything else indicates an error. */
-       int (*bus_read) (struct csr1212_csr *csr, u64 addr,
-                        void *buffer, void *private);
-
-       /* This function is used by csr1212 to allocate a region in units space
-        * in the event that Config ROM entries don't all fit in the predefined
-        * 1K region.  The void *private parameter is private member of struct
-        * csr1212_csr. */
-       u64 (*allocate_addr_range) (u64 size, u32 alignment, void *private);
-
-       /* This function is used by csr1212 to release a region in units space
-        * that is no longer needed. */
-       void (*release_addr) (u64 addr, void *private);
-};
-
-
-/* Descriptor Leaf manipulation macros */
-#define CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT 24
-#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK 0xffffff
-#define CSR1212_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
-
-#define CSR1212_DESCRIPTOR_LEAF_TYPE(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[0]) >> \
-        CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT)
-#define CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[0]) & \
-        CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK)
-
-
-/* Text Descriptor Leaf manipulation macros */
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT 28
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_MASK 0xf /* after shift */
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT 16
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK 0xfff  /* after shift */
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK 0xffff
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD (1 * sizeof(u32))
-
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[1]) >> \
-        CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH_SHIFT)
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) \
-       ((be32_to_cpu((kv)->value.leaf.data[1]) >> \
-         CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_SHIFT) & \
-        CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET_MASK)
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) \
-       (be32_to_cpu((kv)->value.leaf.data[1]) & \
-        CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE_MASK)
-#define CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv) \
-       (&((kv)->value.leaf.data[2]))
-
-
-/* The following 2 function are for creating new Configuration ROM trees.  The
- * first function is used for both creating local trees and parsing remote
- * trees.  The second function adds pertinent information to local Configuration
- * ROM trees - namely data for the bus information block. */
-extern struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops,
-                                             size_t bus_info_size,
-                                             void *private);
-extern void csr1212_init_local_csr(struct csr1212_csr *csr,
-                                  const u32 *bus_info_data, int max_rom);
-
-
-/* Destroy a Configuration ROM tree and release all memory taken by the tree. */
-extern void csr1212_destroy_csr(struct csr1212_csr *csr);
-
-
-/* The following set of functions are fore creating new keyvals for placement in
- * a Configuration ROM tree.  Code that creates new keyvals with these functions
- * must release those keyvals with csr1212_release_keyval() when they are no
- * longer needed. */
-extern struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value);
-extern struct csr1212_keyval *csr1212_new_directory(u8 key);
-extern struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s);
-
-
-/* The following function manages association between keyvals.  Typically,
- * Descriptor Leaves and Directories will be associated with another keyval and
- * it is desirable for the Descriptor keyval to be place immediately after the
- * keyval that it is associated with.
- * Take care with subsequent ROM modifications:  There is no function to remove
- * previously specified associations.
- */
-extern void csr1212_associate_keyval(struct csr1212_keyval *kv,
-                                    struct csr1212_keyval *associate);
-
-
-/* The following functions manage the association of a keyval and directories.
- * A keyval may be attached to more than one directory. */
-extern int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir,
-                                             struct csr1212_keyval *kv);
-extern void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,
-                                                struct csr1212_keyval *kv);
-
-
-/* Creates a complete Configuration ROM image in the list of caches available
- * via csr->cache_head. */
-extern int csr1212_generate_csr_image(struct csr1212_csr *csr);
-
-
-/* This is a convience function for reading a block of data out of one of the
- * caches in the csr->cache_head list. */
-extern int csr1212_read(struct csr1212_csr *csr, u32 offset, void *buffer,
-                       u32 len);
-
-
-/* The following functions are in place for parsing Configuration ROM images.
- * csr1212_parse_keyval() is used should there be a need to directly parse a
- * Configuration ROM directly. */
-extern int csr1212_parse_keyval(struct csr1212_keyval *kv,
-                               struct csr1212_csr_rom_cache *cache);
-extern int csr1212_parse_csr(struct csr1212_csr *csr);
-
-
-/* This function allocates a new cache which may be used for either parsing or
- * generating sub-sets of Configuration ROM images. */
-static inline struct csr1212_csr_rom_cache *
-csr1212_rom_cache_malloc(u32 offset, size_t size)
-{
-       struct csr1212_csr_rom_cache *cache;
-
-       cache = CSR1212_MALLOC(sizeof(*cache) + size);
-       if (!cache)
-               return NULL;
-
-       cache->next = NULL;
-       cache->prev = NULL;
-       cache->filled_head = NULL;
-       cache->filled_tail = NULL;
-       cache->layout_head = NULL;
-       cache->layout_tail = NULL;
-       cache->offset = offset;
-       cache->size = size;
-       cache->ext_rom = NULL;
-
-       return cache;
-}
-
-
-/* This function ensures that a keyval contains data when referencing a keyval
- * created by parsing a Configuration ROM. */
-extern struct csr1212_keyval *
-csr1212_get_keyval(struct csr1212_csr *csr, struct csr1212_keyval *kv);
-
-
-/* This function increments the reference count for a keyval should there be a
- * need for code to retain a keyval that has been parsed. */
-static inline void csr1212_keep_keyval(struct csr1212_keyval *kv)
-{
-       atomic_inc(&kv->refcnt);
-       smp_mb__after_atomic_inc();
-}
-
-
-/* This function decrements a keyval's reference count and will destroy the
- * keyval when there are no more users of the keyval.  This should be called by
- * any code that calls csr1212_keep_keyval() or any of the keyval creation
- * routines csr1212_new_*(). */
-extern void csr1212_release_keyval(struct csr1212_keyval *kv);
-
-
-/*
- * This macro allows for looping over the keyval entries in a directory and it
- * ensures that keyvals from remote ConfigROMs are parsed properly.
- *
- * struct csr1212_csr *_csr points to the CSR associated with dir.
- * struct csr1212_keyval *_kv points to the current keyval (loop index).
- * struct csr1212_keyval *_dir points to the directory to be looped.
- * struct csr1212_dentry *_pos is used internally for indexing.
- *
- * kv will be NULL upon exit of the loop.
- */
-#define csr1212_for_each_dir_entry(_csr, _kv, _dir, _pos)              \
-       for (csr1212_get_keyval((_csr), (_dir)),                        \
-            _pos = (_dir)->value.directory.dentries_head,              \
-            _kv = (_pos) ? csr1212_get_keyval((_csr), _pos->kv) : NULL;\
-            (_kv) && (_pos);                                           \
-            (_kv->associate == NULL) ?                                 \
-                    ((_pos = _pos->next), (_kv = (_pos) ?              \
-                               csr1212_get_keyval((_csr), _pos->kv) :  \
-                               NULL)) :                                \
-                    (_kv = csr1212_get_keyval((_csr), _kv->associate)))
-
-#endif /* __CSR1212_H__ */
diff --git a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
deleted file mode 100644 (file)
index d178699..0000000
+++ /dev/null
@@ -1,289 +0,0 @@
-/*
- * DMA region bookkeeping routines
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/vmalloc.h>
-#include <linux/scatterlist.h>
-
-#include "dma.h"
-
-/* dma_prog_region */
-
-void dma_prog_region_init(struct dma_prog_region *prog)
-{
-       prog->kvirt = NULL;
-       prog->dev = NULL;
-       prog->n_pages = 0;
-       prog->bus_addr = 0;
-}
-
-int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
-                         struct pci_dev *dev)
-{
-       /* round up to page size */
-       n_bytes = PAGE_ALIGN(n_bytes);
-
-       prog->n_pages = n_bytes >> PAGE_SHIFT;
-
-       prog->kvirt = pci_alloc_consistent(dev, n_bytes, &prog->bus_addr);
-       if (!prog->kvirt) {
-               printk(KERN_ERR
-                      "dma_prog_region_alloc: pci_alloc_consistent() failed\n");
-               dma_prog_region_free(prog);
-               return -ENOMEM;
-       }
-
-       prog->dev = dev;
-
-       return 0;
-}
-
-void dma_prog_region_free(struct dma_prog_region *prog)
-{
-       if (prog->kvirt) {
-               pci_free_consistent(prog->dev, prog->n_pages << PAGE_SHIFT,
-                                   prog->kvirt, prog->bus_addr);
-       }
-
-       prog->kvirt = NULL;
-       prog->dev = NULL;
-       prog->n_pages = 0;
-       prog->bus_addr = 0;
-}
-
-/* dma_region */
-
-/**
- * dma_region_init - clear out all fields but do not allocate anything
- */
-void dma_region_init(struct dma_region *dma)
-{
-       dma->kvirt = NULL;
-       dma->dev = NULL;
-       dma->n_pages = 0;
-       dma->n_dma_pages = 0;
-       dma->sglist = NULL;
-}
-
-/**
- * dma_region_alloc - allocate the buffer and map it to the IOMMU
- */
-int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
-                    struct pci_dev *dev, int direction)
-{
-       unsigned int i;
-
-       /* round up to page size */
-       n_bytes = PAGE_ALIGN(n_bytes);
-
-       dma->n_pages = n_bytes >> PAGE_SHIFT;
-
-       dma->kvirt = vmalloc_32(n_bytes);
-       if (!dma->kvirt) {
-               printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n");
-               goto err;
-       }
-
-       /* Clear the ram out, no junk to the user */
-       memset(dma->kvirt, 0, n_bytes);
-
-       /* allocate scatter/gather list */
-       dma->sglist = vmalloc(dma->n_pages * sizeof(*dma->sglist));
-       if (!dma->sglist) {
-               printk(KERN_ERR "dma_region_alloc: vmalloc(sglist) failed\n");
-               goto err;
-       }
-
-       sg_init_table(dma->sglist, dma->n_pages);
-
-       /* fill scatter/gather list with pages */
-       for (i = 0; i < dma->n_pages; i++) {
-               unsigned long va =
-                   (unsigned long)dma->kvirt + (i << PAGE_SHIFT);
-
-               sg_set_page(&dma->sglist[i], vmalloc_to_page((void *)va),
-                               PAGE_SIZE, 0);
-       }
-
-       /* map sglist to the IOMMU */
-       dma->n_dma_pages =
-           pci_map_sg(dev, dma->sglist, dma->n_pages, direction);
-
-       if (dma->n_dma_pages == 0) {
-               printk(KERN_ERR "dma_region_alloc: pci_map_sg() failed\n");
-               goto err;
-       }
-
-       dma->dev = dev;
-       dma->direction = direction;
-
-       return 0;
-
-      err:
-       dma_region_free(dma);
-       return -ENOMEM;
-}
-
-/**
- * dma_region_free - unmap and free the buffer
- */
-void dma_region_free(struct dma_region *dma)
-{
-       if (dma->n_dma_pages) {
-               pci_unmap_sg(dma->dev, dma->sglist, dma->n_pages,
-                            dma->direction);
-               dma->n_dma_pages = 0;
-               dma->dev = NULL;
-       }
-
-       vfree(dma->sglist);
-       dma->sglist = NULL;
-
-       vfree(dma->kvirt);
-       dma->kvirt = NULL;
-       dma->n_pages = 0;
-}
-
-/* find the scatterlist index and remaining offset corresponding to a
-   given offset from the beginning of the buffer */
-static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
-                                 unsigned int start, unsigned long *rem)
-{
-       int i;
-       unsigned long off = offset;
-
-       for (i = start; i < dma->n_dma_pages; i++) {
-               if (off < sg_dma_len(&dma->sglist[i])) {
-                       *rem = off;
-                       break;
-               }
-
-               off -= sg_dma_len(&dma->sglist[i]);
-       }
-
-       BUG_ON(i >= dma->n_dma_pages);
-
-       return i;
-}
-
-/**
- * dma_region_offset_to_bus - get bus address of an offset within a DMA region
- *
- * Returns the DMA bus address of the byte with the given @offset relative to
- * the beginning of the @dma.
- */
-dma_addr_t dma_region_offset_to_bus(struct dma_region * dma,
-                                   unsigned long offset)
-{
-       unsigned long rem = 0;
-
-       struct scatterlist *sg =
-           &dma->sglist[dma_region_find(dma, offset, 0, &rem)];
-       return sg_dma_address(sg) + rem;
-}
-
-/**
- * dma_region_sync_for_cpu - sync the CPU's view of the buffer
- */
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
-                            unsigned long len)
-{
-       int first, last;
-       unsigned long rem = 0;
-
-       if (!len)
-               len = 1;
-
-       first = dma_region_find(dma, offset, 0, &rem);
-       last = dma_region_find(dma, rem + len - 1, first, &rem);
-
-       pci_dma_sync_sg_for_cpu(dma->dev, &dma->sglist[first], last - first + 1,
-                               dma->direction);
-}
-
-/**
- * dma_region_sync_for_device - sync the IO bus' view of the buffer
- */
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
-                               unsigned long len)
-{
-       int first, last;
-       unsigned long rem = 0;
-
-       if (!len)
-               len = 1;
-
-       first = dma_region_find(dma, offset, 0, &rem);
-       last = dma_region_find(dma, rem + len - 1, first, &rem);
-
-       pci_dma_sync_sg_for_device(dma->dev, &dma->sglist[first],
-                                  last - first + 1, dma->direction);
-}
-
-#ifdef CONFIG_MMU
-
-static int dma_region_pagefault(struct vm_area_struct *vma,
-                               struct vm_fault *vmf)
-{
-       struct dma_region *dma = (struct dma_region *)vma->vm_private_data;
-
-       if (!dma->kvirt)
-               return VM_FAULT_SIGBUS;
-
-       if (vmf->pgoff >= dma->n_pages)
-               return VM_FAULT_SIGBUS;
-
-       vmf->page = vmalloc_to_page(dma->kvirt + (vmf->pgoff << PAGE_SHIFT));
-       get_page(vmf->page);
-       return 0;
-}
-
-static const struct vm_operations_struct dma_region_vm_ops = {
-       .fault = dma_region_pagefault,
-};
-
-/**
- * dma_region_mmap - map the buffer into a user space process
- */
-int dma_region_mmap(struct dma_region *dma, struct file *file,
-                   struct vm_area_struct *vma)
-{
-       unsigned long size;
-
-       if (!dma->kvirt)
-               return -EINVAL;
-
-       /* must be page-aligned (XXX: comment is wrong, we could allow pgoff) */
-       if (vma->vm_pgoff != 0)
-               return -EINVAL;
-
-       /* check the length */
-       size = vma->vm_end - vma->vm_start;
-       if (size > (dma->n_pages << PAGE_SHIFT))
-               return -EINVAL;
-
-       vma->vm_ops = &dma_region_vm_ops;
-       vma->vm_private_data = dma;
-       vma->vm_file = file;
-       vma->vm_flags |= VM_RESERVED | VM_ALWAYSDUMP;
-
-       return 0;
-}
-
-#else                          /* CONFIG_MMU */
-
-int dma_region_mmap(struct dma_region *dma, struct file *file,
-                   struct vm_area_struct *vma)
-{
-       return -EINVAL;
-}
-
-#endif                         /* CONFIG_MMU */
diff --git a/drivers/ieee1394/dma.h b/drivers/ieee1394/dma.h
deleted file mode 100644 (file)
index 467373c..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * DMA region bookkeeping routines
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#ifndef IEEE1394_DMA_H
-#define IEEE1394_DMA_H
-
-#include <asm/types.h>
-
-struct file;
-struct pci_dev;
-struct scatterlist;
-struct vm_area_struct;
-
-/**
- * struct dma_prog_region - small contiguous DMA buffer
- * @kvirt:    kernel virtual address
- * @dev:      PCI device
- * @n_pages:  number of kernel pages
- * @bus_addr: base bus address
- *
- * a small, physically contiguous DMA buffer with random-access, synchronous
- * usage characteristics
- */
-struct dma_prog_region {
-       unsigned char *kvirt;
-       struct pci_dev *dev;
-       unsigned int n_pages;
-       dma_addr_t bus_addr;
-};
-
-/* clear out all fields but do not allocate any memory */
-void dma_prog_region_init(struct dma_prog_region *prog);
-int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes,
-                         struct pci_dev *dev);
-void dma_prog_region_free(struct dma_prog_region *prog);
-
-static inline dma_addr_t dma_prog_region_offset_to_bus(
-               struct dma_prog_region *prog, unsigned long offset)
-{
-       return prog->bus_addr + offset;
-}
-
-/**
- * struct dma_region - large non-contiguous DMA buffer
- * @virt:        kernel virtual address
- * @dev:         PCI device
- * @n_pages:     number of kernel pages
- * @n_dma_pages: number of IOMMU pages
- * @sglist:      IOMMU mapping
- * @direction:   PCI_DMA_TODEVICE, etc.
- *
- * a large, non-physically-contiguous DMA buffer with streaming, asynchronous
- * usage characteristics
- */
-struct dma_region {
-       unsigned char *kvirt;
-       struct pci_dev *dev;
-       unsigned int n_pages;
-       unsigned int n_dma_pages;
-       struct scatterlist *sglist;
-       int direction;
-};
-
-void dma_region_init(struct dma_region *dma);
-int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes,
-                    struct pci_dev *dev, int direction);
-void dma_region_free(struct dma_region *dma);
-void dma_region_sync_for_cpu(struct dma_region *dma, unsigned long offset,
-                            unsigned long len);
-void dma_region_sync_for_device(struct dma_region *dma, unsigned long offset,
-                               unsigned long len);
-int  dma_region_mmap(struct dma_region *dma, struct file *file,
-                    struct vm_area_struct *vma);
-dma_addr_t dma_region_offset_to_bus(struct dma_region *dma,
-                                   unsigned long offset);
-
-/**
- * dma_region_i - macro to index into a DMA region (or dma_prog_region)
- */
-#define dma_region_i(_dma, _type, _index) \
-       ( ((_type*) ((_dma)->kvirt)) + (_index) )
-
-#endif /* IEEE1394_DMA_H */
diff --git a/drivers/ieee1394/dv1394-private.h b/drivers/ieee1394/dv1394-private.h
deleted file mode 100644 (file)
index 18b92cb..0000000
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * dv1394-private.h - DV input/output over IEEE 1394 on OHCI chips
- *   Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- *     receive by Dan Dennedy <dan@dennedy.org>
- *
- * based on:
- *   video1394.h - driver for OHCI 1394 boards
- *   Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                          Peter Schlaile <udbz@rz.uni-karlsruhe.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _DV_1394_PRIVATE_H
-#define _DV_1394_PRIVATE_H
-
-#include "ieee1394.h"
-#include "ohci1394.h"
-#include "dma.h"
-
-/* data structures private to the dv1394 driver */
-/* none of this is exposed to user-space */
-
-
-/*
-   the 8-byte CIP (Common Isochronous Packet) header that precedes
-   each packet of DV data.
-
-   See the IEC 61883 standard.
-*/
-
-struct CIP_header { unsigned char b[8]; };
-
-static inline void fill_cip_header(struct CIP_header *cip,
-                                  unsigned char source_node_id,
-                                  unsigned long counter,
-                                  enum pal_or_ntsc format,
-                                  unsigned long timestamp)
-{
-       cip->b[0] = source_node_id;
-       cip->b[1] = 0x78; /* packet size in quadlets (480/4) - even for empty packets! */
-       cip->b[2] = 0x00;
-       cip->b[3] = counter;
-
-       cip->b[4] = 0x80; /* const */
-
-       switch(format) {
-       case DV1394_PAL:
-               cip->b[5] = 0x80;
-               break;
-       case DV1394_NTSC:
-               cip->b[5] = 0x00;
-               break;
-       }
-
-       cip->b[6] = timestamp >> 8;
-       cip->b[7] = timestamp & 0xFF;
-}
-
-
-
-/*
-   DMA commands used to program the OHCI's DMA engine
-
-   See the Texas Instruments OHCI 1394 chipset documentation.
-*/
-
-struct output_more_immediate { __le32 q[8]; };
-struct output_more { __le32 q[4]; };
-struct output_last { __le32 q[4]; };
-struct input_more { __le32 q[4]; };
-struct input_last { __le32 q[4]; };
-
-/* outputs */
-
-static inline void fill_output_more_immediate(struct output_more_immediate *omi,
-                                             unsigned char tag,
-                                             unsigned char channel,
-                                             unsigned char sync_tag,
-                                             unsigned int  payload_size)
-{
-       omi->q[0] = cpu_to_le32(0x02000000 | 8); /* OUTPUT_MORE_IMMEDIATE; 8 is the size of the IT header */
-       omi->q[1] = cpu_to_le32(0);
-       omi->q[2] = cpu_to_le32(0);
-       omi->q[3] = cpu_to_le32(0);
-
-       /* IT packet header */
-       omi->q[4] = cpu_to_le32(  (0x0 << 16)  /* IEEE1394_SPEED_100 */
-                                 | (tag << 14)
-                                 | (channel << 8)
-                                 | (TCODE_ISO_DATA << 4)
-                                 | (sync_tag) );
-
-       /* reserved field; mimic behavior of my Sony DSR-40 */
-       omi->q[5] = cpu_to_le32((payload_size << 16) | (0x7F << 8) | 0xA0);
-
-       omi->q[6] = cpu_to_le32(0);
-       omi->q[7] = cpu_to_le32(0);
-}
-
-static inline void fill_output_more(struct output_more *om,
-                                   unsigned int data_size,
-                                   unsigned long data_phys_addr)
-{
-       om->q[0] = cpu_to_le32(data_size);
-       om->q[1] = cpu_to_le32(data_phys_addr);
-       om->q[2] = cpu_to_le32(0);
-       om->q[3] = cpu_to_le32(0);
-}
-
-static inline void fill_output_last(struct output_last *ol,
-                                   int want_timestamp,
-                                   int want_interrupt,
-                                   unsigned int data_size,
-                                   unsigned long data_phys_addr)
-{
-       u32 temp = 0;
-       temp |= 1 << 28; /* OUTPUT_LAST */
-
-       if (want_timestamp) /* controller will update timestamp at DMA time */
-               temp |= 1 << 27;
-
-       if (want_interrupt)
-               temp |= 3 << 20;
-
-       temp |= 3 << 18; /* must take branch */
-       temp |= data_size;
-
-       ol->q[0] = cpu_to_le32(temp);
-       ol->q[1] = cpu_to_le32(data_phys_addr);
-       ol->q[2] = cpu_to_le32(0);
-       ol->q[3] = cpu_to_le32(0);
-}
-
-/* inputs */
-
-static inline void fill_input_more(struct input_more *im,
-                                  int want_interrupt,
-                                  unsigned int data_size,
-                                  unsigned long data_phys_addr)
-{
-       u32 temp =  2 << 28; /* INPUT_MORE */
-       temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
-       if (want_interrupt)
-               temp |= 0 << 20; /* interrupts, i=0 in packet-per-buffer mode */
-       temp |= 0x0 << 16; /* disable branch to address for packet-per-buffer mode */
-                              /* disable wait on sync field, not used in DV :-( */
-               temp |= data_size;
-
-       im->q[0] = cpu_to_le32(temp);
-       im->q[1] = cpu_to_le32(data_phys_addr);
-       im->q[2] = cpu_to_le32(0); /* branchAddress and Z not use in packet-per-buffer mode */
-       im->q[3] = cpu_to_le32(0); /* xferStatus & resCount, resCount must be initialize to data_size */
-}
-static inline void fill_input_last(struct input_last *il,
-                                   int want_interrupt,
-                                   unsigned int data_size,
-                                   unsigned long data_phys_addr)
-{
-       u32 temp =  3 << 28; /* INPUT_LAST */
-       temp |= 8 << 24; /* s = 1, update xferStatus and resCount */
-       if (want_interrupt)
-               temp |= 3 << 20; /* enable interrupts */
-       temp |= 0xC << 16; /* enable branch to address */
-                              /* disable wait on sync field, not used in DV :-( */
-       temp |= data_size;
-
-       il->q[0] = cpu_to_le32(temp);
-       il->q[1] = cpu_to_le32(data_phys_addr);
-       il->q[2] = cpu_to_le32(1); /* branchAddress (filled in later) and Z = 1 descriptor in next block */
-       il->q[3] = cpu_to_le32(data_size); /* xferStatus & resCount, resCount must be initialize to data_size */
-}
-
-
-
-/*
-   A "DMA descriptor block" consists of several contiguous DMA commands.
-   struct DMA_descriptor_block encapsulates all of the commands necessary
-   to send one packet of DV data.
-
-   There are three different types of these blocks:
-
-        1) command to send an empty packet (CIP header only, no DV data):
-
-           OUTPUT_MORE-Immediate <-- contains the iso header in-line
-           OUTPUT_LAST           <-- points to the CIP header
-
-       2) command to send a full packet when the DV data payload does NOT
-          cross a page boundary:
-
-           OUTPUT_MORE-Immediate <-- contains the iso header in-line
-           OUTPUT_MORE           <-- points to the CIP header
-           OUTPUT_LAST           <-- points to entire DV data payload
-
-       3) command to send a full packet when the DV payload DOES cross
-          a page boundary:
-
-           OUTPUT_MORE-Immediate <-- contains the iso header in-line
-           OUTPUT_MORE           <-- points to the CIP header
-           OUTPUT_MORE           <-- points to first part of DV data payload
-           OUTPUT_LAST           <-- points to second part of DV data payload
-
-   This struct describes all three block types using unions.
-
-   !!! It is vital that an even number of these descriptor blocks fit on one
-   page of memory, since a block cannot cross a page boundary !!!
-
- */
-
-struct DMA_descriptor_block {
-
-       union {
-               struct {
-                       /*  iso header, common to all output block types */
-                       struct output_more_immediate omi;
-
-                       union {
-                               /* empty packet */
-                               struct {
-                                       struct output_last ol;  /* CIP header */
-                               } empty;
-
-                               /* full packet */
-                               struct {
-                                       struct output_more om;  /* CIP header */
-
-                                       union {
-                                              /* payload does not cross page boundary */
-                                               struct {
-                                                       struct output_last ol;  /* data payload */
-                                               } nocross;
-
-                                              /* payload crosses page boundary */
-                                               struct {
-                                                       struct output_more om;  /* data payload */
-                                                       struct output_last ol;  /* data payload */
-                                               } cross;
-                                       } u;
-
-                               } full;
-                       } u;
-               } out;
-
-               struct {
-                       struct input_last il;
-               } in;
-
-       } u;
-
-       /* ensure that PAGE_SIZE % sizeof(struct DMA_descriptor_block) == 0
-          by padding out to 128 bytes */
-       u32 __pad__[12];
-};
-
-
-/* struct frame contains all data associated with one frame in the
-   ringbuffer these are allocated when the DMA context is initialized
-   do_dv1394_init().  They are re-used after the card finishes
-   transmitting the frame. */
-
-struct video_card; /* forward declaration */
-
-struct frame {
-
-       /* points to the struct video_card that owns this frame */
-       struct video_card *video;
-
-       /* index of this frame in video_card->frames[] */
-       unsigned int frame_num;
-
-       /* FRAME_CLEAR - DMA program not set up, waiting for data
-          FRAME_READY - DMA program written, ready to transmit
-
-          Changes to these should be locked against the interrupt
-       */
-       enum {
-               FRAME_CLEAR = 0,
-               FRAME_READY
-       } state;
-
-       /* whether this frame has been DMA'ed already; used only from
-          the IRQ handler to determine whether the frame can be reset */
-       int done;
-
-
-       /* kernel virtual pointer to the start of this frame's data in
-          the user ringbuffer. Use only for CPU access; to get the DMA
-          bus address you must go through the video->user_dma mapping */
-       unsigned long data;
-
-       /* Max # of packets per frame */
-#define MAX_PACKETS 500
-
-
-       /* a PAGE_SIZE memory pool for allocating CIP headers
-          !header_pool must be aligned to PAGE_SIZE! */
-       struct CIP_header *header_pool;
-       dma_addr_t         header_pool_dma;
-
-
-       /* a physically contiguous memory pool for allocating DMA
-          descriptor blocks; usually around 64KB in size
-          !descriptor_pool must be aligned to PAGE_SIZE! */
-       struct DMA_descriptor_block *descriptor_pool;
-       dma_addr_t                   descriptor_pool_dma;
-       unsigned long                descriptor_pool_size;
-
-
-       /* # of packets allocated for this frame */
-       unsigned int n_packets;
-
-
-       /* below are several pointers (kernel virtual addresses, not
-          DMA bus addresses) to parts of the DMA program.  These are
-          set each time the DMA program is written in
-          frame_prepare(). They are used later on, e.g. from the
-          interrupt handler, to check the status of the frame */
-
-       /* points to status/timestamp field of first DMA packet */
-       /* (we'll check it later to monitor timestamp accuracy) */
-       __le32 *frame_begin_timestamp;
-
-       /* the timestamp we assigned to the first packet in the frame */
-       u32 assigned_timestamp;
-
-       /* pointer to the first packet's CIP header (where the timestamp goes) */
-       struct CIP_header *cip_syt1;
-
-       /* pointer to the second packet's CIP header
-          (only set if the first packet was empty) */
-       struct CIP_header *cip_syt2;
-
-       /* in order to figure out what caused an interrupt,
-          store pointers to the status fields of the two packets
-          that can cause interrupts. We'll check these from the
-          interrupt handler.
-       */
-       __le32 *mid_frame_timestamp;
-       __le32 *frame_end_timestamp;
-
-       /* branch address field of final packet. This is effectively
-          the "tail" in the chain of DMA descriptor blocks.
-          We will fill it with the address of the first DMA descriptor
-          block in the subsequent frame, once it is ready.
-       */
-       __le32 *frame_end_branch;
-
-       /* the number of descriptors in the first descriptor block
-          of the frame. Needed to start DMA */
-       int first_n_descriptors;
-};
-
-
-struct packet {
-       __le16  timestamp;
-       u16     invalid;
-       u16     iso_header;
-       __le16  data_length;
-       u32     cip_h1;
-       u32     cip_h2;
-       unsigned char data[480];
-       unsigned char padding[16]; /* force struct size =512 for page alignment */
-};
-
-
-/* allocate/free a frame */
-static struct frame* frame_new(unsigned int frame_num, struct video_card *video);
-static void frame_delete(struct frame *f);
-
-/* reset f so that it can be used again */
-static void frame_reset(struct frame *f);
-
-/* struct video_card contains all data associated with one instance
-   of the dv1394 driver
-*/
-enum modes {
-       MODE_RECEIVE,
-       MODE_TRANSMIT
-};
-
-struct video_card {
-
-       /* ohci card to which this instance corresponds */
-       struct ti_ohci *ohci;
-
-       /* OHCI card id; the link between the VFS inode and a specific video_card
-          (essentially the device minor number) */
-       int id;
-
-       /* entry in dv1394_cards */
-       struct list_head list;
-
-       /* OHCI card IT DMA context number, -1 if not in use */
-       int ohci_it_ctx;
-       struct ohci1394_iso_tasklet it_tasklet;
-
-       /* register offsets for current IT DMA context, 0 if not in use */
-       u32 ohci_IsoXmitContextControlSet;
-       u32 ohci_IsoXmitContextControlClear;
-       u32 ohci_IsoXmitCommandPtr;
-
-       /* OHCI card IR DMA context number, -1 if not in use */
-       struct ohci1394_iso_tasklet ir_tasklet;
-       int ohci_ir_ctx;
-
-       /* register offsets for current IR DMA context, 0 if not in use */
-       u32 ohci_IsoRcvContextControlSet;
-       u32 ohci_IsoRcvContextControlClear;
-       u32 ohci_IsoRcvCommandPtr;
-       u32 ohci_IsoRcvContextMatch;
-
-
-       /* CONCURRENCY CONTROL */
-
-       /* there are THREE levels of locking associated with video_card. */
-
-       /*
-          1) the 'open' flag - this prevents more than one process from
-          opening the device. (the driver currently assumes only one opener).
-          This is a regular int, but use test_and_set_bit() (on bit zero) 
-          for atomicity.
-        */
-       unsigned long open;
-
-       /*
-          2) the spinlock - this provides mutual exclusion between the interrupt
-          handler and process-context operations. Generally you must take the
-          spinlock under the following conditions:
-            1) DMA (and hence the interrupt handler) may be running
-            AND
-            2) you need to operate on the video_card, especially active_frame
-
-            It is OK to play with video_card without taking the spinlock if
-            you are certain that DMA is not running. Even if DMA is running,
-            it is OK to *read* active_frame with the lock, then drop it
-            immediately. This is safe because the interrupt handler will never
-            advance active_frame onto a frame that is not READY (and the spinlock
-            must be held while marking a frame READY).
-
-            spinlock is also used to protect ohci_it_ctx and ohci_ir_ctx,
-            which can be accessed from both process and interrupt context
-        */
-       spinlock_t spinlock;
-
-       /* flag to prevent spurious interrupts (which OHCI seems to
-          generate a lot :) from accessing the struct */
-       int dma_running;
-
-       /*
-         3) the sleeping mutex 'mtx' - this is used from process context only,
-         to serialize various operations on the video_card. Even though only one
-         open() is allowed, we still need to prevent multiple threads of execution
-         from entering calls like read, write, ioctl, etc.
-
-         I honestly can't think of a good reason to use dv1394 from several threads
-         at once, but we need to serialize anyway to prevent oopses =).
-
-         NOTE: if you need both spinlock and mtx, take mtx first to avoid deadlock!
-        */
-       struct mutex mtx;
-
-       /* people waiting for buffer space, please form a line here... */
-       wait_queue_head_t waitq;
-
-       /* support asynchronous I/O signals (SIGIO) */
-       struct fasync_struct *fasync;
-
-       /* the large, non-contiguous (rvmalloc()) ringbuffer for DV
-           data, exposed to user-space via mmap() */
-       unsigned long      dv_buf_size;
-       struct dma_region  dv_buf;
-
-       /* next byte in the ringbuffer that a write() call will fill */
-       size_t write_off;
-
-       struct frame *frames[DV1394_MAX_FRAMES];
-
-       /* n_frames also serves as an indicator that this struct video_card is
-          initialized and ready to run DMA buffers */
-
-       int n_frames;
-
-       /* this is the frame that is currently "owned" by the OHCI DMA controller
-          (set to -1 iff DMA is not running)
-
-          ! must lock against the interrupt handler when accessing it !
-
-          RULES:
-
-              Only the interrupt handler may change active_frame if DMA
-                 is running; if not, process may change it
-
-              If the next frame is READY, the interrupt handler will advance
-              active_frame when the current frame is finished.
-
-              If the next frame is CLEAR, the interrupt handler will re-transmit
-              the current frame, and the dropped_frames counter will be  incremented.
-
-              The interrupt handler will NEVER advance active_frame to a
-              frame that is not READY.
-       */
-       int active_frame;
-       int first_run;
-
-       /* the same locking rules apply to these three fields also: */
-
-       /* altered ONLY from process context. Must check first_clear_frame->state;
-          if it's READY, that means the ringbuffer is full with READY frames;
-          if it's CLEAR, that means one or more ringbuffer frames are CLEAR */
-       unsigned int first_clear_frame;
-
-       /* altered both by process and interrupt */
-       unsigned int n_clear_frames;
-
-       /* only altered by the interrupt */
-       unsigned int dropped_frames;
-
-
-
-       /* the CIP accumulator and continuity counter are properties
-          of the DMA stream as a whole (not a single frame), so they
-          are stored here in the video_card */
-
-       unsigned long cip_accum;
-       unsigned long cip_n, cip_d;
-       unsigned int syt_offset;
-       unsigned int continuity_counter;
-
-       enum pal_or_ntsc pal_or_ntsc;
-
-       /* redundant, but simplifies the code somewhat */
-       unsigned int frame_size; /* in bytes */
-
-       /* the isochronous channel to use, -1 if video card is inactive */
-       int channel;
-
-
-       /* physically contiguous packet ringbuffer for receive */
-       struct dma_region packet_buf;
-       unsigned long  packet_buf_size;
-
-       unsigned int current_packet;
-       int first_frame;        /* received first start frame marker? */
-       enum modes mode;
-};
-
-/*
-   if the video_card is not initialized, then the ONLY fields that are valid are:
-   ohci
-   open
-   n_frames
-*/
-
-static inline int video_card_initialized(struct video_card *v)
-{
-       return v->n_frames > 0;
-}
-
-static int do_dv1394_init(struct video_card *video, struct dv1394_init *init);
-static int do_dv1394_init_default(struct video_card *video);
-static void do_dv1394_shutdown(struct video_card *video, int free_user_buf);
-
-
-/* NTSC empty packet rate accurate to within 0.01%,
-   calibrated against a Sony DSR-40 DVCAM deck */
-
-#define CIP_N_NTSC   68000000
-#define CIP_D_NTSC 1068000000
-
-#define CIP_N_PAL  1
-#define CIP_D_PAL 16
-
-#endif /* _DV_1394_PRIVATE_H */
-
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
deleted file mode 100644 (file)
index c5a031b..0000000
+++ /dev/null
@@ -1,2584 +0,0 @@
-/*
- * dv1394.c - DV input/output over IEEE 1394 on OHCI chips
- *   Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- *     receive by Dan Dennedy <dan@dennedy.org>
- *
- * based on:
- *  video1394.c - video driver for OHCI 1394 boards
- *  Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *
- * 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.
- */
-
-/*
-  OVERVIEW
-
-  I designed dv1394 as a "pipe" that you can use to shoot DV onto a
-  FireWire bus. In transmission mode, dv1394 does the following:
-
-   1. accepts contiguous frames of DV data from user-space, via write()
-      or mmap() (see dv1394.h for the complete API)
-   2. wraps IEC 61883 packets around the DV data, inserting
-      empty synchronization packets as necessary
-   3. assigns accurate SYT timestamps to the outgoing packets
-   4. shoots them out using the OHCI card's IT DMA engine
-
-   Thanks to Dan Dennedy, we now have a receive mode that does the following:
-
-   1. accepts raw IEC 61883 packets from the OHCI card
-   2. re-assembles the DV data payloads into contiguous frames,
-      discarding empty packets
-   3. sends the DV data to user-space via read() or mmap()
-*/
-
-/*
-  TODO:
-
-  - tunable frame-drop behavior: either loop last frame, or halt transmission
-
-  - use a scatter/gather buffer for DMA programs (f->descriptor_pool)
-    so that we don't rely on allocating 64KB of contiguous kernel memory
-    via pci_alloc_consistent()
-
-  DONE:
-  - during reception, better handling of dropped frames and continuity errors
-  - during reception, prevent DMA from bypassing the irq tasklets
-  - reduce irq rate during reception (1/250 packets).
-  - add many more internal buffers during reception with scatter/gather dma.
-  - add dbc (continuity) checking on receive, increment status.dropped_frames
-    if not continuous.
-  - restart IT DMA after a bus reset
-  - safely obtain and release ISO Tx channels in cooperation with OHCI driver
-  - map received DIF blocks to their proper location in DV frame (ensure
-    recovery if dropped packet)
-  - handle bus resets gracefully (OHCI card seems to take care of this itself(!))
-  - do not allow resizing the user_buf once allocated; eliminate nuke_buffer_mappings
-  - eliminated #ifdef DV1394_DEBUG_LEVEL by inventing macros debug_printk and irq_printk
-  - added wmb() and mb() to places where PCI read/write ordering needs to be enforced
-  - set video->id correctly
-  - store video_cards in an array indexed by OHCI card ID, rather than a list
-  - implement DMA context allocation to cooperate with other users of the OHCI
-  - fix all XXX showstoppers
-  - disable IR/IT DMA interrupts on shutdown
-  - flush pci writes to the card by issuing a read
-  - character device dispatching
-  - switch over to the new kernel DMA API (pci_map_*()) (* needs testing on platforms with IOMMU!)
-  - keep all video_cards in a list (for open() via chardev), set file->private_data = video
-  - dv1394_poll should indicate POLLIN when receiving buffers are available
-  - add proc fs interface to set cip_n, cip_d, syt_offset, and video signal
-  - expose xmit and recv as separate devices (not exclusive)
-  - expose NTSC and PAL as separate devices (can be overridden)
-
-*/
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/mutex.h>
-#include <linux/bitops.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <linux/sched.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/string.h>
-#include <linux/compat.h>
-#include <linux/cdev.h>
-
-#include "dv1394.h"
-#include "dv1394-private.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_types.h"
-#include "nodemgr.h"
-#include "ohci1394.h"
-
-/* DEBUG LEVELS:
-   0 - no debugging messages
-   1 - some debugging messages, but none during DMA frame transmission
-   2 - lots of messages, including during DMA frame transmission
-       (will cause underflows if your machine is too slow!)
-*/
-
-#define DV1394_DEBUG_LEVEL 0
-
-/* for debugging use ONLY: allow more than one open() of the device */
-/* #define DV1394_ALLOW_MORE_THAN_ONE_OPEN 1 */
-
-#if DV1394_DEBUG_LEVEL >= 2
-#define irq_printk( args... ) printk( args )
-#else
-#define irq_printk( args... ) do {} while (0)
-#endif
-
-#if DV1394_DEBUG_LEVEL >= 1
-#define debug_printk( args... ) printk( args)
-#else
-#define debug_printk( args... ) do {} while (0)
-#endif
-
-/* issue a dummy PCI read to force the preceding write
-   to be posted to the PCI bus immediately */
-
-static inline void flush_pci_write(struct ti_ohci *ohci)
-{
-       mb();
-       reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-}
-
-static void it_tasklet_func(unsigned long data);
-static void ir_tasklet_func(unsigned long data);
-
-#ifdef CONFIG_COMPAT
-static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
-                              unsigned long arg);
-#endif
-
-/* GLOBAL DATA */
-
-/* list of all video_cards */
-static LIST_HEAD(dv1394_cards);
-static DEFINE_SPINLOCK(dv1394_cards_lock);
-
-/* translate from a struct file* to the corresponding struct video_card* */
-
-static inline struct video_card* file_to_video_card(struct file *file)
-{
-       return file->private_data;
-}
-
-/*** FRAME METHODS *********************************************************/
-
-static void frame_reset(struct frame *f)
-{
-       f->state = FRAME_CLEAR;
-       f->done = 0;
-       f->n_packets = 0;
-       f->frame_begin_timestamp = NULL;
-       f->assigned_timestamp = 0;
-       f->cip_syt1 = NULL;
-       f->cip_syt2 = NULL;
-       f->mid_frame_timestamp = NULL;
-       f->frame_end_timestamp = NULL;
-       f->frame_end_branch = NULL;
-}
-
-static struct frame* frame_new(unsigned int frame_num, struct video_card *video)
-{
-       struct frame *f = kmalloc(sizeof(*f), GFP_KERNEL);
-       if (!f)
-               return NULL;
-
-       f->video = video;
-       f->frame_num = frame_num;
-
-       f->header_pool = pci_alloc_consistent(f->video->ohci->dev, PAGE_SIZE, &f->header_pool_dma);
-       if (!f->header_pool) {
-               printk(KERN_ERR "dv1394: failed to allocate CIP header pool\n");
-               kfree(f);
-               return NULL;
-       }
-
-       debug_printk("dv1394: frame_new: allocated CIP header pool at virt 0x%08lx (contig) dma 0x%08lx size %ld\n",
-                    (unsigned long) f->header_pool, (unsigned long) f->header_pool_dma, PAGE_SIZE);
-
-       f->descriptor_pool_size = MAX_PACKETS * sizeof(struct DMA_descriptor_block);
-       /* make it an even # of pages */
-       f->descriptor_pool_size += PAGE_SIZE - (f->descriptor_pool_size%PAGE_SIZE);
-
-       f->descriptor_pool = pci_alloc_consistent(f->video->ohci->dev,
-                                                 f->descriptor_pool_size,
-                                                 &f->descriptor_pool_dma);
-       if (!f->descriptor_pool) {
-               pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma);
-               kfree(f);
-               return NULL;
-       }
-
-       debug_printk("dv1394: frame_new: allocated DMA program memory at virt 0x%08lx (contig) dma 0x%08lx size %ld\n",
-                    (unsigned long) f->descriptor_pool, (unsigned long) f->descriptor_pool_dma, f->descriptor_pool_size);
-
-       f->data = 0;
-       frame_reset(f);
-
-       return f;
-}
-
-static void frame_delete(struct frame *f)
-{
-       pci_free_consistent(f->video->ohci->dev, PAGE_SIZE, f->header_pool, f->header_pool_dma);
-       pci_free_consistent(f->video->ohci->dev, f->descriptor_pool_size, f->descriptor_pool, f->descriptor_pool_dma);
-       kfree(f);
-}
-
-
-
-
-/*
-   frame_prepare() - build the DMA program for transmitting
-
-   Frame_prepare() must be called OUTSIDE the video->spinlock.
-   However, frame_prepare() must still be serialized, so
-   it should be called WITH the video->mtx taken.
- */
-
-static void frame_prepare(struct video_card *video, unsigned int this_frame)
-{
-       struct frame *f = video->frames[this_frame];
-       int last_frame;
-
-       struct DMA_descriptor_block *block;
-       dma_addr_t block_dma;
-       struct CIP_header *cip;
-       dma_addr_t cip_dma;
-
-       unsigned int n_descriptors, full_packets, packets_per_frame, payload_size;
-
-       /* these flags denote packets that need special attention */
-       int empty_packet, first_packet, last_packet, mid_packet;
-
-       __le32 *branch_address, *last_branch_address = NULL;
-       unsigned long data_p;
-       int first_packet_empty = 0;
-       u32 cycleTimer, ct_sec, ct_cyc, ct_off;
-       unsigned long irq_flags;
-
-       irq_printk("frame_prepare( %d ) ---------------------\n", this_frame);
-
-       full_packets = 0;
-
-
-
-       if (video->pal_or_ntsc == DV1394_PAL)
-               packets_per_frame = DV1394_PAL_PACKETS_PER_FRAME;
-       else
-               packets_per_frame = DV1394_NTSC_PACKETS_PER_FRAME;
-
-       while ( full_packets < packets_per_frame ) {
-               empty_packet = first_packet = last_packet = mid_packet = 0;
-
-               data_p = f->data + full_packets * 480;
-
-               /************************************************/
-               /* allocate a descriptor block and a CIP header */
-               /************************************************/
-
-               /* note: these should NOT cross a page boundary (DMA restriction) */
-
-               if (f->n_packets >= MAX_PACKETS) {
-                       printk(KERN_ERR "dv1394: FATAL ERROR: max packet count exceeded\n");
-                       return;
-               }
-
-               /* the block surely won't cross a page boundary,
-                  since an even number of descriptor_blocks fit on a page */
-               block = &(f->descriptor_pool[f->n_packets]);
-
-               /* DMA address of the block = offset of block relative
-                   to the kernel base address of the descriptor pool
-                   + DMA base address of the descriptor pool */
-               block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;
-
-
-               /* the whole CIP pool fits on one page, so no worries about boundaries */
-               if ( ((unsigned long) &(f->header_pool[f->n_packets]) - (unsigned long) f->header_pool)
-                   > PAGE_SIZE) {
-                       printk(KERN_ERR "dv1394: FATAL ERROR: no room to allocate CIP header\n");
-                       return;
-               }
-
-               cip = &(f->header_pool[f->n_packets]);
-
-               /* DMA address of the CIP header = offset of cip
-                  relative to kernel base address of the header pool
-                  + DMA base address of the header pool */
-               cip_dma = (unsigned long) cip % PAGE_SIZE + f->header_pool_dma;
-
-               /* is this an empty packet? */
-
-               if (video->cip_accum > (video->cip_d - video->cip_n)) {
-                       empty_packet = 1;
-                       payload_size = 8;
-                       video->cip_accum -= (video->cip_d - video->cip_n);
-               } else {
-                       payload_size = 488;
-                       video->cip_accum += video->cip_n;
-               }
-
-               /* there are three important packets each frame:
-
-                  the first packet in the frame - we ask the card to record the timestamp when
-                                                  this packet is actually sent, so we can monitor
-                                                  how accurate our timestamps are. Also, the first
-                                                  packet serves as a semaphore to let us know that
-                                                  it's OK to free the *previous* frame's DMA buffer
-
-                  the last packet in the frame -  this packet is used to detect buffer underflows.
-                                                  if this is the last ready frame, the last DMA block
-                                                  will have a branch back to the beginning of the frame
-                                                  (so that the card will re-send the frame on underflow).
-                                                  if this branch gets taken, we know that at least one
-                                                  frame has been dropped. When the next frame is ready,
-                                                  the branch is pointed to its first packet, and the
-                                                  semaphore is disabled.
-
-                  a "mid" packet slightly before the end of the frame - this packet should trigger
-                                  an interrupt so we can go and assign a timestamp to the first packet
-                                  in the next frame. We don't use the very last packet in the frame
-                                  for this purpose, because that would leave very little time to set
-                                  the timestamp before DMA starts on the next frame.
-               */
-
-               if (f->n_packets == 0) {
-                       first_packet = 1;
-               } else if ( full_packets == (packets_per_frame-1) ) {
-                       last_packet = 1;
-               } else if (f->n_packets == packets_per_frame) {
-                       mid_packet = 1;
-               }
-
-
-               /********************/
-               /* setup CIP header */
-               /********************/
-
-               /* the timestamp will be written later from the
-                  mid-frame interrupt handler. For now we just
-                  store the address of the CIP header(s) that
-                  need a timestamp. */
-
-               /* first packet in the frame needs a timestamp */
-               if (first_packet) {
-                       f->cip_syt1 = cip;
-                       if (empty_packet)
-                               first_packet_empty = 1;
-
-               } else if (first_packet_empty && (f->n_packets == 1) ) {
-                       /* if the first packet was empty, the second
-                          packet's CIP header also needs a timestamp */
-                       f->cip_syt2 = cip;
-               }
-
-               fill_cip_header(cip,
-                               /* the node ID number of the OHCI card */
-                               reg_read(video->ohci, OHCI1394_NodeID) & 0x3F,
-                               video->continuity_counter,
-                               video->pal_or_ntsc,
-                               0xFFFF /* the timestamp is filled in later */);
-
-               /* advance counter, only for full packets */
-               if ( ! empty_packet )
-                       video->continuity_counter++;
-
-               /******************************/
-               /* setup DMA descriptor block */
-               /******************************/
-
-               /* first descriptor - OUTPUT_MORE_IMMEDIATE, for the controller's IT header */
-               fill_output_more_immediate( &(block->u.out.omi), 1, video->channel, 0, payload_size);
-
-               if (empty_packet) {
-                       /* second descriptor - OUTPUT_LAST for CIP header */
-                       fill_output_last( &(block->u.out.u.empty.ol),
-
-                                         /* want completion status on all interesting packets */
-                                         (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                         /* want interrupts on all interesting packets */
-                                         (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                         sizeof(struct CIP_header), /* data size */
-                                         cip_dma);
-
-                       if (first_packet)
-                               f->frame_begin_timestamp = &(block->u.out.u.empty.ol.q[3]);
-                       else if (mid_packet)
-                               f->mid_frame_timestamp = &(block->u.out.u.empty.ol.q[3]);
-                       else if (last_packet) {
-                               f->frame_end_timestamp = &(block->u.out.u.empty.ol.q[3]);
-                               f->frame_end_branch = &(block->u.out.u.empty.ol.q[2]);
-                       }
-
-                       branch_address = &(block->u.out.u.empty.ol.q[2]);
-                       n_descriptors = 3;
-                       if (first_packet)
-                               f->first_n_descriptors = n_descriptors;
-
-               } else { /* full packet */
-
-                       /* second descriptor - OUTPUT_MORE for CIP header */
-                       fill_output_more( &(block->u.out.u.full.om),
-                                         sizeof(struct CIP_header), /* data size */
-                                         cip_dma);
-
-
-                       /* third (and possibly fourth) descriptor - for DV data */
-                       /* the 480-byte payload can cross a page boundary; if so,
-                          we need to split it into two DMA descriptors */
-
-                       /* does the 480-byte data payload cross a page boundary? */
-                       if ( (PAGE_SIZE- ((unsigned long)data_p % PAGE_SIZE) ) < 480 ) {
-
-                               /* page boundary crossed */
-
-                               fill_output_more( &(block->u.out.u.full.u.cross.om),
-                                                 /* data size - how much of data_p fits on the first page */
-                                                 PAGE_SIZE - (data_p % PAGE_SIZE),
-
-                                                 /* DMA address of data_p */
-                                                 dma_region_offset_to_bus(&video->dv_buf,
-                                                                          data_p - (unsigned long) video->dv_buf.kvirt));
-
-                               fill_output_last( &(block->u.out.u.full.u.cross.ol),
-
-                                                 /* want completion status on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 /* want interrupt on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 /* data size - remaining portion of data_p */
-                                                 480 - (PAGE_SIZE - (data_p % PAGE_SIZE)),
-
-                                                 /* DMA address of data_p + PAGE_SIZE - (data_p % PAGE_SIZE) */
-                                                 dma_region_offset_to_bus(&video->dv_buf,
-                                                                          data_p + PAGE_SIZE - (data_p % PAGE_SIZE) - (unsigned long) video->dv_buf.kvirt));
-
-                               if (first_packet)
-                                       f->frame_begin_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);
-                               else if (mid_packet)
-                                       f->mid_frame_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);
-                               else if (last_packet) {
-                                       f->frame_end_timestamp = &(block->u.out.u.full.u.cross.ol.q[3]);
-                                       f->frame_end_branch = &(block->u.out.u.full.u.cross.ol.q[2]);
-                               }
-
-                               branch_address = &(block->u.out.u.full.u.cross.ol.q[2]);
-
-                               n_descriptors = 5;
-                               if (first_packet)
-                                       f->first_n_descriptors = n_descriptors;
-
-                               full_packets++;
-
-                       } else {
-                               /* fits on one page */
-
-                               fill_output_last( &(block->u.out.u.full.u.nocross.ol),
-
-                                                 /* want completion status on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 /* want interrupt on all interesting packets */
-                                                 (first_packet || mid_packet || last_packet) ? 1 : 0,
-
-                                                 480, /* data size (480 bytes of DV data) */
-
-
-                                                 /* DMA address of data_p */
-                                                 dma_region_offset_to_bus(&video->dv_buf,
-                                                                          data_p - (unsigned long) video->dv_buf.kvirt));
-
-                               if (first_packet)
-                                       f->frame_begin_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);
-                               else if (mid_packet)
-                                       f->mid_frame_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);
-                               else if (last_packet) {
-                                       f->frame_end_timestamp = &(block->u.out.u.full.u.nocross.ol.q[3]);
-                                       f->frame_end_branch = &(block->u.out.u.full.u.nocross.ol.q[2]);
-                               }
-
-                               branch_address = &(block->u.out.u.full.u.nocross.ol.q[2]);
-
-                               n_descriptors = 4;
-                               if (first_packet)
-                                       f->first_n_descriptors = n_descriptors;
-
-                               full_packets++;
-                       }
-               }
-
-               /* link this descriptor block into the DMA program by filling in
-                  the branch address of the previous block */
-
-               /* note: we are not linked into the active DMA chain yet */
-
-               if (last_branch_address) {
-                       *(last_branch_address) = cpu_to_le32(block_dma | n_descriptors);
-               }
-
-               last_branch_address = branch_address;
-
-
-               f->n_packets++;
-
-       }
-
-       /* when we first assemble a new frame, set the final branch
-          to loop back up to the top */
-       *(f->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors);
-
-       /* make the latest version of this frame visible to the PCI card */
-       dma_region_sync_for_device(&video->dv_buf, f->data - (unsigned long) video->dv_buf.kvirt, video->frame_size);
-
-       /* lock against DMA interrupt */
-       spin_lock_irqsave(&video->spinlock, irq_flags);
-
-       f->state = FRAME_READY;
-
-       video->n_clear_frames--;
-
-       last_frame = video->first_clear_frame - 1;
-       if (last_frame == -1)
-               last_frame = video->n_frames-1;
-
-       video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
-
-       irq_printk("   frame %d prepared, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n last=%d\n",
-                  this_frame, video->active_frame, video->n_clear_frames, video->first_clear_frame, last_frame);
-
-       irq_printk("   begin_ts %08lx mid_ts %08lx end_ts %08lx end_br %08lx\n",
-                  (unsigned long) f->frame_begin_timestamp,
-                  (unsigned long) f->mid_frame_timestamp,
-                  (unsigned long) f->frame_end_timestamp,
-                  (unsigned long) f->frame_end_branch);
-
-       if (video->active_frame != -1) {
-
-               /* if DMA is already active, we are almost done */
-               /* just link us onto the active DMA chain */
-               if (video->frames[last_frame]->frame_end_branch) {
-                       u32 temp;
-
-                       /* point the previous frame's tail to this frame's head */
-                       *(video->frames[last_frame]->frame_end_branch) = cpu_to_le32(f->descriptor_pool_dma | f->first_n_descriptors);
-
-                       /* this write MUST precede the next one, or we could silently drop frames */
-                       wmb();
-
-                       /* disable the want_status semaphore on the last packet */
-                       temp = le32_to_cpu(*(video->frames[last_frame]->frame_end_branch - 2));
-                       temp &= 0xF7CFFFFF;
-                       *(video->frames[last_frame]->frame_end_branch - 2) = cpu_to_le32(temp);
-
-                       /* flush these writes to memory ASAP */
-                       flush_pci_write(video->ohci);
-
-                       /* NOTE:
-                          ideally the writes should be "atomic": if
-                          the OHCI card reads the want_status flag in
-                          between them, we'll falsely report a
-                          dropped frame. Hopefully this window is too
-                          small to really matter, and the consequence
-                          is rather harmless. */
-
-
-                       irq_printk("     new frame %d linked onto DMA chain\n", this_frame);
-
-               } else {
-                       printk(KERN_ERR "dv1394: last frame not ready???\n");
-               }
-
-       } else {
-
-               u32 transmit_sec, transmit_cyc;
-               u32 ts_cyc;
-
-               /* DMA is stopped, so this is the very first frame */
-               video->active_frame = this_frame;
-
-               /* set CommandPtr to address and size of first descriptor block */
-               reg_write(video->ohci, video->ohci_IsoXmitCommandPtr,
-                         video->frames[video->active_frame]->descriptor_pool_dma |
-                         f->first_n_descriptors);
-
-               /* assign a timestamp based on the current cycle time...
-                  We'll tell the card to begin DMA 100 cycles from now,
-                  and assign a timestamp 103 cycles from now */
-
-               cycleTimer = reg_read(video->ohci, OHCI1394_IsochronousCycleTimer);
-
-               ct_sec = cycleTimer >> 25;
-               ct_cyc = (cycleTimer >> 12) & 0x1FFF;
-               ct_off = cycleTimer & 0xFFF;
-
-               transmit_sec = ct_sec;
-               transmit_cyc = ct_cyc + 100;
-
-               transmit_sec += transmit_cyc/8000;
-               transmit_cyc %= 8000;
-
-               ts_cyc = transmit_cyc + 3;
-               ts_cyc %= 8000;
-
-               f->assigned_timestamp = (ts_cyc&0xF) << 12;
-
-               /* now actually write the timestamp into the appropriate CIP headers */
-               if (f->cip_syt1) {
-                       f->cip_syt1->b[6] = f->assigned_timestamp >> 8;
-                       f->cip_syt1->b[7] = f->assigned_timestamp & 0xFF;
-               }
-               if (f->cip_syt2) {
-                       f->cip_syt2->b[6] = f->assigned_timestamp >> 8;
-                       f->cip_syt2->b[7] = f->assigned_timestamp & 0xFF;
-               }
-
-               /* --- start DMA --- */
-
-               /* clear all bits in ContextControl register */
-
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, 0xFFFFFFFF);
-               wmb();
-
-               /* the OHCI card has the ability to start ISO transmission on a
-                  particular cycle (start-on-cycle). This way we can ensure that
-                  the first DV frame will have an accurate timestamp.
-
-                  However, start-on-cycle only appears to work if the OHCI card
-                  is cycle master! Since the consequences of messing up the first
-                  timestamp are minimal*, just disable start-on-cycle for now.
-
-                  * my DV deck drops the first few frames before it "locks in;"
-                    so the first frame having an incorrect timestamp is inconsequential.
-               */
-
-#if 0
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlSet,
-                         (1 << 31) /* enable start-on-cycle */
-                         | ( (transmit_sec & 0x3) << 29)
-                         | (transmit_cyc << 16));
-               wmb();
-#endif
-
-               video->dma_running = 1;
-
-               /* set the 'run' bit */
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, 0x8000);
-               flush_pci_write(video->ohci);
-
-               /* --- DMA should be running now --- */
-
-               debug_printk("    Cycle = %4u ContextControl = %08x CmdPtr = %08x\n",
-                            (reg_read(video->ohci, OHCI1394_IsochronousCycleTimer) >> 12) & 0x1FFF,
-                            reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-                            reg_read(video->ohci, video->ohci_IsoXmitCommandPtr));
-
-               debug_printk("    DMA start - current cycle %4u, transmit cycle %4u (%2u), assigning ts cycle %2u\n",
-                            ct_cyc, transmit_cyc, transmit_cyc & 0xF, ts_cyc & 0xF);
-
-#if DV1394_DEBUG_LEVEL >= 2
-               {
-                       /* check if DMA is really running */
-                       int i = 0;
-                       while (i < 20) {
-                               mb();
-                               mdelay(1);
-                               if (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) {
-                                       printk("DMA ACTIVE after %d msec\n", i);
-                                       break;
-                               }
-                               i++;
-                       }
-
-                       printk("set = %08x, cmdPtr = %08x\n",
-                              reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-                              reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)
-                              );
-
-                       if ( ! (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) &  (1 << 10)) ) {
-                               printk("DMA did NOT go active after 20ms, event = %x\n",
-                                      reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & 0x1F);
-                       } else
-                               printk("DMA is RUNNING!\n");
-               }
-#endif
-
-       }
-
-
-       spin_unlock_irqrestore(&video->spinlock, irq_flags);
-}
-
-
-
-/*** RECEIVE FUNCTIONS *****************************************************/
-
-/*
-       frame method put_packet
-
-       map and copy the packet data to its location in the frame
-       based upon DIF section and sequence
-*/
-
-static void inline
-frame_put_packet (struct frame *f, struct packet *p)
-{
-       int section_type = p->data[0] >> 5;           /* section type is in bits 5 - 7 */
-       int dif_sequence = p->data[1] >> 4;           /* dif sequence number is in bits 4 - 7 */
-       int dif_block = p->data[2];
-
-       /* sanity check */
-       if (dif_sequence > 11 || dif_block > 149) return;
-
-       switch (section_type) {
-       case 0:           /* 1 Header block */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80, p->data, 480);
-               break;
-
-       case 1:           /* 2 Subcode blocks */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (1 + dif_block) * 80, p->data, 480);
-               break;
-
-       case 2:           /* 3 VAUX blocks */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (3 + dif_block) * 80, p->data, 480);
-               break;
-
-       case 3:           /* 9 Audio blocks interleaved with video */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (6 + dif_block * 16) * 80, p->data, 480);
-               break;
-
-       case 4:           /* 135 Video blocks interleaved with audio */
-               memcpy( (void *) f->data + dif_sequence * 150 * 80 + (7 + (dif_block / 15) + dif_block) * 80, p->data, 480);
-               break;
-
-       default:           /* we can not handle any other data */
-               break;
-       }
-}
-
-
-static void start_dma_receive(struct video_card *video)
-{
-       if (video->first_run == 1) {
-               video->first_run = 0;
-
-               /* start DMA once all of the frames are READY */
-               video->n_clear_frames = 0;
-               video->first_clear_frame = -1;
-               video->current_packet = 0;
-               video->active_frame = 0;
-
-               /* reset iso recv control register */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, 0xFFFFFFFF);
-               wmb();
-
-               /* clear bufferFill, set isochHeader and speed (0=100) */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x40000000);
-
-               /* match on all tags, listen on channel */
-               reg_write(video->ohci, video->ohci_IsoRcvContextMatch, 0xf0000000 | video->channel);
-
-               /* address and first descriptor block + Z=1 */
-               reg_write(video->ohci, video->ohci_IsoRcvCommandPtr,
-                         video->frames[0]->descriptor_pool_dma | 1); /* Z=1 */
-               wmb();
-
-               video->dma_running = 1;
-
-               /* run */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, 0x8000);
-               flush_pci_write(video->ohci);
-
-               debug_printk("dv1394: DMA started\n");
-
-#if DV1394_DEBUG_LEVEL >= 2
-               {
-                       int i;
-
-                       for (i = 0; i < 1000; ++i) {
-                               mdelay(1);
-                               if (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) {
-                                       printk("DMA ACTIVE after %d msec\n", i);
-                                       break;
-                               }
-                       }
-                       if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {
-                               printk("DEAD, event = %x\n",
-                                          reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
-                       } else
-                               printk("RUNNING!\n");
-               }
-#endif
-       } else if ( reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) &  (1 << 11) ) {
-               debug_printk("DEAD, event = %x\n",
-                            reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & 0x1F);
-
-               /* wake */
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
-       }
-}
-
-
-/*
-   receive_packets() - build the DMA program for receiving
-*/
-
-static void receive_packets(struct video_card *video)
-{
-       struct DMA_descriptor_block *block = NULL;
-       dma_addr_t block_dma = 0;
-       struct packet *data = NULL;
-       dma_addr_t data_dma = 0;
-       __le32 *last_branch_address = NULL;
-       unsigned long irq_flags;
-       int want_interrupt = 0;
-       struct frame *f = NULL;
-       int i, j;
-
-       spin_lock_irqsave(&video->spinlock, irq_flags);
-
-       for (j = 0; j < video->n_frames; j++) {
-
-               /* connect frames */
-               if (j > 0 && f != NULL && f->frame_end_branch != NULL)
-                       *(f->frame_end_branch) = cpu_to_le32(video->frames[j]->descriptor_pool_dma | 1); /* set Z=1 */
-
-               f = video->frames[j];
-
-               for (i = 0; i < MAX_PACKETS; i++) {
-                       /* locate a descriptor block and packet from the buffer */
-                       block = &(f->descriptor_pool[i]);
-                       block_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;
-
-                       data = ((struct packet*)video->packet_buf.kvirt) + f->frame_num * MAX_PACKETS + i;
-                       data_dma = dma_region_offset_to_bus( &video->packet_buf,
-                                                            ((unsigned long) data - (unsigned long) video->packet_buf.kvirt) );
-
-                       /* setup DMA descriptor block */
-                       want_interrupt = ((i % (MAX_PACKETS/2)) == 0 || i == (MAX_PACKETS-1));
-                       fill_input_last( &(block->u.in.il), want_interrupt, 512, data_dma);
-
-                       /* link descriptors */
-                       last_branch_address = f->frame_end_branch;
-
-                       if (last_branch_address != NULL)
-                               *(last_branch_address) = cpu_to_le32(block_dma | 1); /* set Z=1 */
-
-                       f->frame_end_branch = &(block->u.in.il.q[2]);
-               }
-
-       } /* next j */
-
-       spin_unlock_irqrestore(&video->spinlock, irq_flags);
-
-}
-
-
-
-/*** MANAGEMENT FUNCTIONS **************************************************/
-
-static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
-{
-       unsigned long flags, new_buf_size;
-       int i;
-       u64 chan_mask;
-       int retval = -EINVAL;
-
-       debug_printk("dv1394: initialising %d\n", video->id);
-       if (init->api_version != DV1394_API_VERSION)
-               return -EINVAL;
-
-       /* first sanitize all the parameters */
-       if ( (init->n_frames < 2) || (init->n_frames > DV1394_MAX_FRAMES) )
-               return -EINVAL;
-
-       if ( (init->format != DV1394_NTSC) && (init->format != DV1394_PAL) )
-               return -EINVAL;
-
-       if ( (init->syt_offset == 0) || (init->syt_offset > 50) )
-               /* default SYT offset is 3 cycles */
-               init->syt_offset = 3;
-
-       if (init->channel > 63)
-               init->channel = 63;
-
-       chan_mask = (u64)1 << init->channel;
-
-       /* calculate what size DMA buffer is needed */
-       if (init->format == DV1394_NTSC)
-               new_buf_size = DV1394_NTSC_FRAME_SIZE * init->n_frames;
-       else
-               new_buf_size = DV1394_PAL_FRAME_SIZE * init->n_frames;
-
-       /* round up to PAGE_SIZE */
-       if (new_buf_size % PAGE_SIZE) new_buf_size += PAGE_SIZE - (new_buf_size % PAGE_SIZE);
-
-       /* don't allow the user to allocate the DMA buffer more than once */
-       if (video->dv_buf.kvirt && video->dv_buf_size != new_buf_size) {
-               printk("dv1394: re-sizing the DMA buffer is not allowed\n");
-               return -EINVAL;
-       }
-
-       /* shutdown the card if it's currently active */
-       /* (the card should not be reset if the parameters are screwy) */
-
-       do_dv1394_shutdown(video, 0);
-
-       /* try to claim the ISO channel */
-       spin_lock_irqsave(&video->ohci->IR_channel_lock, flags);
-       if (video->ohci->ISO_channel_usage & chan_mask) {
-               spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags);
-               retval = -EBUSY;
-               goto err;
-       }
-       video->ohci->ISO_channel_usage |= chan_mask;
-       spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags);
-
-       video->channel = init->channel;
-
-       /* initialize misc. fields of video */
-       video->n_frames = init->n_frames;
-       video->pal_or_ntsc = init->format;
-
-       video->cip_accum = 0;
-       video->continuity_counter = 0;
-
-       video->active_frame = -1;
-       video->first_clear_frame = 0;
-       video->n_clear_frames = video->n_frames;
-       video->dropped_frames = 0;
-
-       video->write_off = 0;
-
-       video->first_run = 1;
-       video->current_packet = -1;
-       video->first_frame = 0;
-
-       if (video->pal_or_ntsc == DV1394_NTSC) {
-               video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_NTSC;
-               video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_NTSC;
-               video->frame_size = DV1394_NTSC_FRAME_SIZE;
-       } else {
-               video->cip_n = init->cip_n != 0 ? init->cip_n : CIP_N_PAL;
-               video->cip_d = init->cip_d != 0 ? init->cip_d : CIP_D_PAL;
-               video->frame_size = DV1394_PAL_FRAME_SIZE;
-       }
-
-       video->syt_offset = init->syt_offset;
-
-       /* find and claim DMA contexts on the OHCI card */
-
-       if (video->ohci_it_ctx == -1) {
-               ohci1394_init_iso_tasklet(&video->it_tasklet, OHCI_ISO_TRANSMIT,
-                                         it_tasklet_func, (unsigned long) video);
-
-               if (ohci1394_register_iso_tasklet(video->ohci, &video->it_tasklet) < 0) {
-                       printk(KERN_ERR "dv1394: could not find an available IT DMA context\n");
-                       retval = -EBUSY;
-                       goto err;
-               }
-
-               video->ohci_it_ctx = video->it_tasklet.context;
-               debug_printk("dv1394: claimed IT DMA context %d\n", video->ohci_it_ctx);
-       }
-
-       if (video->ohci_ir_ctx == -1) {
-               ohci1394_init_iso_tasklet(&video->ir_tasklet, OHCI_ISO_RECEIVE,
-                                         ir_tasklet_func, (unsigned long) video);
-
-               if (ohci1394_register_iso_tasklet(video->ohci, &video->ir_tasklet) < 0) {
-                       printk(KERN_ERR "dv1394: could not find an available IR DMA context\n");
-                       retval = -EBUSY;
-                       goto err;
-               }
-               video->ohci_ir_ctx = video->ir_tasklet.context;
-               debug_printk("dv1394: claimed IR DMA context %d\n", video->ohci_ir_ctx);
-       }
-
-       /* allocate struct frames */
-       for (i = 0; i < init->n_frames; i++) {
-               video->frames[i] = frame_new(i, video);
-
-               if (!video->frames[i]) {
-                       printk(KERN_ERR "dv1394: Cannot allocate frame structs\n");
-                       retval = -ENOMEM;
-                       goto err;
-               }
-       }
-
-       if (!video->dv_buf.kvirt) {
-               /* allocate the ringbuffer */
-               retval = dma_region_alloc(&video->dv_buf, new_buf_size, video->ohci->dev, PCI_DMA_TODEVICE);
-               if (retval)
-                       goto err;
-
-               video->dv_buf_size = new_buf_size;
-
-               debug_printk("dv1394: Allocated %d frame buffers, total %u pages (%u DMA pages), %lu bytes\n", 
-                            video->n_frames, video->dv_buf.n_pages,
-                            video->dv_buf.n_dma_pages, video->dv_buf_size);
-       }
-
-       /* set up the frame->data pointers */
-       for (i = 0; i < video->n_frames; i++)
-               video->frames[i]->data = (unsigned long) video->dv_buf.kvirt + i * video->frame_size;
-
-       if (!video->packet_buf.kvirt) {
-               /* allocate packet buffer */
-               video->packet_buf_size = sizeof(struct packet) * video->n_frames * MAX_PACKETS;
-               if (video->packet_buf_size % PAGE_SIZE)
-                       video->packet_buf_size += PAGE_SIZE - (video->packet_buf_size % PAGE_SIZE);
-
-               retval = dma_region_alloc(&video->packet_buf, video->packet_buf_size,
-                                         video->ohci->dev, PCI_DMA_FROMDEVICE);
-               if (retval)
-                       goto err;
-
-               debug_printk("dv1394: Allocated %d packets in buffer, total %u pages (%u DMA pages), %lu bytes\n",
-                                video->n_frames*MAX_PACKETS, video->packet_buf.n_pages,
-                                video->packet_buf.n_dma_pages, video->packet_buf_size);
-       }
-
-       /* set up register offsets for IT context */
-       /* IT DMA context registers are spaced 16 bytes apart */
-       video->ohci_IsoXmitContextControlSet = OHCI1394_IsoXmitContextControlSet+16*video->ohci_it_ctx;
-       video->ohci_IsoXmitContextControlClear = OHCI1394_IsoXmitContextControlClear+16*video->ohci_it_ctx;
-       video->ohci_IsoXmitCommandPtr = OHCI1394_IsoXmitCommandPtr+16*video->ohci_it_ctx;
-
-       /* enable interrupts for IT context */
-       reg_write(video->ohci, OHCI1394_IsoXmitIntMaskSet, (1 << video->ohci_it_ctx));
-       debug_printk("dv1394: interrupts enabled for IT context %d\n", video->ohci_it_ctx);
-
-       /* set up register offsets for IR context */
-       /* IR DMA context registers are spaced 32 bytes apart */
-       video->ohci_IsoRcvContextControlSet = OHCI1394_IsoRcvContextControlSet+32*video->ohci_ir_ctx;
-       video->ohci_IsoRcvContextControlClear = OHCI1394_IsoRcvContextControlClear+32*video->ohci_ir_ctx;
-       video->ohci_IsoRcvCommandPtr = OHCI1394_IsoRcvCommandPtr+32*video->ohci_ir_ctx;
-       video->ohci_IsoRcvContextMatch = OHCI1394_IsoRcvContextMatch+32*video->ohci_ir_ctx;
-
-       /* enable interrupts for IR context */
-       reg_write(video->ohci, OHCI1394_IsoRecvIntMaskSet, (1 << video->ohci_ir_ctx) );
-       debug_printk("dv1394: interrupts enabled for IR context %d\n", video->ohci_ir_ctx);
-
-       return 0;
-
-err:
-       do_dv1394_shutdown(video, 1);
-       return retval;
-}
-
-/* if the user doesn't bother to call ioctl(INIT) before starting
-   mmap() or read()/write(), just give him some default values */
-
-static int do_dv1394_init_default(struct video_card *video)
-{
-       struct dv1394_init init;
-
-       init.api_version = DV1394_API_VERSION;
-       init.n_frames = DV1394_MAX_FRAMES / 4;
-       init.channel = video->channel;
-       init.format = video->pal_or_ntsc;
-       init.cip_n = video->cip_n;
-       init.cip_d = video->cip_d;
-       init.syt_offset = video->syt_offset;
-
-       return do_dv1394_init(video, &init);
-}
-
-/* do NOT call from interrupt context */
-static void stop_dma(struct video_card *video)
-{
-       unsigned long flags;
-       int i;
-
-       /* no interrupts */
-       spin_lock_irqsave(&video->spinlock, flags);
-
-       video->dma_running = 0;
-
-       if ( (video->ohci_it_ctx == -1) && (video->ohci_ir_ctx == -1) )
-               goto out;
-
-       /* stop DMA if in progress */
-       if ( (video->active_frame != -1) ||
-           (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) ||
-           (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) &  (1 << 10)) ) {
-
-               /* clear the .run bits */
-               reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, (1 << 15));
-               reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, (1 << 15));
-               flush_pci_write(video->ohci);
-
-               video->active_frame = -1;
-               video->first_run = 1;
-
-               /* wait until DMA really stops */
-               i = 0;
-               while (i < 1000) {
-
-                       /* wait 0.1 millisecond */
-                       udelay(100);
-
-                       if ( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) ||
-                           (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear)  & (1 << 10)) ) {
-                               /* still active */
-                               debug_printk("dv1394: stop_dma: DMA not stopped yet\n" );
-                               mb();
-                       } else {
-                               debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10);
-                               break;
-                       }
-
-                       i++;
-               }
-
-               if (i == 1000) {
-                       printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10);
-               }
-       }
-       else
-               debug_printk("dv1394: stop_dma: already stopped.\n");
-
-out:
-       spin_unlock_irqrestore(&video->spinlock, flags);
-}
-
-
-
-static void do_dv1394_shutdown(struct video_card *video, int free_dv_buf)
-{
-       int i;
-
-       debug_printk("dv1394: shutdown...\n");
-
-       /* stop DMA if in progress */
-       stop_dma(video);
-
-       /* release the DMA contexts */
-       if (video->ohci_it_ctx != -1) {
-               video->ohci_IsoXmitContextControlSet = 0;
-               video->ohci_IsoXmitContextControlClear = 0;
-               video->ohci_IsoXmitCommandPtr = 0;
-
-               /* disable interrupts for IT context */
-               reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx));
-
-               /* remove tasklet */
-               ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet);
-               debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx);
-               video->ohci_it_ctx = -1;
-       }
-
-       if (video->ohci_ir_ctx != -1) {
-               video->ohci_IsoRcvContextControlSet = 0;
-               video->ohci_IsoRcvContextControlClear = 0;
-               video->ohci_IsoRcvCommandPtr = 0;
-               video->ohci_IsoRcvContextMatch = 0;
-
-               /* disable interrupts for IR context */
-               reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx));
-
-               /* remove tasklet */
-               ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet);
-               debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx);
-               video->ohci_ir_ctx = -1;
-       }
-
-       /* release the ISO channel */
-       if (video->channel != -1) {
-               u64 chan_mask;
-               unsigned long flags;
-
-               chan_mask = (u64)1 << video->channel;
-
-               spin_lock_irqsave(&video->ohci->IR_channel_lock, flags);
-               video->ohci->ISO_channel_usage &= ~(chan_mask);
-               spin_unlock_irqrestore(&video->ohci->IR_channel_lock, flags);
-
-               video->channel = -1;
-       }
-
-       /* free the frame structs */
-       for (i = 0; i < DV1394_MAX_FRAMES; i++) {
-               if (video->frames[i])
-                       frame_delete(video->frames[i]);
-               video->frames[i] = NULL;
-       }
-
-       video->n_frames = 0;
-
-       /* we can't free the DMA buffer unless it is guaranteed that
-          no more user-space mappings exist */
-
-       if (free_dv_buf) {
-               dma_region_free(&video->dv_buf);
-               video->dv_buf_size = 0;
-       }
-
-       /* free packet buffer */
-       dma_region_free(&video->packet_buf);
-       video->packet_buf_size = 0;
-
-       debug_printk("dv1394: shutdown OK\n");
-}
-
-/*
-       **********************************
-       *** MMAP() THEORY OF OPERATION ***
-       **********************************
-
-        The ringbuffer cannot be re-allocated or freed while
-        a user program maintains a mapping of it. (note that a mapping
-       can persist even after the device fd is closed!)
-
-       So, only let the user process allocate the DMA buffer once.
-       To resize or deallocate it, you must close the device file
-       and open it again.
-
-       Previously Dan M. hacked out a scheme that allowed the DMA
-       buffer to change by forcefully unmapping it from the user's
-       address space. It was prone to error because it's very hard to
-       track all the places the buffer could have been mapped (we
-       would have had to walk the vma list of every process in the
-       system to be sure we found all the mappings!). Instead, we
-       force the user to choose one buffer size and stick with
-       it. This small sacrifice is worth the huge reduction in
-       error-prone code in dv1394.
-*/
-
-static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct video_card *video = file_to_video_card(file);
-       int retval = -EINVAL;
-
-       /*
-        * We cannot use the blocking variant mutex_lock here because .mmap
-        * is called with mmap_sem held, while .ioctl, .read, .write acquire
-        * video->mtx and subsequently call copy_to/from_user which will
-        * grab mmap_sem in case of a page fault.
-        */
-       if (!mutex_trylock(&video->mtx))
-               return -EAGAIN;
-
-       if ( ! video_card_initialized(video) ) {
-               retval = do_dv1394_init_default(video);
-               if (retval)
-                       goto out;
-       }
-
-       retval = dma_region_mmap(&video->dv_buf, file, vma);
-out:
-       mutex_unlock(&video->mtx);
-       return retval;
-}
-
-/*** DEVICE FILE INTERFACE *************************************************/
-
-/* no need to serialize, multiple threads OK */
-static unsigned int dv1394_poll(struct file *file, struct poll_table_struct *wait)
-{
-       struct video_card *video = file_to_video_card(file);
-       unsigned int mask = 0;
-       unsigned long flags;
-
-       poll_wait(file, &video->waitq, wait);
-
-       spin_lock_irqsave(&video->spinlock, flags);
-       if ( video->n_frames == 0 ) {
-
-       } else if ( video->active_frame == -1 ) {
-               /* nothing going on */
-               mask |= POLLOUT;
-       } else {
-               /* any clear/ready buffers? */
-               if (video->n_clear_frames >0)
-                       mask |= POLLOUT | POLLIN;
-       }
-       spin_unlock_irqrestore(&video->spinlock, flags);
-
-       return mask;
-}
-
-static int dv1394_fasync(int fd, struct file *file, int on)
-{
-       /* I just copied this code verbatim from Alan Cox's mouse driver example
-          (Documentation/DocBook/) */
-
-       struct video_card *video = file_to_video_card(file);
-
-       return fasync_helper(fd, file, on, &video->fasync);
-}
-
-static ssize_t dv1394_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
-{
-       struct video_card *video = file_to_video_card(file);
-       DECLARE_WAITQUEUE(wait, current);
-       ssize_t ret;
-       size_t cnt;
-       unsigned long flags;
-       int target_frame;
-
-       /* serialize this to prevent multi-threaded mayhem */
-       if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&video->mtx))
-                       return -EAGAIN;
-       } else {
-               if (mutex_lock_interruptible(&video->mtx))
-                       return -ERESTARTSYS;
-       }
-
-       if ( !video_card_initialized(video) ) {
-               ret = do_dv1394_init_default(video);
-               if (ret) {
-                       mutex_unlock(&video->mtx);
-                       return ret;
-               }
-       }
-
-       ret = 0;
-       add_wait_queue(&video->waitq, &wait);
-
-       while (count > 0) {
-
-               /* must set TASK_INTERRUPTIBLE *before* checking for free
-                  buffers; otherwise we could miss a wakeup if the interrupt
-                  fires between the check and the schedule() */
-
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               target_frame = video->first_clear_frame;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               if (video->frames[target_frame]->state == FRAME_CLEAR) {
-
-                       /* how much room is left in the target frame buffer */
-                       cnt = video->frame_size - (video->write_off - target_frame * video->frame_size);
-
-               } else {
-                       /* buffer is already used */
-                       cnt = 0;
-               }
-
-               if (cnt > count)
-                       cnt = count;
-
-               if (cnt <= 0) {
-                       /* no room left, gotta wait */
-                       if (file->f_flags & O_NONBLOCK) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               if (!ret)
-                                       ret = -ERESTARTSYS;
-                               break;
-                       }
-
-                       schedule();
-
-                       continue; /* start over from 'while(count > 0)...' */
-               }
-
-               if (copy_from_user(video->dv_buf.kvirt + video->write_off, buffer, cnt)) {
-                       if (!ret)
-                               ret = -EFAULT;
-                       break;
-               }
-
-               video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size);
-
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-
-               if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames))
-                               frame_prepare(video, target_frame);
-       }
-
-       remove_wait_queue(&video->waitq, &wait);
-       set_current_state(TASK_RUNNING);
-       mutex_unlock(&video->mtx);
-       return ret;
-}
-
-
-static ssize_t dv1394_read(struct file *file,  char __user *buffer, size_t count, loff_t *ppos)
-{
-       struct video_card *video = file_to_video_card(file);
-       DECLARE_WAITQUEUE(wait, current);
-       ssize_t ret;
-       size_t cnt;
-       unsigned long flags;
-       int target_frame;
-
-       /* serialize this to prevent multi-threaded mayhem */
-       if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&video->mtx))
-                       return -EAGAIN;
-       } else {
-               if (mutex_lock_interruptible(&video->mtx))
-                       return -ERESTARTSYS;
-       }
-
-       if ( !video_card_initialized(video) ) {
-               ret = do_dv1394_init_default(video);
-               if (ret) {
-                       mutex_unlock(&video->mtx);
-                       return ret;
-               }
-               video->continuity_counter = -1;
-
-               receive_packets(video);
-
-               start_dma_receive(video);
-       }
-
-       ret = 0;
-       add_wait_queue(&video->waitq, &wait);
-
-       while (count > 0) {
-
-               /* must set TASK_INTERRUPTIBLE *before* checking for free
-                  buffers; otherwise we could miss a wakeup if the interrupt
-                  fires between the check and the schedule() */
-
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               target_frame = video->first_clear_frame;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               if (target_frame >= 0 &&
-                       video->n_clear_frames > 0 &&
-                       video->frames[target_frame]->state == FRAME_CLEAR) {
-
-                       /* how much room is left in the target frame buffer */
-                       cnt = video->frame_size - (video->write_off - target_frame * video->frame_size);
-
-               } else {
-                       /* buffer is already used */
-                       cnt = 0;
-               }
-
-               if (cnt > count)
-                       cnt = count;
-
-               if (cnt <= 0) {
-                       /* no room left, gotta wait */
-                       if (file->f_flags & O_NONBLOCK) {
-                               if (!ret)
-                                       ret = -EAGAIN;
-                               break;
-                       }
-                       if (signal_pending(current)) {
-                               if (!ret)
-                                       ret = -ERESTARTSYS;
-                               break;
-                       }
-
-                       schedule();
-
-                       continue; /* start over from 'while(count > 0)...' */
-               }
-
-               if (copy_to_user(buffer, video->dv_buf.kvirt + video->write_off, cnt)) {
-                               if (!ret)
-                                       ret = -EFAULT;
-                               break;
-               }
-
-               video->write_off = (video->write_off + cnt) % (video->n_frames * video->frame_size);
-
-               count -= cnt;
-               buffer += cnt;
-               ret += cnt;
-
-               if (video->write_off == video->frame_size * ((target_frame + 1) % video->n_frames)) {
-                       spin_lock_irqsave(&video->spinlock, flags);
-                       video->n_clear_frames--;
-                       video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
-                       spin_unlock_irqrestore(&video->spinlock, flags);
-               }
-       }
-
-       remove_wait_queue(&video->waitq, &wait);
-       set_current_state(TASK_RUNNING);
-       mutex_unlock(&video->mtx);
-       return ret;
-}
-
-
-/*** DEVICE IOCTL INTERFACE ************************************************/
-
-static long dv1394_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct video_card *video = file_to_video_card(file);
-       unsigned long flags;
-       int ret = -EINVAL;
-       void __user *argp = (void __user *)arg;
-
-       DECLARE_WAITQUEUE(wait, current);
-
-       /* serialize this to prevent multi-threaded mayhem */
-       if (file->f_flags & O_NONBLOCK) {
-               if (!mutex_trylock(&video->mtx))
-                       return -EAGAIN;
-       } else {
-               if (mutex_lock_interruptible(&video->mtx))
-                       return -ERESTARTSYS;
-       }
-
-       switch(cmd)
-       {
-       case DV1394_IOC_SUBMIT_FRAMES: {
-               unsigned int n_submit;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = do_dv1394_init_default(video);
-                       if (ret)
-                               goto out;
-               }
-
-               n_submit = (unsigned int) arg;
-
-               if (n_submit > video->n_frames) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               while (n_submit > 0) {
-
-                       add_wait_queue(&video->waitq, &wait);
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       spin_lock_irqsave(&video->spinlock, flags);
-
-                       /* wait until video->first_clear_frame is really CLEAR */
-                       while (video->frames[video->first_clear_frame]->state != FRAME_CLEAR) {
-
-                               spin_unlock_irqrestore(&video->spinlock, flags);
-
-                               if (signal_pending(current)) {
-                                       remove_wait_queue(&video->waitq, &wait);
-                                       set_current_state(TASK_RUNNING);
-                                       ret = -EINTR;
-                                       goto out;
-                               }
-
-                               schedule();
-                               set_current_state(TASK_INTERRUPTIBLE);
-
-                               spin_lock_irqsave(&video->spinlock, flags);
-                       }
-                       spin_unlock_irqrestore(&video->spinlock, flags);
-
-                       remove_wait_queue(&video->waitq, &wait);
-                       set_current_state(TASK_RUNNING);
-
-                       frame_prepare(video, video->first_clear_frame);
-
-                       n_submit--;
-               }
-
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_WAIT_FRAMES: {
-               unsigned int n_wait;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               n_wait = (unsigned int) arg;
-
-               /* since we re-run the last frame on underflow, we will
-                  never actually have n_frames clear frames; at most only
-                  n_frames - 1 */
-
-               if (n_wait > (video->n_frames-1) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               add_wait_queue(&video->waitq, &wait);
-               set_current_state(TASK_INTERRUPTIBLE);
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               while (video->n_clear_frames < n_wait) {
-
-                       spin_unlock_irqrestore(&video->spinlock, flags);
-
-                       if (signal_pending(current)) {
-                               remove_wait_queue(&video->waitq, &wait);
-                               set_current_state(TASK_RUNNING);
-                               ret = -EINTR;
-                               goto out;
-                       }
-
-                       schedule();
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       spin_lock_irqsave(&video->spinlock, flags);
-               }
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               remove_wait_queue(&video->waitq, &wait);
-               set_current_state(TASK_RUNNING);
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_RECEIVE_FRAMES: {
-               unsigned int n_recv;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               n_recv = (unsigned int) arg;
-
-               /* at least one frame must be active */
-               if (n_recv > (video->n_frames-1) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               /* release the clear frames */
-               video->n_clear_frames -= n_recv;
-
-               /* advance the clear frame cursor */
-               video->first_clear_frame = (video->first_clear_frame + n_recv) % video->n_frames;
-
-               /* reset dropped_frames */
-               video->dropped_frames = 0;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_START_RECEIVE: {
-               if ( !video_card_initialized(video) ) {
-                       ret = do_dv1394_init_default(video);
-                       if (ret)
-                               goto out;
-               }
-
-               video->continuity_counter = -1;
-
-               receive_packets(video);
-
-               start_dma_receive(video);
-
-               ret = 0;
-               break;
-       }
-
-       case DV1394_IOC_INIT: {
-               struct dv1394_init init;
-               if (!argp) {
-                       ret = do_dv1394_init_default(video);
-               } else {
-                       if (copy_from_user(&init, argp, sizeof(init))) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       ret = do_dv1394_init(video, &init);
-               }
-               break;
-       }
-
-       case DV1394_IOC_SHUTDOWN:
-               do_dv1394_shutdown(video, 0);
-               ret = 0;
-               break;
-
-
-        case DV1394_IOC_GET_STATUS: {
-               struct dv1394_status status;
-
-               if ( !video_card_initialized(video) ) {
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               status.init.api_version = DV1394_API_VERSION;
-               status.init.channel = video->channel;
-               status.init.n_frames = video->n_frames;
-               status.init.format = video->pal_or_ntsc;
-               status.init.cip_n = video->cip_n;
-               status.init.cip_d = video->cip_d;
-               status.init.syt_offset = video->syt_offset;
-
-               status.first_clear_frame = video->first_clear_frame;
-
-               /* the rest of the fields need to be locked against the interrupt */
-               spin_lock_irqsave(&video->spinlock, flags);
-
-               status.active_frame = video->active_frame;
-               status.n_clear_frames = video->n_clear_frames;
-
-               status.dropped_frames = video->dropped_frames;
-
-               /* reset dropped_frames */
-               video->dropped_frames = 0;
-
-               spin_unlock_irqrestore(&video->spinlock, flags);
-
-               if (copy_to_user(argp, &status, sizeof(status))) {
-                       ret = -EFAULT;
-                       goto out;
-               }
-
-               ret = 0;
-               break;
-       }
-
-       default:
-               break;
-       }
-
- out:
-       mutex_unlock(&video->mtx);
-       return ret;
-}
-
-/*** DEVICE FILE INTERFACE CONTINUED ***************************************/
-
-static int dv1394_open(struct inode *inode, struct file *file)
-{
-       struct video_card *video = NULL;
-
-       if (file->private_data) {
-               video = file->private_data;
-
-       } else {
-               /* look up the card by ID */
-               unsigned long flags;
-               int idx = ieee1394_file_to_instance(file);
-
-               spin_lock_irqsave(&dv1394_cards_lock, flags);
-               if (!list_empty(&dv1394_cards)) {
-                       struct video_card *p;
-                       list_for_each_entry(p, &dv1394_cards, list) {
-                               if ((p->id) == idx) {
-                                       video = p;
-                                       break;
-                               }
-                       }
-               }
-               spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-               if (!video) {
-                       debug_printk("dv1394: OHCI card %d not found", idx);
-                       return -ENODEV;
-               }
-
-               file->private_data = (void*) video;
-       }
-
-#ifndef DV1394_ALLOW_MORE_THAN_ONE_OPEN
-
-       if ( test_and_set_bit(0, &video->open) ) {
-               /* video is already open by someone else */
-               return -EBUSY;
-       }
-
-#endif
-
-       printk(KERN_INFO "%s: NOTE, the dv1394 interface is unsupported "
-              "and will not be available in the new firewire driver stack. "
-              "Try libraw1394 based programs instead.\n", current->comm);
-
-       return nonseekable_open(inode, file);
-}
-
-
-static int dv1394_release(struct inode *inode, struct file *file)
-{
-       struct video_card *video = file_to_video_card(file);
-
-       /* OK to free the DMA buffer, no more mappings can exist */
-       do_dv1394_shutdown(video, 1);
-
-       /* give someone else a turn */
-       clear_bit(0, &video->open);
-
-       return 0;
-}
-
-
-/*** DEVICE DRIVER HANDLERS ************************************************/
-
-static void it_tasklet_func(unsigned long data)
-{
-       int wake = 0;
-       struct video_card *video = (struct video_card*) data;
-
-       spin_lock(&video->spinlock);
-
-       if (!video->dma_running)
-               goto out;
-
-       irq_printk("ContextControl = %08x, CommandPtr = %08x\n",
-              reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-              reg_read(video->ohci, video->ohci_IsoXmitCommandPtr)
-              );
-
-
-       if ( (video->ohci_it_ctx != -1) &&
-           (reg_read(video->ohci, video->ohci_IsoXmitContextControlSet) & (1 << 10)) ) {
-
-               struct frame *f;
-               unsigned int frame, i;
-
-
-               if (video->active_frame == -1)
-                       frame = 0;
-               else
-                       frame = video->active_frame;
-
-               /* check all the DMA-able frames */
-               for (i = 0; i < video->n_frames; i++, frame = (frame+1) % video->n_frames) {
-
-                       irq_printk("IRQ checking frame %d...", frame);
-                       f = video->frames[frame];
-                       if (f->state != FRAME_READY) {
-                               irq_printk("clear, skipping\n");
-                               /* we don't own this frame */
-                               continue;
-                       }
-
-                       irq_printk("DMA\n");
-
-                       /* check the frame begin semaphore to see if we can free the previous frame */
-                       if ( *(f->frame_begin_timestamp) ) {
-                               int prev_frame;
-                               struct frame *prev_f;
-
-
-
-                               /* don't reset, need this later *(f->frame_begin_timestamp) = 0; */
-                               irq_printk("  BEGIN\n");
-
-                               prev_frame = frame - 1;
-                               if (prev_frame == -1)
-                                       prev_frame += video->n_frames;
-                               prev_f = video->frames[prev_frame];
-
-                               /* make sure we can actually garbage collect
-                                  this frame */
-                               if ( (prev_f->state == FRAME_READY) &&
-                                   prev_f->done && (!f->done) )
-                               {
-                                       frame_reset(prev_f);
-                                       video->n_clear_frames++;
-                                       wake = 1;
-                                       video->active_frame = frame;
-
-                                       irq_printk("  BEGIN - freeing previous frame %d, new active frame is %d\n", prev_frame, frame);
-                               } else {
-                                       irq_printk("  BEGIN - can't free yet\n");
-                               }
-
-                               f->done = 1;
-                       }
-
-
-                       /* see if we need to set the timestamp for the next frame */
-                       if ( *(f->mid_frame_timestamp) ) {
-                               struct frame *next_frame;
-                               u32 begin_ts, ts_cyc, ts_off;
-
-                               *(f->mid_frame_timestamp) = 0;
-
-                               begin_ts = le32_to_cpu(*(f->frame_begin_timestamp));
-
-                               irq_printk("  MIDDLE - first packet was sent at cycle %4u (%2u), assigned timestamp was (%2u) %4u\n",
-                                          begin_ts & 0x1FFF, begin_ts & 0xF,
-                                          f->assigned_timestamp >> 12, f->assigned_timestamp & 0xFFF);
-
-                               /* prepare next frame and assign timestamp */
-                               next_frame = video->frames[ (frame+1) % video->n_frames ];
-
-                               if (next_frame->state == FRAME_READY) {
-                                       irq_printk("  MIDDLE - next frame is ready, good\n");
-                               } else {
-                                       debug_printk("dv1394: Underflow! At least one frame has been dropped.\n");
-                                       next_frame = f;
-                               }
-
-                               /* set the timestamp to the timestamp of the last frame sent,
-                                  plus the length of the last frame sent, plus the syt latency */
-                               ts_cyc = begin_ts & 0xF;
-                               /* advance one frame, plus syt latency (typically 2-3) */
-                               ts_cyc += f->n_packets + video->syt_offset ;
-
-                               ts_off = 0;
-
-                               ts_cyc += ts_off/3072;
-                               ts_off %= 3072;
-
-                               next_frame->assigned_timestamp = ((ts_cyc&0xF) << 12) + ts_off;
-                               if (next_frame->cip_syt1) {
-                                       next_frame->cip_syt1->b[6] = next_frame->assigned_timestamp >> 8;
-                                       next_frame->cip_syt1->b[7] = next_frame->assigned_timestamp & 0xFF;
-                               }
-                               if (next_frame->cip_syt2) {
-                                       next_frame->cip_syt2->b[6] = next_frame->assigned_timestamp >> 8;
-                                       next_frame->cip_syt2->b[7] = next_frame->assigned_timestamp & 0xFF;
-                               }
-
-                       }
-
-                       /* see if the frame looped */
-                       if ( *(f->frame_end_timestamp) ) {
-
-                               *(f->frame_end_timestamp) = 0;
-
-                               debug_printk("  END - the frame looped at least once\n");
-
-                               video->dropped_frames++;
-                       }
-
-               } /* for (each frame) */
-       }
-
-       if (wake) {
-               kill_fasync(&video->fasync, SIGIO, POLL_OUT);
-
-               /* wake readers/writers/ioctl'ers */
-               wake_up_interruptible(&video->waitq);
-       }
-
-out:
-       spin_unlock(&video->spinlock);
-}
-
-static void ir_tasklet_func(unsigned long data)
-{
-       int wake = 0;
-       struct video_card *video = (struct video_card*) data;
-
-       spin_lock(&video->spinlock);
-
-       if (!video->dma_running)
-               goto out;
-
-       if ( (video->ohci_ir_ctx != -1) &&
-           (reg_read(video->ohci, video->ohci_IsoRcvContextControlSet) & (1 << 10)) ) {
-
-               int sof=0; /* start-of-frame flag */
-               struct frame *f;
-               u16 packet_length;
-               int i, dbc=0;
-               struct DMA_descriptor_block *block = NULL;
-               u16 xferstatus;
-
-               int next_i, prev_i;
-               struct DMA_descriptor_block *next = NULL;
-               dma_addr_t next_dma = 0;
-               struct DMA_descriptor_block *prev = NULL;
-
-               /* loop over all descriptors in all frames */
-               for (i = 0; i < video->n_frames*MAX_PACKETS; i++) {
-                       struct packet *p = dma_region_i(&video->packet_buf, struct packet, video->current_packet);
-
-                       /* make sure we are seeing the latest changes to p */
-                       dma_region_sync_for_cpu(&video->packet_buf,
-                                               (unsigned long) p - (unsigned long) video->packet_buf.kvirt,
-                                               sizeof(struct packet));
-
-                       packet_length = le16_to_cpu(p->data_length);
-
-                       /* get the descriptor based on packet_buffer cursor */
-                       f = video->frames[video->current_packet / MAX_PACKETS];
-                       block = &(f->descriptor_pool[video->current_packet % MAX_PACKETS]);
-                       xferstatus = le32_to_cpu(block->u.in.il.q[3]) >> 16;
-                       xferstatus &= 0x1F;
-                       irq_printk("ir_tasklet_func: xferStatus/resCount [%d] = 0x%08x\n", i, le32_to_cpu(block->u.in.il.q[3]) );
-
-                       /* get the current frame */
-                       f = video->frames[video->active_frame];
-
-                       /* exclude empty packet */
-                       if (packet_length > 8 && xferstatus == 0x11) {
-                               /* check for start of frame */
-                               /* DRD> Changed to check section type ([0]>>5==0)
-                                  and dif sequence ([1]>>4==0) */
-                               sof = ( (p->data[0] >> 5) == 0 && (p->data[1] >> 4) == 0);
-
-                               dbc = (int) (p->cip_h1 >> 24);
-                               if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) )
-                               {
-                                       printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" );
-                                       video->dropped_frames += video->n_clear_frames + 1;
-                                       video->first_frame = 0;
-                                       video->n_clear_frames = 0;
-                                       video->first_clear_frame = -1;
-                               }
-                               video->continuity_counter = dbc;
-
-                               if (!video->first_frame) {
-                                       if (sof) {
-                                               video->first_frame = 1;
-                                       }
-
-                               } else if (sof) {
-                                       /* close current frame */
-                                       frame_reset(f);  /* f->state = STATE_CLEAR */
-                                       video->n_clear_frames++;
-                                       if (video->n_clear_frames > video->n_frames) {
-                                               video->dropped_frames++;
-                                               printk(KERN_WARNING "dv1394: dropped a frame during reception\n" );
-                                               video->n_clear_frames = video->n_frames-1;
-                                               video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
-                                       }
-                                       if (video->first_clear_frame == -1)
-                                               video->first_clear_frame = video->active_frame;
-
-                                       /* get the next frame */
-                                       video->active_frame = (video->active_frame + 1) % video->n_frames;
-                                       f = video->frames[video->active_frame];
-                                       irq_printk("   frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n",
-                                                  video->active_frame, video->n_clear_frames, video->first_clear_frame);
-                               }
-                               if (video->first_frame) {
-                                       if (sof) {
-                                               /* open next frame */
-                                               f->state = FRAME_READY;
-                                       }
-
-                                       /* copy to buffer */
-                                       if (f->n_packets > (video->frame_size / 480)) {
-                                               printk(KERN_ERR "frame buffer overflow during receive\n");
-                                       }
-
-                                       frame_put_packet(f, p);
-
-                               } /* first_frame */
-                       }
-
-                       /* stop, end of ready packets */
-                       else if (xferstatus == 0) {
-                               break;
-                       }
-
-                       /* reset xferStatus & resCount */
-                       block->u.in.il.q[3] = cpu_to_le32(512);
-
-                       /* terminate dma chain at this (next) packet */
-                       next_i = video->current_packet;
-                       f = video->frames[next_i / MAX_PACKETS];
-                       next = &(f->descriptor_pool[next_i % MAX_PACKETS]);
-                       next_dma = ((unsigned long) block - (unsigned long) f->descriptor_pool) + f->descriptor_pool_dma;
-                       next->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */
-                       next->u.in.il.q[2] = cpu_to_le32(0); /* disable branch */
-
-                       /* link previous to next */
-                       prev_i = (next_i == 0) ? (MAX_PACKETS * video->n_frames - 1) : (next_i - 1);
-                       f = video->frames[prev_i / MAX_PACKETS];
-                       prev = &(f->descriptor_pool[prev_i % MAX_PACKETS]);
-                       if (prev_i % (MAX_PACKETS/2)) {
-                               prev->u.in.il.q[0] &= ~cpu_to_le32(3 << 20); /* no interrupt */
-                       } else {
-                               prev->u.in.il.q[0] |= cpu_to_le32(3 << 20); /* enable interrupt */
-                       }
-                       prev->u.in.il.q[2] = cpu_to_le32(next_dma | 1); /* set Z=1 */
-                       wmb();
-
-                       /* wake up DMA in case it fell asleep */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
-
-                       /* advance packet_buffer cursor */
-                       video->current_packet = (video->current_packet + 1) % (MAX_PACKETS * video->n_frames);
-
-               } /* for all packets */
-
-               wake = 1; /* why the hell not? */
-
-       } /* receive interrupt */
-
-       if (wake) {
-               kill_fasync(&video->fasync, SIGIO, POLL_IN);
-
-               /* wake readers/writers/ioctl'ers */
-               wake_up_interruptible(&video->waitq);
-       }
-
-out:
-       spin_unlock(&video->spinlock);
-}
-
-static struct cdev dv1394_cdev;
-static const struct file_operations dv1394_fops=
-{
-       .owner =        THIS_MODULE,
-       .poll =         dv1394_poll,
-       .unlocked_ioctl = dv1394_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = dv1394_compat_ioctl,
-#endif
-       .mmap =         dv1394_mmap,
-       .open =         dv1394_open,
-       .write =        dv1394_write,
-       .read =         dv1394_read,
-       .release =      dv1394_release,
-       .fasync =       dv1394_fasync,
-       .llseek =       no_llseek,
-};
-
-
-/*** HOTPLUG STUFF **********************************************************/
-/*
- * Export information about protocols/devices supported by this driver.
- */
-#ifdef MODULE
-static const struct ieee1394_device_id dv1394_id_table[] = {
-       {
-               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-               .specifier_id   = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
-               .version        = AVC_SW_VERSION_ENTRY & 0xffffff
-       },
-       { }
-};
-
-MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table);
-#endif /* MODULE */
-
-static struct hpsb_protocol_driver dv1394_driver = {
-       .name = "dv1394",
-};
-
-
-/*** IEEE1394 HPSB CALLBACKS ***********************************************/
-
-static int dv1394_init(struct ti_ohci *ohci, enum pal_or_ntsc format, enum modes mode)
-{
-       struct video_card *video;
-       unsigned long flags;
-       int i;
-
-       video = kzalloc(sizeof(*video), GFP_KERNEL);
-       if (!video) {
-               printk(KERN_ERR "dv1394: cannot allocate video_card\n");
-               return -1;
-       }
-
-       video->ohci = ohci;
-       /* lower 2 bits of id indicate which of four "plugs"
-          per host */
-       video->id = ohci->host->id << 2;
-       if (format == DV1394_NTSC)
-               video->id |= mode;
-       else
-               video->id |= 2 + mode;
-
-       video->ohci_it_ctx = -1;
-       video->ohci_ir_ctx = -1;
-
-       video->ohci_IsoXmitContextControlSet = 0;
-       video->ohci_IsoXmitContextControlClear = 0;
-       video->ohci_IsoXmitCommandPtr = 0;
-
-       video->ohci_IsoRcvContextControlSet = 0;
-       video->ohci_IsoRcvContextControlClear = 0;
-       video->ohci_IsoRcvCommandPtr = 0;
-       video->ohci_IsoRcvContextMatch = 0;
-
-       video->n_frames = 0; /* flag that video is not initialized */
-       video->channel = 63; /* default to broadcast channel */
-       video->active_frame = -1;
-
-       /* initialize the following */
-       video->pal_or_ntsc = format;
-       video->cip_n = 0; /* 0 = use builtin default */
-       video->cip_d = 0;
-       video->syt_offset = 0;
-       video->mode = mode;
-
-       for (i = 0; i < DV1394_MAX_FRAMES; i++)
-               video->frames[i] = NULL;
-
-       dma_region_init(&video->dv_buf);
-       video->dv_buf_size = 0;
-       dma_region_init(&video->packet_buf);
-       video->packet_buf_size = 0;
-
-       clear_bit(0, &video->open);
-       spin_lock_init(&video->spinlock);
-       video->dma_running = 0;
-       mutex_init(&video->mtx);
-       init_waitqueue_head(&video->waitq);
-       video->fasync = NULL;
-
-       spin_lock_irqsave(&dv1394_cards_lock, flags);
-       INIT_LIST_HEAD(&video->list);
-       list_add_tail(&video->list, &dv1394_cards);
-       spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-       debug_printk("dv1394: dv1394_init() OK on ID %d\n", video->id);
-       return 0;
-}
-
-static void dv1394_remove_host(struct hpsb_host *host)
-{
-       struct video_card *video, *tmp_video;
-       unsigned long flags;
-       int found_ohci_card = 0;
-
-       do {
-               video = NULL;
-               spin_lock_irqsave(&dv1394_cards_lock, flags);
-               list_for_each_entry(tmp_video, &dv1394_cards, list) {
-                       if ((tmp_video->id >> 2) == host->id) {
-                               list_del(&tmp_video->list);
-                               video = tmp_video;
-                               found_ohci_card = 1;
-                               break;
-                       }
-               }
-               spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-               if (video) {
-                       do_dv1394_shutdown(video, 1);
-                       kfree(video);
-               }
-       } while (video);
-
-       if (found_ohci_card)
-               device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
-                          IEEE1394_MINOR_BLOCK_DV1394 * 16 + (host->id << 2)));
-}
-
-static void dv1394_add_host(struct hpsb_host *host)
-{
-       struct ti_ohci *ohci;
-       int id = host->id;
-
-       /* We only work with the OHCI-1394 driver */
-       if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-               return;
-
-       ohci = (struct ti_ohci *)host->hostdata;
-
-       device_create(hpsb_protocol_class, NULL,
-                     MKDEV(IEEE1394_MAJOR,
-                           IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)),
-                     NULL, "dv1394-%d", id);
-
-       dv1394_init(ohci, DV1394_NTSC, MODE_RECEIVE);
-       dv1394_init(ohci, DV1394_NTSC, MODE_TRANSMIT);
-       dv1394_init(ohci, DV1394_PAL, MODE_RECEIVE);
-       dv1394_init(ohci, DV1394_PAL, MODE_TRANSMIT);
-}
-
-
-/* Bus reset handler. In the event of a bus reset, we may need to
-   re-start the DMA contexts - otherwise the user program would
-   end up waiting forever.
-*/
-
-static void dv1394_host_reset(struct hpsb_host *host)
-{
-       struct video_card *video = NULL, *tmp_vid;
-       unsigned long flags;
-
-       /* We only work with the OHCI-1394 driver */
-       if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-               return;
-
-       /* find the corresponding video_cards */
-       spin_lock_irqsave(&dv1394_cards_lock, flags);
-       list_for_each_entry(tmp_vid, &dv1394_cards, list) {
-               if ((tmp_vid->id >> 2) == host->id) {
-                       video = tmp_vid;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&dv1394_cards_lock, flags);
-
-       if (!video)
-               return;
-
-
-       spin_lock_irqsave(&video->spinlock, flags);
-
-       if (!video->dma_running)
-               goto out;
-
-       /* check IT context */
-       if (video->ohci_it_ctx != -1) {
-               u32 ctx;
-
-               ctx = reg_read(video->ohci, video->ohci_IsoXmitContextControlSet);
-
-               /* if (RUN but not ACTIVE) */
-               if ( (ctx & (1<<15)) &&
-                   !(ctx & (1<<10)) ) {
-
-                       debug_printk("dv1394: IT context stopped due to bus reset; waking it up\n");
-
-                       /* to be safe, assume a frame has been dropped. User-space programs
-                          should handle this condition like an underflow. */
-                       video->dropped_frames++;
-
-                       /* for some reason you must clear, then re-set the RUN bit to restart DMA */
-
-                       /* clear RUN */
-                       reg_write(video->ohci, video->ohci_IsoXmitContextControlClear, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set RUN */
-                       reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set the WAKE bit (just in case; this isn't strictly necessary) */
-                       reg_write(video->ohci, video->ohci_IsoXmitContextControlSet, (1 << 12));
-                       flush_pci_write(video->ohci);
-
-                       irq_printk("dv1394: AFTER IT restart ctx 0x%08x ptr 0x%08x\n",
-                                  reg_read(video->ohci, video->ohci_IsoXmitContextControlSet),
-                                  reg_read(video->ohci, video->ohci_IsoXmitCommandPtr));
-               }
-       }
-
-       /* check IR context */
-       if (video->ohci_ir_ctx != -1) {
-               u32 ctx;
-
-               ctx = reg_read(video->ohci, video->ohci_IsoRcvContextControlSet);
-
-               /* if (RUN but not ACTIVE) */
-               if ( (ctx & (1<<15)) &&
-                   !(ctx & (1<<10)) ) {
-
-                       debug_printk("dv1394: IR context stopped due to bus reset; waking it up\n");
-
-                       /* to be safe, assume a frame has been dropped. User-space programs
-                          should handle this condition like an overflow. */
-                       video->dropped_frames++;
-
-                       /* for some reason you must clear, then re-set the RUN bit to restart DMA */
-                       /* XXX this doesn't work for me, I can't get IR DMA to restart :[ */
-
-                       /* clear RUN */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlClear, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set RUN */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 15));
-                       flush_pci_write(video->ohci);
-
-                       /* set the WAKE bit (just in case; this isn't strictly necessary) */
-                       reg_write(video->ohci, video->ohci_IsoRcvContextControlSet, (1 << 12));
-                       flush_pci_write(video->ohci);
-
-                       irq_printk("dv1394: AFTER IR restart ctx 0x%08x ptr 0x%08x\n",
-                                  reg_read(video->ohci, video->ohci_IsoRcvContextControlSet),
-                                  reg_read(video->ohci, video->ohci_IsoRcvCommandPtr));
-               }
-       }
-
-out:
-       spin_unlock_irqrestore(&video->spinlock, flags);
-
-       /* wake readers/writers/ioctl'ers */
-       wake_up_interruptible(&video->waitq);
-}
-
-static struct hpsb_highlevel dv1394_highlevel = {
-       .name =         "dv1394",
-       .add_host =     dv1394_add_host,
-       .remove_host =  dv1394_remove_host,
-       .host_reset =   dv1394_host_reset,
-};
-
-#ifdef CONFIG_COMPAT
-
-#define DV1394_IOC32_INIT       _IOW('#', 0x06, struct dv1394_init32)
-#define DV1394_IOC32_GET_STATUS _IOR('#', 0x0c, struct dv1394_status32)
-
-struct dv1394_init32 {
-       u32 api_version;
-       u32 channel;
-       u32 n_frames;
-       u32 format;
-       u32 cip_n;
-       u32 cip_d;
-       u32 syt_offset;
-};
-
-struct dv1394_status32 {
-       struct dv1394_init32 init;
-       s32 active_frame;
-       u32 first_clear_frame;
-       u32 n_clear_frames;
-       u32 dropped_frames;
-};
-
-/* RED-PEN: this should use compat_alloc_userspace instead */
-
-static int handle_dv1394_init(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct dv1394_init32 dv32;
-       struct dv1394_init dv;
-       mm_segment_t old_fs;
-       int ret;
-
-       if (file->f_op->unlocked_ioctl != dv1394_ioctl)
-               return -EFAULT;
-
-       if (copy_from_user(&dv32, (void __user *)arg, sizeof(dv32)))
-               return -EFAULT;
-
-       dv.api_version = dv32.api_version;
-       dv.channel = dv32.channel;
-       dv.n_frames = dv32.n_frames;
-       dv.format = dv32.format;
-       dv.cip_n = (unsigned long)dv32.cip_n;
-       dv.cip_d = (unsigned long)dv32.cip_d;
-       dv.syt_offset = dv32.syt_offset;
-
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = dv1394_ioctl(file, DV1394_IOC_INIT, (unsigned long)&dv);
-       set_fs(old_fs);
-
-       return ret;
-}
-
-static int handle_dv1394_get_status(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct dv1394_status32 dv32;
-       struct dv1394_status dv;
-       mm_segment_t old_fs;
-       int ret;
-
-       if (file->f_op->unlocked_ioctl != dv1394_ioctl)
-               return -EFAULT;
-
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = dv1394_ioctl(file, DV1394_IOC_GET_STATUS, (unsigned long)&dv);
-       set_fs(old_fs);
-
-       if (!ret) {
-               dv32.init.api_version = dv.init.api_version;
-               dv32.init.channel = dv.init.channel;
-               dv32.init.n_frames = dv.init.n_frames;
-               dv32.init.format = dv.init.format;
-               dv32.init.cip_n = (u32)dv.init.cip_n;
-               dv32.init.cip_d = (u32)dv.init.cip_d;
-               dv32.init.syt_offset = dv.init.syt_offset;
-               dv32.active_frame = dv.active_frame;
-               dv32.first_clear_frame = dv.first_clear_frame;
-               dv32.n_clear_frames = dv.n_clear_frames;
-               dv32.dropped_frames = dv.dropped_frames;
-
-               if (copy_to_user((struct dv1394_status32 __user *)arg, &dv32, sizeof(dv32)))
-                       ret = -EFAULT;
-       }
-
-       return ret;
-}
-
-
-
-static long dv1394_compat_ioctl(struct file *file, unsigned int cmd,
-                              unsigned long arg)
-{
-       switch (cmd) {
-       case DV1394_IOC_SHUTDOWN:
-       case DV1394_IOC_SUBMIT_FRAMES:
-       case DV1394_IOC_WAIT_FRAMES:
-       case DV1394_IOC_RECEIVE_FRAMES:
-       case DV1394_IOC_START_RECEIVE:
-               return dv1394_ioctl(file, cmd, arg);
-
-       case DV1394_IOC32_INIT:
-               return handle_dv1394_init(file, cmd, arg);
-       case DV1394_IOC32_GET_STATUS:
-               return handle_dv1394_get_status(file, cmd, arg);
-       default:
-               return -ENOIOCTLCMD;
-       }
-}
-
-#endif /* CONFIG_COMPAT */
-
-
-/*** KERNEL MODULE HANDLERS ************************************************/
-
-MODULE_AUTHOR("Dan Maas <dmaas@dcine.com>, Dan Dennedy <dan@dennedy.org>");
-MODULE_DESCRIPTION("driver for DV input/output on OHCI board");
-MODULE_SUPPORTED_DEVICE("dv1394");
-MODULE_LICENSE("GPL");
-
-static void __exit dv1394_exit_module(void)
-{
-       hpsb_unregister_protocol(&dv1394_driver);
-       hpsb_unregister_highlevel(&dv1394_highlevel);
-       cdev_del(&dv1394_cdev);
-}
-
-static int __init dv1394_init_module(void)
-{
-       int ret;
-
-       cdev_init(&dv1394_cdev, &dv1394_fops);
-       dv1394_cdev.owner = THIS_MODULE;
-       ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
-       if (ret) {
-               printk(KERN_ERR "dv1394: unable to register character device\n");
-               return ret;
-       }
-
-       hpsb_register_highlevel(&dv1394_highlevel);
-
-       ret = hpsb_register_protocol(&dv1394_driver);
-       if (ret) {
-               printk(KERN_ERR "dv1394: failed to register protocol\n");
-               hpsb_unregister_highlevel(&dv1394_highlevel);
-               cdev_del(&dv1394_cdev);
-               return ret;
-       }
-
-       return 0;
-}
-
-module_init(dv1394_init_module);
-module_exit(dv1394_exit_module);
diff --git a/drivers/ieee1394/dv1394.h b/drivers/ieee1394/dv1394.h
deleted file mode 100644 (file)
index 5807f52..0000000
+++ /dev/null
@@ -1,305 +0,0 @@
-/*
- * dv1394.h - DV input/output over IEEE 1394 on OHCI chips
- *   Copyright (C)2001 Daniel Maas <dmaas@dcine.com>
- *     receive by Dan Dennedy <dan@dennedy.org>
- *
- * based on:
- *   video1394.h - driver for OHCI 1394 boards
- *   Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                          Peter Schlaile <udbz@rz.uni-karlsruhe.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _DV_1394_H
-#define _DV_1394_H
-
-/* This is the public user-space interface. Try not to break it. */
-
-#define DV1394_API_VERSION 0x20011127
-
-/* ********************
-   **                **
-   **   DV1394 API   **
-   **                **
-   ********************
-
-   There are two methods of operating the DV1394 DV output device.
-
-   1)
-
-   The simplest is an interface based on write(): simply write
-   full DV frames of data to the device, and they will be transmitted
-   as quickly as possible. The FD may be set for non-blocking I/O,
-   in which case you can use select() or poll() to wait for output
-   buffer space.
-
-   To set the DV output parameters (e.g. whether you want NTSC or PAL
-   video), use the DV1394_INIT ioctl, passing in the parameters you
-   want in a struct dv1394_init.
-
-   Example 1:
-         To play a raw .DV file:   cat foo.DV > /dev/dv1394
-        (cat will use write() internally)
-
-   Example 2:
-           static struct dv1394_init init = {
-             0x63,        (broadcast channel)
-              4,           (four-frame ringbuffer)
-             DV1394_NTSC, (send NTSC video)
-             0, 0         (default empty packet rate)
-           }
-
-          ioctl(fd, DV1394_INIT, &init);
-
-          while (1) {
-                 read( <a raw DV file>, buf, DV1394_NTSC_FRAME_SIZE );
-                 write( <the dv1394 FD>, buf, DV1394_NTSC_FRAME_SIZE );
-           }
-
-   2)
-
-   For more control over buffering, and to avoid unnecessary copies
-   of the DV data, you can use the more sophisticated the mmap() interface.
-   First, call the DV1394_INIT ioctl to specify your parameters,
-   including the number of frames in the ringbuffer. Then, calling mmap()
-   on the dv1394 device will give you direct access to the ringbuffer
-   from which the DV card reads your frame data.
-
-   The ringbuffer is simply one large, contiguous region of memory
-   containing two or more frames of packed DV data. Each frame of DV data
-   is 120000 bytes (NTSC) or 144000 bytes (PAL).
-
-   Fill one or more frames in the ringbuffer, then use the DV1394_SUBMIT_FRAMES
-   ioctl to begin I/O. You can use either the DV1394_WAIT_FRAMES ioctl
-   or select()/poll() to wait until the frames are transmitted. Next, you'll
-   need to call the DV1394_GET_STATUS ioctl to determine which ringbuffer
-   frames are clear (ready to be filled with new DV data). Finally, use
-   DV1394_SUBMIT_FRAMES again to send the new data to the DV output.
-
-
-   Example: here is what a four-frame ringbuffer might look like
-            during DV transmission:
-
-
-         frame 0   frame 1   frame 2   frame 3
-
-       *--------------------------------------*
-        | CLEAR   | DV data | DV data | CLEAR  |
-        *--------------------------------------*
-                   <ACTIVE>
-
-       transmission goes in this direction --->>>
-
-
-   The DV hardware is currently transmitting the data in frame 1.
-   Once frame 1 is finished, it will automatically transmit frame 2.
-   (if frame 2 finishes before frame 3 is submitted, the device
-   will continue to transmit frame 2, and will increase the dropped_frames
-   counter each time it repeats the transmission).
-
-
-   If you called DV1394_GET_STATUS at this instant, you would
-   receive the following values:
-
-                  n_frames          = 4
-                 active_frame      = 1
-                 first_clear_frame = 3
-                 n_clear_frames    = 2
-
-   At this point, you should write new DV data into frame 3 and optionally
-   frame 0. Then call DV1394_SUBMIT_FRAMES to inform the device that
-   it may transmit the new frames.
-
-   ERROR HANDLING
-
-   An error (buffer underflow/overflow or a break in the DV stream due
-   to a 1394 bus reset) can be detected by checking the dropped_frames
-   field of struct dv1394_status (obtained through the
-   DV1394_GET_STATUS ioctl).
-
-   The best way to recover from such an error is to re-initialize
-   dv1394, either by using the DV1394_INIT ioctl call, or closing the
-   file descriptor and opening it again. (note that you must unmap all
-   ringbuffer mappings when closing the file descriptor, or else
-   dv1394 will still be considered 'in use').
-
-   MAIN LOOP
-
-   For maximum efficiency and robustness against bus errors, you are
-   advised to model the main loop of your application after the
-   following pseudo-code example:
-
-   (checks of system call return values omitted for brevity; always
-   check return values in your code!)
-
-   while ( frames left ) {
-
-    struct pollfd *pfd = ...;
-
-    pfd->fd = dv1394_fd;
-    pfd->revents = 0;
-    pfd->events = POLLOUT | POLLIN; (OUT for transmit, IN for receive)
-
-    (add other sources of I/O here)
-
-    poll(pfd, 1, -1); (or select(); add a timeout if you want)
-
-    if (pfd->revents) {
-         struct dv1394_status status;
-
-         ioctl(dv1394_fd, DV1394_GET_STATUS, &status);
-
-        if (status.dropped_frames > 0) {
-             reset_dv1394();
-         } else {
-              for (int i = 0; i < status.n_clear_frames; i++) {
-                 copy_DV_frame();
-              }
-         }
-    }
-   }
-
-   where copy_DV_frame() reads or writes on the dv1394 file descriptor
-   (read/write mode) or copies data to/from the mmap ringbuffer and
-   then calls ioctl(DV1394_SUBMIT_FRAMES) to notify dv1394 that new
-   frames are availble (mmap mode).
-
-   reset_dv1394() is called in the event of a buffer
-   underflow/overflow or a halt in the DV stream (e.g. due to a 1394
-   bus reset). To guarantee recovery from the error, this function
-   should close the dv1394 file descriptor (and munmap() all
-   ringbuffer mappings, if you are using them), then re-open the
-   dv1394 device (and re-map the ringbuffer).
-
-*/
-
-
-/* maximum number of frames in the ringbuffer */
-#define DV1394_MAX_FRAMES 32
-
-/* number of *full* isochronous packets per DV frame */
-#define DV1394_NTSC_PACKETS_PER_FRAME 250
-#define DV1394_PAL_PACKETS_PER_FRAME  300
-
-/* size of one frame's worth of DV data, in bytes */
-#define DV1394_NTSC_FRAME_SIZE (480 * DV1394_NTSC_PACKETS_PER_FRAME)
-#define DV1394_PAL_FRAME_SIZE  (480 * DV1394_PAL_PACKETS_PER_FRAME)
-
-
-/* ioctl() commands */
-#include "ieee1394-ioctl.h"
-
-
-enum pal_or_ntsc {
-       DV1394_NTSC = 0,
-       DV1394_PAL
-};
-
-
-
-
-/* this is the argument to DV1394_INIT */
-struct dv1394_init {
-       /* DV1394_API_VERSION */
-       unsigned int api_version;
-
-       /* isochronous transmission channel to use */
-       unsigned int channel;
-
-       /* number of frames in the ringbuffer. Must be at least 2
-          and at most DV1394_MAX_FRAMES. */
-       unsigned int n_frames;
-
-       /* send/receive PAL or NTSC video format */
-       enum pal_or_ntsc format;
-
-       /* the following are used only for transmission */
-
-       /* set these to zero unless you want a
-          non-default empty packet rate (see below) */
-       unsigned long cip_n;
-       unsigned long cip_d;
-
-       /* set this to zero unless you want a
-          non-default SYT cycle offset (default = 3 cycles) */
-       unsigned int syt_offset;
-};
-
-/* NOTE: you may only allocate the DV frame ringbuffer once each time
-   you open the dv1394 device. DV1394_INIT will fail if you call it a
-   second time with different 'n_frames' or 'format' arguments (which
-   would imply a different size for the ringbuffer). If you need a
-   different buffer size, simply close and re-open the device, then
-   initialize it with your new settings. */
-
-/* Q: What are cip_n and cip_d? */
-
-/*
-  A: DV video streams do not utilize 100% of the potential bandwidth offered
-  by IEEE 1394 (FireWire). To achieve the correct rate of data transmission,
-  DV devices must periodically insert empty packets into the 1394 data stream.
-  Typically there is one empty packet per 14-16 data-carrying packets.
-
-  Some DV devices will accept a wide range of empty packet rates, while others
-  require a precise rate. If the dv1394 driver produces empty packets at
-  a rate that your device does not accept, you may see ugly patterns on the
-  DV output, or even no output at all.
-
-  The default empty packet insertion rate seems to work for many people; if
-  your DV output is stable, you can simply ignore this discussion. However,
-  we have exposed the empty packet rate as a parameter to support devices that
-  do not work with the default rate.
-
-  The decision to insert an empty packet is made with a numerator/denominator
-  algorithm. Empty packets are produced at an average rate of CIP_N / CIP_D.
-  You can alter the empty packet rate by passing non-zero values for cip_n
-  and cip_d to the INIT ioctl.
-
- */
-
-
-
-struct dv1394_status {
-       /* this embedded init struct returns the current dv1394
-          parameters in use */
-       struct dv1394_init init;
-
-       /* the ringbuffer frame that is currently being
-          displayed. (-1 if the device is not transmitting anything) */
-       int active_frame;
-
-       /* index of the first buffer (ahead of active_frame) that
-          is ready to be filled with data */
-       unsigned int first_clear_frame;
-
-       /* how many buffers, including first_clear_buffer, are
-          ready to be filled with data */
-       unsigned int n_clear_frames;
-
-       /* how many times the DV stream has underflowed, overflowed,
-          or otherwise encountered an error, since the previous call
-          to DV1394_GET_STATUS */
-       unsigned int dropped_frames;
-
-       /* N.B. The dropped_frames counter is only a lower bound on the actual
-          number of dropped frames, with the special case that if dropped_frames
-          is zero, then it is guaranteed that NO frames have been dropped
-          since the last call to DV1394_GET_STATUS.
-       */
-};
-
-
-#endif /* _DV_1394_H */
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
deleted file mode 100644 (file)
index 6340382..0000000
+++ /dev/null
@@ -1,1720 +0,0 @@
-/*
- * eth1394.c -- IPv4 driver for Linux IEEE-1394 Subsystem
- *
- * Copyright (C) 2001-2003 Ben Collins <bcollins@debian.org>
- *               2000 Bonin Franck <boninf@free.fr>
- *               2003 Steve Kinneberg <kinnebergsteve@acmsystems.com>
- *
- * Mainly based on work by Emanuel Pirker and Andreas E. Bombe
- *
- * 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.
- */
-
-/*
- * This driver intends to support RFC 2734, which describes a method for
- * transporting IPv4 datagrams over IEEE-1394 serial busses.
- *
- * TODO:
- * RFC 2734 related:
- * - Add MCAP. Limited Multicast exists only to 224.0.0.1 and 224.0.0.2.
- *
- * Non-RFC 2734 related:
- * - Handle fragmented skb's coming from the networking layer.
- * - Move generic GASP reception to core 1394 code
- * - Convert kmalloc/kfree for link fragments to use kmem_cache_* instead
- * - Stability improvements
- * - Performance enhancements
- * - Consider garbage collecting old partial datagrams after X amount of time
- */
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/workqueue.h>
-
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/ip.h>
-#include <linux/in.h>
-#include <linux/tcp.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-#include <asm/uaccess.h>
-#include <asm/delay.h>
-#include <asm/unaligned.h>
-#include <net/arp.h>
-
-#include "config_roms.h"
-#include "csr1212.h"
-#include "eth1394.h"
-#include "highlevel.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-#include "iso.h"
-#include "nodemgr.h"
-
-#define ETH1394_PRINT_G(level, fmt, args...) \
-       printk(level "%s: " fmt, driver_name, ## args)
-
-#define ETH1394_PRINT(level, dev_name, fmt, args...) \
-       printk(level "%s: %s: " fmt, driver_name, dev_name, ## args)
-
-struct fragment_info {
-       struct list_head list;
-       int offset;
-       int len;
-};
-
-struct partial_datagram {
-       struct list_head list;
-       u16 dgl;
-       u16 dg_size;
-       __be16 ether_type;
-       struct sk_buff *skb;
-       char *pbuf;
-       struct list_head frag_info;
-};
-
-struct pdg_list {
-       struct list_head list;  /* partial datagram list per node       */
-       unsigned int sz;        /* partial datagram list size per node  */
-       spinlock_t lock;        /* partial datagram lock                */
-};
-
-struct eth1394_host_info {
-       struct hpsb_host *host;
-       struct net_device *dev;
-};
-
-struct eth1394_node_ref {
-       struct unit_directory *ud;
-       struct list_head list;
-};
-
-struct eth1394_node_info {
-       u16 maxpayload;         /* max payload                  */
-       u8 sspd;                /* max speed                    */
-       u64 fifo;               /* FIFO address                 */
-       struct pdg_list pdg;    /* partial RX datagram lists    */
-       int dgl;                /* outgoing datagram label      */
-};
-
-static const char driver_name[] = "eth1394";
-
-static struct kmem_cache *packet_task_cache;
-
-static struct hpsb_highlevel eth1394_highlevel;
-
-/* Use common.lf to determine header len */
-static const int hdr_type_len[] = {
-       sizeof(struct eth1394_uf_hdr),
-       sizeof(struct eth1394_ff_hdr),
-       sizeof(struct eth1394_sf_hdr),
-       sizeof(struct eth1394_sf_hdr)
-};
-
-static const u16 eth1394_speedto_maxpayload[] = {
-/*     S100, S200, S400, S800, S1600, S3200 */
-       512, 1024, 2048, 4096,  4096,  4096
-};
-
-MODULE_AUTHOR("Ben Collins (bcollins@debian.org)");
-MODULE_DESCRIPTION("IEEE 1394 IPv4 Driver (IPv4-over-1394 as per RFC 2734)");
-MODULE_LICENSE("GPL");
-
-/*
- * The max_partial_datagrams parameter is the maximum number of fragmented
- * datagrams per node that eth1394 will keep in memory.  Providing an upper
- * bound allows us to limit the amount of memory that partial datagrams
- * consume in the event that some partial datagrams are never completed.
- */
-static int max_partial_datagrams = 25;
-module_param(max_partial_datagrams, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(max_partial_datagrams,
-                "Maximum number of partially received fragmented datagrams "
-                "(default = 25).");
-
-
-static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
-                           unsigned short type, const void *daddr,
-                           const void *saddr, unsigned len);
-static int ether1394_rebuild_header(struct sk_buff *skb);
-static int ether1394_header_parse(const struct sk_buff *skb,
-                                 unsigned char *haddr);
-static int ether1394_header_cache(const struct neighbour *neigh,
-                                 struct hh_cache *hh);
-static void ether1394_header_cache_update(struct hh_cache *hh,
-                                         const struct net_device *dev,
-                                         const unsigned char *haddr);
-static netdev_tx_t ether1394_tx(struct sk_buff *skb,
-                               struct net_device *dev);
-static void ether1394_iso(struct hpsb_iso *iso);
-
-static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
-                          quadlet_t *data, u64 addr, size_t len, u16 flags);
-static void ether1394_add_host(struct hpsb_host *host);
-static void ether1394_remove_host(struct hpsb_host *host);
-static void ether1394_host_reset(struct hpsb_host *host);
-
-/* Function for incoming 1394 packets */
-static const struct hpsb_address_ops addr_ops = {
-       .write =        ether1394_write,
-};
-
-/* Ieee1394 highlevel driver functions */
-static struct hpsb_highlevel eth1394_highlevel = {
-       .name =         driver_name,
-       .add_host =     ether1394_add_host,
-       .remove_host =  ether1394_remove_host,
-       .host_reset =   ether1394_host_reset,
-};
-
-static int ether1394_recv_init(struct eth1394_priv *priv)
-{
-       unsigned int iso_buf_size;
-
-       /* FIXME: rawiso limits us to PAGE_SIZE */
-       iso_buf_size = min((unsigned int)PAGE_SIZE,
-                          2 * (1U << (priv->host->csr.max_rec + 1)));
-
-       priv->iso = hpsb_iso_recv_init(priv->host,
-                                      ETHER1394_GASP_BUFFERS * iso_buf_size,
-                                      ETHER1394_GASP_BUFFERS,
-                                      priv->broadcast_channel,
-                                      HPSB_ISO_DMA_PACKET_PER_BUFFER,
-                                      1, ether1394_iso);
-       if (priv->iso == NULL) {
-               ETH1394_PRINT_G(KERN_ERR, "Failed to allocate IR context\n");
-               priv->bc_state = ETHER1394_BC_ERROR;
-               return -EAGAIN;
-       }
-
-       if (hpsb_iso_recv_start(priv->iso, -1, (1 << 3), -1) < 0)
-               priv->bc_state = ETHER1394_BC_STOPPED;
-       else
-               priv->bc_state = ETHER1394_BC_RUNNING;
-       return 0;
-}
-
-/* This is called after an "ifup" */
-static int ether1394_open(struct net_device *dev)
-{
-       struct eth1394_priv *priv = netdev_priv(dev);
-       int ret;
-
-       if (priv->bc_state == ETHER1394_BC_ERROR) {
-               ret = ether1394_recv_init(priv);
-               if (ret)
-                       return ret;
-       }
-       netif_start_queue(dev);
-       return 0;
-}
-
-/* This is called after an "ifdown" */
-static int ether1394_stop(struct net_device *dev)
-{
-       /* flush priv->wake */
-       flush_scheduled_work();
-
-       netif_stop_queue(dev);
-       return 0;
-}
-
-/* FIXME: What to do if we timeout? I think a host reset is probably in order,
- * so that's what we do. Should we increment the stat counters too?  */
-static void ether1394_tx_timeout(struct net_device *dev)
-{
-       struct hpsb_host *host =
-                       ((struct eth1394_priv *)netdev_priv(dev))->host;
-
-       ETH1394_PRINT(KERN_ERR, dev->name, "Timeout, resetting host\n");
-       ether1394_host_reset(host);
-}
-
-static inline int ether1394_max_mtu(struct hpsb_host* host)
-{
-       return (1 << (host->csr.max_rec + 1))
-                       - sizeof(union eth1394_hdr) - ETHER1394_GASP_OVERHEAD;
-}
-
-static int ether1394_change_mtu(struct net_device *dev, int new_mtu)
-{
-       int max_mtu;
-
-       if (new_mtu < 68)
-               return -EINVAL;
-
-       max_mtu = ether1394_max_mtu(
-                       ((struct eth1394_priv *)netdev_priv(dev))->host);
-       if (new_mtu > max_mtu) {
-               ETH1394_PRINT(KERN_INFO, dev->name,
-                             "Local node constrains MTU to %d\n", max_mtu);
-               return -ERANGE;
-       }
-
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-static void purge_partial_datagram(struct list_head *old)
-{
-       struct partial_datagram *pd;
-       struct list_head *lh, *n;
-       struct fragment_info *fi;
-
-       pd = list_entry(old, struct partial_datagram, list);
-
-       list_for_each_safe(lh, n, &pd->frag_info) {
-               fi = list_entry(lh, struct fragment_info, list);
-               list_del(lh);
-               kfree(fi);
-       }
-       list_del(old);
-       kfree_skb(pd->skb);
-       kfree(pd);
-}
-
-/******************************************
- * 1394 bus activity functions
- ******************************************/
-
-static struct eth1394_node_ref *eth1394_find_node(struct list_head *inl,
-                                                 struct unit_directory *ud)
-{
-       struct eth1394_node_ref *node;
-
-       list_for_each_entry(node, inl, list)
-               if (node->ud == ud)
-                       return node;
-
-       return NULL;
-}
-
-static struct eth1394_node_ref *eth1394_find_node_guid(struct list_head *inl,
-                                                      u64 guid)
-{
-       struct eth1394_node_ref *node;
-
-       list_for_each_entry(node, inl, list)
-               if (node->ud->ne->guid == guid)
-                       return node;
-
-       return NULL;
-}
-
-static struct eth1394_node_ref *eth1394_find_node_nodeid(struct list_head *inl,
-                                                        nodeid_t nodeid)
-{
-       struct eth1394_node_ref *node;
-
-       list_for_each_entry(node, inl, list)
-               if (node->ud->ne->nodeid == nodeid)
-                       return node;
-
-       return NULL;
-}
-
-static int eth1394_new_node(struct eth1394_host_info *hi,
-                           struct unit_directory *ud)
-{
-       struct eth1394_priv *priv;
-       struct eth1394_node_ref *new_node;
-       struct eth1394_node_info *node_info;
-
-       new_node = kmalloc(sizeof(*new_node), GFP_KERNEL);
-       if (!new_node)
-               return -ENOMEM;
-
-       node_info = kmalloc(sizeof(*node_info), GFP_KERNEL);
-       if (!node_info) {
-               kfree(new_node);
-               return -ENOMEM;
-       }
-
-       spin_lock_init(&node_info->pdg.lock);
-       INIT_LIST_HEAD(&node_info->pdg.list);
-       node_info->pdg.sz = 0;
-       node_info->fifo = CSR1212_INVALID_ADDR_SPACE;
-
-       dev_set_drvdata(&ud->device, node_info);
-       new_node->ud = ud;
-
-       priv = netdev_priv(hi->dev);
-       list_add_tail(&new_node->list, &priv->ip_node_list);
-       return 0;
-}
-
-static int eth1394_probe(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct eth1394_host_info *hi;
-
-       ud = container_of(dev, struct unit_directory, device);
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
-       if (!hi)
-               return -ENOENT;
-
-       return eth1394_new_node(hi, ud);
-}
-
-static int eth1394_remove(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-       struct eth1394_node_ref *old_node;
-       struct eth1394_node_info *node_info;
-       struct list_head *lh, *n;
-       unsigned long flags;
-
-       ud = container_of(dev, struct unit_directory, device);
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
-       if (!hi)
-               return -ENOENT;
-
-       priv = netdev_priv(hi->dev);
-
-       old_node = eth1394_find_node(&priv->ip_node_list, ud);
-       if (!old_node)
-               return 0;
-
-       list_del(&old_node->list);
-       kfree(old_node);
-
-       node_info = dev_get_drvdata(&ud->device);
-
-       spin_lock_irqsave(&node_info->pdg.lock, flags);
-       /* The partial datagram list should be empty, but we'll just
-        * make sure anyway... */
-       list_for_each_safe(lh, n, &node_info->pdg.list)
-               purge_partial_datagram(lh);
-       spin_unlock_irqrestore(&node_info->pdg.lock, flags);
-
-       kfree(node_info);
-       dev_set_drvdata(&ud->device, NULL);
-       return 0;
-}
-
-static int eth1394_update(struct unit_directory *ud)
-{
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-       struct eth1394_node_ref *node;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, ud->ne->host);
-       if (!hi)
-               return -ENOENT;
-
-       priv = netdev_priv(hi->dev);
-       node = eth1394_find_node(&priv->ip_node_list, ud);
-       if (node)
-               return 0;
-
-       return eth1394_new_node(hi, ud);
-}
-
-static const struct ieee1394_device_id eth1394_id_table[] = {
-       {
-               .match_flags = (IEEE1394_MATCH_SPECIFIER_ID |
-                               IEEE1394_MATCH_VERSION),
-               .specifier_id = ETHER1394_GASP_SPECIFIER_ID,
-               .version = ETHER1394_GASP_VERSION,
-       },
-       {}
-};
-
-MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table);
-
-static struct hpsb_protocol_driver eth1394_proto_driver = {
-       .name           = driver_name,
-       .id_table       = eth1394_id_table,
-       .update         = eth1394_update,
-       .driver         = {
-               .probe          = eth1394_probe,
-               .remove         = eth1394_remove,
-       },
-};
-
-static void ether1394_reset_priv(struct net_device *dev, int set_mtu)
-{
-       unsigned long flags;
-       int i;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       struct hpsb_host *host = priv->host;
-       u64 guid = get_unaligned((u64 *)&(host->csr.rom->bus_info_data[3]));
-       int max_speed = IEEE1394_SPEED_MAX;
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       memset(priv->ud_list, 0, sizeof(priv->ud_list));
-       priv->bc_maxpayload = 512;
-
-       /* Determine speed limit */
-       /* FIXME: This is broken for nodes with link speed < PHY speed,
-        * and it is suboptimal for S200B...S800B hardware.
-        * The result of nodemgr's speed probe should be used somehow. */
-       for (i = 0; i < host->node_count; i++) {
-               /* take care of S100B...S400B PHY ports */
-               if (host->speed[i] == SELFID_SPEED_UNKNOWN) {
-                       max_speed = IEEE1394_SPEED_100;
-                       break;
-               }
-               if (max_speed > host->speed[i])
-                       max_speed = host->speed[i];
-       }
-       priv->bc_sspd = max_speed;
-
-       if (set_mtu) {
-               /* Use the RFC 2734 default 1500 octets or the maximum payload
-                * as initial MTU */
-               dev->mtu = min(1500, ether1394_max_mtu(host));
-
-               /* Set our hardware address while we're at it */
-               memcpy(dev->dev_addr, &guid, sizeof(u64));
-               memset(dev->broadcast, 0xff, sizeof(u64));
-       }
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static const struct header_ops ether1394_header_ops = {
-       .create         = ether1394_header,
-       .rebuild        = ether1394_rebuild_header,
-       .cache          = ether1394_header_cache,
-       .cache_update   = ether1394_header_cache_update,
-       .parse          = ether1394_header_parse,
-};
-
-static const struct net_device_ops ether1394_netdev_ops = {
-       .ndo_open       = ether1394_open,
-       .ndo_stop       = ether1394_stop,
-       .ndo_start_xmit = ether1394_tx,
-       .ndo_tx_timeout = ether1394_tx_timeout,
-       .ndo_change_mtu = ether1394_change_mtu,
-};
-
-static void ether1394_init_dev(struct net_device *dev)
-{
-
-       dev->header_ops         = &ether1394_header_ops;
-       dev->netdev_ops         = &ether1394_netdev_ops;
-
-       dev->watchdog_timeo     = ETHER1394_TIMEOUT;
-       dev->flags              = IFF_BROADCAST | IFF_MULTICAST;
-       dev->features           = NETIF_F_HIGHDMA;
-       dev->addr_len           = ETH1394_ALEN;
-       dev->hard_header_len    = ETH1394_HLEN;
-       dev->type               = ARPHRD_IEEE1394;
-
-       /* FIXME: This value was copied from ether_setup(). Is it too much? */
-       dev->tx_queue_len       = 1000;
-}
-
-/*
- * Wake the queue up after commonly encountered transmit failure conditions are
- * hopefully over.  Currently only tlabel exhaustion is accounted for.
- */
-static void ether1394_wake_queue(struct work_struct *work)
-{
-       struct eth1394_priv *priv;
-       struct hpsb_packet *packet;
-
-       priv = container_of(work, struct eth1394_priv, wake);
-       packet = hpsb_alloc_packet(0);
-
-       /* This is really bad, but unjam the queue anyway. */
-       if (!packet)
-               goto out;
-
-       packet->host = priv->host;
-       packet->node_id = priv->wake_node;
-       /*
-        * A transaction label is all we really want.  If we get one, it almost
-        * always means we can get a lot more because the ieee1394 core recycled
-        * a whole batch of tlabels, at last.
-        */
-       if (hpsb_get_tlabel(packet) == 0)
-               hpsb_free_tlabel(packet);
-
-       hpsb_free_packet(packet);
-out:
-       netif_wake_queue(priv->wake_dev);
-}
-
-/*
- * This function is called every time a card is found. It is generally called
- * when the module is installed. This is where we add all of our ethernet
- * devices. One for each host.
- */
-static void ether1394_add_host(struct hpsb_host *host)
-{
-       struct eth1394_host_info *hi = NULL;
-       struct net_device *dev = NULL;
-       struct eth1394_priv *priv;
-       u64 fifo_addr;
-
-       if (hpsb_config_rom_ip1394_add(host) != 0) {
-               ETH1394_PRINT_G(KERN_ERR, "Can't add IP-over-1394 ROM entry\n");
-               return;
-       }
-
-       fifo_addr = hpsb_allocate_and_register_addrspace(
-                       &eth1394_highlevel, host, &addr_ops,
-                       ETHER1394_REGION_ADDR_LEN, ETHER1394_REGION_ADDR_LEN,
-                       CSR1212_INVALID_ADDR_SPACE, CSR1212_INVALID_ADDR_SPACE);
-       if (fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
-               ETH1394_PRINT_G(KERN_ERR, "Cannot register CSR space\n");
-               hpsb_config_rom_ip1394_remove(host);
-               return;
-       }
-
-       dev = alloc_netdev(sizeof(*priv), "eth%d", ether1394_init_dev);
-       if (dev == NULL) {
-               ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
-               goto out;
-       }
-
-       SET_NETDEV_DEV(dev, &host->device);
-
-       priv = netdev_priv(dev);
-       INIT_LIST_HEAD(&priv->ip_node_list);
-       spin_lock_init(&priv->lock);
-       priv->host = host;
-       priv->local_fifo = fifo_addr;
-       INIT_WORK(&priv->wake, ether1394_wake_queue);
-       priv->wake_dev = dev;
-
-       hi = hpsb_create_hostinfo(&eth1394_highlevel, host, sizeof(*hi));
-       if (hi == NULL) {
-               ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
-               goto out;
-       }
-
-       ether1394_reset_priv(dev, 1);
-
-       if (register_netdev(dev)) {
-               ETH1394_PRINT_G(KERN_ERR, "Cannot register the driver\n");
-               goto out;
-       }
-
-       ETH1394_PRINT(KERN_INFO, dev->name, "IPv4 over IEEE 1394 (fw-host%d)\n",
-                     host->id);
-
-       hi->host = host;
-       hi->dev = dev;
-
-       /* Ignore validity in hopes that it will be set in the future.  It'll
-        * be checked when the eth device is opened. */
-       priv->broadcast_channel = host->csr.broadcast_channel & 0x3f;
-
-       ether1394_recv_init(priv);
-       return;
-out:
-       if (dev)
-               free_netdev(dev);
-       if (hi)
-               hpsb_destroy_hostinfo(&eth1394_highlevel, host);
-       hpsb_unregister_addrspace(&eth1394_highlevel, host, fifo_addr);
-       hpsb_config_rom_ip1394_remove(host);
-}
-
-/* Remove a card from our list */
-static void ether1394_remove_host(struct hpsb_host *host)
-{
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
-       if (!hi)
-               return;
-       priv = netdev_priv(hi->dev);
-       hpsb_unregister_addrspace(&eth1394_highlevel, host, priv->local_fifo);
-       hpsb_config_rom_ip1394_remove(host);
-       if (priv->iso)
-               hpsb_iso_shutdown(priv->iso);
-       unregister_netdev(hi->dev);
-       free_netdev(hi->dev);
-}
-
-/* A bus reset happened */
-static void ether1394_host_reset(struct hpsb_host *host)
-{
-       struct eth1394_host_info *hi;
-       struct eth1394_priv *priv;
-       struct net_device *dev;
-       struct list_head *lh, *n;
-       struct eth1394_node_ref *node;
-       struct eth1394_node_info *node_info;
-       unsigned long flags;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
-
-       /* This can happen for hosts that we don't use */
-       if (!hi)
-               return;
-
-       dev = hi->dev;
-       priv = netdev_priv(dev);
-
-       /* Reset our private host data, but not our MTU */
-       netif_stop_queue(dev);
-       ether1394_reset_priv(dev, 0);
-
-       list_for_each_entry(node, &priv->ip_node_list, list) {
-               node_info = dev_get_drvdata(&node->ud->device);
-
-               spin_lock_irqsave(&node_info->pdg.lock, flags);
-
-               list_for_each_safe(lh, n, &node_info->pdg.list)
-                       purge_partial_datagram(lh);
-
-               INIT_LIST_HEAD(&(node_info->pdg.list));
-               node_info->pdg.sz = 0;
-
-               spin_unlock_irqrestore(&node_info->pdg.lock, flags);
-       }
-
-       netif_wake_queue(dev);
-}
-
-/******************************************
- * HW Header net device functions
- ******************************************/
-/* These functions have been adapted from net/ethernet/eth.c */
-
-/* Create a fake MAC header for an arbitrary protocol layer.
- * saddr=NULL means use device source address
- * daddr=NULL means leave destination address (eg unresolved arp). */
-static int ether1394_header(struct sk_buff *skb, struct net_device *dev,
-                           unsigned short type, const void *daddr,
-                           const void *saddr, unsigned len)
-{
-       struct eth1394hdr *eth =
-                       (struct eth1394hdr *)skb_push(skb, ETH1394_HLEN);
-
-       eth->h_proto = htons(type);
-
-       if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
-               memset(eth->h_dest, 0, dev->addr_len);
-               return dev->hard_header_len;
-       }
-
-       if (daddr) {
-               memcpy(eth->h_dest, daddr, dev->addr_len);
-               return dev->hard_header_len;
-       }
-
-       return -dev->hard_header_len;
-}
-
-/* Rebuild the faked MAC header. This is called after an ARP
- * (or in future other address resolution) has completed on this
- * sk_buff. We now let ARP fill in the other fields.
- *
- * This routine CANNOT use cached dst->neigh!
- * Really, it is used only when dst->neigh is wrong.
- */
-static int ether1394_rebuild_header(struct sk_buff *skb)
-{
-       struct eth1394hdr *eth = (struct eth1394hdr *)skb->data;
-
-       if (eth->h_proto == htons(ETH_P_IP))
-               return arp_find((unsigned char *)&eth->h_dest, skb);
-
-       ETH1394_PRINT(KERN_DEBUG, skb->dev->name,
-                     "unable to resolve type %04x addresses\n",
-                     ntohs(eth->h_proto));
-       return 0;
-}
-
-static int ether1394_header_parse(const struct sk_buff *skb,
-                                 unsigned char *haddr)
-{
-       memcpy(haddr, skb->dev->dev_addr, ETH1394_ALEN);
-       return ETH1394_ALEN;
-}
-
-static int ether1394_header_cache(const struct neighbour *neigh,
-                                 struct hh_cache *hh)
-{
-       __be16 type = hh->hh_type;
-       struct net_device *dev = neigh->dev;
-       struct eth1394hdr *eth =
-               (struct eth1394hdr *)((u8 *)hh->hh_data + 16 - ETH1394_HLEN);
-
-       if (type == htons(ETH_P_802_3))
-               return -1;
-
-       eth->h_proto = type;
-       memcpy(eth->h_dest, neigh->ha, dev->addr_len);
-
-       hh->hh_len = ETH1394_HLEN;
-       return 0;
-}
-
-/* Called by Address Resolution module to notify changes in address. */
-static void ether1394_header_cache_update(struct hh_cache *hh,
-                                         const struct net_device *dev,
-                                         const unsigned char * haddr)
-{
-       memcpy((u8 *)hh->hh_data + 16 - ETH1394_HLEN, haddr, dev->addr_len);
-}
-
-/******************************************
- * Datagram reception code
- ******************************************/
-
-/* Copied from net/ethernet/eth.c */
-static __be16 ether1394_type_trans(struct sk_buff *skb, struct net_device *dev)
-{
-       struct eth1394hdr *eth;
-       unsigned char *rawp;
-
-       skb_reset_mac_header(skb);
-       skb_pull(skb, ETH1394_HLEN);
-       eth = eth1394_hdr(skb);
-
-       if (*eth->h_dest & 1) {
-               if (memcmp(eth->h_dest, dev->broadcast, dev->addr_len) == 0)
-                       skb->pkt_type = PACKET_BROADCAST;
-#if 0
-               else
-                       skb->pkt_type = PACKET_MULTICAST;
-#endif
-       } else {
-               if (memcmp(eth->h_dest, dev->dev_addr, dev->addr_len))
-                       skb->pkt_type = PACKET_OTHERHOST;
-       }
-
-       if (ntohs(eth->h_proto) >= 1536)
-               return eth->h_proto;
-
-       rawp = skb->data;
-
-       if (*(unsigned short *)rawp == 0xFFFF)
-               return htons(ETH_P_802_3);
-
-       return htons(ETH_P_802_2);
-}
-
-/* Parse an encapsulated IP1394 header into an ethernet frame packet.
- * We also perform ARP translation here, if need be.  */
-static __be16 ether1394_parse_encap(struct sk_buff *skb, struct net_device *dev,
-                                nodeid_t srcid, nodeid_t destid,
-                                __be16 ether_type)
-{
-       struct eth1394_priv *priv = netdev_priv(dev);
-       __be64 dest_hw;
-       __be16 ret = 0;
-
-       /* Setup our hw addresses. We use these to build the ethernet header. */
-       if (destid == (LOCAL_BUS | ALL_NODES))
-               dest_hw = ~cpu_to_be64(0);  /* broadcast */
-       else
-               dest_hw = cpu_to_be64((u64)priv->host->csr.guid_hi << 32 |
-                                     priv->host->csr.guid_lo);
-
-       /* If this is an ARP packet, convert it. First, we want to make
-        * use of some of the fields, since they tell us a little bit
-        * about the sending machine.  */
-       if (ether_type == htons(ETH_P_ARP)) {
-               struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
-               struct arphdr *arp = (struct arphdr *)skb->data;
-               unsigned char *arp_ptr = (unsigned char *)(arp + 1);
-               u64 fifo_addr = (u64)ntohs(arp1394->fifo_hi) << 32 |
-                                          ntohl(arp1394->fifo_lo);
-               u8 max_rec = min(priv->host->csr.max_rec,
-                                (u8)(arp1394->max_rec));
-               int sspd = arp1394->sspd;
-               u16 maxpayload;
-               struct eth1394_node_ref *node;
-               struct eth1394_node_info *node_info;
-               __be64 guid;
-
-               /* Sanity check. MacOSX seems to be sending us 131 in this
-                * field (atleast on my Panther G5). Not sure why. */
-               if (sspd > 5 || sspd < 0)
-                       sspd = 0;
-
-               maxpayload = min(eth1394_speedto_maxpayload[sspd],
-                                (u16)(1 << (max_rec + 1)));
-
-               guid = get_unaligned(&arp1394->s_uniq_id);
-               node = eth1394_find_node_guid(&priv->ip_node_list,
-                                             be64_to_cpu(guid));
-               if (!node)
-                       return cpu_to_be16(0);
-
-               node_info = dev_get_drvdata(&node->ud->device);
-
-               /* Update our speed/payload/fifo_offset table */
-               node_info->maxpayload = maxpayload;
-               node_info->sspd =       sspd;
-               node_info->fifo =       fifo_addr;
-
-               /* Now that we're done with the 1394 specific stuff, we'll
-                * need to alter some of the data.  Believe it or not, all
-                * that needs to be done is sender_IP_address needs to be
-                * moved, the destination hardware address get stuffed
-                * in and the hardware address length set to 8.
-                *
-                * IMPORTANT: The code below overwrites 1394 specific data
-                * needed above so keep the munging of the data for the
-                * higher level IP stack last. */
-
-               arp->ar_hln = 8;
-               arp_ptr += arp->ar_hln;         /* skip over sender unique id */
-               *(u32 *)arp_ptr = arp1394->sip; /* move sender IP addr */
-               arp_ptr += arp->ar_pln;         /* skip over sender IP addr */
-
-               if (arp->ar_op == htons(ARPOP_REQUEST))
-                       memset(arp_ptr, 0, sizeof(u64));
-               else
-                       memcpy(arp_ptr, dev->dev_addr, sizeof(u64));
-       }
-
-       /* Now add the ethernet header. */
-       if (dev_hard_header(skb, dev, ntohs(ether_type), &dest_hw, NULL,
-                           skb->len) >= 0)
-               ret = ether1394_type_trans(skb, dev);
-
-       return ret;
-}
-
-static int fragment_overlap(struct list_head *frag_list, int offset, int len)
-{
-       struct fragment_info *fi;
-       int end = offset + len;
-
-       list_for_each_entry(fi, frag_list, list)
-               if (offset < fi->offset + fi->len && end > fi->offset)
-                       return 1;
-
-       return 0;
-}
-
-static struct list_head *find_partial_datagram(struct list_head *pdgl, int dgl)
-{
-       struct partial_datagram *pd;
-
-       list_for_each_entry(pd, pdgl, list)
-               if (pd->dgl == dgl)
-                       return &pd->list;
-
-       return NULL;
-}
-
-/* Assumes that new fragment does not overlap any existing fragments */
-static int new_fragment(struct list_head *frag_info, int offset, int len)
-{
-       struct list_head *lh;
-       struct fragment_info *fi, *fi2, *new;
-
-       list_for_each(lh, frag_info) {
-               fi = list_entry(lh, struct fragment_info, list);
-               if (fi->offset + fi->len == offset) {
-                       /* The new fragment can be tacked on to the end */
-                       fi->len += len;
-                       /* Did the new fragment plug a hole? */
-                       fi2 = list_entry(lh->next, struct fragment_info, list);
-                       if (fi->offset + fi->len == fi2->offset) {
-                               /* glue fragments together */
-                               fi->len += fi2->len;
-                               list_del(lh->next);
-                               kfree(fi2);
-                       }
-                       return 0;
-               } else if (offset + len == fi->offset) {
-                       /* The new fragment can be tacked on to the beginning */
-                       fi->offset = offset;
-                       fi->len += len;
-                       /* Did the new fragment plug a hole? */
-                       fi2 = list_entry(lh->prev, struct fragment_info, list);
-                       if (fi2->offset + fi2->len == fi->offset) {
-                               /* glue fragments together */
-                               fi2->len += fi->len;
-                               list_del(lh);
-                               kfree(fi);
-                       }
-                       return 0;
-               } else if (offset > fi->offset + fi->len) {
-                       break;
-               } else if (offset + len < fi->offset) {
-                       lh = lh->prev;
-                       break;
-               }
-       }
-
-       new = kmalloc(sizeof(*new), GFP_ATOMIC);
-       if (!new)
-               return -ENOMEM;
-
-       new->offset = offset;
-       new->len = len;
-
-       list_add(&new->list, lh);
-       return 0;
-}
-
-static int new_partial_datagram(struct net_device *dev, struct list_head *pdgl,
-                               int dgl, int dg_size, char *frag_buf,
-                               int frag_off, int frag_len)
-{
-       struct partial_datagram *new;
-
-       new = kmalloc(sizeof(*new), GFP_ATOMIC);
-       if (!new)
-               return -ENOMEM;
-
-       INIT_LIST_HEAD(&new->frag_info);
-
-       if (new_fragment(&new->frag_info, frag_off, frag_len) < 0) {
-               kfree(new);
-               return -ENOMEM;
-       }
-
-       new->dgl = dgl;
-       new->dg_size = dg_size;
-
-       new->skb = dev_alloc_skb(dg_size + dev->hard_header_len + 15);
-       if (!new->skb) {
-               struct fragment_info *fi = list_entry(new->frag_info.next,
-                                                     struct fragment_info,
-                                                     list);
-               kfree(fi);
-               kfree(new);
-               return -ENOMEM;
-       }
-
-       skb_reserve(new->skb, (dev->hard_header_len + 15) & ~15);
-       new->pbuf = skb_put(new->skb, dg_size);
-       memcpy(new->pbuf + frag_off, frag_buf, frag_len);
-
-       list_add(&new->list, pdgl);
-       return 0;
-}
-
-static int update_partial_datagram(struct list_head *pdgl, struct list_head *lh,
-                                  char *frag_buf, int frag_off, int frag_len)
-{
-       struct partial_datagram *pd =
-                       list_entry(lh, struct partial_datagram, list);
-
-       if (new_fragment(&pd->frag_info, frag_off, frag_len) < 0)
-               return -ENOMEM;
-
-       memcpy(pd->pbuf + frag_off, frag_buf, frag_len);
-
-       /* Move list entry to beginnig of list so that oldest partial
-        * datagrams percolate to the end of the list */
-       list_move(lh, pdgl);
-       return 0;
-}
-
-static int is_datagram_complete(struct list_head *lh, int dg_size)
-{
-       struct partial_datagram *pd;
-       struct fragment_info *fi;
-
-       pd = list_entry(lh, struct partial_datagram, list);
-       fi = list_entry(pd->frag_info.next, struct fragment_info, list);
-
-       return (fi->len == dg_size);
-}
-
-/* Packet reception. We convert the IP1394 encapsulation header to an
- * ethernet header, and fill it with some of our other fields. This is
- * an incoming packet from the 1394 bus.  */
-static int ether1394_data_handler(struct net_device *dev, int srcid, int destid,
-                                 char *buf, int len)
-{
-       struct sk_buff *skb;
-       unsigned long flags;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       union eth1394_hdr *hdr = (union eth1394_hdr *)buf;
-       __be16 ether_type = cpu_to_be16(0);  /* initialized to clear warning */
-       int hdr_len;
-       struct unit_directory *ud = priv->ud_list[NODEID_TO_NODE(srcid)];
-       struct eth1394_node_info *node_info;
-
-       if (!ud) {
-               struct eth1394_node_ref *node;
-               node = eth1394_find_node_nodeid(&priv->ip_node_list, srcid);
-               if (unlikely(!node)) {
-                       HPSB_PRINT(KERN_ERR, "ether1394 rx: sender nodeid "
-                                  "lookup failure: " NODE_BUS_FMT,
-                                  NODE_BUS_ARGS(priv->host, srcid));
-                       dev->stats.rx_dropped++;
-                       return -1;
-               }
-               ud = node->ud;
-
-               priv->ud_list[NODEID_TO_NODE(srcid)] = ud;
-       }
-
-       node_info = dev_get_drvdata(&ud->device);
-
-       /* First, did we receive a fragmented or unfragmented datagram? */
-       hdr->words.word1 = ntohs(hdr->words.word1);
-
-       hdr_len = hdr_type_len[hdr->common.lf];
-
-       if (hdr->common.lf == ETH1394_HDR_LF_UF) {
-               /* An unfragmented datagram has been received by the ieee1394
-                * bus. Build an skbuff around it so we can pass it to the
-                * high level network layer. */
-
-               skb = dev_alloc_skb(len + dev->hard_header_len + 15);
-               if (unlikely(!skb)) {
-                       ETH1394_PRINT_G(KERN_ERR, "Out of memory\n");
-                       dev->stats.rx_dropped++;
-                       return -1;
-               }
-               skb_reserve(skb, (dev->hard_header_len + 15) & ~15);
-               memcpy(skb_put(skb, len - hdr_len), buf + hdr_len,
-                      len - hdr_len);
-               ether_type = hdr->uf.ether_type;
-       } else {
-               /* A datagram fragment has been received, now the fun begins. */
-
-               struct list_head *pdgl, *lh;
-               struct partial_datagram *pd;
-               int fg_off;
-               int fg_len = len - hdr_len;
-               int dg_size;
-               int dgl;
-               int retval;
-               struct pdg_list *pdg = &(node_info->pdg);
-
-               hdr->words.word3 = ntohs(hdr->words.word3);
-               /* The 4th header word is reserved so no need to do ntohs() */
-
-               if (hdr->common.lf == ETH1394_HDR_LF_FF) {
-                       ether_type = hdr->ff.ether_type;
-                       dgl = hdr->ff.dgl;
-                       dg_size = hdr->ff.dg_size + 1;
-                       fg_off = 0;
-               } else {
-                       hdr->words.word2 = ntohs(hdr->words.word2);
-                       dgl = hdr->sf.dgl;
-                       dg_size = hdr->sf.dg_size + 1;
-                       fg_off = hdr->sf.fg_off;
-               }
-               spin_lock_irqsave(&pdg->lock, flags);
-
-               pdgl = &(pdg->list);
-               lh = find_partial_datagram(pdgl, dgl);
-
-               if (lh == NULL) {
-                       while (pdg->sz >= max_partial_datagrams) {
-                               /* remove the oldest */
-                               purge_partial_datagram(pdgl->prev);
-                               pdg->sz--;
-                       }
-
-                       retval = new_partial_datagram(dev, pdgl, dgl, dg_size,
-                                                     buf + hdr_len, fg_off,
-                                                     fg_len);
-                       if (retval < 0) {
-                               spin_unlock_irqrestore(&pdg->lock, flags);
-                               goto bad_proto;
-                       }
-                       pdg->sz++;
-                       lh = find_partial_datagram(pdgl, dgl);
-               } else {
-                       pd = list_entry(lh, struct partial_datagram, list);
-
-                       if (fragment_overlap(&pd->frag_info, fg_off, fg_len)) {
-                               /* Overlapping fragments, obliterate old
-                                * datagram and start new one. */
-                               purge_partial_datagram(lh);
-                               retval = new_partial_datagram(dev, pdgl, dgl,
-                                                             dg_size,
-                                                             buf + hdr_len,
-                                                             fg_off, fg_len);
-                               if (retval < 0) {
-                                       pdg->sz--;
-                                       spin_unlock_irqrestore(&pdg->lock, flags);
-                                       goto bad_proto;
-                               }
-                       } else {
-                               retval = update_partial_datagram(pdgl, lh,
-                                                                buf + hdr_len,
-                                                                fg_off, fg_len);
-                               if (retval < 0) {
-                                       /* Couldn't save off fragment anyway
-                                        * so might as well obliterate the
-                                        * datagram now. */
-                                       purge_partial_datagram(lh);
-                                       pdg->sz--;
-                                       spin_unlock_irqrestore(&pdg->lock, flags);
-                                       goto bad_proto;
-                               }
-                       } /* fragment overlap */
-               } /* new datagram or add to existing one */
-
-               pd = list_entry(lh, struct partial_datagram, list);
-
-               if (hdr->common.lf == ETH1394_HDR_LF_FF)
-                       pd->ether_type = ether_type;
-
-               if (is_datagram_complete(lh, dg_size)) {
-                       ether_type = pd->ether_type;
-                       pdg->sz--;
-                       skb = skb_get(pd->skb);
-                       purge_partial_datagram(lh);
-                       spin_unlock_irqrestore(&pdg->lock, flags);
-               } else {
-                       /* Datagram is not complete, we're done for the
-                        * moment. */
-                       spin_unlock_irqrestore(&pdg->lock, flags);
-                       return 0;
-               }
-       } /* unframgented datagram or fragmented one */
-
-       /* Write metadata, and then pass to the receive level */
-       skb->dev = dev;
-       skb->ip_summed = CHECKSUM_UNNECESSARY;  /* don't check it */
-
-       /* Parse the encapsulation header. This actually does the job of
-        * converting to an ethernet frame header, aswell as arp
-        * conversion if needed. ARP conversion is easier in this
-        * direction, since we are using ethernet as our backend.  */
-       skb->protocol = ether1394_parse_encap(skb, dev, srcid, destid,
-                                             ether_type);
-
-       spin_lock_irqsave(&priv->lock, flags);
-
-       if (!skb->protocol) {
-               dev->stats.rx_errors++;
-               dev->stats.rx_dropped++;
-               dev_kfree_skb_any(skb);
-       } else if (netif_rx(skb) == NET_RX_DROP) {
-               dev->stats.rx_errors++;
-               dev->stats.rx_dropped++;
-       } else {
-               dev->stats.rx_packets++;
-               dev->stats.rx_bytes += skb->len;
-       }
-
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-bad_proto:
-       if (netif_queue_stopped(dev))
-               netif_wake_queue(dev);
-
-       return 0;
-}
-
-static int ether1394_write(struct hpsb_host *host, int srcid, int destid,
-                          quadlet_t *data, u64 addr, size_t len, u16 flags)
-{
-       struct eth1394_host_info *hi;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, host);
-       if (unlikely(!hi)) {
-               ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n",
-                               host->id);
-               return RCODE_ADDRESS_ERROR;
-       }
-
-       if (ether1394_data_handler(hi->dev, srcid, destid, (char*)data, len))
-               return RCODE_ADDRESS_ERROR;
-       else
-               return RCODE_COMPLETE;
-}
-
-static void ether1394_iso(struct hpsb_iso *iso)
-{
-       __be32 *data;
-       char *buf;
-       struct eth1394_host_info *hi;
-       struct net_device *dev;
-       unsigned int len;
-       u32 specifier_id;
-       u16 source_id;
-       int i;
-       int nready;
-
-       hi = hpsb_get_hostinfo(&eth1394_highlevel, iso->host);
-       if (unlikely(!hi)) {
-               ETH1394_PRINT_G(KERN_ERR, "No net device at fw-host%d\n",
-                               iso->host->id);
-               return;
-       }
-
-       dev = hi->dev;
-
-       nready = hpsb_iso_n_ready(iso);
-       for (i = 0; i < nready; i++) {
-               struct hpsb_iso_packet_info *info =
-                       &iso->infos[(iso->first_packet + i) % iso->buf_packets];
-               data = (__be32 *)(iso->data_buf.kvirt + info->offset);
-
-               /* skip over GASP header */
-               buf = (char *)data + 8;
-               len = info->len - 8;
-
-               specifier_id = (be32_to_cpu(data[0]) & 0xffff) << 8 |
-                              (be32_to_cpu(data[1]) & 0xff000000) >> 24;
-               source_id = be32_to_cpu(data[0]) >> 16;
-
-               if (info->channel != (iso->host->csr.broadcast_channel & 0x3f)
-                   || specifier_id != ETHER1394_GASP_SPECIFIER_ID) {
-                       /* This packet is not for us */
-                       continue;
-               }
-               ether1394_data_handler(dev, source_id, LOCAL_BUS | ALL_NODES,
-                                      buf, len);
-       }
-
-       hpsb_iso_recv_release_packets(iso, i);
-
-}
-
-/******************************************
- * Datagram transmission code
- ******************************************/
-
-/* Convert a standard ARP packet to 1394 ARP. The first 8 bytes (the entire
- * arphdr) is the same format as the ip1394 header, so they overlap.  The rest
- * needs to be munged a bit.  The remainder of the arphdr is formatted based
- * on hwaddr len and ipaddr len.  We know what they'll be, so it's easy to
- * judge.
- *
- * Now that the EUI is used for the hardware address all we need to do to make
- * this work for 1394 is to insert 2 quadlets that contain max_rec size,
- * speed, and unicast FIFO address information between the sender_unique_id
- * and the IP addresses.
- */
-static void ether1394_arp_to_1394arp(struct sk_buff *skb,
-                                    struct net_device *dev)
-{
-       struct eth1394_priv *priv = netdev_priv(dev);
-       struct arphdr *arp = (struct arphdr *)skb->data;
-       unsigned char *arp_ptr = (unsigned char *)(arp + 1);
-       struct eth1394_arp *arp1394 = (struct eth1394_arp *)skb->data;
-
-       arp1394->hw_addr_len    = 16;
-       arp1394->sip            = *(u32*)(arp_ptr + ETH1394_ALEN);
-       arp1394->max_rec        = priv->host->csr.max_rec;
-       arp1394->sspd           = priv->host->csr.lnk_spd;
-       arp1394->fifo_hi        = htons(priv->local_fifo >> 32);
-       arp1394->fifo_lo        = htonl(priv->local_fifo & ~0x0);
-}
-
-/* We need to encapsulate the standard header with our own. We use the
- * ethernet header's proto for our own. */
-static unsigned int ether1394_encapsulate_prep(unsigned int max_payload,
-                                              __be16 proto,
-                                              union eth1394_hdr *hdr,
-                                              u16 dg_size, u16 dgl)
-{
-       unsigned int adj_max_payload =
-                               max_payload - hdr_type_len[ETH1394_HDR_LF_UF];
-
-       /* Does it all fit in one packet? */
-       if (dg_size <= adj_max_payload) {
-               hdr->uf.lf = ETH1394_HDR_LF_UF;
-               hdr->uf.ether_type = proto;
-       } else {
-               hdr->ff.lf = ETH1394_HDR_LF_FF;
-               hdr->ff.ether_type = proto;
-               hdr->ff.dg_size = dg_size - 1;
-               hdr->ff.dgl = dgl;
-               adj_max_payload = max_payload - hdr_type_len[ETH1394_HDR_LF_FF];
-       }
-       return DIV_ROUND_UP(dg_size, adj_max_payload);
-}
-
-static unsigned int ether1394_encapsulate(struct sk_buff *skb,
-                                         unsigned int max_payload,
-                                         union eth1394_hdr *hdr)
-{
-       union eth1394_hdr *bufhdr;
-       int ftype = hdr->common.lf;
-       int hdrsz = hdr_type_len[ftype];
-       unsigned int adj_max_payload = max_payload - hdrsz;
-
-       switch (ftype) {
-       case ETH1394_HDR_LF_UF:
-               bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz);
-               bufhdr->words.word1 = htons(hdr->words.word1);
-               bufhdr->words.word2 = hdr->words.word2;
-               break;
-
-       case ETH1394_HDR_LF_FF:
-               bufhdr = (union eth1394_hdr *)skb_push(skb, hdrsz);
-               bufhdr->words.word1 = htons(hdr->words.word1);
-               bufhdr->words.word2 = hdr->words.word2;
-               bufhdr->words.word3 = htons(hdr->words.word3);
-               bufhdr->words.word4 = 0;
-
-               /* Set frag type here for future interior fragments */
-               hdr->common.lf = ETH1394_HDR_LF_IF;
-               hdr->sf.fg_off = 0;
-               break;
-
-       default:
-               hdr->sf.fg_off += adj_max_payload;
-               bufhdr = (union eth1394_hdr *)skb_pull(skb, adj_max_payload);
-               if (max_payload >= skb->len)
-                       hdr->common.lf = ETH1394_HDR_LF_LF;
-               bufhdr->words.word1 = htons(hdr->words.word1);
-               bufhdr->words.word2 = htons(hdr->words.word2);
-               bufhdr->words.word3 = htons(hdr->words.word3);
-               bufhdr->words.word4 = 0;
-       }
-       return min(max_payload, skb->len);
-}
-
-static struct hpsb_packet *ether1394_alloc_common_packet(struct hpsb_host *host)
-{
-       struct hpsb_packet *p;
-
-       p = hpsb_alloc_packet(0);
-       if (p) {
-               p->host = host;
-               p->generation = get_hpsb_generation(host);
-               p->type = hpsb_async;
-       }
-       return p;
-}
-
-static int ether1394_prep_write_packet(struct hpsb_packet *p,
-                                      struct hpsb_host *host, nodeid_t node,
-                                      u64 addr, void *data, int tx_len)
-{
-       p->node_id = node;
-
-       if (hpsb_get_tlabel(p))
-               return -EAGAIN;
-
-       p->tcode = TCODE_WRITEB;
-       p->header_size = 16;
-       p->expect_response = 1;
-       p->header[0] =
-               p->node_id << 16 | p->tlabel << 10 | 1 << 8 | TCODE_WRITEB << 4;
-       p->header[1] = host->node_id << 16 | addr >> 32;
-       p->header[2] = addr & 0xffffffff;
-       p->header[3] = tx_len << 16;
-       p->data_size = (tx_len + 3) & ~3;
-       p->data = data;
-
-       return 0;
-}
-
-static void ether1394_prep_gasp_packet(struct hpsb_packet *p,
-                                      struct eth1394_priv *priv,
-                                      struct sk_buff *skb, int length)
-{
-       p->header_size = 4;
-       p->tcode = TCODE_STREAM_DATA;
-
-       p->header[0] = length << 16 | 3 << 14 | priv->broadcast_channel << 8 |
-                      TCODE_STREAM_DATA << 4;
-       p->data_size = length;
-       p->data = (quadlet_t *)skb->data - 2;
-       p->data[0] = cpu_to_be32(priv->host->node_id << 16 |
-                                ETHER1394_GASP_SPECIFIER_ID_HI);
-       p->data[1] = cpu_to_be32(ETHER1394_GASP_SPECIFIER_ID_LO << 24 |
-                                ETHER1394_GASP_VERSION);
-
-       p->speed_code = priv->bc_sspd;
-
-       /* prevent hpsb_send_packet() from overriding our speed code */
-       p->node_id = LOCAL_BUS | ALL_NODES;
-}
-
-static void ether1394_free_packet(struct hpsb_packet *packet)
-{
-       if (packet->tcode != TCODE_STREAM_DATA)
-               hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-}
-
-static void ether1394_complete_cb(void *__ptask);
-
-static int ether1394_send_packet(struct packet_task *ptask, unsigned int tx_len)
-{
-       struct eth1394_priv *priv = ptask->priv;
-       struct hpsb_packet *packet = NULL;
-
-       packet = ether1394_alloc_common_packet(priv->host);
-       if (!packet)
-               return -ENOMEM;
-
-       if (ptask->tx_type == ETH1394_GASP) {
-               int length = tx_len + 2 * sizeof(quadlet_t);
-
-               ether1394_prep_gasp_packet(packet, priv, ptask->skb, length);
-       } else if (ether1394_prep_write_packet(packet, priv->host,
-                                              ptask->dest_node,
-                                              ptask->addr, ptask->skb->data,
-                                              tx_len)) {
-               hpsb_free_packet(packet);
-               return -EAGAIN;
-       }
-
-       ptask->packet = packet;
-       hpsb_set_packet_complete_task(ptask->packet, ether1394_complete_cb,
-                                     ptask);
-
-       if (hpsb_send_packet(packet) < 0) {
-               ether1394_free_packet(packet);
-               return -EIO;
-       }
-
-       return 0;
-}
-
-/* Task function to be run when a datagram transmission is completed */
-static void ether1394_dg_complete(struct packet_task *ptask, int fail)
-{
-       struct sk_buff *skb = ptask->skb;
-       struct net_device *dev = skb->dev;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       unsigned long flags;
-
-       /* Statistics */
-       spin_lock_irqsave(&priv->lock, flags);
-       if (fail) {
-               dev->stats.tx_dropped++;
-               dev->stats.tx_errors++;
-       } else {
-               dev->stats.tx_bytes += skb->len;
-               dev->stats.tx_packets++;
-       }
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       dev_kfree_skb_any(skb);
-       kmem_cache_free(packet_task_cache, ptask);
-}
-
-/* Callback for when a packet has been sent and the status of that packet is
- * known */
-static void ether1394_complete_cb(void *__ptask)
-{
-       struct packet_task *ptask = (struct packet_task *)__ptask;
-       struct hpsb_packet *packet = ptask->packet;
-       int fail = 0;
-
-       if (packet->tcode != TCODE_STREAM_DATA)
-               fail = hpsb_packet_success(packet);
-
-       ether1394_free_packet(packet);
-
-       ptask->outstanding_pkts--;
-       if (ptask->outstanding_pkts > 0 && !fail) {
-               int tx_len, err;
-
-               /* Add the encapsulation header to the fragment */
-               tx_len = ether1394_encapsulate(ptask->skb, ptask->max_payload,
-                                              &ptask->hdr);
-               err = ether1394_send_packet(ptask, tx_len);
-               if (err) {
-                       if (err == -EAGAIN)
-                               ETH1394_PRINT_G(KERN_ERR, "Out of tlabels\n");
-
-                       ether1394_dg_complete(ptask, 1);
-               }
-       } else {
-               ether1394_dg_complete(ptask, fail);
-       }
-}
-
-/* Transmit a packet (called by kernel) */
-static netdev_tx_t ether1394_tx(struct sk_buff *skb,
-                               struct net_device *dev)
-{
-       struct eth1394hdr hdr_buf;
-       struct eth1394_priv *priv = netdev_priv(dev);
-       __be16 proto;
-       unsigned long flags;
-       nodeid_t dest_node;
-       eth1394_tx_type tx_type;
-       unsigned int tx_len;
-       unsigned int max_payload;
-       u16 dg_size;
-       u16 dgl;
-       struct packet_task *ptask;
-       struct eth1394_node_ref *node;
-       struct eth1394_node_info *node_info = NULL;
-
-       ptask = kmem_cache_alloc(packet_task_cache, GFP_ATOMIC);
-       if (ptask == NULL)
-               goto fail;
-
-       /* XXX Ignore this for now. Noticed that when MacOSX is the IRM,
-        * it does not set our validity bit. We need to compensate for
-        * that somewhere else, but not in eth1394. */
-#if 0
-       if ((priv->host->csr.broadcast_channel & 0xc0000000) != 0xc0000000)
-               goto fail;
-#endif
-
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (!skb)
-               goto fail;
-
-       /* Get rid of the fake eth1394 header, but first make a copy.
-        * We might need to rebuild the header on tx failure. */
-       memcpy(&hdr_buf, skb->data, sizeof(hdr_buf));
-       skb_pull(skb, ETH1394_HLEN);
-
-       proto = hdr_buf.h_proto;
-       dg_size = skb->len;
-
-       /* Set the transmission type for the packet.  ARP packets and IP
-        * broadcast packets are sent via GASP. */
-       if (memcmp(hdr_buf.h_dest, dev->broadcast, ETH1394_ALEN) == 0 ||
-           proto == htons(ETH_P_ARP) ||
-           (proto == htons(ETH_P_IP) &&
-            IN_MULTICAST(ntohl(ip_hdr(skb)->daddr)))) {
-               tx_type = ETH1394_GASP;
-               dest_node = LOCAL_BUS | ALL_NODES;
-               max_payload = priv->bc_maxpayload - ETHER1394_GASP_OVERHEAD;
-               BUG_ON(max_payload < 512 - ETHER1394_GASP_OVERHEAD);
-               dgl = priv->bc_dgl;
-               if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
-                       priv->bc_dgl++;
-       } else {
-               __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest);
-
-               node = eth1394_find_node_guid(&priv->ip_node_list,
-                                             be64_to_cpu(guid));
-               if (!node)
-                       goto fail;
-
-               node_info = dev_get_drvdata(&node->ud->device);
-               if (node_info->fifo == CSR1212_INVALID_ADDR_SPACE)
-                       goto fail;
-
-               dest_node = node->ud->ne->nodeid;
-               max_payload = node_info->maxpayload;
-               BUG_ON(max_payload < 512 - ETHER1394_GASP_OVERHEAD);
-
-               dgl = node_info->dgl;
-               if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF])
-                       node_info->dgl++;
-               tx_type = ETH1394_WRREQ;
-       }
-
-       /* If this is an ARP packet, convert it */
-       if (proto == htons(ETH_P_ARP))
-               ether1394_arp_to_1394arp(skb, dev);
-
-       ptask->hdr.words.word1 = 0;
-       ptask->hdr.words.word2 = 0;
-       ptask->hdr.words.word3 = 0;
-       ptask->hdr.words.word4 = 0;
-       ptask->skb = skb;
-       ptask->priv = priv;
-       ptask->tx_type = tx_type;
-
-       if (tx_type != ETH1394_GASP) {
-               u64 addr;
-
-               spin_lock_irqsave(&priv->lock, flags);
-               addr = node_info->fifo;
-               spin_unlock_irqrestore(&priv->lock, flags);
-
-               ptask->addr = addr;
-               ptask->dest_node = dest_node;
-       }
-
-       ptask->tx_type = tx_type;
-       ptask->max_payload = max_payload;
-       ptask->outstanding_pkts = ether1394_encapsulate_prep(max_payload,
-                                       proto, &ptask->hdr, dg_size, dgl);
-
-       /* Add the encapsulation header to the fragment */
-       tx_len = ether1394_encapsulate(skb, max_payload, &ptask->hdr);
-       dev->trans_start = jiffies;
-       if (ether1394_send_packet(ptask, tx_len)) {
-               if (dest_node == (LOCAL_BUS | ALL_NODES))
-                       goto fail;
-
-               /* At this point we want to restore the packet.  When we return
-                * here with NETDEV_TX_BUSY we will get another entrance in this
-                * routine with the same skb and we need it to look the same.
-                * So we pull 4 more bytes, then build the header again. */
-               skb_pull(skb, 4);
-               ether1394_header(skb, dev, ntohs(hdr_buf.h_proto),
-                                hdr_buf.h_dest, NULL, 0);
-
-               /* Most failures of ether1394_send_packet are recoverable. */
-               netif_stop_queue(dev);
-               priv->wake_node = dest_node;
-               schedule_work(&priv->wake);
-               kmem_cache_free(packet_task_cache, ptask);
-               return NETDEV_TX_BUSY;
-       }
-
-       return NETDEV_TX_OK;
-fail:
-       if (ptask)
-               kmem_cache_free(packet_task_cache, ptask);
-
-       if (skb != NULL)
-               dev_kfree_skb(skb);
-
-       spin_lock_irqsave(&priv->lock, flags);
-       dev->stats.tx_dropped++;
-       dev->stats.tx_errors++;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       return NETDEV_TX_OK;
-}
-
-static int __init ether1394_init_module(void)
-{
-       int err;
-
-       packet_task_cache = kmem_cache_create("packet_task",
-                                             sizeof(struct packet_task),
-                                             0, 0, NULL);
-       if (!packet_task_cache)
-               return -ENOMEM;
-
-       hpsb_register_highlevel(&eth1394_highlevel);
-       err = hpsb_register_protocol(&eth1394_proto_driver);
-       if (err) {
-               hpsb_unregister_highlevel(&eth1394_highlevel);
-               kmem_cache_destroy(packet_task_cache);
-       }
-       return err;
-}
-
-static void __exit ether1394_exit_module(void)
-{
-       hpsb_unregister_protocol(&eth1394_proto_driver);
-       hpsb_unregister_highlevel(&eth1394_highlevel);
-       kmem_cache_destroy(packet_task_cache);
-}
-
-module_init(ether1394_init_module);
-module_exit(ether1394_exit_module);
diff --git a/drivers/ieee1394/eth1394.h b/drivers/ieee1394/eth1394.h
deleted file mode 100644 (file)
index d53bac4..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * eth1394.h -- Ethernet driver for Linux IEEE-1394 Subsystem
- *
- * Copyright (C) 2000 Bonin Franck <boninf@free.fr>
- *           (C) 2001 Ben Collins <bcollins@debian.org>
- *
- * Mainly based on work by Emanuel Pirker and Andreas E. Bombe
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __ETH1394_H
-#define __ETH1394_H
-
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <asm/byteorder.h>
-
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-
-/* Register for incoming packets. This is 4096 bytes, which supports up to
- * S3200 (per Table 16-3 of IEEE 1394b-2002). */
-#define ETHER1394_REGION_ADDR_LEN      4096
-
-/* GASP identifier numbers for IPv4 over IEEE 1394 */
-#define ETHER1394_GASP_SPECIFIER_ID    0x00005E
-#define ETHER1394_GASP_SPECIFIER_ID_HI ((0x00005E >> 8) & 0xffff)
-#define ETHER1394_GASP_SPECIFIER_ID_LO (0x00005E & 0xff)
-#define ETHER1394_GASP_VERSION         1
-
-#define ETHER1394_GASP_OVERHEAD        (2 * sizeof(quadlet_t)) /* for GASP header */
-
-#define ETHER1394_GASP_BUFFERS 16
-
-#define NODE_SET               (ALL_NODES + 1)         /* Node set == 64 */
-
-enum eth1394_bc_states { ETHER1394_BC_ERROR,
-                        ETHER1394_BC_RUNNING,
-                        ETHER1394_BC_STOPPED };
-
-
-/* Private structure for our ethernet driver */
-struct eth1394_priv {
-       struct hpsb_host *host;         /* The card for this dev         */
-       u16 bc_maxpayload;              /* Max broadcast payload         */
-       u8 bc_sspd;                     /* Max broadcast speed           */
-       u64 local_fifo;                 /* Local FIFO Address            */
-       spinlock_t lock;                /* Private lock                  */
-       int broadcast_channel;          /* Async stream Broadcast Channel */
-       enum eth1394_bc_states bc_state; /* broadcast channel state      */
-       struct hpsb_iso *iso;           /* Async stream recv handle      */
-       int bc_dgl;                     /* Outgoing broadcast datagram label */
-       struct list_head ip_node_list;  /* List of IP capable nodes      */
-       struct unit_directory *ud_list[ALL_NODES]; /* Cached unit dir list */
-
-       struct work_struct wake;        /* Wake up after xmit failure    */
-       struct net_device *wake_dev;    /* Stupid backlink for .wake     */
-       nodeid_t wake_node;             /* Destination of failed xmit    */
-};
-
-
-/* Define a fake hardware header format for the networking core.  Note that
- * header size cannot exceed 16 bytes as that is the size of the header cache.
- * Also, we do not need the source address in the header so we omit it and
- * keep the header to under 16 bytes */
-#define ETH1394_ALEN (8)
-#define ETH1394_HLEN (10)
-
-struct eth1394hdr {
-       unsigned char   h_dest[ETH1394_ALEN];   /* destination eth1394 addr     */
-       __be16          h_proto;                /* packet type ID field */
-}  __attribute__((packed));
-
-static inline struct eth1394hdr *eth1394_hdr(const struct sk_buff *skb)
-{
-       return (struct eth1394hdr *)skb_mac_header(skb);
-}
-
-typedef enum {ETH1394_GASP, ETH1394_WRREQ} eth1394_tx_type;
-
-/* IP1394 headers */
-
-/* Unfragmented */
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_uf_hdr {
-       u16 lf:2;
-       u16 res:14;
-       __be16 ether_type;              /* Ethernet packet type */
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_uf_hdr {
-       u16 res:14;
-       u16 lf:2;
-       __be16 ether_type;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-/* First fragment */
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_ff_hdr {
-       u16 lf:2;
-       u16 res1:2;
-       u16 dg_size:12;         /* Datagram size */
-       __be16 ether_type;              /* Ethernet packet type */
-       u16 dgl;                /* Datagram label */
-       u16 res2;
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_ff_hdr {
-       u16 dg_size:12;
-       u16 res1:2;
-       u16 lf:2;
-       __be16 ether_type;
-       u16 dgl;
-       u16 res2;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-/* XXX: Subsequent fragments, including last */
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_sf_hdr {
-       u16 lf:2;
-       u16 res1:2;
-       u16 dg_size:12;         /* Datagram size */
-       u16 res2:4;
-       u16 fg_off:12;          /* Fragment offset */
-       u16 dgl;                /* Datagram label */
-       u16 res3;
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_sf_hdr {
-       u16 dg_size:12;
-       u16 res1:2;
-       u16 lf:2;
-       u16 fg_off:12;
-       u16 res2:4;
-       u16 dgl;
-       u16 res3;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-#if defined __BIG_ENDIAN_BITFIELD
-struct eth1394_common_hdr {
-       u16 lf:2;
-       u16 pad1:14;
-} __attribute__((packed));
-#elif defined __LITTLE_ENDIAN_BITFIELD
-struct eth1394_common_hdr {
-       u16 pad1:14;
-       u16 lf:2;
-} __attribute__((packed));
-#else
-#error Unknown bit field type
-#endif
-
-struct eth1394_hdr_words {
-       u16 word1;
-       u16 word2;
-       u16 word3;
-       u16 word4;
-};
-
-union eth1394_hdr {
-       struct eth1394_common_hdr common;
-       struct eth1394_uf_hdr uf;
-       struct eth1394_ff_hdr ff;
-       struct eth1394_sf_hdr sf;
-       struct eth1394_hdr_words words;
-};
-
-/* End of IP1394 headers */
-
-/* Fragment types */
-#define ETH1394_HDR_LF_UF      0       /* unfragmented         */
-#define ETH1394_HDR_LF_FF      1       /* first fragment       */
-#define ETH1394_HDR_LF_LF      2       /* last fragment        */
-#define ETH1394_HDR_LF_IF      3       /* interior fragment    */
-
-#define IP1394_HW_ADDR_LEN     16      /* As per RFC           */
-
-/* Our arp packet (ARPHRD_IEEE1394) */
-struct eth1394_arp {
-       u16 hw_type;            /* 0x0018       */
-       u16 proto_type;         /* 0x0806       */
-       u8 hw_addr_len;         /* 16           */
-       u8 ip_addr_len;         /* 4            */
-       u16 opcode;             /* ARP Opcode   */
-       /* Above is exactly the same format as struct arphdr */
-
-       __be64 s_uniq_id;       /* Sender's 64bit EUI           */
-       u8 max_rec;             /* Sender's max packet size             */
-       u8 sspd;                /* Sender's max speed                   */
-       __be16 fifo_hi;         /* hi 16bits of sender's FIFO addr      */
-       __be32 fifo_lo;         /* lo 32bits of sender's FIFO addr      */
-       u32 sip;                /* Sender's IP Address                  */
-       u32 tip;                /* IP Address of requested hw addr      */
-};
-
-/* Network timeout */
-#define ETHER1394_TIMEOUT      100000
-
-/* This is our task struct. It's used for the packet complete callback.  */
-struct packet_task {
-       struct sk_buff *skb;
-       int outstanding_pkts;
-       eth1394_tx_type tx_type;
-       int max_payload;
-       struct hpsb_packet *packet;
-       struct eth1394_priv *priv;
-       union eth1394_hdr hdr;
-       u64 addr;
-       u16 dest_node;
-};
-
-#endif /* __ETH1394_H */
diff --git a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
deleted file mode 100644 (file)
index 4bc4435..0000000
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Copyright (C) 1999 Andreas E. Bombe
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Christian Toegel <christian.toegel@gmx.at>
- *        unregister address space
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        unregister address space
- *
- */
-
-#include <linux/slab.h>
-#include <linux/list.h>
-#include <linux/bitops.h>
-
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "nodemgr.h"
-
-
-struct hl_host_info {
-       struct list_head list;
-       struct hpsb_host *host;
-       size_t size;
-       unsigned long key;
-       void *data;
-};
-
-
-static LIST_HEAD(hl_drivers);
-static DECLARE_RWSEM(hl_drivers_sem);
-
-static LIST_HEAD(hl_irqs);
-static DEFINE_RWLOCK(hl_irqs_lock);
-
-static DEFINE_RWLOCK(addr_space_lock);
-
-
-static struct hl_host_info *hl_get_hostinfo(struct hpsb_highlevel *hl,
-                                           struct hpsb_host *host)
-{
-       struct hl_host_info *hi = NULL;
-
-       if (!hl || !host)
-               return NULL;
-
-       read_lock(&hl->host_info_lock);
-       list_for_each_entry(hi, &hl->host_info_list, list) {
-               if (hi->host == host) {
-                       read_unlock(&hl->host_info_lock);
-                       return hi;
-               }
-       }
-       read_unlock(&hl->host_info_lock);
-       return NULL;
-}
-
-/**
- * hpsb_get_hostinfo - retrieve a hostinfo pointer bound to this driver/host
- *
- * Returns a per @host and @hl driver data structure that was previously stored
- * by hpsb_create_hostinfo.
- */
-void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
-{
-       struct hl_host_info *hi = hl_get_hostinfo(hl, host);
-
-       return hi ? hi->data : NULL;
-}
-
-/**
- * hpsb_create_hostinfo - allocate a hostinfo pointer bound to this driver/host
- *
- * Allocate a hostinfo pointer backed by memory with @data_size and bind it to
- * to this @hl driver and @host.  If @data_size is zero, then the return here is
- * only valid for error checking.
- */
-void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          size_t data_size)
-{
-       struct hl_host_info *hi;
-       void *data;
-       unsigned long flags;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi) {
-               HPSB_ERR("%s called hpsb_create_hostinfo when hostinfo already"
-                        " exists", hl->name);
-               return NULL;
-       }
-
-       hi = kzalloc(sizeof(*hi) + data_size, GFP_ATOMIC);
-       if (!hi)
-               return NULL;
-
-       if (data_size) {
-               data = hi->data = hi + 1;
-               hi->size = data_size;
-       } else
-               data = hi;
-
-       hi->host = host;
-
-       write_lock_irqsave(&hl->host_info_lock, flags);
-       list_add_tail(&hi->list, &hl->host_info_list);
-       write_unlock_irqrestore(&hl->host_info_lock, flags);
-
-       return data;
-}
-
-/**
- * hpsb_set_hostinfo - set the hostinfo pointer to something useful
- *
- * Usually follows a call to hpsb_create_hostinfo, where the size is 0.
- */
-int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                     void *data)
-{
-       struct hl_host_info *hi;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi) {
-               if (!hi->size && !hi->data) {
-                       hi->data = data;
-                       return 0;
-               } else
-                       HPSB_ERR("%s called hpsb_set_hostinfo when hostinfo "
-                                "already has data", hl->name);
-       } else
-               HPSB_ERR("%s called hpsb_set_hostinfo when no hostinfo exists",
-                        hl->name);
-       return -EINVAL;
-}
-
-/**
- * hpsb_destroy_hostinfo - free and remove a hostinfo pointer
- *
- * Free and remove the hostinfo pointer bound to this @hl driver and @host.
- */
-void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host)
-{
-       struct hl_host_info *hi;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi) {
-               unsigned long flags;
-               write_lock_irqsave(&hl->host_info_lock, flags);
-               list_del(&hi->list);
-               write_unlock_irqrestore(&hl->host_info_lock, flags);
-               kfree(hi);
-       }
-       return;
-}
-
-/**
- * hpsb_set_hostinfo_key - set an alternate lookup key for an hostinfo
- *
- * Sets an alternate lookup key for the hostinfo bound to this @hl driver and
- * @host.
- */
-void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          unsigned long key)
-{
-       struct hl_host_info *hi;
-
-       hi = hl_get_hostinfo(hl, host);
-       if (hi)
-               hi->key = key;
-       return;
-}
-
-/**
- * hpsb_get_hostinfo_bykey - retrieve a hostinfo pointer by its alternate key
- */
-void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
-{
-       struct hl_host_info *hi;
-       void *data = NULL;
-
-       if (!hl)
-               return NULL;
-
-       read_lock(&hl->host_info_lock);
-       list_for_each_entry(hi, &hl->host_info_list, list) {
-               if (hi->key == key) {
-                       data = hi->data;
-                       break;
-               }
-       }
-       read_unlock(&hl->host_info_lock);
-       return data;
-}
-
-static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
-{
-       struct hpsb_highlevel *hl = __data;
-
-       hl->add_host(host);
-
-       if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
-               HPSB_ERR("Failed to generate Configuration ROM image for host "
-                        "%s-%d", hl->name, host->id);
-       return 0;
-}
-
-/**
- * hpsb_register_highlevel - register highlevel driver
- *
- * The name pointer in @hl has to stay valid at all times because the string is
- * not copied.
- */
-void hpsb_register_highlevel(struct hpsb_highlevel *hl)
-{
-       unsigned long flags;
-
-       hpsb_init_highlevel(hl);
-       INIT_LIST_HEAD(&hl->addr_list);
-
-       down_write(&hl_drivers_sem);
-       list_add_tail(&hl->hl_list, &hl_drivers);
-       up_write(&hl_drivers_sem);
-
-       write_lock_irqsave(&hl_irqs_lock, flags);
-       list_add_tail(&hl->irq_list, &hl_irqs);
-       write_unlock_irqrestore(&hl_irqs_lock, flags);
-
-       if (hl->add_host)
-               nodemgr_for_each_host(hl, highlevel_for_each_host_reg);
-       return;
-}
-
-static void __delete_addr(struct hpsb_address_serve *as)
-{
-       list_del(&as->host_list);
-       list_del(&as->hl_list);
-       kfree(as);
-}
-
-static void __unregister_host(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                             int update_cr)
-{
-       unsigned long flags;
-       struct list_head *lh, *next;
-       struct hpsb_address_serve *as;
-
-       /* First, let the highlevel driver unreg */
-       if (hl->remove_host)
-               hl->remove_host(host);
-
-       /* Remove any addresses that are matched for this highlevel driver
-        * and this particular host. */
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each_safe (lh, next, &hl->addr_list) {
-               as = list_entry(lh, struct hpsb_address_serve, hl_list);
-               if (as->host == host)
-                       __delete_addr(as);
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-
-       /* Now update the config-rom to reflect anything removed by the
-        * highlevel driver. */
-       if (update_cr && host->update_config_rom &&
-           hpsb_update_config_rom_image(host) < 0)
-               HPSB_ERR("Failed to generate Configuration ROM image for host "
-                        "%s-%d", hl->name, host->id);
-
-       /* Finally remove all the host info associated between these two. */
-       hpsb_destroy_hostinfo(hl, host);
-}
-
-static int highlevel_for_each_host_unreg(struct hpsb_host *host, void *__data)
-{
-       struct hpsb_highlevel *hl = __data;
-
-       __unregister_host(hl, host, 1);
-       return 0;
-}
-
-/**
- * hpsb_unregister_highlevel - unregister highlevel driver
- */
-void hpsb_unregister_highlevel(struct hpsb_highlevel *hl)
-{
-       unsigned long flags;
-
-       write_lock_irqsave(&hl_irqs_lock, flags);
-       list_del(&hl->irq_list);
-       write_unlock_irqrestore(&hl_irqs_lock, flags);
-
-       down_write(&hl_drivers_sem);
-       list_del(&hl->hl_list);
-       up_write(&hl_drivers_sem);
-
-       nodemgr_for_each_host(hl, highlevel_for_each_host_unreg);
-}
-
-/**
- * hpsb_allocate_and_register_addrspace - alloc' and reg' a host address space
- *
- * @start and @end are 48 bit pointers and have to be quadlet aligned.
- * @end points to the first address behind the handled addresses.  This
- * function can be called multiple times for a single hpsb_highlevel @hl to
- * implement sparse register sets.  The requested region must not overlap any
- * previously allocated region, otherwise registering will fail.
- *
- * It returns true for successful allocation.  Address spaces can be
- * unregistered with hpsb_unregister_addrspace.  All remaining address spaces
- * are automatically deallocated together with the hpsb_highlevel @hl.
- */
-u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
-                                        struct hpsb_host *host,
-                                        const struct hpsb_address_ops *ops,
-                                        u64 size, u64 alignment,
-                                        u64 start, u64 end)
-{
-       struct hpsb_address_serve *as, *a1, *a2;
-       struct list_head *entry;
-       u64 retval = CSR1212_INVALID_ADDR_SPACE;
-       unsigned long flags;
-       u64 align_mask = ~(alignment - 1);
-
-       if ((alignment & 3) || (alignment > 0x800000000000ULL) ||
-           (hweight64(alignment) != 1)) {
-               HPSB_ERR("%s called with invalid alignment: 0x%048llx",
-                        __func__, (unsigned long long)alignment);
-               return retval;
-       }
-
-       /* default range,
-        * avoids controller's posted write area (see OHCI 1.1 clause 1.5) */
-       if (start == CSR1212_INVALID_ADDR_SPACE &&
-           end   == CSR1212_INVALID_ADDR_SPACE) {
-               start = host->middle_addr_space;
-               end   = CSR1212_ALL_SPACE_END;
-       }
-
-       if (((start|end) & ~align_mask) || (start >= end) ||
-           (end > CSR1212_ALL_SPACE_END)) {
-               HPSB_ERR("%s called with invalid addresses "
-                        "(start = %012Lx  end = %012Lx)", __func__,
-                        (unsigned long long)start,(unsigned long long)end);
-               return retval;
-       }
-
-       as = kmalloc(sizeof(*as), GFP_KERNEL);
-       if (!as)
-               return retval;
-
-       INIT_LIST_HEAD(&as->host_list);
-       INIT_LIST_HEAD(&as->hl_list);
-       as->op = ops;
-       as->host = host;
-
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each(entry, &host->addr_space) {
-               u64 a1sa, a1ea;
-               u64 a2sa, a2ea;
-
-               a1 = list_entry(entry, struct hpsb_address_serve, host_list);
-               a2 = list_entry(entry->next, struct hpsb_address_serve,
-                               host_list);
-
-               a1sa = a1->start & align_mask;
-               a1ea = (a1->end + alignment -1) & align_mask;
-               a2sa = a2->start & align_mask;
-               a2ea = (a2->end + alignment -1) & align_mask;
-
-               if ((a2sa - a1ea >= size) && (a2sa - start >= size) &&
-                   (a2sa > start)) {
-                       as->start = max(start, a1ea);
-                       as->end = as->start + size;
-                       list_add(&as->host_list, entry);
-                       list_add_tail(&as->hl_list, &hl->addr_list);
-                       retval = as->start;
-                       break;
-               }
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-
-       if (retval == CSR1212_INVALID_ADDR_SPACE)
-               kfree(as);
-       return retval;
-}
-
-/**
- * hpsb_register_addrspace - register a host address space
- *
- * @start and @end are 48 bit pointers and have to be quadlet aligned.
- * @end points to the first address behind the handled addresses.  This
- * function can be called multiple times for a single hpsb_highlevel @hl to
- * implement sparse register sets.  The requested region must not overlap any
- * previously allocated region, otherwise registering will fail.
- *
- * It returns true for successful allocation.  Address spaces can be
- * unregistered with hpsb_unregister_addrspace.  All remaining address spaces
- * are automatically deallocated together with the hpsb_highlevel @hl.
- */
-int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                           const struct hpsb_address_ops *ops,
-                           u64 start, u64 end)
-{
-       struct hpsb_address_serve *as;
-       struct list_head *lh;
-       int retval = 0;
-       unsigned long flags;
-
-       if (((start|end) & 3) || (start >= end) ||
-           (end > CSR1212_ALL_SPACE_END)) {
-               HPSB_ERR("%s called with invalid addresses", __func__);
-               return 0;
-       }
-
-       as = kmalloc(sizeof(*as), GFP_KERNEL);
-       if (!as)
-               return 0;
-
-       INIT_LIST_HEAD(&as->host_list);
-       INIT_LIST_HEAD(&as->hl_list);
-       as->op = ops;
-       as->start = start;
-       as->end = end;
-       as->host = host;
-
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each(lh, &host->addr_space) {
-               struct hpsb_address_serve *as_this =
-                       list_entry(lh, struct hpsb_address_serve, host_list);
-               struct hpsb_address_serve *as_next =
-                       list_entry(lh->next, struct hpsb_address_serve,
-                                  host_list);
-
-               if (as_this->end > as->start)
-                       break;
-
-               if (as_next->start >= as->end) {
-                       list_add(&as->host_list, lh);
-                       list_add_tail(&as->hl_list, &hl->addr_list);
-                       retval = 1;
-                       break;
-               }
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-
-       if (retval == 0)
-               kfree(as);
-       return retval;
-}
-
-int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                             u64 start)
-{
-       int retval = 0;
-       struct hpsb_address_serve *as;
-       struct list_head *lh, *next;
-       unsigned long flags;
-
-       write_lock_irqsave(&addr_space_lock, flags);
-       list_for_each_safe (lh, next, &hl->addr_list) {
-               as = list_entry(lh, struct hpsb_address_serve, hl_list);
-               if (as->start == start && as->host == host) {
-                       __delete_addr(as);
-                       retval = 1;
-                       break;
-               }
-       }
-       write_unlock_irqrestore(&addr_space_lock, flags);
-       return retval;
-}
-
-static const struct hpsb_address_ops dummy_ops;
-
-/* dummy address spaces as lower and upper bounds of the host's a.s. list */
-static void init_hpsb_highlevel(struct hpsb_host *host)
-{
-       INIT_LIST_HEAD(&host->dummy_zero_addr.host_list);
-       INIT_LIST_HEAD(&host->dummy_zero_addr.hl_list);
-       INIT_LIST_HEAD(&host->dummy_max_addr.host_list);
-       INIT_LIST_HEAD(&host->dummy_max_addr.hl_list);
-
-       host->dummy_zero_addr.op = host->dummy_max_addr.op = &dummy_ops;
-
-       host->dummy_zero_addr.start = host->dummy_zero_addr.end = 0;
-       host->dummy_max_addr.start = host->dummy_max_addr.end = ((u64) 1) << 48;
-
-       list_add_tail(&host->dummy_zero_addr.host_list, &host->addr_space);
-       list_add_tail(&host->dummy_max_addr.host_list, &host->addr_space);
-}
-
-void highlevel_add_host(struct hpsb_host *host)
-{
-       struct hpsb_highlevel *hl;
-
-       init_hpsb_highlevel(host);
-
-       down_read(&hl_drivers_sem);
-       list_for_each_entry(hl, &hl_drivers, hl_list) {
-               if (hl->add_host)
-                       hl->add_host(host);
-       }
-       up_read(&hl_drivers_sem);
-       if (host->update_config_rom && hpsb_update_config_rom_image(host) < 0)
-               HPSB_ERR("Failed to generate Configuration ROM image for host "
-                        "%s-%d", hl->name, host->id);
-}
-
-void highlevel_remove_host(struct hpsb_host *host)
-{
-       struct hpsb_highlevel *hl;
-
-       down_read(&hl_drivers_sem);
-       list_for_each_entry(hl, &hl_drivers, hl_list)
-               __unregister_host(hl, host, 0);
-       up_read(&hl_drivers_sem);
-}
-
-void highlevel_host_reset(struct hpsb_host *host)
-{
-       unsigned long flags;
-       struct hpsb_highlevel *hl;
-
-       read_lock_irqsave(&hl_irqs_lock, flags);
-       list_for_each_entry(hl, &hl_irqs, irq_list) {
-               if (hl->host_reset)
-                       hl->host_reset(host);
-       }
-       read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
-void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
-                          void *data, size_t length)
-{
-       unsigned long flags;
-       struct hpsb_highlevel *hl;
-       int cts = ((quadlet_t *)data)[0] >> 4;
-
-       read_lock_irqsave(&hl_irqs_lock, flags);
-       list_for_each_entry(hl, &hl_irqs, irq_list) {
-               if (hl->fcp_request)
-                       hl->fcp_request(host, nodeid, direction, cts, data,
-                                       length);
-       }
-       read_unlock_irqrestore(&hl_irqs_lock, flags);
-}
-
-/*
- * highlevel_read, highlevel_write, highlevel_lock, highlevel_lock64:
- *
- * These functions are called to handle transactions. They are called when a
- * packet arrives.  The flags argument contains the second word of the first
- * header quadlet of the incoming packet (containing transaction label, retry
- * code, transaction code and priority).  These functions either return a
- * response code or a negative number.  In the first case a response will be
- * generated.  In the latter case, no response will be sent and the driver which
- * handled the request will send the response itself.
- */
-int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
-                  unsigned int length, u16 flags)
-{
-       struct hpsb_address_serve *as;
-       unsigned int partlength;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       partlength = min(as->end - addr, (u64) length);
-
-                       if (as->op->read)
-                               rcode = as->op->read(host, nodeid, data,
-                                                    addr, partlength, flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-
-                       data += partlength;
-                       length -= partlength;
-                       addr += partlength;
-
-                       if ((rcode != RCODE_COMPLETE) || !length)
-                               break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-
-       if (length && (rcode == RCODE_COMPLETE))
-               rcode = RCODE_ADDRESS_ERROR;
-       return rcode;
-}
-
-int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
-                   u64 addr, unsigned int length, u16 flags)
-{
-       struct hpsb_address_serve *as;
-       unsigned int partlength;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       partlength = min(as->end - addr, (u64) length);
-
-                       if (as->op->write)
-                               rcode = as->op->write(host, nodeid, destid,
-                                                     data, addr, partlength,
-                                                     flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-
-                       data += partlength;
-                       length -= partlength;
-                       addr += partlength;
-
-                       if ((rcode != RCODE_COMPLETE) || !length)
-                               break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-
-       if (length && (rcode == RCODE_COMPLETE))
-               rcode = RCODE_ADDRESS_ERROR;
-       return rcode;
-}
-
-int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                  u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                  u16 flags)
-{
-       struct hpsb_address_serve *as;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       if (as->op->lock)
-                               rcode = as->op->lock(host, nodeid, store, addr,
-                                                    data, arg, ext_tcode,
-                                                    flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-                       break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-       return rcode;
-}
-
-int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                    u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                    u16 flags)
-{
-       struct hpsb_address_serve *as;
-       int rcode = RCODE_ADDRESS_ERROR;
-
-       read_lock(&addr_space_lock);
-
-       list_for_each_entry(as, &host->addr_space, host_list) {
-               if (as->start > addr)
-                       break;
-
-               if (as->end > addr) {
-                       if (as->op->lock64)
-                               rcode = as->op->lock64(host, nodeid, store,
-                                                      addr, data, arg,
-                                                      ext_tcode, flags);
-                       else
-                               rcode = RCODE_TYPE_ERROR;
-                       break;
-               }
-       }
-       read_unlock(&addr_space_lock);
-       return rcode;
-}
diff --git a/drivers/ieee1394/highlevel.h b/drivers/ieee1394/highlevel.h
deleted file mode 100644 (file)
index 9dba89f..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-#ifndef IEEE1394_HIGHLEVEL_H
-#define IEEE1394_HIGHLEVEL_H
-
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-struct module;
-
-#include "ieee1394_types.h"
-
-struct hpsb_host;
-
-/* internal to ieee1394 core */
-struct hpsb_address_serve {
-       struct list_head host_list;     /* per host list */
-       struct list_head hl_list;       /* hpsb_highlevel list */
-       const struct hpsb_address_ops *op;
-       struct hpsb_host *host;
-       u64 start;      /* first address handled, quadlet aligned */
-       u64 end;        /* first address behind, quadlet aligned */
-};
-
-/* Only the following structures are of interest to actual highlevel drivers. */
-
-struct hpsb_highlevel {
-       const char *name;
-
-       /* Any of the following pointers can legally be NULL. */
-
-       /* New host initialized.  Will also be called during
-        * hpsb_register_highlevel for all hosts already installed. */
-       void (*add_host)(struct hpsb_host *host);
-
-       /* Host about to be removed.  Will also be called during
-        * hpsb_unregister_highlevel once for each host. */
-       void (*remove_host)(struct hpsb_host *host);
-
-       /* Host experienced bus reset with possible configuration changes.
-        * Note that this one may occur during interrupt/bottom half handling.
-        * You can not expect to be able to do stock hpsb_reads. */
-       void (*host_reset)(struct hpsb_host *host);
-
-       /* A write request was received on either the FCP_COMMAND (direction =
-        * 0) or the FCP_RESPONSE (direction = 1) register.  The cts arg
-        * contains the cts field (first byte of data). */
-       void (*fcp_request)(struct hpsb_host *host, int nodeid, int direction,
-                           int cts, u8 *data, size_t length);
-
-       /* These are initialized by the subsystem when the
-        * hpsb_higlevel is registered. */
-       struct list_head hl_list;
-       struct list_head irq_list;
-       struct list_head addr_list;
-
-       struct list_head host_info_list;
-       rwlock_t host_info_lock;
-};
-
-struct hpsb_address_ops {
-       /*
-        * Null function pointers will make the respective operation complete
-        * with RCODE_TYPE_ERROR.  Makes for easy to implement read-only
-        * registers (just leave everything but read NULL).
-        *
-        * All functions shall return appropriate IEEE 1394 rcodes.
-        */
-
-       /* These functions have to implement block reads for themselves.
-        *
-        * These functions either return a response code or a negative number.
-        * In the first case a response will be generated.  In the latter case,
-        * no response will be sent and the driver which handled the request
-        * will send the response itself. */
-       int (*read)(struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-                   u64 addr, size_t length, u16 flags);
-       int (*write)(struct hpsb_host *host, int nodeid, int destid,
-                    quadlet_t *data, u64 addr, size_t length, u16 flags);
-
-       /* Lock transactions: write results of ext_tcode operation into
-        * *store. */
-       int (*lock)(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                   u16 flags);
-       int (*lock64)(struct hpsb_host *host, int nodeid, octlet_t *store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                     u16 flags);
-};
-
-void highlevel_add_host(struct hpsb_host *host);
-void highlevel_remove_host(struct hpsb_host *host);
-void highlevel_host_reset(struct hpsb_host *host);
-int highlevel_read(struct hpsb_host *host, int nodeid, void *data, u64 addr,
-                  unsigned int length, u16 flags);
-int highlevel_write(struct hpsb_host *host, int nodeid, int destid, void *data,
-                   u64 addr, unsigned int length, u16 flags);
-int highlevel_lock(struct hpsb_host *host, int nodeid, quadlet_t *store,
-                  u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                  u16 flags);
-int highlevel_lock64(struct hpsb_host *host, int nodeid, octlet_t *store,
-                    u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                    u16 flags);
-void highlevel_fcp_request(struct hpsb_host *host, int nodeid, int direction,
-                          void *data, size_t length);
-
-/**
- * hpsb_init_highlevel - initialize a struct hpsb_highlevel
- *
- * This is only necessary if hpsb_get_hostinfo_bykey can be called
- * before hpsb_register_highlevel.
- */
-static inline void hpsb_init_highlevel(struct hpsb_highlevel *hl)
-{
-       rwlock_init(&hl->host_info_lock);
-       INIT_LIST_HEAD(&hl->host_info_list);
-}
-void hpsb_register_highlevel(struct hpsb_highlevel *hl);
-void hpsb_unregister_highlevel(struct hpsb_highlevel *hl);
-
-u64 hpsb_allocate_and_register_addrspace(struct hpsb_highlevel *hl,
-                                        struct hpsb_host *host,
-                                        const struct hpsb_address_ops *ops,
-                                        u64 size, u64 alignment,
-                                        u64 start, u64 end);
-int hpsb_register_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                           const struct hpsb_address_ops *ops,
-                           u64 start, u64 end);
-int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                             u64 start);
-
-void *hpsb_get_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
-void *hpsb_create_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          size_t data_size);
-void hpsb_destroy_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host);
-void hpsb_set_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                          unsigned long key);
-void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key);
-int hpsb_set_hostinfo(struct hpsb_highlevel *hl, struct hpsb_host *host,
-                     void *data);
-
-#endif /* IEEE1394_HIGHLEVEL_H */
diff --git a/drivers/ieee1394/hosts.c b/drivers/ieee1394/hosts.c
deleted file mode 100644 (file)
index e947d8f..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Low level (host adapter) management.
- *
- * Copyright (C) 1999 Andreas E. Bombe
- * Copyright (C) 1999 Emanuel Pirker
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/mutex.h>
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "nodemgr.h"
-#include "csr.h"
-#include "config_roms.h"
-
-
-static void delayed_reset_bus(struct work_struct *work)
-{
-       struct hpsb_host *host =
-               container_of(work, struct hpsb_host, delayed_reset.work);
-       u8 generation = host->csr.generation + 1;
-
-       /* The generation field rolls over to 2 rather than 0 per IEEE
-        * 1394a-2000. */
-       if (generation > 0xf || generation < 2)
-               generation = 2;
-
-       csr_set_bus_info_generation(host->csr.rom, generation);
-       if (csr1212_generate_csr_image(host->csr.rom) != CSR1212_SUCCESS) {
-               /* CSR image creation failed.
-                * Reset generation field and do not issue a bus reset. */
-               csr_set_bus_info_generation(host->csr.rom,
-                                           host->csr.generation);
-               return;
-       }
-
-       host->csr.generation = generation;
-
-       host->update_config_rom = 0;
-       if (host->driver->set_hw_config_rom)
-               host->driver->set_hw_config_rom(host,
-                                               host->csr.rom->bus_info_data);
-
-       host->csr.gen_timestamp[host->csr.generation] = jiffies;
-       hpsb_reset_bus(host, SHORT_RESET);
-}
-
-static int dummy_transmit_packet(struct hpsb_host *h, struct hpsb_packet *p)
-{
-       return 0;
-}
-
-static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
-{
-       return -1;
-}
-
-static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command,
-                       unsigned long arg)
-{
-       return -1;
-}
-
-static struct hpsb_host_driver dummy_driver = {
-       .transmit_packet = dummy_transmit_packet,
-       .devctl =          dummy_devctl,
-       .isoctl =          dummy_isoctl
-};
-
-static int alloc_hostnum_cb(struct hpsb_host *host, void *__data)
-{
-       int *hostnum = __data;
-
-       if (host->id == *hostnum)
-               return 1;
-
-       return 0;
-}
-
-static DEFINE_MUTEX(host_num_alloc);
-
-/**
- * hpsb_alloc_host - allocate a new host controller.
- * @drv: the driver that will manage the host controller
- * @extra: number of extra bytes to allocate for the driver
- *
- * Allocate a &hpsb_host and initialize the general subsystem specific
- * fields.  If the driver needs to store per host data, as drivers
- * usually do, the amount of memory required can be specified by the
- * @extra parameter.  Once allocated, the driver should initialize the
- * driver specific parts, enable the controller and make it available
- * to the general subsystem using hpsb_add_host().
- *
- * Return Value: a pointer to the &hpsb_host if successful, %NULL if
- * no memory was available.
- */
-struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
-                                 struct device *dev)
-{
-       struct hpsb_host *h;
-       int i;
-       int hostnum = 0;
-
-       h = kzalloc(sizeof(*h) + extra, GFP_KERNEL);
-       if (!h)
-               return NULL;
-
-       h->csr.rom = csr1212_create_csr(&csr_bus_ops, CSR_BUS_INFO_SIZE, h);
-       if (!h->csr.rom)
-               goto fail;
-
-       h->hostdata = h + 1;
-       h->driver = drv;
-
-       INIT_LIST_HEAD(&h->pending_packets);
-       INIT_LIST_HEAD(&h->addr_space);
-
-       for (i = 2; i < 16; i++)
-               h->csr.gen_timestamp[i] = jiffies - 60 * HZ;
-
-       atomic_set(&h->generation, 0);
-
-       INIT_DELAYED_WORK(&h->delayed_reset, delayed_reset_bus);
-       
-       init_timer(&h->timeout);
-       h->timeout.data = (unsigned long) h;
-       h->timeout.function = abort_timedouts;
-       h->timeout_interval = HZ / 20; /* 50ms, half of minimum SPLIT_TIMEOUT */
-
-       h->topology_map = h->csr.topology_map + 3;
-       h->speed_map = (u8 *)(h->csr.speed_map + 2);
-
-       mutex_lock(&host_num_alloc);
-       while (nodemgr_for_each_host(&hostnum, alloc_hostnum_cb))
-               hostnum++;
-       mutex_unlock(&host_num_alloc);
-       h->id = hostnum;
-
-       memcpy(&h->device, &nodemgr_dev_template_host, sizeof(h->device));
-       h->device.parent = dev;
-       set_dev_node(&h->device, dev_to_node(dev));
-       dev_set_name(&h->device, "fw-host%d", h->id);
-
-       h->host_dev.parent = &h->device;
-       h->host_dev.class = &hpsb_host_class;
-       dev_set_name(&h->host_dev, "fw-host%d", h->id);
-
-       if (device_register(&h->device))
-               goto fail;
-       if (device_register(&h->host_dev)) {
-               device_unregister(&h->device);
-               goto fail;
-       }
-       get_device(&h->device);
-
-       return h;
-
-fail:
-       kfree(h);
-       return NULL;
-}
-
-int hpsb_add_host(struct hpsb_host *host)
-{
-       if (hpsb_default_host_entry(host))
-               return -ENOMEM;
-
-       highlevel_add_host(host);
-       return 0;
-}
-
-void hpsb_resume_host(struct hpsb_host *host)
-{
-       if (host->driver->set_hw_config_rom)
-               host->driver->set_hw_config_rom(host,
-                                               host->csr.rom->bus_info_data);
-       host->driver->devctl(host, RESET_BUS, SHORT_RESET);
-}
-
-void hpsb_remove_host(struct hpsb_host *host)
-{
-       host->is_shutdown = 1;
-
-       cancel_delayed_work(&host->delayed_reset);
-       flush_scheduled_work();
-
-       host->driver = &dummy_driver;
-       highlevel_remove_host(host);
-
-       device_unregister(&host->host_dev);
-       device_unregister(&host->device);
-}
-
-/**
- * hpsb_update_config_rom_image - updates configuration ROM image of a host
- *
- * Updates the configuration ROM image of a host.  rom_version must be the
- * current version, otherwise it will fail with return value -1. If this
- * host does not support config-rom-update, it will return -%EINVAL.
- * Return value 0 indicates success.
- */
-int hpsb_update_config_rom_image(struct hpsb_host *host)
-{
-       unsigned long reset_delay;
-       int next_gen = host->csr.generation + 1;
-
-       if (!host->update_config_rom)
-               return -EINVAL;
-
-       if (next_gen > 0xf)
-               next_gen = 2;
-
-       /* Stop the delayed interrupt, we're about to change the config rom and
-        * it would be a waste to do a bus reset twice. */
-       cancel_delayed_work(&host->delayed_reset);
-
-       /* IEEE 1394a-2000 prohibits using the same generation number
-        * twice in a 60 second period. */
-       if (time_before(jiffies, host->csr.gen_timestamp[next_gen] + 60 * HZ))
-               /* Wait 60 seconds from the last time this generation number was
-                * used. */
-               reset_delay =
-                       (60 * HZ) + host->csr.gen_timestamp[next_gen] - jiffies;
-       else
-               /* Wait 1 second in case some other code wants to change the
-                * Config ROM in the near future. */
-               reset_delay = HZ;
-
-       PREPARE_DELAYED_WORK(&host->delayed_reset, delayed_reset_bus);
-       schedule_delayed_work(&host->delayed_reset, reset_delay);
-
-       return 0;
-}
diff --git a/drivers/ieee1394/hosts.h b/drivers/ieee1394/hosts.h
deleted file mode 100644 (file)
index 49c3590..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-#ifndef _IEEE1394_HOSTS_H
-#define _IEEE1394_HOSTS_H
-
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/timer.h>
-#include <linux/types.h>
-#include <linux/workqueue.h>
-#include <asm/atomic.h>
-
-struct pci_dev;
-struct module;
-
-#include "ieee1394_types.h"
-#include "csr.h"
-#include "highlevel.h"
-
-struct hpsb_packet;
-struct hpsb_iso;
-
-struct hpsb_host {
-       struct list_head host_list;
-
-       void *hostdata;
-
-       atomic_t generation;
-
-       struct list_head pending_packets;
-       struct timer_list timeout;
-       unsigned long timeout_interval;
-
-       int node_count;      /* number of identified nodes on this bus */
-       int selfid_count;    /* total number of SelfIDs received */
-       int nodes_active;    /* number of nodes with active link layer */
-
-       nodeid_t node_id;    /* node ID of this host */
-       nodeid_t irm_id;     /* ID of this bus' isochronous resource manager */
-       nodeid_t busmgr_id;  /* ID of this bus' bus manager */
-
-       /* this nodes state */
-       unsigned in_bus_reset:1;
-       unsigned is_shutdown:1;
-       unsigned resume_packet_sent:1;
-
-       /* this nodes' duties on the bus */
-       unsigned is_root:1;
-       unsigned is_cycmst:1;
-       unsigned is_irm:1;
-       unsigned is_busmgr:1;
-
-       int reset_retries;
-       quadlet_t *topology_map;
-       u8 *speed_map;
-
-       int id;
-       struct hpsb_host_driver *driver;
-       struct pci_dev *pdev;
-       struct device device;
-       struct device host_dev;
-
-       struct delayed_work delayed_reset;
-       unsigned config_roms:31;
-       unsigned update_config_rom:1;
-
-       struct list_head addr_space;
-       u64 low_addr_space;     /* upper bound of physical DMA area */
-       u64 middle_addr_space;  /* upper bound of posted write area */
-
-       u8 speed[ALL_NODES];    /* speed between each node and local node */
-
-       /* per node tlabel allocation */
-       u8 next_tl[ALL_NODES];
-       struct { DECLARE_BITMAP(map, 64); } tl_pool[ALL_NODES];
-
-       struct csr_control csr;
-
-       struct hpsb_address_serve dummy_zero_addr;
-       struct hpsb_address_serve dummy_max_addr;
-};
-
-enum devctl_cmd {
-       /* Host is requested to reset its bus and cancel all outstanding async
-        * requests.  If arg == 1, it shall also attempt to become root on the
-        * bus.  Return void. */
-       RESET_BUS,
-
-       /* Arg is void, return value is the hardware cycle counter value. */
-       GET_CYCLE_COUNTER,
-
-       /* Set the hardware cycle counter to the value in arg, return void.
-        * FIXME - setting is probably not required. */
-       SET_CYCLE_COUNTER,
-
-       /* Configure hardware for new bus ID in arg, return void. */
-       SET_BUS_ID,
-
-       /* If arg true, start sending cycle start packets, stop if arg == 0.
-        * Return void. */
-       ACT_CYCLE_MASTER,
-
-       /* Cancel all outstanding async requests without resetting the bus.
-        * Return void. */
-       CANCEL_REQUESTS,
-};
-
-enum isoctl_cmd {
-       /* rawiso API - see iso.h for the meanings of these commands
-        * (they correspond exactly to the hpsb_iso_* API functions)
-        * INIT = allocate resources
-        * START = begin transmission/reception
-        * STOP = halt transmission/reception
-        * QUEUE/RELEASE = produce/consume packets
-        * SHUTDOWN = deallocate resources
-        */
-
-       XMIT_INIT,
-       XMIT_START,
-       XMIT_STOP,
-       XMIT_QUEUE,
-       XMIT_SHUTDOWN,
-
-       RECV_INIT,
-       RECV_LISTEN_CHANNEL,   /* multi-channel only */
-       RECV_UNLISTEN_CHANNEL, /* multi-channel only */
-       RECV_SET_CHANNEL_MASK, /* multi-channel only; arg is a *u64 */
-       RECV_START,
-       RECV_STOP,
-       RECV_RELEASE,
-       RECV_SHUTDOWN,
-       RECV_FLUSH
-};
-
-enum reset_types {
-       /* 166 microsecond reset -- only type of reset available on
-          non-1394a capable controllers */
-       LONG_RESET,
-
-       /* Short (arbitrated) reset -- only available on 1394a capable
-          controllers */
-       SHORT_RESET,
-
-       /* Variants that set force_root before issueing the bus reset */
-       LONG_RESET_FORCE_ROOT, SHORT_RESET_FORCE_ROOT,
-
-       /* Variants that clear force_root before issueing the bus reset */
-       LONG_RESET_NO_FORCE_ROOT, SHORT_RESET_NO_FORCE_ROOT
-};
-
-struct hpsb_host_driver {
-       struct module *owner;
-       const char *name;
-
-       /* The hardware driver may optionally support a function that is used
-        * to set the hardware ConfigROM if the hardware supports handling
-        * reads to the ConfigROM on its own. */
-       void (*set_hw_config_rom)(struct hpsb_host *host,
-                                 __be32 *config_rom);
-
-       /* This function shall implement packet transmission based on
-        * packet->type.  It shall CRC both parts of the packet (unless
-        * packet->type == raw) and do byte-swapping as necessary or instruct
-        * the hardware to do so.  It can return immediately after the packet
-        * was queued for sending.  After sending, hpsb_sent_packet() has to be
-        * called.  Return 0 on success, negative errno on failure.
-        * NOTE: The function must be callable in interrupt context.
-        */
-       int (*transmit_packet)(struct hpsb_host *host,
-                              struct hpsb_packet *packet);
-
-       /* This function requests miscellanous services from the driver, see
-        * above for command codes and expected actions.  Return -1 for unknown
-        * command, though that should never happen.
-        */
-       int (*devctl)(struct hpsb_host *host, enum devctl_cmd command, int arg);
-
-        /* ISO transmission/reception functions. Return 0 on success, -1
-         * (or -EXXX errno code) on failure. If the low-level driver does not
-         * support the new ISO API, set isoctl to NULL.
-         */
-       int (*isoctl)(struct hpsb_iso *iso, enum isoctl_cmd command,
-                     unsigned long arg);
-
-       /* This function is mainly to redirect local CSR reads/locks to the iso
-        * management registers (bus manager id, bandwidth available, channels
-        * available) to the hardware registers in OHCI.  reg is 0,1,2,3 for bus
-        * mgr, bwdth avail, ch avail hi, ch avail lo respectively (the same ids
-        * as OHCI uses).  data and compare are the new data and expected data
-        * respectively, return value is the old value.
-        */
-       quadlet_t (*hw_csr_reg) (struct hpsb_host *host, int reg,
-                                quadlet_t data, quadlet_t compare);
-};
-
-struct hpsb_host *hpsb_alloc_host(struct hpsb_host_driver *drv, size_t extra,
-                                 struct device *dev);
-int hpsb_add_host(struct hpsb_host *host);
-void hpsb_resume_host(struct hpsb_host *host);
-void hpsb_remove_host(struct hpsb_host *host);
-int hpsb_update_config_rom_image(struct hpsb_host *host);
-
-#endif /* _IEEE1394_HOSTS_H */
diff --git a/drivers/ieee1394/ieee1394-ioctl.h b/drivers/ieee1394/ieee1394-ioctl.h
deleted file mode 100644 (file)
index 46878fe..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Base file for all ieee1394 ioctl's.
- * Linux-1394 has allocated base '#' with a range of 0x00-0x3f.
- */
-
-#ifndef __IEEE1394_IOCTL_H
-#define __IEEE1394_IOCTL_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-/* DV1394 Gets 10 */
-
-/* Get the driver ready to transmit video.  pass a struct dv1394_init* as
- * the parameter (see below), or NULL to get default parameters */
-#define DV1394_IOC_INIT                        _IOW('#', 0x06, struct dv1394_init)
-
-/* Stop transmitting video and free the ringbuffer */
-#define DV1394_IOC_SHUTDOWN            _IO ('#', 0x07)
-
-/* Submit N new frames to be transmitted, where the index of the first new
- * frame is first_clear_buffer, and the index of the last new frame is
- * (first_clear_buffer + N) % n_frames */
-#define DV1394_IOC_SUBMIT_FRAMES       _IO ('#', 0x08)
-
-/* Block until N buffers are clear (pass N as the parameter) Because we
- * re-transmit the last frame on underrun, there will at most be n_frames
- * - 1 clear frames at any time */
-#define DV1394_IOC_WAIT_FRAMES         _IO ('#', 0x09)
-
-/* Capture new frames that have been received, where the index of the
- * first new frame is first_clear_buffer, and the index of the last new
- * frame is (first_clear_buffer + N) % n_frames */
-#define DV1394_IOC_RECEIVE_FRAMES      _IO ('#', 0x0a)
-
-/* Tell card to start receiving DMA */
-#define DV1394_IOC_START_RECEIVE       _IO ('#', 0x0b)
-
-/* Pass a struct dv1394_status* as the parameter */
-#define DV1394_IOC_GET_STATUS          _IOR('#', 0x0c, struct dv1394_status)
-
-
-/* Video1394 Gets 10 */
-
-#define VIDEO1394_IOC_LISTEN_CHANNEL           \
-       _IOWR('#', 0x10, struct video1394_mmap)
-#define VIDEO1394_IOC_UNLISTEN_CHANNEL         \
-       _IOW ('#', 0x11, int)
-#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER      \
-       _IOW ('#', 0x12, struct video1394_wait)
-#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER       \
-       _IOWR('#', 0x13, struct video1394_wait)
-#define VIDEO1394_IOC_TALK_CHANNEL             \
-       _IOWR('#', 0x14, struct video1394_mmap)
-#define VIDEO1394_IOC_UNTALK_CHANNEL           \
-       _IOW ('#', 0x15, int)
-/*
- * This one is broken: it really wanted
- * "sizeof (struct video1394_wait) + sizeof (struct video1394_queue_variable)"
- * but got just a "size_t"
- */
-#define VIDEO1394_IOC_TALK_QUEUE_BUFFER        \
-       _IOW ('#', 0x16, size_t)
-#define VIDEO1394_IOC_TALK_WAIT_BUFFER         \
-       _IOW ('#', 0x17, struct video1394_wait)
-#define VIDEO1394_IOC_LISTEN_POLL_BUFFER       \
-       _IOWR('#', 0x18, struct video1394_wait)
-
-
-/* Raw1394's ISO interface */
-#define RAW1394_IOC_ISO_XMIT_INIT              \
-       _IOW ('#', 0x1a, struct raw1394_iso_status)
-#define RAW1394_IOC_ISO_RECV_INIT              \
-       _IOWR('#', 0x1b, struct raw1394_iso_status)
-#define RAW1394_IOC_ISO_RECV_START             \
-       _IOC (_IOC_WRITE, '#', 0x1c, sizeof(int) * 3)
-#define RAW1394_IOC_ISO_XMIT_START             \
-       _IOC (_IOC_WRITE, '#', 0x1d, sizeof(int) * 2)
-#define RAW1394_IOC_ISO_XMIT_RECV_STOP         \
-       _IO  ('#', 0x1e)
-#define RAW1394_IOC_ISO_GET_STATUS             \
-       _IOR ('#', 0x1f, struct raw1394_iso_status)
-#define RAW1394_IOC_ISO_SHUTDOWN               \
-       _IO  ('#', 0x20)
-#define RAW1394_IOC_ISO_QUEUE_ACTIVITY         \
-       _IO  ('#', 0x21)
-#define RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL    \
-       _IOW ('#', 0x22, unsigned char)
-#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL  \
-       _IOW ('#', 0x23, unsigned char)
-#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK  \
-       _IOW ('#', 0x24, __u64)
-#define RAW1394_IOC_ISO_RECV_PACKETS           \
-       _IOW ('#', 0x25, struct raw1394_iso_packets)
-#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS   \
-       _IOW ('#', 0x26, unsigned int)
-#define RAW1394_IOC_ISO_XMIT_PACKETS           \
-       _IOW ('#', 0x27, struct raw1394_iso_packets)
-#define RAW1394_IOC_ISO_XMIT_SYNC              \
-       _IO  ('#', 0x28)
-#define RAW1394_IOC_ISO_RECV_FLUSH             \
-       _IO  ('#', 0x29)
-#define RAW1394_IOC_GET_CYCLE_TIMER            \
-       _IOR ('#', 0x30, struct raw1394_cycle_timer)
-
-#endif /* __IEEE1394_IOCTL_H */
diff --git a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
deleted file mode 100644 (file)
index af320e2..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Generic IEEE 1394 definitions
- */
-
-#ifndef _IEEE1394_IEEE1394_H
-#define _IEEE1394_IEEE1394_H
-
-#define TCODE_WRITEQ           0x0
-#define TCODE_WRITEB           0x1
-#define TCODE_WRITE_RESPONSE   0x2
-#define TCODE_READQ            0x4
-#define TCODE_READB            0x5
-#define TCODE_READQ_RESPONSE   0x6
-#define TCODE_READB_RESPONSE   0x7
-#define TCODE_CYCLE_START      0x8
-#define TCODE_LOCK_REQUEST     0x9
-#define TCODE_ISO_DATA         0xa
-#define TCODE_STREAM_DATA      0xa
-#define TCODE_LOCK_RESPONSE    0xb
-
-#define RCODE_COMPLETE         0x0
-#define RCODE_CONFLICT_ERROR   0x4
-#define RCODE_DATA_ERROR       0x5
-#define RCODE_TYPE_ERROR       0x6
-#define RCODE_ADDRESS_ERROR    0x7
-
-#define EXTCODE_MASK_SWAP      0x1
-#define EXTCODE_COMPARE_SWAP   0x2
-#define EXTCODE_FETCH_ADD      0x3
-#define EXTCODE_LITTLE_ADD     0x4
-#define EXTCODE_BOUNDED_ADD    0x5
-#define EXTCODE_WRAP_ADD       0x6
-
-#define ACK_COMPLETE           0x1
-#define ACK_PENDING            0x2
-#define ACK_BUSY_X             0x4
-#define ACK_BUSY_A             0x5
-#define ACK_BUSY_B             0x6
-#define ACK_TARDY              0xb
-#define ACK_CONFLICT_ERROR     0xc
-#define ACK_DATA_ERROR         0xd
-#define ACK_TYPE_ERROR         0xe
-#define ACK_ADDRESS_ERROR      0xf
-
-/* Non-standard "ACK codes" for internal use */
-#define ACKX_NONE              (-1)
-#define ACKX_SEND_ERROR                (-2)
-#define ACKX_ABORTED           (-3)
-#define ACKX_TIMEOUT           (-4)
-
-#define IEEE1394_SPEED_100     0x00
-#define IEEE1394_SPEED_200     0x01
-#define IEEE1394_SPEED_400     0x02
-#define IEEE1394_SPEED_800     0x03
-#define IEEE1394_SPEED_1600    0x04
-#define IEEE1394_SPEED_3200    0x05
-#define IEEE1394_SPEED_MAX     IEEE1394_SPEED_3200
-
-/* Maps speed values above to a string representation */
-extern const char *hpsb_speedto_str[];
-
-/* 1394a cable PHY packets */
-#define SELFID_PWRCL_NO_POWER          0x0
-#define SELFID_PWRCL_PROVIDE_15W       0x1
-#define SELFID_PWRCL_PROVIDE_30W       0x2
-#define SELFID_PWRCL_PROVIDE_45W       0x3
-#define SELFID_PWRCL_USE_1W            0x4
-#define SELFID_PWRCL_USE_3W            0x5
-#define SELFID_PWRCL_USE_6W            0x6
-#define SELFID_PWRCL_USE_10W           0x7
-
-#define SELFID_PORT_CHILD              0x3
-#define SELFID_PORT_PARENT             0x2
-#define SELFID_PORT_NCONN              0x1
-#define SELFID_PORT_NONE               0x0
-
-#define SELFID_SPEED_UNKNOWN           0x3     /* 1394b PHY */
-
-#define PHYPACKET_LINKON                       0x40000000
-#define PHYPACKET_PHYCONFIG_R                  0x00800000
-#define PHYPACKET_PHYCONFIG_T                  0x00400000
-#define EXTPHYPACKET_TYPE_PING                 0x00000000
-#define EXTPHYPACKET_TYPE_REMOTEACCESS_BASE    0x00040000
-#define EXTPHYPACKET_TYPE_REMOTEACCESS_PAGED   0x00140000
-#define EXTPHYPACKET_TYPE_REMOTEREPLY_BASE     0x000C0000
-#define EXTPHYPACKET_TYPE_REMOTEREPLY_PAGED    0x001C0000
-#define EXTPHYPACKET_TYPE_REMOTECOMMAND                0x00200000
-#define EXTPHYPACKET_TYPE_REMOTECONFIRMATION   0x00280000
-#define EXTPHYPACKET_TYPE_RESUME               0x003C0000
-
-#define EXTPHYPACKET_TYPEMASK                  0xC0FC0000
-
-#define PHYPACKET_PORT_SHIFT           24
-#define PHYPACKET_GAPCOUNT_SHIFT       16
-
-/* 1394a PHY register map bitmasks */
-#define PHY_00_PHYSICAL_ID     0xFC
-#define PHY_00_R               0x02 /* Root */
-#define PHY_00_PS              0x01 /* Power Status*/
-#define PHY_01_RHB             0x80 /* Root Hold-Off */
-#define PHY_01_IBR             0x80 /* Initiate Bus Reset */
-#define PHY_01_GAP_COUNT       0x3F
-#define PHY_02_EXTENDED                0xE0 /* 0x7 for 1394a-compliant PHY */
-#define PHY_02_TOTAL_PORTS     0x1F
-#define PHY_03_MAX_SPEED       0xE0
-#define PHY_03_DELAY           0x0F
-#define PHY_04_LCTRL           0x80 /* Link Active Report Control */
-#define PHY_04_CONTENDER       0x40
-#define PHY_04_JITTER          0x38
-#define PHY_04_PWR_CLASS       0x07 /* Power Class */
-#define PHY_05_WATCHDOG                0x80
-#define PHY_05_ISBR            0x40 /* Initiate Short Bus Reset */
-#define PHY_05_LOOP            0x20 /* Loop Detect */
-#define PHY_05_PWR_FAIL                0x10 /* Cable Power Failure Detect */
-#define PHY_05_TIMEOUT         0x08 /* Arbitration State Machine Timeout */
-#define PHY_05_PORT_EVENT      0x04 /* Port Event Detect */
-#define PHY_05_ENAB_ACCEL      0x02 /* Enable Arbitration Acceleration */
-#define PHY_05_ENAB_MULTI      0x01 /* Ena. Multispeed Packet Concatenation */
-
-#include <asm/byteorder.h>
-
-/* '1' '3' '9' '4' in ASCII */
-#define IEEE1394_BUSID_MAGIC   cpu_to_be32(0x31333934)
-
-#ifdef __BIG_ENDIAN_BITFIELD
-
-struct selfid {
-       u32 packet_identifier:2; /* always binary 10 */
-       u32 phy_id:6;
-       /* byte */
-       u32 extended:1; /* if true is struct ext_selfid */
-       u32 link_active:1;
-       u32 gap_count:6;
-       /* byte */
-       u32 speed:2;
-       u32 phy_delay:2;
-       u32 contender:1;
-       u32 power_class:3;
-       /* byte */
-       u32 port0:2;
-       u32 port1:2;
-       u32 port2:2;
-       u32 initiated_reset:1;
-       u32 more_packets:1;
-} __attribute__((packed));
-
-struct ext_selfid {
-       u32 packet_identifier:2; /* always binary 10 */
-       u32 phy_id:6;
-       /* byte */
-       u32 extended:1; /* if false is struct selfid */
-       u32 seq_nr:3;
-       u32 reserved:2;
-       u32 porta:2;
-       /* byte */
-       u32 portb:2;
-       u32 portc:2;
-       u32 portd:2;
-       u32 porte:2;
-       /* byte */
-       u32 portf:2;
-       u32 portg:2;
-       u32 porth:2;
-       u32 reserved2:1;
-       u32 more_packets:1;
-} __attribute__((packed));
-
-#elif defined __LITTLE_ENDIAN_BITFIELD /* __BIG_ENDIAN_BITFIELD */
-
-/*
- * Note: these mean to be bit fields of a big endian SelfID as seen on a little
- * endian machine.  Without swapping.
- */
-
-struct selfid {
-       u32 phy_id:6;
-       u32 packet_identifier:2; /* always binary 10 */
-       /* byte */
-       u32 gap_count:6;
-       u32 link_active:1;
-       u32 extended:1; /* if true is struct ext_selfid */
-       /* byte */
-       u32 power_class:3;
-       u32 contender:1;
-       u32 phy_delay:2;
-       u32 speed:2;
-       /* byte */
-       u32 more_packets:1;
-       u32 initiated_reset:1;
-       u32 port2:2;
-       u32 port1:2;
-       u32 port0:2;
-} __attribute__((packed));
-
-struct ext_selfid {
-       u32 phy_id:6;
-       u32 packet_identifier:2; /* always binary 10 */
-       /* byte */
-       u32 porta:2;
-       u32 reserved:2;
-       u32 seq_nr:3;
-       u32 extended:1; /* if false is struct selfid */
-       /* byte */
-       u32 porte:2;
-       u32 portd:2;
-       u32 portc:2;
-       u32 portb:2;
-       /* byte */
-       u32 more_packets:1;
-       u32 reserved2:1;
-       u32 porth:2;
-       u32 portg:2;
-       u32 portf:2;
-} __attribute__((packed));
-
-#else
-#error What? PDP endian?
-#endif /* __BIG_ENDIAN_BITFIELD */
-
-#endif /* _IEEE1394_IEEE1394_H */
diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
deleted file mode 100644 (file)
index 8723380..0000000
+++ /dev/null
@@ -1,1380 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Core support: hpsb_packet management, packet handling and forwarding to
- *               highlevel or lowlevel code
- *
- * Copyright (C) 1999, 2000 Andreas E. Bombe
- *                     2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        loopback functionality in hpsb_send_packet
- *        allow highlevel drivers to disable automatic response generation
- *              and to generate responses themselves (deferred)
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/bitops.h>
-#include <linux/kdev_t.h>
-#include <linux/freezer.h>
-#include <linux/suspend.h>
-#include <linux/kthread.h>
-#include <linux/preempt.h>
-#include <linux/time.h>
-
-#include <asm/system.h>
-#include <asm/byteorder.h>
-
-#include "ieee1394_types.h"
-#include "ieee1394.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "ieee1394_transactions.h"
-#include "csr.h"
-#include "nodemgr.h"
-#include "dma.h"
-#include "iso.h"
-#include "config_roms.h"
-
-/*
- * Disable the nodemgr detection and config rom reading functionality.
- */
-static int disable_nodemgr;
-module_param(disable_nodemgr, int, 0444);
-MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
-
-/* Disable Isochronous Resource Manager functionality */
-int hpsb_disable_irm = 0;
-module_param_named(disable_irm, hpsb_disable_irm, bool, 0444);
-MODULE_PARM_DESC(disable_irm,
-                "Disable Isochronous Resource Manager functionality.");
-
-/* We are GPL, so treat us special */
-MODULE_LICENSE("GPL");
-
-/* Some globals used */
-const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
-struct class *hpsb_protocol_class;
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-static void dump_packet(const char *text, quadlet_t *data, int size, int speed)
-{
-       int i;
-
-       size /= 4;
-       size = (size > 4 ? 4 : size);
-
-       printk(KERN_DEBUG "ieee1394: %s", text);
-       if (speed > -1 && speed < 6)
-               printk(" at %s", hpsb_speedto_str[speed]);
-       printk(":");
-       for (i = 0; i < size; i++)
-               printk(" %08x", data[i]);
-       printk("\n");
-}
-#else
-#define dump_packet(a,b,c,d) do {} while (0)
-#endif
-
-static void abort_requests(struct hpsb_host *host);
-static void queue_packet_complete(struct hpsb_packet *packet);
-
-
-/**
- * hpsb_set_packet_complete_task - set task that runs when a packet completes
- * @packet: the packet whose completion we want the task added to
- * @routine: function to call
- * @data: data (if any) to pass to the above function
- *
- * Set the task that runs when a packet completes. You cannot call this more
- * than once on a single packet before it is sent.
- *
- * Typically, the complete @routine is responsible to call hpsb_free_packet().
- */
-void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
-                                  void (*routine)(void *), void *data)
-{
-       WARN_ON(packet->complete_routine != NULL);
-       packet->complete_routine = routine;
-       packet->complete_data = data;
-       return;
-}
-
-/**
- * hpsb_alloc_packet - allocate new packet structure
- * @data_size: size of the data block to be allocated, in bytes
- *
- * This function allocates, initializes and returns a new &struct hpsb_packet.
- * It can be used in interrupt context.  A header block is always included and
- * initialized with zeros.  Its size is big enough to contain all possible 1394
- * headers.  The data block is only allocated if @data_size is not zero.
- *
- * For packets for which responses will be received the @data_size has to be big
- * enough to contain the response's data block since no further allocation
- * occurs at response matching time.
- *
- * The packet's generation value will be set to the current generation number
- * for ease of use.  Remember to overwrite it with your own recorded generation
- * number if you can not be sure that your code will not race with a bus reset.
- *
- * Return value: A pointer to a &struct hpsb_packet or NULL on allocation
- * failure.
- */
-struct hpsb_packet *hpsb_alloc_packet(size_t data_size)
-{
-       struct hpsb_packet *packet;
-
-       data_size = ((data_size + 3) & ~3);
-
-       packet = kzalloc(sizeof(*packet) + data_size, GFP_ATOMIC);
-       if (!packet)
-               return NULL;
-
-       packet->state = hpsb_unused;
-       packet->generation = -1;
-       INIT_LIST_HEAD(&packet->driver_list);
-       INIT_LIST_HEAD(&packet->queue);
-       atomic_set(&packet->refcnt, 1);
-
-       if (data_size) {
-               packet->data = packet->embedded_data;
-               packet->allocated_data_size = data_size;
-       }
-       return packet;
-}
-
-/**
- * hpsb_free_packet - free packet and data associated with it
- * @packet: packet to free (is NULL safe)
- *
- * Frees @packet->data only if it was allocated through hpsb_alloc_packet().
- */
-void hpsb_free_packet(struct hpsb_packet *packet)
-{
-       if (packet && atomic_dec_and_test(&packet->refcnt)) {
-               BUG_ON(!list_empty(&packet->driver_list) ||
-                      !list_empty(&packet->queue));
-               kfree(packet);
-       }
-}
-
-/**
- * hpsb_reset_bus - initiate bus reset on the given host
- * @host: host controller whose bus to reset
- * @type: one of enum reset_types
- *
- * Returns 1 if bus reset already in progress, 0 otherwise.
- */
-int hpsb_reset_bus(struct hpsb_host *host, int type)
-{
-       if (!host->in_bus_reset) {
-               host->driver->devctl(host, RESET_BUS, type);
-               return 0;
-       } else {
-               return 1;
-       }
-}
-
-/**
- * hpsb_read_cycle_timer - read cycle timer register and system time
- * @host: host whose isochronous cycle timer register is read
- * @cycle_timer: address of bitfield to return the register contents
- * @local_time: address to return the system time
- *
- * The format of * @cycle_timer, is described in OHCI 1.1 clause 5.13. This
- * format is also read from non-OHCI controllers. * @local_time contains the
- * system time in microseconds since the Epoch, read at the moment when the
- * cycle timer was read.
- *
- * Return value: 0 for success or error number otherwise.
- */
-int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
-                         u64 *local_time)
-{
-       int ctr;
-       struct timeval tv;
-       unsigned long flags;
-
-       if (!host || !cycle_timer || !local_time)
-               return -EINVAL;
-
-       preempt_disable();
-       local_irq_save(flags);
-
-       ctr = host->driver->devctl(host, GET_CYCLE_COUNTER, 0);
-       if (ctr)
-               do_gettimeofday(&tv);
-
-       local_irq_restore(flags);
-       preempt_enable();
-
-       if (!ctr)
-               return -EIO;
-       *cycle_timer = ctr;
-       *local_time = tv.tv_sec * 1000000ULL + tv.tv_usec;
-       return 0;
-}
-
-/**
- * hpsb_bus_reset - notify a bus reset to the core
- *
- * For host driver module usage.  Safe to use in interrupt context, although
- * quite complex; so you may want to run it in the bottom rather than top half.
- *
- * Returns 1 if bus reset already in progress, 0 otherwise.
- */
-int hpsb_bus_reset(struct hpsb_host *host)
-{
-       if (host->in_bus_reset) {
-               HPSB_NOTICE("%s called while bus reset already in progress",
-                           __func__);
-               return 1;
-       }
-
-       abort_requests(host);
-       host->in_bus_reset = 1;
-       host->irm_id = -1;
-       host->is_irm = 0;
-       host->busmgr_id = -1;
-       host->is_busmgr = 0;
-       host->is_cycmst = 0;
-       host->node_count = 0;
-       host->selfid_count = 0;
-
-       return 0;
-}
-
-
-/*
- * Verify num_of_selfids SelfIDs and return number of nodes.  Return zero in
- * case verification failed.
- */
-static int check_selfids(struct hpsb_host *host)
-{
-       int nodeid = -1;
-       int rest_of_selfids = host->selfid_count;
-       struct selfid *sid = (struct selfid *)host->topology_map;
-       struct ext_selfid *esid;
-       int esid_seq = 23;
-
-       host->nodes_active = 0;
-
-       while (rest_of_selfids--) {
-               if (!sid->extended) {
-                       nodeid++;
-                       esid_seq = 0;
-
-                       if (sid->phy_id != nodeid) {
-                               HPSB_INFO("SelfIDs failed monotony check with "
-                                         "%d", sid->phy_id);
-                               return 0;
-                       }
-
-                       if (sid->link_active) {
-                               host->nodes_active++;
-                               if (sid->contender)
-                                       host->irm_id = LOCAL_BUS | sid->phy_id;
-                       }
-               } else {
-                       esid = (struct ext_selfid *)sid;
-
-                       if ((esid->phy_id != nodeid)
-                           || (esid->seq_nr != esid_seq)) {
-                               HPSB_INFO("SelfIDs failed monotony check with "
-                                         "%d/%d", esid->phy_id, esid->seq_nr);
-                               return 0;
-                       }
-                       esid_seq++;
-               }
-               sid++;
-       }
-
-       esid = (struct ext_selfid *)(sid - 1);
-       while (esid->extended) {
-               if ((esid->porta == SELFID_PORT_PARENT) ||
-                   (esid->portb == SELFID_PORT_PARENT) ||
-                   (esid->portc == SELFID_PORT_PARENT) ||
-                   (esid->portd == SELFID_PORT_PARENT) ||
-                   (esid->porte == SELFID_PORT_PARENT) ||
-                   (esid->portf == SELFID_PORT_PARENT) ||
-                   (esid->portg == SELFID_PORT_PARENT) ||
-                   (esid->porth == SELFID_PORT_PARENT)) {
-                       HPSB_INFO("SelfIDs failed root check on "
-                                 "extended SelfID");
-                       return 0;
-               }
-               esid--;
-       }
-
-       sid = (struct selfid *)esid;
-       if ((sid->port0 == SELFID_PORT_PARENT) ||
-           (sid->port1 == SELFID_PORT_PARENT) ||
-           (sid->port2 == SELFID_PORT_PARENT)) {
-               HPSB_INFO("SelfIDs failed root check");
-               return 0;
-       }
-
-       host->node_count = nodeid + 1;
-       return 1;
-}
-
-static void build_speed_map(struct hpsb_host *host, int nodecount)
-{
-       u8 cldcnt[nodecount];
-       u8 *map = host->speed_map;
-       u8 *speedcap = host->speed;
-       u8 local_link_speed = host->csr.lnk_spd;
-       struct selfid *sid;
-       struct ext_selfid *esid;
-       int i, j, n;
-
-       for (i = 0; i < (nodecount * 64); i += 64) {
-               for (j = 0; j < nodecount; j++) {
-                       map[i+j] = IEEE1394_SPEED_MAX;
-               }
-       }
-
-       for (i = 0; i < nodecount; i++) {
-               cldcnt[i] = 0;
-       }
-
-       /* find direct children count and speed */
-       for (sid = (struct selfid *)&host->topology_map[host->selfid_count-1],
-                    n = nodecount - 1;
-            (void *)sid >= (void *)host->topology_map; sid--) {
-               if (sid->extended) {
-                       esid = (struct ext_selfid *)sid;
-
-                       if (esid->porta == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portb == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portc == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portd == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->porte == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portf == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->portg == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (esid->porth == SELFID_PORT_CHILD) cldcnt[n]++;
-                } else {
-                       if (sid->port0 == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (sid->port1 == SELFID_PORT_CHILD) cldcnt[n]++;
-                       if (sid->port2 == SELFID_PORT_CHILD) cldcnt[n]++;
-
-                       speedcap[n] = sid->speed;
-                       if (speedcap[n] > local_link_speed)
-                               speedcap[n] = local_link_speed;
-                       n--;
-               }
-       }
-
-       /* set self mapping */
-       for (i = 0; i < nodecount; i++) {
-               map[64*i + i] = speedcap[i];
-       }
-
-       /* fix up direct children count to total children count;
-        * also fix up speedcaps for sibling and parent communication */
-       for (i = 1; i < nodecount; i++) {
-               for (j = cldcnt[i], n = i - 1; j > 0; j--) {
-                       cldcnt[i] += cldcnt[n];
-                       speedcap[n] = min(speedcap[n], speedcap[i]);
-                       n -= cldcnt[n] + 1;
-               }
-       }
-
-       for (n = 0; n < nodecount; n++) {
-               for (i = n - cldcnt[n]; i <= n; i++) {
-                       for (j = 0; j < (n - cldcnt[n]); j++) {
-                               map[j*64 + i] = map[i*64 + j] =
-                                       min(map[i*64 + j], speedcap[n]);
-                       }
-                       for (j = n + 1; j < nodecount; j++) {
-                               map[j*64 + i] = map[i*64 + j] =
-                                       min(map[i*64 + j], speedcap[n]);
-                       }
-               }
-       }
-
-       /* assume a maximum speed for 1394b PHYs, nodemgr will correct it */
-       if (local_link_speed > SELFID_SPEED_UNKNOWN)
-               for (i = 0; i < nodecount; i++)
-                       if (speedcap[i] == SELFID_SPEED_UNKNOWN)
-                               speedcap[i] = local_link_speed;
-}
-
-
-/**
- * hpsb_selfid_received - hand over received selfid packet to the core
- *
- * For host driver module usage.  Safe to use in interrupt context.
- *
- * The host driver should have done a successful complement check (second
- * quadlet is complement of first) beforehand.
- */
-void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid)
-{
-       if (host->in_bus_reset) {
-               HPSB_VERBOSE("Including SelfID 0x%x", sid);
-               host->topology_map[host->selfid_count++] = sid;
-       } else {
-               HPSB_NOTICE("Spurious SelfID packet (0x%08x) received from bus %d",
-                           sid, NODEID_TO_BUS(host->node_id));
-       }
-}
-
-/**
- * hpsb_selfid_complete - notify completion of SelfID stage to the core
- *
- * For host driver module usage.  Safe to use in interrupt context, although
- * quite complex; so you may want to run it in the bottom rather than top half.
- *
- * Notify completion of SelfID stage to the core and report new physical ID
- * and whether host is root now.
- */
-void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot)
-{
-       if (!host->in_bus_reset)
-               HPSB_NOTICE("SelfID completion called outside of bus reset!");
-
-       host->node_id = LOCAL_BUS | phyid;
-       host->is_root = isroot;
-
-       if (!check_selfids(host)) {
-               if (host->reset_retries++ < 20) {
-                       /* selfid stage did not complete without error */
-                       HPSB_NOTICE("Error in SelfID stage, resetting");
-                       host->in_bus_reset = 0;
-                       /* this should work from ohci1394 now... */
-                       hpsb_reset_bus(host, LONG_RESET);
-                       return;
-               } else {
-                       HPSB_NOTICE("Stopping out-of-control reset loop");
-                       HPSB_NOTICE("Warning - topology map and speed map will not be valid");
-                       host->reset_retries = 0;
-               }
-       } else {
-               host->reset_retries = 0;
-               build_speed_map(host, host->node_count);
-       }
-
-       HPSB_VERBOSE("selfid_complete called with successful SelfID stage "
-                    "... irm_id: 0x%X node_id: 0x%X",host->irm_id,host->node_id);
-
-       /* irm_id is kept up to date by check_selfids() */
-       if (host->irm_id == host->node_id) {
-               host->is_irm = 1;
-       } else {
-               host->is_busmgr = 0;
-               host->is_irm = 0;
-       }
-
-       if (isroot) {
-               host->driver->devctl(host, ACT_CYCLE_MASTER, 1);
-               host->is_cycmst = 1;
-       }
-       atomic_inc(&host->generation);
-       host->in_bus_reset = 0;
-       highlevel_host_reset(host);
-}
-
-static DEFINE_SPINLOCK(pending_packets_lock);
-
-/**
- * hpsb_packet_sent - notify core of sending a packet
- *
- * For host driver module usage.  Safe to call from within a transmit packet
- * routine.
- *
- * Notify core of sending a packet.  Ackcode is the ack code returned for async
- * transmits or ACKX_SEND_ERROR if the transmission failed completely; ACKX_NONE
- * for other cases (internal errors that don't justify a panic).
- */
-void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
-                     int ackcode)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&pending_packets_lock, flags);
-
-       packet->ack_code = ackcode;
-
-       if (packet->no_waiter || packet->state == hpsb_complete) {
-               /* if packet->no_waiter, must not have a tlabel allocated */
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-               hpsb_free_packet(packet);
-               return;
-       }
-
-       atomic_dec(&packet->refcnt);    /* drop HC's reference */
-       /* here the packet must be on the host->pending_packets queue */
-
-       if (ackcode != ACK_PENDING || !packet->expect_response) {
-               packet->state = hpsb_complete;
-               list_del_init(&packet->queue);
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-               queue_packet_complete(packet);
-               return;
-       }
-
-       packet->state = hpsb_pending;
-       packet->sendtime = jiffies;
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       mod_timer(&host->timeout, jiffies + host->timeout_interval);
-}
-
-/**
- * hpsb_send_phy_config - transmit a PHY configuration packet on the bus
- * @host: host that PHY config packet gets sent through
- * @rootid: root whose force_root bit should get set (-1 = don't set force_root)
- * @gapcnt: gap count value to set (-1 = don't set gap count)
- *
- * This function sends a PHY config packet on the bus through the specified
- * host.
- *
- * Return value: 0 for success or negative error number otherwise.
- */
-int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt)
-{
-       struct hpsb_packet *packet;
-       quadlet_t d = 0;
-       int retval = 0;
-
-       if (rootid >= ALL_NODES || rootid < -1 || gapcnt > 0x3f || gapcnt < -1 ||
-          (rootid == -1 && gapcnt == -1)) {
-               HPSB_DEBUG("Invalid Parameter: rootid = %d   gapcnt = %d",
-                          rootid, gapcnt);
-               return -EINVAL;
-       }
-
-       if (rootid != -1)
-               d |= PHYPACKET_PHYCONFIG_R | rootid << PHYPACKET_PORT_SHIFT;
-       if (gapcnt != -1)
-               d |= PHYPACKET_PHYCONFIG_T | gapcnt << PHYPACKET_GAPCOUNT_SHIFT;
-
-       packet = hpsb_make_phypacket(host, d);
-       if (!packet)
-               return -ENOMEM;
-
-       packet->generation = get_hpsb_generation(host);
-       retval = hpsb_send_packet_and_wait(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
-
-/**
- * hpsb_send_packet - transmit a packet on the bus
- * @packet: packet to send
- *
- * The packet is sent through the host specified in the packet->host field.
- * Before sending, the packet's transmit speed is automatically determined
- * using the local speed map when it is an async, non-broadcast packet.
- *
- * Possibilities for failure are that host is either not initialized, in bus
- * reset, the packet's generation number doesn't match the current generation
- * number or the host reports a transmit error.
- *
- * Return value: 0 on success, negative errno on failure.
- */
-int hpsb_send_packet(struct hpsb_packet *packet)
-{
-       struct hpsb_host *host = packet->host;
-
-       if (host->is_shutdown)
-               return -EINVAL;
-       if (host->in_bus_reset ||
-           (packet->generation != get_hpsb_generation(host)))
-               return -EAGAIN;
-
-       packet->state = hpsb_queued;
-
-       /* This just seems silly to me */
-       WARN_ON(packet->no_waiter && packet->expect_response);
-
-       if (!packet->no_waiter || packet->expect_response) {
-               unsigned long flags;
-
-               atomic_inc(&packet->refcnt);
-               /* Set the initial "sendtime" to 10 seconds from now, to
-                  prevent premature expiry.  If a packet takes more than
-                  10 seconds to hit the wire, we have bigger problems :) */
-               packet->sendtime = jiffies + 10 * HZ;
-               spin_lock_irqsave(&pending_packets_lock, flags);
-               list_add_tail(&packet->queue, &host->pending_packets);
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-       }
-
-       if (packet->node_id == host->node_id) {
-               /* it is a local request, so handle it locally */
-
-               quadlet_t *data;
-               size_t size = packet->data_size + packet->header_size;
-
-               data = kmalloc(size, GFP_ATOMIC);
-               if (!data) {
-                       HPSB_ERR("unable to allocate memory for concatenating header and data");
-                       return -ENOMEM;
-               }
-
-               memcpy(data, packet->header, packet->header_size);
-
-               if (packet->data_size)
-                       memcpy(((u8*)data) + packet->header_size, packet->data, packet->data_size);
-
-               dump_packet("send packet local", packet->header, packet->header_size, -1);
-
-               hpsb_packet_sent(host, packet, packet->expect_response ? ACK_PENDING : ACK_COMPLETE);
-               hpsb_packet_received(host, data, size, 0);
-
-               kfree(data);
-
-               return 0;
-       }
-
-       if (packet->type == hpsb_async &&
-           NODEID_TO_NODE(packet->node_id) != ALL_NODES)
-               packet->speed_code =
-                       host->speed[NODEID_TO_NODE(packet->node_id)];
-
-       dump_packet("send packet", packet->header, packet->header_size, packet->speed_code);
-
-       return host->driver->transmit_packet(host, packet);
-}
-
-/* We could just use complete() directly as the packet complete
- * callback, but this is more typesafe, in the sense that we get a
- * compiler error if the prototype for complete() changes. */
-
-static void complete_packet(void *data)
-{
-       complete((struct completion *) data);
-}
-
-/**
- * hpsb_send_packet_and_wait - enqueue packet, block until transaction completes
- * @packet: packet to send
- *
- * Return value: 0 on success, negative errno on failure.
- */
-int hpsb_send_packet_and_wait(struct hpsb_packet *packet)
-{
-       struct completion done;
-       int retval;
-
-       init_completion(&done);
-       hpsb_set_packet_complete_task(packet, complete_packet, &done);
-       retval = hpsb_send_packet(packet);
-       if (retval == 0)
-               wait_for_completion(&done);
-
-       return retval;
-}
-
-static void send_packet_nocare(struct hpsb_packet *packet)
-{
-       if (hpsb_send_packet(packet) < 0) {
-               hpsb_free_packet(packet);
-       }
-}
-
-static size_t packet_size_to_data_size(size_t packet_size, size_t header_size,
-                                      size_t buffer_size, int tcode)
-{
-       size_t ret = packet_size <= header_size ? 0 : packet_size - header_size;
-
-       if (unlikely(ret > buffer_size))
-               ret = buffer_size;
-
-       if (unlikely(ret + header_size != packet_size))
-               HPSB_ERR("unexpected packet size %zd (tcode %d), bug?",
-                        packet_size, tcode);
-       return ret;
-}
-
-static void handle_packet_response(struct hpsb_host *host, int tcode,
-                                  quadlet_t *data, size_t size)
-{
-       struct hpsb_packet *packet;
-       int tlabel = (data[0] >> 10) & 0x3f;
-       size_t header_size;
-       unsigned long flags;
-
-       spin_lock_irqsave(&pending_packets_lock, flags);
-
-       list_for_each_entry(packet, &host->pending_packets, queue)
-               if (packet->tlabel == tlabel &&
-                   packet->node_id == (data[1] >> 16))
-                       goto found;
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-       HPSB_DEBUG("unsolicited response packet received - %s",
-                  "no tlabel match");
-       dump_packet("contents", data, 16, -1);
-       return;
-
-found:
-       switch (packet->tcode) {
-       case TCODE_WRITEQ:
-       case TCODE_WRITEB:
-               if (unlikely(tcode != TCODE_WRITE_RESPONSE))
-                       break;
-               header_size = 12;
-               size = 0;
-               goto dequeue;
-
-       case TCODE_READQ:
-               if (unlikely(tcode != TCODE_READQ_RESPONSE))
-                       break;
-               header_size = 16;
-               size = 0;
-               goto dequeue;
-
-       case TCODE_READB:
-               if (unlikely(tcode != TCODE_READB_RESPONSE))
-                       break;
-               header_size = 16;
-               size = packet_size_to_data_size(size, header_size,
-                                               packet->allocated_data_size,
-                                               tcode);
-               goto dequeue;
-
-       case TCODE_LOCK_REQUEST:
-               if (unlikely(tcode != TCODE_LOCK_RESPONSE))
-                       break;
-               header_size = 16;
-               size = packet_size_to_data_size(min(size, (size_t)(16 + 8)),
-                                               header_size,
-                                               packet->allocated_data_size,
-                                               tcode);
-               goto dequeue;
-       }
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-       HPSB_DEBUG("unsolicited response packet received - %s",
-                  "tcode mismatch");
-       dump_packet("contents", data, 16, -1);
-       return;
-
-dequeue:
-       list_del_init(&packet->queue);
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       if (packet->state == hpsb_queued) {
-               packet->sendtime = jiffies;
-               packet->ack_code = ACK_PENDING;
-       }
-       packet->state = hpsb_complete;
-
-       memcpy(packet->header, data, header_size);
-       if (size)
-               memcpy(packet->data, data + 4, size);
-
-       queue_packet_complete(packet);
-}
-
-
-static struct hpsb_packet *create_reply_packet(struct hpsb_host *host,
-                                              quadlet_t *data, size_t dsize)
-{
-       struct hpsb_packet *p;
-
-       p = hpsb_alloc_packet(dsize);
-       if (unlikely(p == NULL)) {
-               /* FIXME - send data_error response */
-               HPSB_ERR("out of memory, cannot send response packet");
-               return NULL;
-       }
-
-       p->type = hpsb_async;
-       p->state = hpsb_unused;
-       p->host = host;
-       p->node_id = data[1] >> 16;
-       p->tlabel = (data[0] >> 10) & 0x3f;
-       p->no_waiter = 1;
-
-       p->generation = get_hpsb_generation(host);
-
-       if (dsize % 4)
-               p->data[dsize / 4] = 0;
-
-       return p;
-}
-
-#define PREP_ASYNC_HEAD_RCODE(tc) \
-       packet->tcode = tc; \
-       packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
-               | (1 << 8) | (tc << 4); \
-       packet->header[1] = (packet->host->node_id << 16) | (rcode << 12); \
-       packet->header[2] = 0
-
-static void fill_async_readquad_resp(struct hpsb_packet *packet, int rcode,
-                             quadlet_t data)
-{
-       PREP_ASYNC_HEAD_RCODE(TCODE_READQ_RESPONSE);
-       packet->header[3] = data;
-       packet->header_size = 16;
-       packet->data_size = 0;
-}
-
-static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode,
-                              int length)
-{
-       if (rcode != RCODE_COMPLETE)
-               length = 0;
-
-       PREP_ASYNC_HEAD_RCODE(TCODE_READB_RESPONSE);
-       packet->header[3] = length << 16;
-       packet->header_size = 16;
-       packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
-}
-
-static void fill_async_write_resp(struct hpsb_packet *packet, int rcode)
-{
-       PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE);
-       packet->header_size = 12;
-       packet->data_size = 0;
-}
-
-static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extcode,
-                         int length)
-{
-       if (rcode != RCODE_COMPLETE)
-               length = 0;
-
-       PREP_ASYNC_HEAD_RCODE(TCODE_LOCK_RESPONSE);
-       packet->header[3] = (length << 16) | extcode;
-       packet->header_size = 16;
-       packet->data_size = length;
-}
-
-static void handle_incoming_packet(struct hpsb_host *host, int tcode,
-                                  quadlet_t *data, size_t size,
-                                  int write_acked)
-{
-       struct hpsb_packet *packet;
-       int length, rcode, extcode;
-       quadlet_t buffer;
-       nodeid_t source = data[1] >> 16;
-       nodeid_t dest = data[0] >> 16;
-       u16 flags = (u16) data[0];
-       u64 addr;
-
-       /* FIXME?
-        * Out-of-bounds lengths are left for highlevel_read|write to cap. */
-
-       switch (tcode) {
-       case TCODE_WRITEQ:
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_write(host, source, dest, data + 3,
-                                       addr, 4, flags);
-               goto handle_write_request;
-
-       case TCODE_WRITEB:
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_write(host, source, dest, data + 4,
-                                       addr, data[3] >> 16, flags);
-handle_write_request:
-               if (rcode < 0 || write_acked ||
-                   NODEID_TO_NODE(data[0] >> 16) == NODE_MASK)
-                       return;
-               /* not a broadcast write, reply */
-               packet = create_reply_packet(host, data, 0);
-               if (packet) {
-                       fill_async_write_resp(packet, rcode);
-                       send_packet_nocare(packet);
-               }
-               return;
-
-       case TCODE_READQ:
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_read(host, source, &buffer, addr, 4, flags);
-               if (rcode < 0)
-                       return;
-
-               packet = create_reply_packet(host, data, 0);
-               if (packet) {
-                       fill_async_readquad_resp(packet, rcode, buffer);
-                       send_packet_nocare(packet);
-               }
-               return;
-
-       case TCODE_READB:
-               length = data[3] >> 16;
-               packet = create_reply_packet(host, data, length);
-               if (!packet)
-                       return;
-
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-               rcode = highlevel_read(host, source, packet->data, addr,
-                                      length, flags);
-               if (rcode < 0) {
-                       hpsb_free_packet(packet);
-                       return;
-               }
-               fill_async_readblock_resp(packet, rcode, length);
-               send_packet_nocare(packet);
-               return;
-
-       case TCODE_LOCK_REQUEST:
-               length = data[3] >> 16;
-               extcode = data[3] & 0xffff;
-               addr = (((u64)(data[1] & 0xffff)) << 32) | data[2];
-
-               packet = create_reply_packet(host, data, 8);
-               if (!packet)
-                       return;
-
-               if (extcode == 0 || extcode >= 7) {
-                       /* let switch default handle error */
-                       length = 0;
-               }
-
-               switch (length) {
-               case 4:
-                       rcode = highlevel_lock(host, source, packet->data, addr,
-                                              data[4], 0, extcode, flags);
-                       fill_async_lock_resp(packet, rcode, extcode, 4);
-                       break;
-               case 8:
-                       if (extcode != EXTCODE_FETCH_ADD &&
-                           extcode != EXTCODE_LITTLE_ADD) {
-                               rcode = highlevel_lock(host, source,
-                                                      packet->data, addr,
-                                                      data[5], data[4],
-                                                      extcode, flags);
-                               fill_async_lock_resp(packet, rcode, extcode, 4);
-                       } else {
-                               rcode = highlevel_lock64(host, source,
-                                            (octlet_t *)packet->data, addr,
-                                            *(octlet_t *)(data + 4), 0ULL,
-                                            extcode, flags);
-                               fill_async_lock_resp(packet, rcode, extcode, 8);
-                       }
-                       break;
-               case 16:
-                       rcode = highlevel_lock64(host, source,
-                                                (octlet_t *)packet->data, addr,
-                                                *(octlet_t *)(data + 6),
-                                                *(octlet_t *)(data + 4),
-                                                extcode, flags);
-                       fill_async_lock_resp(packet, rcode, extcode, 8);
-                       break;
-               default:
-                       rcode = RCODE_TYPE_ERROR;
-                       fill_async_lock_resp(packet, rcode, extcode, 0);
-               }
-
-               if (rcode < 0)
-                       hpsb_free_packet(packet);
-               else
-                       send_packet_nocare(packet);
-               return;
-       }
-}
-
-/**
- * hpsb_packet_received - hand over received packet to the core
- *
- * For host driver module usage.
- *
- * The contents of data are expected to be the full packet but with the CRCs
- * left out (data block follows header immediately), with the header (i.e. the
- * first four quadlets) in machine byte order and the data block in big endian.
- * *@data can be safely overwritten after this call.
- *
- * If the packet is a write request, @write_acked is to be set to true if it was
- * ack_complete'd already, false otherwise.  This argument is ignored for any
- * other packet type.
- */
-void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
-                         int write_acked)
-{
-       int tcode;
-
-       if (unlikely(host->in_bus_reset)) {
-               HPSB_DEBUG("received packet during reset; ignoring");
-               return;
-       }
-
-       dump_packet("received packet", data, size, -1);
-
-       tcode = (data[0] >> 4) & 0xf;
-
-       switch (tcode) {
-       case TCODE_WRITE_RESPONSE:
-       case TCODE_READQ_RESPONSE:
-       case TCODE_READB_RESPONSE:
-       case TCODE_LOCK_RESPONSE:
-               handle_packet_response(host, tcode, data, size);
-               break;
-
-       case TCODE_WRITEQ:
-       case TCODE_WRITEB:
-       case TCODE_READQ:
-       case TCODE_READB:
-       case TCODE_LOCK_REQUEST:
-               handle_incoming_packet(host, tcode, data, size, write_acked);
-               break;
-
-       case TCODE_CYCLE_START:
-               /* simply ignore this packet if it is passed on */
-               break;
-
-       default:
-               HPSB_DEBUG("received packet with bogus transaction code %d",
-                          tcode);
-               break;
-       }
-}
-
-static void abort_requests(struct hpsb_host *host)
-{
-       struct hpsb_packet *packet, *p;
-       struct list_head tmp;
-       unsigned long flags;
-
-       host->driver->devctl(host, CANCEL_REQUESTS, 0);
-
-       INIT_LIST_HEAD(&tmp);
-       spin_lock_irqsave(&pending_packets_lock, flags);
-       list_splice_init(&host->pending_packets, &tmp);
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       list_for_each_entry_safe(packet, p, &tmp, queue) {
-               list_del_init(&packet->queue);
-               packet->state = hpsb_complete;
-               packet->ack_code = ACKX_ABORTED;
-               queue_packet_complete(packet);
-       }
-}
-
-void abort_timedouts(unsigned long __opaque)
-{
-       struct hpsb_host *host = (struct hpsb_host *)__opaque;
-       struct hpsb_packet *packet, *p;
-       struct list_head tmp;
-       unsigned long flags, expire, j;
-
-       spin_lock_irqsave(&host->csr.lock, flags);
-       expire = host->csr.expire;
-       spin_unlock_irqrestore(&host->csr.lock, flags);
-
-       j = jiffies;
-       INIT_LIST_HEAD(&tmp);
-       spin_lock_irqsave(&pending_packets_lock, flags);
-
-       list_for_each_entry_safe(packet, p, &host->pending_packets, queue) {
-               if (time_before(packet->sendtime + expire, j))
-                       list_move_tail(&packet->queue, &tmp);
-               else
-                       /* Since packets are added to the tail, the oldest
-                        * ones are first, always. When we get to one that
-                        * isn't timed out, the rest aren't either. */
-                       break;
-       }
-       if (!list_empty(&host->pending_packets))
-               mod_timer(&host->timeout, j + host->timeout_interval);
-
-       spin_unlock_irqrestore(&pending_packets_lock, flags);
-
-       list_for_each_entry_safe(packet, p, &tmp, queue) {
-               list_del_init(&packet->queue);
-               packet->state = hpsb_complete;
-               packet->ack_code = ACKX_TIMEOUT;
-               queue_packet_complete(packet);
-       }
-}
-
-static struct task_struct *khpsbpkt_thread;
-static LIST_HEAD(hpsbpkt_queue);
-
-static void queue_packet_complete(struct hpsb_packet *packet)
-{
-       unsigned long flags;
-
-       if (packet->no_waiter) {
-               hpsb_free_packet(packet);
-               return;
-       }
-       if (packet->complete_routine != NULL) {
-               spin_lock_irqsave(&pending_packets_lock, flags);
-               list_add_tail(&packet->queue, &hpsbpkt_queue);
-               spin_unlock_irqrestore(&pending_packets_lock, flags);
-               wake_up_process(khpsbpkt_thread);
-       }
-       return;
-}
-
-/*
- * Kernel thread which handles packets that are completed.  This way the
- * packet's "complete" function is asynchronously run in process context.
- * Only packets which have a "complete" function may be sent here.
- */
-static int hpsbpkt_thread(void *__hi)
-{
-       struct hpsb_packet *packet, *p;
-       struct list_head tmp;
-       int may_schedule;
-
-       while (!kthread_should_stop()) {
-
-               INIT_LIST_HEAD(&tmp);
-               spin_lock_irq(&pending_packets_lock);
-               list_splice_init(&hpsbpkt_queue, &tmp);
-               spin_unlock_irq(&pending_packets_lock);
-
-               list_for_each_entry_safe(packet, p, &tmp, queue) {
-                       list_del_init(&packet->queue);
-                       packet->complete_routine(packet->complete_data);
-               }
-
-               set_current_state(TASK_INTERRUPTIBLE);
-               spin_lock_irq(&pending_packets_lock);
-               may_schedule = list_empty(&hpsbpkt_queue);
-               spin_unlock_irq(&pending_packets_lock);
-               if (may_schedule)
-                       schedule();
-               __set_current_state(TASK_RUNNING);
-       }
-       return 0;
-}
-
-static int __init ieee1394_init(void)
-{
-       int i, ret;
-
-       /* non-fatal error */
-       if (hpsb_init_config_roms()) {
-               HPSB_ERR("Failed to initialize some config rom entries.\n");
-               HPSB_ERR("Some features may not be available\n");
-       }
-
-       khpsbpkt_thread = kthread_run(hpsbpkt_thread, NULL, "khpsbpkt");
-       if (IS_ERR(khpsbpkt_thread)) {
-               HPSB_ERR("Failed to start hpsbpkt thread!\n");
-               ret = PTR_ERR(khpsbpkt_thread);
-               goto exit_cleanup_config_roms;
-       }
-
-       if (register_chrdev_region(IEEE1394_CORE_DEV, 256, "ieee1394")) {
-               HPSB_ERR("unable to register character device major %d!\n", IEEE1394_MAJOR);
-               ret = -ENODEV;
-               goto exit_release_kernel_thread;
-       }
-
-       ret = bus_register(&ieee1394_bus_type);
-       if (ret < 0) {
-               HPSB_INFO("bus register failed");
-               goto release_chrdev;
-       }
-
-       for (i = 0; fw_bus_attrs[i]; i++) {
-               ret = bus_create_file(&ieee1394_bus_type, fw_bus_attrs[i]);
-               if (ret < 0) {
-                       while (i >= 0) {
-                               bus_remove_file(&ieee1394_bus_type,
-                                               fw_bus_attrs[i--]);
-                       }
-                       bus_unregister(&ieee1394_bus_type);
-                       goto release_chrdev;
-               }
-       }
-
-       ret = class_register(&hpsb_host_class);
-       if (ret < 0)
-               goto release_all_bus;
-
-       hpsb_protocol_class = class_create(THIS_MODULE, "ieee1394_protocol");
-       if (IS_ERR(hpsb_protocol_class)) {
-               ret = PTR_ERR(hpsb_protocol_class);
-               goto release_class_host;
-       }
-
-       ret = init_csr();
-       if (ret) {
-               HPSB_INFO("init csr failed");
-               ret = -ENOMEM;
-               goto release_class_protocol;
-       }
-
-       if (disable_nodemgr) {
-               HPSB_INFO("nodemgr and IRM functionality disabled");
-               /* We shouldn't contend for IRM with nodemgr disabled, since
-                  nodemgr implements functionality required of ieee1394a-2000
-                  IRMs */
-               hpsb_disable_irm = 1;
-
-               return 0;
-       }
-
-       if (hpsb_disable_irm) {
-               HPSB_INFO("IRM functionality disabled");
-       }
-
-       ret = init_ieee1394_nodemgr();
-       if (ret < 0) {
-               HPSB_INFO("init nodemgr failed");
-               goto cleanup_csr;
-       }
-
-       return 0;
-
-cleanup_csr:
-       cleanup_csr();
-release_class_protocol:
-       class_destroy(hpsb_protocol_class);
-release_class_host:
-       class_unregister(&hpsb_host_class);
-release_all_bus:
-       for (i = 0; fw_bus_attrs[i]; i++)
-               bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
-       bus_unregister(&ieee1394_bus_type);
-release_chrdev:
-       unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
-exit_release_kernel_thread:
-       kthread_stop(khpsbpkt_thread);
-exit_cleanup_config_roms:
-       hpsb_cleanup_config_roms();
-       return ret;
-}
-
-static void __exit ieee1394_cleanup(void)
-{
-       int i;
-
-       if (!disable_nodemgr)
-               cleanup_ieee1394_nodemgr();
-
-       cleanup_csr();
-
-       class_destroy(hpsb_protocol_class);
-       class_unregister(&hpsb_host_class);
-       for (i = 0; fw_bus_attrs[i]; i++)
-               bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
-       bus_unregister(&ieee1394_bus_type);
-
-       kthread_stop(khpsbpkt_thread);
-
-       hpsb_cleanup_config_roms();
-
-       unregister_chrdev_region(IEEE1394_CORE_DEV, 256);
-}
-
-fs_initcall(ieee1394_init);
-module_exit(ieee1394_cleanup);
-
-/* Exported symbols */
-
-/** hosts.c **/
-EXPORT_SYMBOL(hpsb_alloc_host);
-EXPORT_SYMBOL(hpsb_add_host);
-EXPORT_SYMBOL(hpsb_resume_host);
-EXPORT_SYMBOL(hpsb_remove_host);
-EXPORT_SYMBOL(hpsb_update_config_rom_image);
-
-/** ieee1394_core.c **/
-EXPORT_SYMBOL(hpsb_speedto_str);
-EXPORT_SYMBOL(hpsb_protocol_class);
-EXPORT_SYMBOL(hpsb_set_packet_complete_task);
-EXPORT_SYMBOL(hpsb_alloc_packet);
-EXPORT_SYMBOL(hpsb_free_packet);
-EXPORT_SYMBOL(hpsb_send_packet);
-EXPORT_SYMBOL(hpsb_reset_bus);
-EXPORT_SYMBOL(hpsb_read_cycle_timer);
-EXPORT_SYMBOL(hpsb_bus_reset);
-EXPORT_SYMBOL(hpsb_selfid_received);
-EXPORT_SYMBOL(hpsb_selfid_complete);
-EXPORT_SYMBOL(hpsb_packet_sent);
-EXPORT_SYMBOL(hpsb_packet_received);
-EXPORT_SYMBOL_GPL(hpsb_disable_irm);
-
-/** ieee1394_transactions.c **/
-EXPORT_SYMBOL(hpsb_get_tlabel);
-EXPORT_SYMBOL(hpsb_free_tlabel);
-EXPORT_SYMBOL(hpsb_make_readpacket);
-EXPORT_SYMBOL(hpsb_make_writepacket);
-EXPORT_SYMBOL(hpsb_make_streampacket);
-EXPORT_SYMBOL(hpsb_make_lockpacket);
-EXPORT_SYMBOL(hpsb_make_lock64packet);
-EXPORT_SYMBOL(hpsb_make_phypacket);
-EXPORT_SYMBOL(hpsb_read);
-EXPORT_SYMBOL(hpsb_write);
-EXPORT_SYMBOL(hpsb_lock);
-EXPORT_SYMBOL(hpsb_packet_success);
-
-/** highlevel.c **/
-EXPORT_SYMBOL(hpsb_register_highlevel);
-EXPORT_SYMBOL(hpsb_unregister_highlevel);
-EXPORT_SYMBOL(hpsb_register_addrspace);
-EXPORT_SYMBOL(hpsb_unregister_addrspace);
-EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace);
-EXPORT_SYMBOL(hpsb_get_hostinfo);
-EXPORT_SYMBOL(hpsb_create_hostinfo);
-EXPORT_SYMBOL(hpsb_destroy_hostinfo);
-EXPORT_SYMBOL(hpsb_set_hostinfo_key);
-EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
-EXPORT_SYMBOL(hpsb_set_hostinfo);
-
-/** nodemgr.c **/
-EXPORT_SYMBOL(hpsb_node_fill_packet);
-EXPORT_SYMBOL(hpsb_node_write);
-EXPORT_SYMBOL(__hpsb_register_protocol);
-EXPORT_SYMBOL(hpsb_unregister_protocol);
-
-/** csr.c **/
-EXPORT_SYMBOL(hpsb_update_config_rom);
-
-/** dma.c **/
-EXPORT_SYMBOL(dma_prog_region_init);
-EXPORT_SYMBOL(dma_prog_region_alloc);
-EXPORT_SYMBOL(dma_prog_region_free);
-EXPORT_SYMBOL(dma_region_init);
-EXPORT_SYMBOL(dma_region_alloc);
-EXPORT_SYMBOL(dma_region_free);
-EXPORT_SYMBOL(dma_region_sync_for_cpu);
-EXPORT_SYMBOL(dma_region_sync_for_device);
-EXPORT_SYMBOL(dma_region_mmap);
-EXPORT_SYMBOL(dma_region_offset_to_bus);
-
-/** iso.c **/
-EXPORT_SYMBOL(hpsb_iso_xmit_init);
-EXPORT_SYMBOL(hpsb_iso_recv_init);
-EXPORT_SYMBOL(hpsb_iso_xmit_start);
-EXPORT_SYMBOL(hpsb_iso_recv_start);
-EXPORT_SYMBOL(hpsb_iso_recv_listen_channel);
-EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel);
-EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask);
-EXPORT_SYMBOL(hpsb_iso_stop);
-EXPORT_SYMBOL(hpsb_iso_shutdown);
-EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet);
-EXPORT_SYMBOL(hpsb_iso_xmit_sync);
-EXPORT_SYMBOL(hpsb_iso_recv_release_packets);
-EXPORT_SYMBOL(hpsb_iso_n_ready);
-EXPORT_SYMBOL(hpsb_iso_packet_sent);
-EXPORT_SYMBOL(hpsb_iso_packet_received);
-EXPORT_SYMBOL(hpsb_iso_wake);
-EXPORT_SYMBOL(hpsb_iso_recv_flush);
-
-/** csr1212.c **/
-EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
-EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
-EXPORT_SYMBOL(csr1212_get_keyval);
-EXPORT_SYMBOL(csr1212_new_directory);
-EXPORT_SYMBOL(csr1212_parse_keyval);
-EXPORT_SYMBOL(csr1212_read);
-EXPORT_SYMBOL(csr1212_release_keyval);
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
deleted file mode 100644 (file)
index 28b9f58..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-#ifndef _IEEE1394_CORE_H
-#define _IEEE1394_CORE_H
-
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/list.h>
-#include <linux/types.h>
-#include <linux/cdev.h>
-#include <asm/atomic.h>
-
-#include "hosts.h"
-#include "ieee1394_types.h"
-
-struct hpsb_packet {
-       /* This struct is basically read-only for hosts with the exception of
-        * the data buffer contents and driver_list. */
-
-       /* This can be used for host driver internal linking.
-        *
-        * NOTE: This must be left in init state when the driver is done
-        * with it (e.g. by using list_del_init()), since the core does
-        * some sanity checks to make sure the packet is not on a
-        * driver_list when free'ing it. */
-       struct list_head driver_list;
-
-       nodeid_t node_id;
-
-       /* hpsb_raw = send as-is, do not CRC (but still byte-swap it) */
-       enum { hpsb_async, hpsb_raw } __attribute__((packed)) type;
-
-       /* Okay, this is core internal and a no care for hosts.
-        * queued   = queued for sending
-        * pending  = sent, waiting for response
-        * complete = processing completed, successful or not
-        */
-       enum {
-               hpsb_unused, hpsb_queued, hpsb_pending, hpsb_complete
-       } __attribute__((packed)) state;
-
-       /* These are core-internal. */
-       signed char tlabel;
-       signed char ack_code;
-       unsigned char tcode;
-
-       unsigned expect_response:1;
-       unsigned no_waiter:1;
-
-       /* Speed to transmit with: 0 = 100Mbps, 1 = 200Mbps, 2 = 400Mbps */
-       unsigned speed_code:2;
-
-       struct hpsb_host *host;
-       unsigned int generation;
-
-       atomic_t refcnt;
-       struct list_head queue;
-
-       /* Function (and possible data to pass to it) to call when this
-        * packet is completed.  */
-       void (*complete_routine)(void *);
-       void *complete_data;
-
-       /* Store jiffies for implementing bus timeouts. */
-       unsigned long sendtime;
-
-       /* Core-internal.  */
-       size_t allocated_data_size;     /* as allocated */
-
-       /* Sizes are in bytes. To be set by caller of hpsb_alloc_packet. */
-       size_t data_size;               /* as filled in */
-       size_t header_size;             /* as filled in, not counting the CRC */
-
-       /* Buffers */
-       quadlet_t *data;                /* can be DMA-mapped */
-       quadlet_t header[5];
-       quadlet_t embedded_data[0];     /* keep as last member */
-};
-
-void hpsb_set_packet_complete_task(struct hpsb_packet *packet,
-                                  void (*routine)(void *), void *data);
-static inline struct hpsb_packet *driver_packet(struct list_head *l)
-{
-       return list_entry(l, struct hpsb_packet, driver_list);
-}
-void abort_timedouts(unsigned long __opaque);
-struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
-void hpsb_free_packet(struct hpsb_packet *packet);
-
-/**
- * get_hpsb_generation - generation counter for the complete 1394 subsystem
- *
- * Generation gets incremented on every change in the subsystem (notably on bus
- * resets). Use the functions, not the variable.
- */
-static inline unsigned int get_hpsb_generation(struct hpsb_host *host)
-{
-       return atomic_read(&host->generation);
-}
-
-int hpsb_send_phy_config(struct hpsb_host *host, int rootid, int gapcnt);
-int hpsb_send_packet(struct hpsb_packet *packet);
-int hpsb_send_packet_and_wait(struct hpsb_packet *packet);
-int hpsb_reset_bus(struct hpsb_host *host, int type);
-int hpsb_read_cycle_timer(struct hpsb_host *host, u32 *cycle_timer,
-                         u64 *local_time);
-
-int hpsb_bus_reset(struct hpsb_host *host);
-void hpsb_selfid_received(struct hpsb_host *host, quadlet_t sid);
-void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot);
-void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet,
-                     int ackcode);
-void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size,
-                         int write_acked);
-
-/*
- * CHARACTER DEVICE DISPATCHING
- *
- * All ieee1394 character device drivers share the same major number
- * (major 171).  The 256 minor numbers are allocated to the various
- * task-specific interfaces (raw1394, video1394, dv1394, etc) in
- * blocks of 16.
- *
- * The core ieee1394.o module allocates the device number region
- * 171:0-255, the various drivers must then cdev_add() their cdev
- * objects to handle their respective sub-regions.
- *
- * Minor device number block allocations:
- *
- * Block 0  (  0- 15)  raw1394
- * Block 1  ( 16- 31)  video1394
- * Block 2  ( 32- 47)  dv1394
- *
- * Blocks 3-14 free for future allocation
- *
- * Block 15 (240-255)  reserved for drivers under development, etc.
- */
-
-#define IEEE1394_MAJOR                  171
-
-#define IEEE1394_MINOR_BLOCK_RAW1394      0
-#define IEEE1394_MINOR_BLOCK_VIDEO1394    1
-#define IEEE1394_MINOR_BLOCK_DV1394       2
-#define IEEE1394_MINOR_BLOCK_EXPERIMENTAL 15
-
-#define IEEE1394_CORE_DEV        MKDEV(IEEE1394_MAJOR, 0)
-#define IEEE1394_RAW1394_DEV     MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_RAW1394 * 16)
-#define IEEE1394_VIDEO1394_DEV   MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_VIDEO1394 * 16)
-#define IEEE1394_DV1394_DEV      MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_DV1394 * 16)
-#define IEEE1394_EXPERIMENTAL_DEV MKDEV(IEEE1394_MAJOR, \
-                                       IEEE1394_MINOR_BLOCK_EXPERIMENTAL * 16)
-
-/**
- * ieee1394_file_to_instance - get the index within a minor number block
- */
-static inline unsigned char ieee1394_file_to_instance(struct file *file)
-{
-       int idx = cdev_index(file->f_path.dentry->d_inode);
-       if (idx < 0)
-               idx = 0;
-       return idx;
-}
-
-extern int hpsb_disable_irm;
-
-/* Our sysfs bus entry */
-extern struct bus_type ieee1394_bus_type;
-extern struct class hpsb_host_class;
-extern struct class *hpsb_protocol_class;
-
-#endif /* _IEEE1394_CORE_H */
diff --git a/drivers/ieee1394/ieee1394_hotplug.h b/drivers/ieee1394/ieee1394_hotplug.h
deleted file mode 100644 (file)
index dd5500e..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _IEEE1394_HOTPLUG_H
-#define _IEEE1394_HOTPLUG_H
-
-/* Unit spec id and sw version entry for some protocols */
-#define AVC_UNIT_SPEC_ID_ENTRY         0x0000A02D
-#define AVC_SW_VERSION_ENTRY           0x00010001
-#define CAMERA_UNIT_SPEC_ID_ENTRY      0x0000A02D
-#define CAMERA_SW_VERSION_ENTRY                0x00000100
-
-/* /include/linux/mod_devicetable.h defines:
- *     IEEE1394_MATCH_VENDOR_ID
- *     IEEE1394_MATCH_MODEL_ID
- *     IEEE1394_MATCH_SPECIFIER_ID
- *     IEEE1394_MATCH_VERSION
- *     struct ieee1394_device_id
- */
-#include <linux/mod_devicetable.h>
-
-#endif /* _IEEE1394_HOTPLUG_H */
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
deleted file mode 100644 (file)
index 675b313..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Transaction support.
- *
- * Copyright (C) 1999 Andreas E. Bombe
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/bitops.h>
-#include <linux/compiler.h>
-#include <linux/hardirq.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/sched.h>  /* because linux/wait.h is broken if CONFIG_SMP=n */
-#include <linux/wait.h>
-
-#include <asm/bug.h>
-#include <asm/errno.h>
-#include <asm/system.h>
-
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "ieee1394_transactions.h"
-
-#define PREP_ASYNC_HEAD_ADDRESS(tc) \
-        packet->tcode = tc; \
-        packet->header[0] = (packet->node_id << 16) | (packet->tlabel << 10) \
-                | (1 << 8) | (tc << 4); \
-        packet->header[1] = (packet->host->node_id << 16) | (addr >> 32); \
-        packet->header[2] = addr & 0xffffffff
-
-#ifndef HPSB_DEBUG_TLABELS
-static
-#endif
-DEFINE_SPINLOCK(hpsb_tlabel_lock);
-
-static DECLARE_WAIT_QUEUE_HEAD(tlabel_wq);
-
-static void fill_async_readquad(struct hpsb_packet *packet, u64 addr)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_READQ);
-       packet->header_size = 12;
-       packet->data_size = 0;
-       packet->expect_response = 1;
-}
-
-static void fill_async_readblock(struct hpsb_packet *packet, u64 addr,
-                                int length)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_READB);
-       packet->header[3] = length << 16;
-       packet->header_size = 16;
-       packet->data_size = 0;
-       packet->expect_response = 1;
-}
-
-static void fill_async_writequad(struct hpsb_packet *packet, u64 addr,
-                                quadlet_t data)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEQ);
-       packet->header[3] = data;
-       packet->header_size = 16;
-       packet->data_size = 0;
-       packet->expect_response = 1;
-}
-
-static void fill_async_writeblock(struct hpsb_packet *packet, u64 addr,
-                                 int length)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_WRITEB);
-       packet->header[3] = length << 16;
-       packet->header_size = 16;
-       packet->expect_response = 1;
-       packet->data_size = length + (length % 4 ? 4 - (length % 4) : 0);
-}
-
-static void fill_async_lock(struct hpsb_packet *packet, u64 addr, int extcode,
-                           int length)
-{
-       PREP_ASYNC_HEAD_ADDRESS(TCODE_LOCK_REQUEST);
-       packet->header[3] = (length << 16) | extcode;
-       packet->header_size = 16;
-       packet->data_size = length;
-       packet->expect_response = 1;
-}
-
-static void fill_phy_packet(struct hpsb_packet *packet, quadlet_t data)
-{
-       packet->header[0] = data;
-       packet->header[1] = ~data;
-       packet->header_size = 8;
-       packet->data_size = 0;
-       packet->expect_response = 0;
-       packet->type = hpsb_raw;        /* No CRC added */
-       packet->speed_code = IEEE1394_SPEED_100;        /* Force speed to be 100Mbps */
-}
-
-static void fill_async_stream_packet(struct hpsb_packet *packet, int length,
-                                    int channel, int tag, int sync)
-{
-       packet->header[0] = (length << 16) | (tag << 14) | (channel << 8)
-           | (TCODE_STREAM_DATA << 4) | sync;
-
-       packet->header_size = 4;
-       packet->data_size = length;
-       packet->type = hpsb_async;
-       packet->tcode = TCODE_ISO_DATA;
-}
-
-/* same as hpsb_get_tlabel, except that it returns immediately */
-static int hpsb_get_tlabel_atomic(struct hpsb_packet *packet)
-{
-       unsigned long flags, *tp;
-       u8 *next;
-       int tlabel, n = NODEID_TO_NODE(packet->node_id);
-
-       /* Broadcast transactions are complete once the request has been sent.
-        * Use the same transaction label for all broadcast transactions. */
-       if (unlikely(n == ALL_NODES)) {
-               packet->tlabel = 0;
-               return 0;
-       }
-       tp = packet->host->tl_pool[n].map;
-       next = &packet->host->next_tl[n];
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-       tlabel = find_next_zero_bit(tp, 64, *next);
-       if (tlabel > 63)
-               tlabel = find_first_zero_bit(tp, 64);
-       if (tlabel > 63) {
-               spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-               return -EAGAIN;
-       }
-       __set_bit(tlabel, tp);
-       *next = (tlabel + 1) & 63;
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       packet->tlabel = tlabel;
-       return 0;
-}
-
-/**
- * hpsb_get_tlabel - allocate a transaction label
- * @packet: the packet whose tlabel and tl_pool we set
- *
- * Every asynchronous transaction on the 1394 bus needs a transaction
- * label to match the response to the request.  This label has to be
- * different from any other transaction label in an outstanding request to
- * the same node to make matching possible without ambiguity.
- *
- * There are 64 different tlabels, so an allocated tlabel has to be freed
- * with hpsb_free_tlabel() after the transaction is complete (unless it's
- * reused again for the same target node).
- *
- * Return value: Zero on success, otherwise non-zero. A non-zero return
- * generally means there are no available tlabels. If this is called out
- * of interrupt or atomic context, then it will sleep until can return a
- * tlabel or a signal is received.
- */
-int hpsb_get_tlabel(struct hpsb_packet *packet)
-{
-       if (irqs_disabled() || in_atomic())
-               return hpsb_get_tlabel_atomic(packet);
-
-       /* NB: The macro wait_event_interruptible() is called with a condition
-        * argument with side effect.  This is only possible because the side
-        * effect does not occur until the condition became true, and
-        * wait_event_interruptible() won't evaluate the condition again after
-        * that. */
-       return wait_event_interruptible(tlabel_wq,
-                                       !hpsb_get_tlabel_atomic(packet));
-}
-
-/**
- * hpsb_free_tlabel - free an allocated transaction label
- * @packet: packet whose tlabel and tl_pool needs to be cleared
- *
- * Frees the transaction label allocated with hpsb_get_tlabel().  The
- * tlabel has to be freed after the transaction is complete (i.e. response
- * was received for a split transaction or packet was sent for a unified
- * transaction).
- *
- * A tlabel must not be freed twice.
- */
-void hpsb_free_tlabel(struct hpsb_packet *packet)
-{
-       unsigned long flags, *tp;
-       int tlabel, n = NODEID_TO_NODE(packet->node_id);
-
-       if (unlikely(n == ALL_NODES))
-               return;
-       tp = packet->host->tl_pool[n].map;
-       tlabel = packet->tlabel;
-       BUG_ON(tlabel > 63 || tlabel < 0);
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-       BUG_ON(!__test_and_clear_bit(tlabel, tp));
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       wake_up_interruptible(&tlabel_wq);
-}
-
-/**
- * hpsb_packet_success - Make sense of the ack and reply codes
- *
- * Make sense of the ack and reply codes and return more convenient error codes:
- * 0 = success.  -%EBUSY = node is busy, try again.  -%EAGAIN = error which can
- * probably resolved by retry.  -%EREMOTEIO = node suffers from an internal
- * error.  -%EACCES = this transaction is not allowed on requested address.
- * -%EINVAL = invalid address at node.
- */
-int hpsb_packet_success(struct hpsb_packet *packet)
-{
-       switch (packet->ack_code) {
-       case ACK_PENDING:
-               switch ((packet->header[1] >> 12) & 0xf) {
-               case RCODE_COMPLETE:
-                       return 0;
-               case RCODE_CONFLICT_ERROR:
-                       return -EAGAIN;
-               case RCODE_DATA_ERROR:
-                       return -EREMOTEIO;
-               case RCODE_TYPE_ERROR:
-                       return -EACCES;
-               case RCODE_ADDRESS_ERROR:
-                       return -EINVAL;
-               default:
-                       HPSB_ERR("received reserved rcode %d from node %d",
-                                (packet->header[1] >> 12) & 0xf,
-                                packet->node_id);
-                       return -EAGAIN;
-               }
-
-       case ACK_BUSY_X:
-       case ACK_BUSY_A:
-       case ACK_BUSY_B:
-               return -EBUSY;
-
-       case ACK_TYPE_ERROR:
-               return -EACCES;
-
-       case ACK_COMPLETE:
-               if (packet->tcode == TCODE_WRITEQ
-                   || packet->tcode == TCODE_WRITEB) {
-                       return 0;
-               } else {
-                       HPSB_ERR("impossible ack_complete from node %d "
-                                "(tcode %d)", packet->node_id, packet->tcode);
-                       return -EAGAIN;
-               }
-
-       case ACK_DATA_ERROR:
-               if (packet->tcode == TCODE_WRITEB
-                   || packet->tcode == TCODE_LOCK_REQUEST) {
-                       return -EAGAIN;
-               } else {
-                       HPSB_ERR("impossible ack_data_error from node %d "
-                                "(tcode %d)", packet->node_id, packet->tcode);
-                       return -EAGAIN;
-               }
-
-       case ACK_ADDRESS_ERROR:
-               return -EINVAL;
-
-       case ACK_TARDY:
-       case ACK_CONFLICT_ERROR:
-       case ACKX_NONE:
-       case ACKX_SEND_ERROR:
-       case ACKX_ABORTED:
-       case ACKX_TIMEOUT:
-               /* error while sending */
-               return -EAGAIN;
-
-       default:
-               HPSB_ERR("got invalid ack %d from node %d (tcode %d)",
-                        packet->ack_code, packet->node_id, packet->tcode);
-               return -EAGAIN;
-       }
-}
-
-struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, size_t length)
-{
-       struct hpsb_packet *packet;
-
-       if (length == 0)
-               return NULL;
-
-       packet = hpsb_alloc_packet(length);
-       if (!packet)
-               return NULL;
-
-       packet->host = host;
-       packet->node_id = node;
-
-       if (hpsb_get_tlabel(packet)) {
-               hpsb_free_packet(packet);
-               return NULL;
-       }
-
-       if (length == 4)
-               fill_async_readquad(packet, addr);
-       else
-               fill_async_readblock(packet, addr, length);
-
-       return packet;
-}
-
-struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host, nodeid_t node,
-                                         u64 addr, quadlet_t * buffer,
-                                         size_t length)
-{
-       struct hpsb_packet *packet;
-
-       if (length == 0)
-               return NULL;
-
-       packet = hpsb_alloc_packet(length);
-       if (!packet)
-               return NULL;
-
-       if (length % 4) {       /* zero padding bytes */
-               packet->data[length >> 2] = 0;
-       }
-       packet->host = host;
-       packet->node_id = node;
-
-       if (hpsb_get_tlabel(packet)) {
-               hpsb_free_packet(packet);
-               return NULL;
-       }
-
-       if (length == 4) {
-               fill_async_writequad(packet, addr, buffer ? *buffer : 0);
-       } else {
-               fill_async_writeblock(packet, addr, length);
-               if (buffer)
-                       memcpy(packet->data, buffer, length);
-       }
-
-       return packet;
-}
-
-struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 * buffer,
-                                          int length, int channel, int tag,
-                                          int sync)
-{
-       struct hpsb_packet *packet;
-
-       if (length == 0)
-               return NULL;
-
-       packet = hpsb_alloc_packet(length);
-       if (!packet)
-               return NULL;
-
-       if (length % 4) {       /* zero padding bytes */
-               packet->data[length >> 2] = 0;
-       }
-       packet->host = host;
-
-       /* Because it is too difficult to determine all PHY speeds and link
-        * speeds here, we use S100... */
-       packet->speed_code = IEEE1394_SPEED_100;
-
-       /* ...and prevent hpsb_send_packet() from overriding it. */
-       packet->node_id = LOCAL_BUS | ALL_NODES;
-
-       if (hpsb_get_tlabel(packet)) {
-               hpsb_free_packet(packet);
-               return NULL;
-       }
-
-       fill_async_stream_packet(packet, length, channel, tag, sync);
-       if (buffer)
-               memcpy(packet->data, buffer, length);
-
-       return packet;
-}
-
-struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, int extcode,
-                                        quadlet_t * data, quadlet_t arg)
-{
-       struct hpsb_packet *p;
-       u32 length;
-
-       p = hpsb_alloc_packet(8);
-       if (!p)
-               return NULL;
-
-       p->host = host;
-       p->node_id = node;
-       if (hpsb_get_tlabel(p)) {
-               hpsb_free_packet(p);
-               return NULL;
-       }
-
-       switch (extcode) {
-       case EXTCODE_FETCH_ADD:
-       case EXTCODE_LITTLE_ADD:
-               length = 4;
-               if (data)
-                       p->data[0] = *data;
-               break;
-       default:
-               length = 8;
-               if (data) {
-                       p->data[0] = arg;
-                       p->data[1] = *data;
-               }
-               break;
-       }
-       fill_async_lock(p, addr, extcode, length);
-
-       return p;
-}
-
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
-                                          nodeid_t node, u64 addr, int extcode,
-                                          octlet_t * data, octlet_t arg)
-{
-       struct hpsb_packet *p;
-       u32 length;
-
-       p = hpsb_alloc_packet(16);
-       if (!p)
-               return NULL;
-
-       p->host = host;
-       p->node_id = node;
-       if (hpsb_get_tlabel(p)) {
-               hpsb_free_packet(p);
-               return NULL;
-       }
-
-       switch (extcode) {
-       case EXTCODE_FETCH_ADD:
-       case EXTCODE_LITTLE_ADD:
-               length = 8;
-               if (data) {
-                       p->data[0] = *data >> 32;
-                       p->data[1] = *data & 0xffffffff;
-               }
-               break;
-       default:
-               length = 16;
-               if (data) {
-                       p->data[0] = arg >> 32;
-                       p->data[1] = arg & 0xffffffff;
-                       p->data[2] = *data >> 32;
-                       p->data[3] = *data & 0xffffffff;
-               }
-               break;
-       }
-       fill_async_lock(p, addr, extcode, length);
-
-       return p;
-}
-
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data)
-{
-       struct hpsb_packet *p;
-
-       p = hpsb_alloc_packet(0);
-       if (!p)
-               return NULL;
-
-       p->host = host;
-       fill_phy_packet(p, data);
-
-       return p;
-}
-
-/*
- * FIXME - these functions should probably read from / write to user space to
- * avoid in kernel buffers for user space callers
- */
-
-/**
- * hpsb_read - generic read function
- *
- * Recognizes the local node ID and act accordingly.  Automatically uses a
- * quadlet read request if @length == 4 and and a block read request otherwise.
- * It does not yet support lengths that are not a multiple of 4.
- *
- * You must explicitly specifiy the @generation for which the node ID is valid,
- * to avoid sending packets to the wrong nodes when we race with a bus reset.
- */
-int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, quadlet_t * buffer, size_t length)
-{
-       struct hpsb_packet *packet;
-       int retval = 0;
-
-       if (length == 0)
-               return -EINVAL;
-
-       packet = hpsb_make_readpacket(host, node, addr, length);
-
-       if (!packet) {
-               return -ENOMEM;
-       }
-
-       packet->generation = generation;
-       retval = hpsb_send_packet_and_wait(packet);
-       if (retval < 0)
-               goto hpsb_read_fail;
-
-       retval = hpsb_packet_success(packet);
-
-       if (retval == 0) {
-               if (length == 4) {
-                       *buffer = packet->header[3];
-               } else {
-                       memcpy(buffer, packet->data, length);
-               }
-       }
-
-      hpsb_read_fail:
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
-
-/**
- * hpsb_write - generic write function
- *
- * Recognizes the local node ID and act accordingly.  Automatically uses a
- * quadlet write request if @length == 4 and and a block write request
- * otherwise.  It does not yet support lengths that are not a multiple of 4.
- *
- * You must explicitly specifiy the @generation for which the node ID is valid,
- * to avoid sending packets to the wrong nodes when we race with a bus reset.
- */
-int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-              u64 addr, quadlet_t * buffer, size_t length)
-{
-       struct hpsb_packet *packet;
-       int retval;
-
-       if (length == 0)
-               return -EINVAL;
-
-       packet = hpsb_make_writepacket(host, node, addr, buffer, length);
-
-       if (!packet)
-               return -ENOMEM;
-
-       packet->generation = generation;
-       retval = hpsb_send_packet_and_wait(packet);
-       if (retval < 0)
-               goto hpsb_write_fail;
-
-       retval = hpsb_packet_success(packet);
-
-      hpsb_write_fail:
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
-
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, int extcode, quadlet_t *data, quadlet_t arg)
-{
-       struct hpsb_packet *packet;
-       int retval = 0;
-
-       packet = hpsb_make_lockpacket(host, node, addr, extcode, data, arg);
-       if (!packet)
-               return -ENOMEM;
-
-       packet->generation = generation;
-       retval = hpsb_send_packet_and_wait(packet);
-       if (retval < 0)
-               goto hpsb_lock_fail;
-
-       retval = hpsb_packet_success(packet);
-
-       if (retval == 0)
-               *data = packet->data[0];
-
-hpsb_lock_fail:
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-
-       return retval;
-}
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
deleted file mode 100644 (file)
index 20b693b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef _IEEE1394_TRANSACTIONS_H
-#define _IEEE1394_TRANSACTIONS_H
-
-#include <linux/types.h>
-
-#include "ieee1394_types.h"
-
-struct hpsb_packet;
-struct hpsb_host;
-
-int hpsb_get_tlabel(struct hpsb_packet *packet);
-void hpsb_free_tlabel(struct hpsb_packet *packet);
-struct hpsb_packet *hpsb_make_readpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, size_t length);
-struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
-                                        u64 addr, int extcode, quadlet_t *data,
-                                        quadlet_t arg);
-struct hpsb_packet *hpsb_make_lock64packet(struct hpsb_host *host,
-                                          nodeid_t node, u64 addr, int extcode,
-                                          octlet_t *data, octlet_t arg);
-struct hpsb_packet *hpsb_make_phypacket(struct hpsb_host *host, quadlet_t data);
-struct hpsb_packet *hpsb_make_writepacket(struct hpsb_host *host,
-                                         nodeid_t node, u64 addr,
-                                         quadlet_t *buffer, size_t length);
-struct hpsb_packet *hpsb_make_streampacket(struct hpsb_host *host, u8 *buffer,
-                                           int length, int channel, int tag,
-                                          int sync);
-int hpsb_packet_success(struct hpsb_packet *packet);
-int hpsb_read(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, quadlet_t *buffer, size_t length);
-int hpsb_write(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-              u64 addr, quadlet_t *buffer, size_t length);
-int hpsb_lock(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-             u64 addr, int extcode, quadlet_t *data, quadlet_t arg);
-
-#ifdef HPSB_DEBUG_TLABELS
-extern spinlock_t hpsb_tlabel_lock;
-#endif
-
-#endif /* _IEEE1394_TRANSACTIONS_H */
diff --git a/drivers/ieee1394/ieee1394_types.h b/drivers/ieee1394/ieee1394_types.h
deleted file mode 100644 (file)
index 9803aaa..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-#ifndef _IEEE1394_TYPES_H
-#define _IEEE1394_TYPES_H
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <asm/byteorder.h>
-
-typedef u32 quadlet_t;
-typedef u64 octlet_t;
-typedef u16 nodeid_t;
-
-typedef u8  byte_t;
-typedef u64 nodeaddr_t;
-typedef u16 arm_length_t;
-
-#define BUS_MASK  0xffc0
-#define BUS_SHIFT 6
-#define NODE_MASK 0x003f
-#define LOCAL_BUS 0xffc0
-#define ALL_NODES 0x003f
-
-#define NODEID_TO_BUS(nodeid)  ((nodeid & BUS_MASK) >> BUS_SHIFT)
-#define NODEID_TO_NODE(nodeid) (nodeid & NODE_MASK)
-
-/* Can be used to consistently print a node/bus ID. */
-#define NODE_BUS_FMT           "%d-%02d:%04d"
-#define NODE_BUS_ARGS(__host, __nodeid)        \
-       __host->id, NODEID_TO_NODE(__nodeid), NODEID_TO_BUS(__nodeid)
-
-#define HPSB_PRINT(level, fmt, args...) \
-       printk(level "ieee1394: " fmt "\n" , ## args)
-
-#define HPSB_DEBUG(fmt, args...)       HPSB_PRINT(KERN_DEBUG, fmt , ## args)
-#define HPSB_INFO(fmt, args...)                HPSB_PRINT(KERN_INFO, fmt , ## args)
-#define HPSB_NOTICE(fmt, args...)      HPSB_PRINT(KERN_NOTICE, fmt , ## args)
-#define HPSB_WARN(fmt, args...)                HPSB_PRINT(KERN_WARNING, fmt , ## args)
-#define HPSB_ERR(fmt, args...)         HPSB_PRINT(KERN_ERR, fmt , ## args)
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define HPSB_VERBOSE(fmt, args...)     HPSB_PRINT(KERN_DEBUG, fmt , ## args)
-#define HPSB_DEBUG_TLABELS
-#else
-#define HPSB_VERBOSE(fmt, args...)     do {} while (0)
-#endif
-
-#ifdef __BIG_ENDIAN
-
-static inline void *memcpy_le32(u32 *dest, const u32 *__src, size_t count)
-{
-       void *tmp = dest;
-       u32 *src = (u32 *)__src;
-
-       count /= 4;
-       while (count--)
-               *dest++ = swab32p(src++);
-       return tmp;
-}
-
-#else
-
-static __inline__ void *memcpy_le32(u32 *dest, const u32 *src, size_t count)
-{
-       return memcpy(dest, src, count);
-}
-
-#endif /* __BIG_ENDIAN */
-
-#endif /* _IEEE1394_TYPES_H */
diff --git a/drivers/ieee1394/init_ohci1394_dma.c b/drivers/ieee1394/init_ohci1394_dma.c
deleted file mode 100644 (file)
index ddaab6e..0000000
+++ /dev/null
@@ -1,285 +0,0 @@
-/*
- * init_ohci1394_dma.c - Initializes physical DMA on all OHCI 1394 controllers
- *
- * Copyright (C) 2006-2007      Bernhard Kaindl <bk@suse.de>
- *
- * Derived from drivers/ieee1394/ohci1394.c and arch/x86/kernel/early-quirks.c
- * this file has functions to:
- * - scan the PCI very early on boot for all OHCI 1394-compliant controllers
- * - reset and initialize them and make them join the IEEE1394 bus and
- * - enable physical DMA on them to allow remote debugging
- *
- * All code and data is marked as __init and __initdata, respective as
- * during boot, all OHCI1394 controllers may be claimed by the firewire
- * stack and at this point, this code should not touch them anymore.
- *
- * To use physical DMA after the initialization of the firewire stack,
- * be sure that the stack enables it and (re-)attach after the bus reset
- * which may be caused by the firewire stack initialization.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/interrupt.h>   /* for ohci1394.h */
-#include <linux/delay.h>
-#include <linux/pci.h>         /* for PCI defines */
-#include <linux/init_ohci1394_dma.h>
-#include <asm/pci-direct.h>    /* for direct PCI config space access */
-#include <asm/fixmap.h>
-
-#include "ieee1394_types.h"
-#include "ohci1394.h"
-
-int __initdata init_ohci1394_dma_early;
-
-/* Reads a PHY register of an OHCI-1394 controller */
-static inline u8 __init get_phy_reg(struct ti_ohci *ohci, u8 addr)
-{
-       int i;
-       quadlet_t r;
-
-       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
-                       break;
-               mdelay(1);
-       }
-       r = reg_read(ohci, OHCI1394_PhyControl);
-
-       return (r & 0x00ff0000) >> 16;
-}
-
-/* Writes to a PHY register of an OHCI-1394 controller */
-static inline void __init set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
-{
-       int i;
-
-       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               u32 r = reg_read(ohci, OHCI1394_PhyControl);
-               if (!(r & 0x00004000))
-                       break;
-               mdelay(1);
-       }
-}
-
-/* Resets an OHCI-1394 controller (for sane state before initialization) */
-static inline void __init init_ohci1394_soft_reset(struct ti_ohci *ohci) {
-       int i;
-
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (!(reg_read(ohci, OHCI1394_HCControlSet)
-                                  & OHCI1394_HCControl_softReset))
-                       break;
-               mdelay(1);
-       }
-}
-
-/* Basic OHCI-1394 register and port inititalization */
-static inline void __init init_ohci1394_initialize(struct ti_ohci *ohci)
-{
-       quadlet_t bus_options;
-       int num_ports, i;
-
-       /* Put some defaults to these undefined bus options */
-       bus_options = reg_read(ohci, OHCI1394_BusOptions);
-       bus_options |=  0x60000000; /* Enable CMC and ISC */
-       bus_options &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
-       bus_options &= ~0x18000000; /* Disable PMC and BMC */
-       reg_write(ohci, OHCI1394_BusOptions, bus_options);
-
-       /* Set the bus number */
-       reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
-
-       /* Enable posted writes */
-       reg_write(ohci, OHCI1394_HCControlSet,
-                       OHCI1394_HCControl_postedWriteEnable);
-
-       /* Clear link control register */
-       reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
-
-       /* enable phys */
-       reg_write(ohci, OHCI1394_LinkControlSet,
-                       OHCI1394_LinkControl_RcvPhyPkt);
-
-       /* Don't accept phy packets into AR request context */
-       reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
-
-       /* Clear the Isochonouys interrupt masks */
-       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
-
-       /* Accept asyncronous transfer requests from all nodes for now */
-       reg_write(ohci,OHCI1394_AsReqFilterHiSet, 0x80000000);
-
-       /* Specify asyncronous transfer retries */
-       reg_write(ohci, OHCI1394_ATRetries,
-                 OHCI1394_MAX_AT_REQ_RETRIES |
-                 (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
-                 (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
-
-       /* We don't want hardware swapping */
-       reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
-
-       /* Enable link */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
-
-       /* If anything is connected to a port, make sure it is enabled */
-       num_ports = get_phy_reg(ohci, 2) & 0xf;
-       for (i = 0; i < num_ports; i++) {
-               unsigned int status;
-
-               set_phy_reg(ohci, 7, i);
-               status = get_phy_reg(ohci, 8);
-
-               if (status & 0x20)
-                       set_phy_reg(ohci, 8, status & ~1);
-       }
-}
-
-/**
- * init_ohci1394_wait_for_busresets - wait until bus resets are completed
- *
- * OHCI1394 initialization itself and any device going on- or offline
- * and any cable issue cause a IEEE1394 bus reset. The OHCI1394 spec
- * specifies that physical DMA is disabled on each bus reset and it
- * has to be enabled after each bus reset when needed. We resort
- * to polling here because on early boot, we have no interrupts.
- */
-static inline void __init init_ohci1394_wait_for_busresets(struct ti_ohci *ohci)
-{
-       int i, events;
-
-       for (i=0; i < 9; i++) {
-               mdelay(200);
-               events = reg_read(ohci, OHCI1394_IntEventSet);
-               if (events & OHCI1394_busReset)
-                       reg_write(ohci, OHCI1394_IntEventClear,
-                                       OHCI1394_busReset);
-       }
-}
-
-/**
- * init_ohci1394_enable_physical_dma - Enable physical DMA for remote debugging
- * This enables remote DMA access over IEEE1394 from every host for the low
- * 4GB of address space. DMA accesses above 4GB are not available currently.
- */
-static inline void __init init_ohci1394_enable_physical_dma(struct ti_ohci *hci)
-{
-       reg_write(hci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
-       reg_write(hci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
-       reg_write(hci, OHCI1394_PhyUpperBound, 0xffff0000);
-}
-
-/**
- * init_ohci1394_reset_and_init_dma - init controller and enable DMA
- * This initializes the given controller and enables physical DMA engine in it.
- */
-static inline void __init init_ohci1394_reset_and_init_dma(struct ti_ohci *ohci)
-{
-       /* Start off with a soft reset, clears everything to a sane state. */
-       init_ohci1394_soft_reset(ohci);
-
-       /* Accessing some registers without LPS enabled may cause lock up */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
-
-       /* Disable and clear interrupts */
-       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-
-       mdelay(50); /* Wait 50msec to make sure we have full link enabled */
-
-       init_ohci1394_initialize(ohci);
-       /*
-        * The initialization causes at least one IEEE1394 bus reset. Enabling
-        * physical DMA only works *after* *all* bus resets have calmed down:
-        */
-       init_ohci1394_wait_for_busresets(ohci);
-
-       /* We had to wait and do this now if we want to debug early problems */
-       init_ohci1394_enable_physical_dma(ohci);
-}
-
-/**
- * init_ohci1394_controller - Map the registers of the controller and init DMA
- * This maps the registers of the specified controller and initializes it
- */
-static inline void __init init_ohci1394_controller(int num, int slot, int func)
-{
-       unsigned long ohci_base;
-       struct ti_ohci ohci;
-
-       printk(KERN_INFO "init_ohci1394_dma: initializing OHCI-1394"
-                        " at %02x:%02x.%x\n", num, slot, func);
-
-       ohci_base = read_pci_config(num, slot, func, PCI_BASE_ADDRESS_0+(0<<2))
-                                                  & PCI_BASE_ADDRESS_MEM_MASK;
-
-       set_fixmap_nocache(FIX_OHCI1394_BASE, ohci_base);
-
-       ohci.registers = (void *)fix_to_virt(FIX_OHCI1394_BASE);
-
-       init_ohci1394_reset_and_init_dma(&ohci);
-}
-
-/**
- * debug_init_ohci1394_dma - scan for OHCI1394 controllers and init DMA on them
- * Scans the whole PCI space for OHCI1394 controllers and inits DMA on them
- */
-void __init init_ohci1394_dma_on_all_controllers(void)
-{
-       int num, slot, func;
-
-       if (!early_pci_allowed())
-               return;
-
-       /* Poor man's PCI discovery, the only thing we can do at early boot */
-       for (num = 0; num < 32; num++) {
-               for (slot = 0; slot < 32; slot++) {
-                       for (func = 0; func < 8; func++) {
-                               u32 class = read_pci_config(num,slot,func,
-                                                       PCI_CLASS_REVISION);
-                               if ((class == 0xffffffff))
-                                       continue; /* No device at this func */
-
-                               if (class>>8 != PCI_CLASS_SERIAL_FIREWIRE_OHCI)
-                                       continue; /* Not an OHCI-1394 device */
-
-                               init_ohci1394_controller(num, slot, func);
-                               break; /* Assume one controller per device */
-                       }
-               }
-       }
-       printk(KERN_INFO "init_ohci1394_dma: finished initializing OHCI DMA\n");
-}
-
-/**
- * setup_init_ohci1394_early - enables early OHCI1394 DMA initialization
- */
-static int __init setup_ohci1394_dma(char *opt)
-{
-       if (!strcmp(opt, "early"))
-               init_ohci1394_dma_early = 1;
-       return 0;
-}
-
-/* passing ohci1394_dma=early on boot causes early OHCI1394 DMA initialization */
-early_param("ohci1394_dma", setup_ohci1394_dma);
diff --git a/drivers/ieee1394/iso.c b/drivers/ieee1394/iso.c
deleted file mode 100644 (file)
index 1cf6487..0000000
+++ /dev/null
@@ -1,568 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * kernel ISO transmission/reception
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-
-#include "hosts.h"
-#include "iso.h"
-
-/**
- * hpsb_iso_stop - stop DMA
- */
-void hpsb_iso_stop(struct hpsb_iso *iso)
-{
-       if (!(iso->flags & HPSB_ISO_DRIVER_STARTED))
-               return;
-
-       iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
-                                 XMIT_STOP : RECV_STOP, 0);
-       iso->flags &= ~HPSB_ISO_DRIVER_STARTED;
-}
-
-/**
- * hpsb_iso_shutdown - deallocate buffer and DMA context
- */
-void hpsb_iso_shutdown(struct hpsb_iso *iso)
-{
-       if (iso->flags & HPSB_ISO_DRIVER_INIT) {
-               hpsb_iso_stop(iso);
-               iso->host->driver->isoctl(iso, iso->type == HPSB_ISO_XMIT ?
-                                         XMIT_SHUTDOWN : RECV_SHUTDOWN, 0);
-               iso->flags &= ~HPSB_ISO_DRIVER_INIT;
-       }
-
-       dma_region_free(&iso->data_buf);
-       kfree(iso);
-}
-
-static struct hpsb_iso *hpsb_iso_common_init(struct hpsb_host *host,
-                                            enum hpsb_iso_type type,
-                                            unsigned int data_buf_size,
-                                            unsigned int buf_packets,
-                                            int channel, int dma_mode,
-                                            int irq_interval,
-                                            void (*callback) (struct hpsb_iso
-                                                              *))
-{
-       struct hpsb_iso *iso;
-       int dma_direction;
-
-       /* make sure driver supports the ISO API */
-       if (!host->driver->isoctl) {
-               printk(KERN_INFO
-                      "ieee1394: host driver '%s' does not support the rawiso API\n",
-                      host->driver->name);
-               return NULL;
-       }
-
-       /* sanitize parameters */
-
-       if (buf_packets < 2)
-               buf_packets = 2;
-
-       if ((dma_mode < HPSB_ISO_DMA_DEFAULT)
-           || (dma_mode > HPSB_ISO_DMA_PACKET_PER_BUFFER))
-               dma_mode = HPSB_ISO_DMA_DEFAULT;
-
-       if ((irq_interval < 0) || (irq_interval > buf_packets / 4))
-               irq_interval = buf_packets / 4;
-       if (irq_interval == 0)  /* really interrupt for each packet */
-               irq_interval = 1;
-
-       if (channel < -1 || channel >= 64)
-               return NULL;
-
-       /* channel = -1 is OK for multi-channel recv but not for xmit */
-       if (type == HPSB_ISO_XMIT && channel < 0)
-               return NULL;
-
-       /* allocate and write the struct hpsb_iso */
-
-       iso =
-           kmalloc(sizeof(*iso) +
-                   buf_packets * sizeof(struct hpsb_iso_packet_info),
-                   GFP_KERNEL);
-       if (!iso)
-               return NULL;
-
-       iso->infos = (struct hpsb_iso_packet_info *)(iso + 1);
-
-       iso->type = type;
-       iso->host = host;
-       iso->hostdata = NULL;
-       iso->callback = callback;
-       init_waitqueue_head(&iso->waitq);
-       iso->channel = channel;
-       iso->irq_interval = irq_interval;
-       iso->dma_mode = dma_mode;
-       dma_region_init(&iso->data_buf);
-       iso->buf_size = PAGE_ALIGN(data_buf_size);
-       iso->buf_packets = buf_packets;
-       iso->pkt_dma = 0;
-       iso->first_packet = 0;
-       spin_lock_init(&iso->lock);
-
-       if (iso->type == HPSB_ISO_XMIT) {
-               iso->n_ready_packets = iso->buf_packets;
-               dma_direction = PCI_DMA_TODEVICE;
-       } else {
-               iso->n_ready_packets = 0;
-               dma_direction = PCI_DMA_FROMDEVICE;
-       }
-
-       atomic_set(&iso->overflows, 0);
-       iso->bytes_discarded = 0;
-       iso->flags = 0;
-       iso->prebuffer = 0;
-
-       /* allocate the packet buffer */
-       if (dma_region_alloc
-           (&iso->data_buf, iso->buf_size, host->pdev, dma_direction))
-               goto err;
-
-       return iso;
-
-      err:
-       hpsb_iso_shutdown(iso);
-       return NULL;
-}
-
-/**
- * hpsb_iso_n_ready - returns number of packets ready to send or receive
- */
-int hpsb_iso_n_ready(struct hpsb_iso *iso)
-{
-       unsigned long flags;
-       int val;
-
-       spin_lock_irqsave(&iso->lock, flags);
-       val = iso->n_ready_packets;
-       spin_unlock_irqrestore(&iso->lock, flags);
-
-       return val;
-}
-
-/**
- * hpsb_iso_xmit_init - allocate the buffer and DMA context
- */
-struct hpsb_iso *hpsb_iso_xmit_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int speed,
-                                   int irq_interval,
-                                   void (*callback) (struct hpsb_iso *))
-{
-       struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_XMIT,
-                                                   data_buf_size, buf_packets,
-                                                   channel,
-                                                   HPSB_ISO_DMA_DEFAULT,
-                                                   irq_interval, callback);
-       if (!iso)
-               return NULL;
-
-       iso->speed = speed;
-
-       /* tell the driver to start working */
-       if (host->driver->isoctl(iso, XMIT_INIT, 0))
-               goto err;
-
-       iso->flags |= HPSB_ISO_DRIVER_INIT;
-       return iso;
-
-      err:
-       hpsb_iso_shutdown(iso);
-       return NULL;
-}
-
-/**
- * hpsb_iso_recv_init - allocate the buffer and DMA context
- *
- * Note, if channel = -1, multi-channel receive is enabled.
- */
-struct hpsb_iso *hpsb_iso_recv_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int dma_mode,
-                                   int irq_interval,
-                                   void (*callback) (struct hpsb_iso *))
-{
-       struct hpsb_iso *iso = hpsb_iso_common_init(host, HPSB_ISO_RECV,
-                                                   data_buf_size, buf_packets,
-                                                   channel, dma_mode,
-                                                   irq_interval, callback);
-       if (!iso)
-               return NULL;
-
-       /* tell the driver to start working */
-       if (host->driver->isoctl(iso, RECV_INIT, 0))
-               goto err;
-
-       iso->flags |= HPSB_ISO_DRIVER_INIT;
-       return iso;
-
-      err:
-       hpsb_iso_shutdown(iso);
-       return NULL;
-}
-
-/**
- * hpsb_iso_recv_listen_channel
- *
- * multi-channel only
- */
-int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel)
-{
-       if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_LISTEN_CHANNEL, channel);
-}
-
-/**
- * hpsb_iso_recv_unlisten_channel
- *
- * multi-channel only
- */
-int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel)
-{
-       if (iso->type != HPSB_ISO_RECV || iso->channel != -1 || channel >= 64)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_UNLISTEN_CHANNEL, channel);
-}
-
-/**
- * hpsb_iso_recv_set_channel_mask
- *
- * multi-channel only
- */
-int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
-{
-       if (iso->type != HPSB_ISO_RECV || iso->channel != -1)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_SET_CHANNEL_MASK,
-                                        (unsigned long)&mask);
-}
-
-/**
- * hpsb_iso_recv_flush - check for arrival of new packets
- *
- * check for arrival of new packets immediately (even if irq_interval
- * has not yet been reached)
- */
-int hpsb_iso_recv_flush(struct hpsb_iso *iso)
-{
-       if (iso->type != HPSB_ISO_RECV)
-               return -EINVAL;
-       return iso->host->driver->isoctl(iso, RECV_FLUSH, 0);
-}
-
-static int do_iso_xmit_start(struct hpsb_iso *iso, int cycle)
-{
-       int retval = iso->host->driver->isoctl(iso, XMIT_START, cycle);
-       if (retval)
-               return retval;
-
-       iso->flags |= HPSB_ISO_DRIVER_STARTED;
-       return retval;
-}
-
-/**
- * hpsb_iso_xmit_start - start DMA
- */
-int hpsb_iso_xmit_start(struct hpsb_iso *iso, int cycle, int prebuffer)
-{
-       if (iso->type != HPSB_ISO_XMIT)
-               return -1;
-
-       if (iso->flags & HPSB_ISO_DRIVER_STARTED)
-               return 0;
-
-       if (cycle < -1)
-               cycle = -1;
-       else if (cycle >= 8000)
-               cycle %= 8000;
-
-       iso->xmit_cycle = cycle;
-
-       if (prebuffer < 0)
-               prebuffer = iso->buf_packets - 1;
-       else if (prebuffer == 0)
-               prebuffer = 1;
-
-       if (prebuffer >= iso->buf_packets)
-               prebuffer = iso->buf_packets - 1;
-
-       iso->prebuffer = prebuffer;
-
-       /* remember the starting cycle; DMA will commence from xmit_queue_packets()
-          once enough packets have been buffered */
-       iso->start_cycle = cycle;
-
-       return 0;
-}
-
-/**
- * hpsb_iso_recv_start - start DMA
- */
-int hpsb_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
-{
-       int retval = 0;
-       int isoctl_args[3];
-
-       if (iso->type != HPSB_ISO_RECV)
-               return -1;
-
-       if (iso->flags & HPSB_ISO_DRIVER_STARTED)
-               return 0;
-
-       if (cycle < -1)
-               cycle = -1;
-       else if (cycle >= 8000)
-               cycle %= 8000;
-
-       isoctl_args[0] = cycle;
-
-       if (tag_mask < 0)
-               /* match all tags */
-               tag_mask = 0xF;
-       isoctl_args[1] = tag_mask;
-
-       isoctl_args[2] = sync;
-
-       retval =
-           iso->host->driver->isoctl(iso, RECV_START,
-                                     (unsigned long)&isoctl_args[0]);
-       if (retval)
-               return retval;
-
-       iso->flags |= HPSB_ISO_DRIVER_STARTED;
-       return retval;
-}
-
-/* check to make sure the user has not supplied bogus values of offset/len
- * that would cause the kernel to access memory outside the buffer */
-static int hpsb_iso_check_offset_len(struct hpsb_iso *iso,
-                                    unsigned int offset, unsigned short len,
-                                    unsigned int *out_offset,
-                                    unsigned short *out_len)
-{
-       if (offset >= iso->buf_size)
-               return -EFAULT;
-
-       /* make sure the packet does not go beyond the end of the buffer */
-       if (offset + len > iso->buf_size)
-               return -EFAULT;
-
-       /* check for wrap-around */
-       if (offset + len < offset)
-               return -EFAULT;
-
-       /* now we can trust 'offset' and 'length' */
-       *out_offset = offset;
-       *out_len = len;
-
-       return 0;
-}
-
-/**
- * hpsb_iso_xmit_queue_packet - queue a packet for transmission.
- *
- * @offset is relative to the beginning of the DMA buffer, where the packet's
- * data payload should already have been placed.
- */
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
-                              u8 tag, u8 sy)
-{
-       struct hpsb_iso_packet_info *info;
-       unsigned long flags;
-       int rv;
-
-       if (iso->type != HPSB_ISO_XMIT)
-               return -EINVAL;
-
-       /* is there space in the buffer? */
-       if (iso->n_ready_packets <= 0) {
-               return -EBUSY;
-       }
-
-       info = &iso->infos[iso->first_packet];
-
-       /* check for bogus offset/length */
-       if (hpsb_iso_check_offset_len
-           (iso, offset, len, &info->offset, &info->len))
-               return -EFAULT;
-
-       info->tag = tag;
-       info->sy = sy;
-
-       spin_lock_irqsave(&iso->lock, flags);
-
-       rv = iso->host->driver->isoctl(iso, XMIT_QUEUE, (unsigned long)info);
-       if (rv)
-               goto out;
-
-       /* increment cursors */
-       iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
-       iso->xmit_cycle = (iso->xmit_cycle + 1) % 8000;
-       iso->n_ready_packets--;
-
-       if (iso->prebuffer != 0) {
-               iso->prebuffer--;
-               if (iso->prebuffer <= 0) {
-                       iso->prebuffer = 0;
-                       rv = do_iso_xmit_start(iso, iso->start_cycle);
-               }
-       }
-
-      out:
-       spin_unlock_irqrestore(&iso->lock, flags);
-       return rv;
-}
-
-/**
- * hpsb_iso_xmit_sync - wait until all queued packets have been transmitted
- */
-int hpsb_iso_xmit_sync(struct hpsb_iso *iso)
-{
-       if (iso->type != HPSB_ISO_XMIT)
-               return -EINVAL;
-
-       return wait_event_interruptible(iso->waitq,
-                                       hpsb_iso_n_ready(iso) ==
-                                       iso->buf_packets);
-}
-
-/**
- * hpsb_iso_packet_sent
- *
- * Available to low-level drivers.
- *
- * Call after a packet has been transmitted to the bus (interrupt context is
- * OK).  @cycle is the _exact_ cycle the packet was sent on.  @error should be
- * non-zero if some sort of error occurred when sending the packet.
- */
-void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&iso->lock, flags);
-
-       /* predict the cycle of the next packet to be queued */
-
-       /* jump ahead by the number of packets that are already buffered */
-       cycle += iso->buf_packets - iso->n_ready_packets;
-       cycle %= 8000;
-
-       iso->xmit_cycle = cycle;
-       iso->n_ready_packets++;
-       iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
-
-       if (iso->n_ready_packets == iso->buf_packets || error != 0) {
-               /* the buffer has run empty! */
-               atomic_inc(&iso->overflows);
-       }
-
-       spin_unlock_irqrestore(&iso->lock, flags);
-}
-
-/**
- * hpsb_iso_packet_received
- *
- * Available to low-level drivers.
- *
- * Call after a packet has been received (interrupt context is OK).
- */
-void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
-                             u16 total_len, u16 cycle, u8 channel, u8 tag,
-                             u8 sy)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&iso->lock, flags);
-
-       if (iso->n_ready_packets == iso->buf_packets) {
-               /* overflow! */
-               atomic_inc(&iso->overflows);
-               /* Record size of this discarded packet */
-               iso->bytes_discarded += total_len;
-       } else {
-               struct hpsb_iso_packet_info *info = &iso->infos[iso->pkt_dma];
-               info->offset = offset;
-               info->len = len;
-               info->total_len = total_len;
-               info->cycle = cycle;
-               info->channel = channel;
-               info->tag = tag;
-               info->sy = sy;
-
-               iso->pkt_dma = (iso->pkt_dma + 1) % iso->buf_packets;
-               iso->n_ready_packets++;
-       }
-
-       spin_unlock_irqrestore(&iso->lock, flags);
-}
-
-/**
- * hpsb_iso_recv_release_packets - release packets, reuse buffer
- *
- * @n_packets have been read out of the buffer, re-use the buffer space
- */
-int hpsb_iso_recv_release_packets(struct hpsb_iso *iso, unsigned int n_packets)
-{
-       unsigned long flags;
-       unsigned int i;
-       int rv = 0;
-
-       if (iso->type != HPSB_ISO_RECV)
-               return -1;
-
-       spin_lock_irqsave(&iso->lock, flags);
-       for (i = 0; i < n_packets; i++) {
-               rv = iso->host->driver->isoctl(iso, RECV_RELEASE,
-                                              (unsigned long)&iso->infos[iso->
-                                                                         first_packet]);
-               if (rv)
-                       break;
-
-               iso->first_packet = (iso->first_packet + 1) % iso->buf_packets;
-               iso->n_ready_packets--;
-
-               /* release memory from packets discarded when queue was full  */
-               if (iso->n_ready_packets == 0) {        /* Release only after all prior packets handled */
-                       if (iso->bytes_discarded != 0) {
-                               struct hpsb_iso_packet_info inf;
-                               inf.total_len = iso->bytes_discarded;
-                               iso->host->driver->isoctl(iso, RECV_RELEASE,
-                                                         (unsigned long)&inf);
-                               iso->bytes_discarded = 0;
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&iso->lock, flags);
-       return rv;
-}
-
-/**
- * hpsb_iso_wake
- *
- * Available to low-level drivers.
- *
- * Call to wake waiting processes after buffer space has opened up.
- */
-void hpsb_iso_wake(struct hpsb_iso *iso)
-{
-       wake_up_interruptible(&iso->waitq);
-
-       if (iso->callback)
-               iso->callback(iso);
-}
diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h
deleted file mode 100644 (file)
index c2089c0..0000000
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * kernel ISO transmission/reception
- *
- * Copyright (C) 2002 Maas Digital LLC
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#ifndef IEEE1394_ISO_H
-#define IEEE1394_ISO_H
-
-#include <linux/spinlock_types.h>
-#include <linux/wait.h>
-#include <asm/atomic.h>
-#include <asm/types.h>
-
-#include "dma.h"
-
-struct hpsb_host;
-
-/* high-level ISO interface */
-
-/*
- * This API sends and receives isochronous packets on a large,
- * virtually-contiguous kernel memory buffer. The buffer may be mapped
- * into a user-space process for zero-copy transmission and reception.
- *
- * There are no explicit boundaries between packets in the buffer. A
- * packet may be transmitted or received at any location. However,
- * low-level drivers may impose certain restrictions on alignment or
- * size of packets. (e.g. in OHCI no packet may cross a page boundary,
- * and packets should be quadlet-aligned)
- */
-
-/* Packet descriptor - the API maintains a ring buffer of these packet
- * descriptors in kernel memory (hpsb_iso.infos[]).  */
-struct hpsb_iso_packet_info {
-       /* offset of data payload relative to the first byte of the buffer */
-       __u32 offset;
-
-       /* length of the data payload, in bytes (not including the isochronous
-        * header) */
-       __u16 len;
-
-       /* (recv only) the cycle number (mod 8000) on which the packet was
-        * received */
-       __u16 cycle;
-
-       /* (recv only) channel on which the packet was received */
-       __u8 channel;
-
-       /* 2-bit 'tag' and 4-bit 'sy' fields of the isochronous header */
-       __u8 tag;
-       __u8 sy;
-
-       /* length in bytes of the packet including header/trailer.
-        * MUST be at structure end, since the first part of this structure is
-        * also defined in raw1394.h (i.e. struct raw1394_iso_packet_info), is
-        * copied to userspace and is accessed there through libraw1394. */
-       __u16 total_len;
-};
-
-enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 };
-
-/* The mode of the dma when receiving iso data. Must be supported by chip */
-enum raw1394_iso_dma_recv_mode {
-       HPSB_ISO_DMA_DEFAULT = -1,
-       HPSB_ISO_DMA_OLD_ABI = 0,
-       HPSB_ISO_DMA_BUFFERFILL = 1,
-       HPSB_ISO_DMA_PACKET_PER_BUFFER = 2
-};
-
-struct hpsb_iso {
-       enum hpsb_iso_type type;
-
-       /* pointer to low-level driver and its private data */
-       struct hpsb_host *host;
-       void *hostdata;
-
-       /* a function to be called (from interrupt context) after
-        * outgoing packets have been sent, or incoming packets have
-        * arrived */
-       void (*callback)(struct hpsb_iso*);
-
-       /* wait for buffer space */
-       wait_queue_head_t waitq;
-
-       int speed; /* IEEE1394_SPEED_100, 200, or 400 */
-       int channel; /* -1 if multichannel */
-       int dma_mode; /* dma receive mode */
-
-
-       /* greatest # of packets between interrupts - controls
-        * the maximum latency of the buffer */
-       int irq_interval;
-
-       /* the buffer for packet data payloads */
-       struct dma_region data_buf;
-
-       /* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */
-       unsigned int buf_size;
-
-       /* # of packets in the ringbuffer */
-       unsigned int buf_packets;
-
-       /* protects packet cursors */
-       spinlock_t lock;
-
-       /* the index of the next packet that will be produced
-          or consumed by the user */
-       int first_packet;
-
-       /* the index of the next packet that will be transmitted
-          or received by the 1394 hardware */
-       int pkt_dma;
-
-       /* how many packets, starting at first_packet:
-        * (transmit) are ready to be filled with data
-        * (receive)  contain received data */
-       int n_ready_packets;
-
-       /* how many times the buffer has overflowed or underflowed */
-       atomic_t overflows;
-       /* how many cycles were skipped for a given context */
-       atomic_t skips;
-
-       /* Current number of bytes lost in discarded packets */
-       int bytes_discarded;
-
-       /* private flags to track initialization progress */
-#define HPSB_ISO_DRIVER_INIT     (1<<0)
-#define HPSB_ISO_DRIVER_STARTED  (1<<1)
-       unsigned int flags;
-
-       /* # of packets left to prebuffer (xmit only) */
-       int prebuffer;
-
-       /* starting cycle for DMA (xmit only) */
-       int start_cycle;
-
-       /* cycle at which next packet will be transmitted,
-        * -1 if not known */
-       int xmit_cycle;
-
-       /* ringbuffer of packet descriptors in regular kernel memory
-        * XXX Keep this last, since we use over-allocated memory from
-        * this entry to fill this field. */
-       struct hpsb_iso_packet_info *infos;
-};
-
-/* functions available to high-level drivers (e.g. raw1394) */
-
-struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int speed,
-                                   int irq_interval,
-                                   void (*callback)(struct hpsb_iso*));
-struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
-                                   unsigned int data_buf_size,
-                                   unsigned int buf_packets,
-                                   int channel,
-                                   int dma_mode,
-                                   int irq_interval,
-                                   void (*callback)(struct hpsb_iso*));
-int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel);
-int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel);
-int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask);
-int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle,
-                       int prebuffer);
-int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle,
-                       int tag_mask, int sync);
-void hpsb_iso_stop(struct hpsb_iso *iso);
-void hpsb_iso_shutdown(struct hpsb_iso *iso);
-int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len,
-                              u8 tag, u8 sy);
-int hpsb_iso_xmit_sync(struct hpsb_iso *iso);
-int hpsb_iso_recv_release_packets(struct hpsb_iso *recv,
-                                 unsigned int n_packets);
-int hpsb_iso_recv_flush(struct hpsb_iso *iso);
-int hpsb_iso_n_ready(struct hpsb_iso *iso);
-
-/* the following are callbacks available to low-level drivers */
-
-void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error);
-void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
-                             u16 total_len, u16 cycle, u8 channel, u8 tag,
-                             u8 sy);
-void hpsb_iso_wake(struct hpsb_iso *iso);
-
-#endif /* IEEE1394_ISO_H */
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
deleted file mode 100644 (file)
index 1835021..0000000
+++ /dev/null
@@ -1,1901 +0,0 @@
-/*
- * Node information (ConfigROM) collection and management.
- *
- * Copyright (C) 2000          Andreas E. Bombe
- *               2001-2003     Ben Collins <bcollins@debian.net>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- */
-
-#include <linux/bitmap.h>
-#include <linux/kernel.h>
-#include <linux/kmemcheck.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
-#include <linux/freezer.h>
-#include <asm/atomic.h>
-
-#include "csr.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_types.h"
-#include "ieee1394_transactions.h"
-#include "nodemgr.h"
-
-static int ignore_drivers;
-module_param(ignore_drivers, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ignore_drivers, "Disable automatic probing for drivers.");
-
-struct nodemgr_csr_info {
-       struct hpsb_host *host;
-       nodeid_t nodeid;
-       unsigned int generation;
-
-       kmemcheck_bitfield_begin(flags);
-       unsigned int speed_unverified:1;
-       kmemcheck_bitfield_end(flags);
-};
-
-
-/*
- * Correct the speed map entry.  This is necessary
- *  - for nodes with link speed < phy speed,
- *  - for 1394b nodes with negotiated phy port speed < IEEE1394_SPEED_MAX.
- * A possible speed is determined by trial and error, using quadlet reads.
- */
-static int nodemgr_check_speed(struct nodemgr_csr_info *ci, u64 addr,
-                              quadlet_t *buffer)
-{
-       quadlet_t q;
-       u8 i, *speed, old_speed, good_speed;
-       int error;
-
-       speed = &(ci->host->speed[NODEID_TO_NODE(ci->nodeid)]);
-       old_speed = *speed;
-       good_speed = IEEE1394_SPEED_MAX + 1;
-
-       /* Try every speed from S100 to old_speed.
-        * If we did it the other way around, a too low speed could be caught
-        * if the retry succeeded for some other reason, e.g. because the link
-        * just finished its initialization. */
-       for (i = IEEE1394_SPEED_100; i <= old_speed; i++) {
-               *speed = i;
-               error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                                 &q, 4);
-               if (error)
-                       break;
-               *buffer = q;
-               good_speed = i;
-       }
-       if (good_speed <= IEEE1394_SPEED_MAX) {
-               HPSB_DEBUG("Speed probe of node " NODE_BUS_FMT " yields %s",
-                          NODE_BUS_ARGS(ci->host, ci->nodeid),
-                          hpsb_speedto_str[good_speed]);
-               *speed = good_speed;
-               ci->speed_unverified = 0;
-               return 0;
-       }
-       *speed = old_speed;
-       return error;
-}
-
-static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr,
-                           void *buffer, void *__ci)
-{
-       struct nodemgr_csr_info *ci = (struct nodemgr_csr_info*)__ci;
-       int i, error;
-
-       for (i = 1; ; i++) {
-               error = hpsb_read(ci->host, ci->nodeid, ci->generation, addr,
-                                 buffer, 4);
-               if (!error) {
-                       ci->speed_unverified = 0;
-                       break;
-               }
-               /* Give up after 3rd failure. */
-               if (i == 3)
-                       break;
-
-               /* The ieee1394_core guessed the node's speed capability from
-                * the self ID.  Check whether a lower speed works. */
-               if (ci->speed_unverified) {
-                       error = nodemgr_check_speed(ci, addr, buffer);
-                       if (!error)
-                               break;
-               }
-               if (msleep_interruptible(334))
-                       return -EINTR;
-       }
-       return error;
-}
-
-static struct csr1212_bus_ops nodemgr_csr_ops = {
-       .bus_read =     nodemgr_bus_read,
-};
-
-
-/*
- * Basically what we do here is start off retrieving the bus_info block.
- * From there will fill in some info about the node, verify it is of IEEE
- * 1394 type, and that the crc checks out ok. After that we start off with
- * the root directory, and subdirectories. To do this, we retrieve the
- * quadlet header for a directory, find out the length, and retrieve the
- * complete directory entry (be it a leaf or a directory). We then process
- * it and add the info to our structure for that particular node.
- *
- * We verify CRC's along the way for each directory/block/leaf. The entire
- * node structure is generic, and simply stores the information in a way
- * that's easy to parse by the protocol interface.
- */
-
-/*
- * The nodemgr relies heavily on the Driver Model for device callbacks and
- * driver/device mappings. The old nodemgr used to handle all this itself,
- * but now we are much simpler because of the LDM.
- */
-
-struct host_info {
-       struct hpsb_host *host;
-       struct list_head list;
-       struct task_struct *thread;
-};
-
-static int nodemgr_bus_match(struct device * dev, struct device_driver * drv);
-static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env);
-
-struct bus_type ieee1394_bus_type = {
-       .name           = "ieee1394",
-       .match          = nodemgr_bus_match,
-};
-
-static void host_cls_release(struct device *dev)
-{
-       put_device(&container_of((dev), struct hpsb_host, host_dev)->device);
-}
-
-struct class hpsb_host_class = {
-       .name           = "ieee1394_host",
-       .dev_release    = host_cls_release,
-};
-
-static void ne_cls_release(struct device *dev)
-{
-       put_device(&container_of((dev), struct node_entry, node_dev)->device);
-}
-
-static struct class nodemgr_ne_class = {
-       .name           = "ieee1394_node",
-       .dev_release    = ne_cls_release,
-};
-
-static void ud_cls_release(struct device *dev)
-{
-       put_device(&container_of((dev), struct unit_directory, unit_dev)->device);
-}
-
-/* The name here is only so that unit directory hotplug works with old
- * style hotplug, which only ever did unit directories anyway.
- */
-static struct class nodemgr_ud_class = {
-       .name           = "ieee1394",
-       .dev_release    = ud_cls_release,
-       .dev_uevent     = nodemgr_uevent,
-};
-
-static struct hpsb_highlevel nodemgr_highlevel;
-
-
-static void nodemgr_release_ud(struct device *dev)
-{
-       struct unit_directory *ud = container_of(dev, struct unit_directory, device);
-
-       if (ud->vendor_name_kv)
-               csr1212_release_keyval(ud->vendor_name_kv);
-       if (ud->model_name_kv)
-               csr1212_release_keyval(ud->model_name_kv);
-
-       kfree(ud);
-}
-
-static void nodemgr_release_ne(struct device *dev)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-
-       if (ne->vendor_name_kv)
-               csr1212_release_keyval(ne->vendor_name_kv);
-
-       kfree(ne);
-}
-
-
-static void nodemgr_release_host(struct device *dev)
-{
-       struct hpsb_host *host = container_of(dev, struct hpsb_host, device);
-
-       csr1212_destroy_csr(host->csr.rom);
-
-       kfree(host);
-}
-
-static int nodemgr_ud_platform_data;
-
-static struct device nodemgr_dev_template_ud = {
-       .bus            = &ieee1394_bus_type,
-       .release        = nodemgr_release_ud,
-       .platform_data  = &nodemgr_ud_platform_data,
-};
-
-static struct device nodemgr_dev_template_ne = {
-       .bus            = &ieee1394_bus_type,
-       .release        = nodemgr_release_ne,
-};
-
-/* This dummy driver prevents the host devices from being scanned. We have no
- * useful drivers for them yet, and there would be a deadlock possible if the
- * driver core scans the host device while the host's low-level driver (i.e.
- * the host's parent device) is being removed. */
-static struct device_driver nodemgr_mid_layer_driver = {
-       .bus            = &ieee1394_bus_type,
-       .name           = "nodemgr",
-       .owner          = THIS_MODULE,
-};
-
-struct device nodemgr_dev_template_host = {
-       .bus            = &ieee1394_bus_type,
-       .release        = nodemgr_release_host,
-};
-
-
-#define fw_attr(class, class_type, field, type, format_string)         \
-static ssize_t fw_show_##class##_##field (struct device *dev, struct device_attribute *attr, char *buf)\
-{                                                                      \
-       class_type *class;                                              \
-       class = container_of(dev, class_type, device);                  \
-       return sprintf(buf, format_string, (type)class->field);         \
-}                                                                      \
-static struct device_attribute dev_attr_##class##_##field = {          \
-       .attr = {.name = __stringify(field), .mode = S_IRUGO },         \
-       .show   = fw_show_##class##_##field,                            \
-};
-
-#define fw_attr_td(class, class_type, td_kv)                           \
-static ssize_t fw_show_##class##_##td_kv (struct device *dev, struct device_attribute *attr, char *buf)\
-{                                                                      \
-       int len;                                                        \
-       class_type *class = container_of(dev, class_type, device);      \
-       len = (class->td_kv->value.leaf.len - 2) * sizeof(quadlet_t);   \
-       memcpy(buf,                                                     \
-              CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(class->td_kv),      \
-              len);                                                    \
-       while (buf[len - 1] == '\0')                                    \
-               len--;                                                  \
-       buf[len++] = '\n';                                              \
-       buf[len] = '\0';                                                \
-       return len;                                                     \
-}                                                                      \
-static struct device_attribute dev_attr_##class##_##td_kv = {          \
-       .attr = {.name = __stringify(td_kv), .mode = S_IRUGO },         \
-       .show   = fw_show_##class##_##td_kv,                            \
-};
-
-
-#define fw_drv_attr(field, type, format_string)                        \
-static ssize_t fw_drv_show_##field (struct device_driver *drv, char *buf) \
-{                                                              \
-       struct hpsb_protocol_driver *driver;                    \
-       driver = container_of(drv, struct hpsb_protocol_driver, driver); \
-       return sprintf(buf, format_string, (type)driver->field);\
-}                                                              \
-static struct driver_attribute driver_attr_drv_##field = {     \
-       .attr = {.name = __stringify(field), .mode = S_IRUGO }, \
-       .show   = fw_drv_show_##field,                          \
-};
-
-
-static ssize_t fw_show_ne_bus_options(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-
-       return sprintf(buf, "IRMC(%d) CMC(%d) ISC(%d) BMC(%d) PMC(%d) GEN(%d) "
-                      "LSPD(%d) MAX_REC(%d) MAX_ROM(%d) CYC_CLK_ACC(%d)\n",
-                      ne->busopt.irmc,
-                      ne->busopt.cmc, ne->busopt.isc, ne->busopt.bmc,
-                      ne->busopt.pmc, ne->busopt.generation, ne->busopt.lnkspd,
-                      ne->busopt.max_rec,
-                      ne->busopt.max_rom,
-                      ne->busopt.cyc_clk_acc);
-}
-static DEVICE_ATTR(bus_options,S_IRUGO,fw_show_ne_bus_options,NULL);
-
-
-#ifdef HPSB_DEBUG_TLABELS
-static ssize_t fw_show_ne_tlabels_free(struct device *dev,
-                                      struct device_attribute *attr, char *buf)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-       unsigned long flags;
-       unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
-       int tf;
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-       tf = 64 - bitmap_weight(tp, 64);
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       return sprintf(buf, "%d\n", tf);
-}
-static DEVICE_ATTR(tlabels_free,S_IRUGO,fw_show_ne_tlabels_free,NULL);
-
-
-static ssize_t fw_show_ne_tlabels_mask(struct device *dev,
-                                      struct device_attribute *attr, char *buf)
-{
-       struct node_entry *ne = container_of(dev, struct node_entry, device);
-       unsigned long flags;
-       unsigned long *tp = ne->host->tl_pool[NODEID_TO_NODE(ne->nodeid)].map;
-       u64 tm;
-
-       spin_lock_irqsave(&hpsb_tlabel_lock, flags);
-#if (BITS_PER_LONG <= 32)
-       tm = ((u64)tp[0] << 32) + tp[1];
-#else
-       tm = tp[0];
-#endif
-       spin_unlock_irqrestore(&hpsb_tlabel_lock, flags);
-
-       return sprintf(buf, "0x%016llx\n", (unsigned long long)tm);
-}
-static DEVICE_ATTR(tlabels_mask, S_IRUGO, fw_show_ne_tlabels_mask, NULL);
-#endif /* HPSB_DEBUG_TLABELS */
-
-
-static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
-{
-       struct unit_directory *ud = container_of(dev, struct unit_directory, device);
-       int state = simple_strtoul(buf, NULL, 10);
-
-       if (state == 1) {
-               ud->ignore_driver = 1;
-               device_release_driver(dev);
-       } else if (state == 0)
-               ud->ignore_driver = 0;
-
-       return count;
-}
-static ssize_t fw_get_ignore_driver(struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct unit_directory *ud = container_of(dev, struct unit_directory, device);
-
-       return sprintf(buf, "%d\n", ud->ignore_driver);
-}
-static DEVICE_ATTR(ignore_driver, S_IWUSR | S_IRUGO, fw_get_ignore_driver, fw_set_ignore_driver);
-
-
-static ssize_t fw_set_rescan(struct bus_type *bus, const char *buf,
-                            size_t count)
-{
-       int error = 0;
-
-       if (simple_strtoul(buf, NULL, 10) == 1)
-               error = bus_rescan_devices(&ieee1394_bus_type);
-       return error ? error : count;
-}
-static ssize_t fw_get_rescan(struct bus_type *bus, char *buf)
-{
-       return sprintf(buf, "You can force a rescan of the bus for "
-                       "drivers by writing a 1 to this file\n");
-}
-static BUS_ATTR(rescan, S_IWUSR | S_IRUGO, fw_get_rescan, fw_set_rescan);
-
-
-static ssize_t fw_set_ignore_drivers(struct bus_type *bus, const char *buf, size_t count)
-{
-       int state = simple_strtoul(buf, NULL, 10);
-
-       if (state == 1)
-               ignore_drivers = 1;
-       else if (state == 0)
-               ignore_drivers = 0;
-
-       return count;
-}
-static ssize_t fw_get_ignore_drivers(struct bus_type *bus, char *buf)
-{
-       return sprintf(buf, "%d\n", ignore_drivers);
-}
-static BUS_ATTR(ignore_drivers, S_IWUSR | S_IRUGO, fw_get_ignore_drivers, fw_set_ignore_drivers);
-
-
-struct bus_attribute *const fw_bus_attrs[] = {
-       &bus_attr_rescan,
-       &bus_attr_ignore_drivers,
-       NULL
-};
-
-
-fw_attr(ne, struct node_entry, capabilities, unsigned int, "0x%06x\n")
-fw_attr(ne, struct node_entry, nodeid, unsigned int, "0x%04x\n")
-
-fw_attr(ne, struct node_entry, vendor_id, unsigned int, "0x%06x\n")
-fw_attr_td(ne, struct node_entry, vendor_name_kv)
-
-fw_attr(ne, struct node_entry, guid, unsigned long long, "0x%016Lx\n")
-fw_attr(ne, struct node_entry, guid_vendor_id, unsigned int, "0x%06x\n")
-fw_attr(ne, struct node_entry, in_limbo, int, "%d\n");
-
-static struct device_attribute *const fw_ne_attrs[] = {
-       &dev_attr_ne_guid,
-       &dev_attr_ne_guid_vendor_id,
-       &dev_attr_ne_capabilities,
-       &dev_attr_ne_vendor_id,
-       &dev_attr_ne_nodeid,
-       &dev_attr_bus_options,
-#ifdef HPSB_DEBUG_TLABELS
-       &dev_attr_tlabels_free,
-       &dev_attr_tlabels_mask,
-#endif
-};
-
-
-
-fw_attr(ud, struct unit_directory, address, unsigned long long, "0x%016Lx\n")
-fw_attr(ud, struct unit_directory, length, int, "%d\n")
-/* These are all dependent on the value being provided */
-fw_attr(ud, struct unit_directory, vendor_id, unsigned int, "0x%06x\n")
-fw_attr(ud, struct unit_directory, model_id, unsigned int, "0x%06x\n")
-fw_attr(ud, struct unit_directory, specifier_id, unsigned int, "0x%06x\n")
-fw_attr(ud, struct unit_directory, version, unsigned int, "0x%06x\n")
-fw_attr_td(ud, struct unit_directory, vendor_name_kv)
-fw_attr_td(ud, struct unit_directory, model_name_kv)
-
-static struct device_attribute *const fw_ud_attrs[] = {
-       &dev_attr_ud_address,
-       &dev_attr_ud_length,
-       &dev_attr_ignore_driver,
-};
-
-
-fw_attr(host, struct hpsb_host, node_count, int, "%d\n")
-fw_attr(host, struct hpsb_host, selfid_count, int, "%d\n")
-fw_attr(host, struct hpsb_host, nodes_active, int, "%d\n")
-fw_attr(host, struct hpsb_host, in_bus_reset, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_root, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_cycmst, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_irm, int, "%d\n")
-fw_attr(host, struct hpsb_host, is_busmgr, int, "%d\n")
-
-static struct device_attribute *const fw_host_attrs[] = {
-       &dev_attr_host_node_count,
-       &dev_attr_host_selfid_count,
-       &dev_attr_host_nodes_active,
-       &dev_attr_host_in_bus_reset,
-       &dev_attr_host_is_root,
-       &dev_attr_host_is_cycmst,
-       &dev_attr_host_is_irm,
-       &dev_attr_host_is_busmgr,
-};
-
-
-static ssize_t fw_show_drv_device_ids(struct device_driver *drv, char *buf)
-{
-       struct hpsb_protocol_driver *driver;
-       const struct ieee1394_device_id *id;
-       int length = 0;
-       char *scratch = buf;
-
-       driver = container_of(drv, struct hpsb_protocol_driver, driver);
-       id = driver->id_table;
-       if (!id)
-               return 0;
-
-       for (; id->match_flags != 0; id++) {
-               int need_coma = 0;
-
-               if (id->match_flags & IEEE1394_MATCH_VENDOR_ID) {
-                       length += sprintf(scratch, "vendor_id=0x%06x", id->vendor_id);
-                       scratch = buf + length;
-                       need_coma++;
-               }
-
-               if (id->match_flags & IEEE1394_MATCH_MODEL_ID) {
-                       length += sprintf(scratch, "%smodel_id=0x%06x",
-                                         need_coma++ ? "," : "",
-                                         id->model_id);
-                       scratch = buf + length;
-               }
-
-               if (id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) {
-                       length += sprintf(scratch, "%sspecifier_id=0x%06x",
-                                         need_coma++ ? "," : "",
-                                         id->specifier_id);
-                       scratch = buf + length;
-               }
-
-               if (id->match_flags & IEEE1394_MATCH_VERSION) {
-                       length += sprintf(scratch, "%sversion=0x%06x",
-                                         need_coma++ ? "," : "",
-                                         id->version);
-                       scratch = buf + length;
-               }
-
-               if (need_coma) {
-                       *scratch++ = '\n';
-                       length++;
-               }
-       }
-
-       return length;
-}
-static DRIVER_ATTR(device_ids,S_IRUGO,fw_show_drv_device_ids,NULL);
-
-
-fw_drv_attr(name, const char *, "%s\n")
-
-static struct driver_attribute *const fw_drv_attrs[] = {
-       &driver_attr_drv_name,
-       &driver_attr_device_ids,
-};
-
-
-static void nodemgr_create_drv_files(struct hpsb_protocol_driver *driver)
-{
-       struct device_driver *drv = &driver->driver;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++)
-               if (driver_create_file(drv, fw_drv_attrs[i]))
-                       goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static void nodemgr_remove_drv_files(struct hpsb_protocol_driver *driver)
-{
-       struct device_driver *drv = &driver->driver;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_drv_attrs); i++)
-               driver_remove_file(drv, fw_drv_attrs[i]);
-}
-
-
-static void nodemgr_create_ne_dev_files(struct node_entry *ne)
-{
-       struct device *dev = &ne->device;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_ne_attrs); i++)
-               if (device_create_file(dev, fw_ne_attrs[i]))
-                       goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static void nodemgr_create_host_dev_files(struct hpsb_host *host)
-{
-       struct device *dev = &host->device;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_host_attrs); i++)
-               if (device_create_file(dev, fw_host_attrs[i]))
-                       goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
-                                              nodeid_t nodeid);
-
-static void nodemgr_update_host_dev_links(struct hpsb_host *host)
-{
-       struct device *dev = &host->device;
-       struct node_entry *ne;
-
-       sysfs_remove_link(&dev->kobj, "irm_id");
-       sysfs_remove_link(&dev->kobj, "busmgr_id");
-       sysfs_remove_link(&dev->kobj, "host_id");
-
-       if ((ne = find_entry_by_nodeid(host, host->irm_id)) &&
-           sysfs_create_link(&dev->kobj, &ne->device.kobj, "irm_id"))
-               goto fail;
-       if ((ne = find_entry_by_nodeid(host, host->busmgr_id)) &&
-           sysfs_create_link(&dev->kobj, &ne->device.kobj, "busmgr_id"))
-               goto fail;
-       if ((ne = find_entry_by_nodeid(host, host->node_id)) &&
-           sysfs_create_link(&dev->kobj, &ne->device.kobj, "host_id"))
-               goto fail;
-       return;
-fail:
-       HPSB_ERR("Failed to update sysfs attributes for host %d", host->id);
-}
-
-static void nodemgr_create_ud_dev_files(struct unit_directory *ud)
-{
-       struct device *dev = &ud->device;
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(fw_ud_attrs); i++)
-               if (device_create_file(dev, fw_ud_attrs[i]))
-                       goto fail;
-       if (ud->flags & UNIT_DIRECTORY_SPECIFIER_ID)
-               if (device_create_file(dev, &dev_attr_ud_specifier_id))
-                       goto fail;
-       if (ud->flags & UNIT_DIRECTORY_VERSION)
-               if (device_create_file(dev, &dev_attr_ud_version))
-                       goto fail;
-       if (ud->flags & UNIT_DIRECTORY_VENDOR_ID) {
-               if (device_create_file(dev, &dev_attr_ud_vendor_id))
-                       goto fail;
-               if (ud->vendor_name_kv &&
-                   device_create_file(dev, &dev_attr_ud_vendor_name_kv))
-                       goto fail;
-       }
-       if (ud->flags & UNIT_DIRECTORY_MODEL_ID) {
-               if (device_create_file(dev, &dev_attr_ud_model_id))
-                       goto fail;
-               if (ud->model_name_kv &&
-                   device_create_file(dev, &dev_attr_ud_model_name_kv))
-                       goto fail;
-       }
-       return;
-fail:
-       HPSB_ERR("Failed to add sysfs attribute");
-}
-
-
-static int nodemgr_bus_match(struct device * dev, struct device_driver * drv)
-{
-       struct hpsb_protocol_driver *driver;
-       struct unit_directory *ud;
-       const struct ieee1394_device_id *id;
-
-       /* We only match unit directories */
-       if (dev->platform_data != &nodemgr_ud_platform_data)
-               return 0;
-
-       ud = container_of(dev, struct unit_directory, device);
-       if (ud->ne->in_limbo || ud->ignore_driver)
-               return 0;
-
-       /* We only match drivers of type hpsb_protocol_driver */
-       if (drv == &nodemgr_mid_layer_driver)
-               return 0;
-
-       driver = container_of(drv, struct hpsb_protocol_driver, driver);
-       id = driver->id_table;
-       if (!id)
-               return 0;
-
-       for (; id->match_flags != 0; id++) {
-               if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&
-                   id->vendor_id != ud->vendor_id)
-                       continue;
-
-               if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&
-                   id->model_id != ud->model_id)
-                       continue;
-
-               if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&
-                   id->specifier_id != ud->specifier_id)
-                       continue;
-
-               if ((id->match_flags & IEEE1394_MATCH_VERSION) &&
-                   id->version != ud->version)
-                       continue;
-
-               return 1;
-       }
-
-       return 0;
-}
-
-
-static DEFINE_MUTEX(nodemgr_serialize_remove_uds);
-
-static int match_ne(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct node_entry *ne = data;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       return ud->ne == ne;
-}
-
-static void nodemgr_remove_uds(struct node_entry *ne)
-{
-       struct device *dev;
-       struct unit_directory *ud;
-
-       /* Use class_find device to iterate the devices. Since this code
-        * may be called from other contexts besides the knodemgrds,
-        * protect it by nodemgr_serialize_remove_uds.
-        */
-       mutex_lock(&nodemgr_serialize_remove_uds);
-       for (;;) {
-               dev = class_find_device(&nodemgr_ud_class, NULL, ne, match_ne);
-               if (!dev)
-                       break;
-               ud = container_of(dev, struct unit_directory, unit_dev);
-               put_device(dev);
-               device_unregister(&ud->unit_dev);
-               device_unregister(&ud->device);
-       }
-       mutex_unlock(&nodemgr_serialize_remove_uds);
-}
-
-
-static void nodemgr_remove_ne(struct node_entry *ne)
-{
-       struct device *dev;
-
-       dev = get_device(&ne->device);
-       if (!dev)
-               return;
-
-       HPSB_DEBUG("Node removed: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);
-       nodemgr_remove_uds(ne);
-
-       device_unregister(&ne->node_dev);
-       device_unregister(dev);
-
-       put_device(dev);
-}
-
-static int remove_host_dev(struct device *dev, void *data)
-{
-       if (dev->bus == &ieee1394_bus_type)
-               nodemgr_remove_ne(container_of(dev, struct node_entry,
-                                 device));
-       return 0;
-}
-
-static void nodemgr_remove_host_dev(struct device *dev)
-{
-       device_for_each_child(dev, NULL, remove_host_dev);
-       sysfs_remove_link(&dev->kobj, "irm_id");
-       sysfs_remove_link(&dev->kobj, "busmgr_id");
-       sysfs_remove_link(&dev->kobj, "host_id");
-}
-
-
-static void nodemgr_update_bus_options(struct node_entry *ne)
-{
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-       static const u16 mr[] = { 4, 64, 1024, 0};
-#endif
-       quadlet_t busoptions = be32_to_cpu(ne->csr->bus_info_data[2]);
-
-       ne->busopt.irmc         = (busoptions >> 31) & 1;
-       ne->busopt.cmc          = (busoptions >> 30) & 1;
-       ne->busopt.isc          = (busoptions >> 29) & 1;
-       ne->busopt.bmc          = (busoptions >> 28) & 1;
-       ne->busopt.pmc          = (busoptions >> 27) & 1;
-       ne->busopt.cyc_clk_acc  = (busoptions >> 16) & 0xff;
-       ne->busopt.max_rec      = 1 << (((busoptions >> 12) & 0xf) + 1);
-       ne->busopt.max_rom      = (busoptions >> 8) & 0x3;
-       ne->busopt.generation   = (busoptions >> 4) & 0xf;
-       ne->busopt.lnkspd       = busoptions & 0x7;
-
-       HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "
-                    "cyc_clk_acc=%d max_rec=%d max_rom=%d gen=%d lspd=%d",
-                    busoptions, ne->busopt.irmc, ne->busopt.cmc,
-                    ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,
-                    ne->busopt.cyc_clk_acc, ne->busopt.max_rec,
-                    mr[ne->busopt.max_rom],
-                    ne->busopt.generation, ne->busopt.lnkspd);
-}
-
-
-static struct node_entry *nodemgr_create_node(octlet_t guid,
-                               struct csr1212_csr *csr, struct hpsb_host *host,
-                               nodeid_t nodeid, unsigned int generation)
-{
-       struct node_entry *ne;
-
-       ne = kzalloc(sizeof(*ne), GFP_KERNEL);
-       if (!ne)
-               goto fail_alloc;
-
-       ne->host = host;
-       ne->nodeid = nodeid;
-       ne->generation = generation;
-       ne->needs_probe = true;
-
-       ne->guid = guid;
-       ne->guid_vendor_id = (guid >> 40) & 0xffffff;
-       ne->csr = csr;
-
-       memcpy(&ne->device, &nodemgr_dev_template_ne,
-              sizeof(ne->device));
-       ne->device.parent = &host->device;
-       dev_set_name(&ne->device, "%016Lx", (unsigned long long)(ne->guid));
-
-       ne->node_dev.parent = &ne->device;
-       ne->node_dev.class = &nodemgr_ne_class;
-       dev_set_name(&ne->node_dev, "%016Lx", (unsigned long long)(ne->guid));
-
-       if (device_register(&ne->device))
-               goto fail_devreg;
-       if (device_register(&ne->node_dev))
-               goto fail_classdevreg;
-       get_device(&ne->device);
-
-       nodemgr_create_ne_dev_files(ne);
-
-       nodemgr_update_bus_options(ne);
-
-       HPSB_DEBUG("%s added: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  (host->node_id == nodeid) ? "Host" : "Node",
-                  NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
-
-       return ne;
-
-fail_classdevreg:
-       device_unregister(&ne->device);
-fail_devreg:
-       kfree(ne);
-fail_alloc:
-       HPSB_ERR("Failed to create node ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                NODE_BUS_ARGS(host, nodeid), (unsigned long long)guid);
-
-       return NULL;
-}
-
-static int match_ne_guid(struct device *dev, void *data)
-{
-       struct node_entry *ne;
-       u64 *guid = data;
-
-       ne = container_of(dev, struct node_entry, node_dev);
-       return ne->guid == *guid;
-}
-
-static struct node_entry *find_entry_by_guid(u64 guid)
-{
-       struct device *dev;
-       struct node_entry *ne;
-
-       dev = class_find_device(&nodemgr_ne_class, NULL, &guid, match_ne_guid);
-       if (!dev)
-               return NULL;
-       ne = container_of(dev, struct node_entry, node_dev);
-       put_device(dev);
-
-       return ne;
-}
-
-struct match_nodeid_parameter {
-       struct hpsb_host *host;
-       nodeid_t nodeid;
-};
-
-static int match_ne_nodeid(struct device *dev, void *data)
-{
-       int found = 0;
-       struct node_entry *ne;
-       struct match_nodeid_parameter *p = data;
-
-       if (!dev)
-               goto ret;
-       ne = container_of(dev, struct node_entry, node_dev);
-       if (ne->host == p->host && ne->nodeid == p->nodeid)
-               found = 1;
-ret:
-       return found;
-}
-
-static struct node_entry *find_entry_by_nodeid(struct hpsb_host *host,
-                                              nodeid_t nodeid)
-{
-       struct device *dev;
-       struct node_entry *ne;
-       struct match_nodeid_parameter p;
-
-       p.host = host;
-       p.nodeid = nodeid;
-
-       dev = class_find_device(&nodemgr_ne_class, NULL, &p, match_ne_nodeid);
-       if (!dev)
-               return NULL;
-       ne = container_of(dev, struct node_entry, node_dev);
-       put_device(dev);
-
-       return ne;
-}
-
-
-static void nodemgr_register_device(struct node_entry *ne, 
-       struct unit_directory *ud, struct device *parent)
-{
-       memcpy(&ud->device, &nodemgr_dev_template_ud,
-              sizeof(ud->device));
-
-       ud->device.parent = parent;
-
-       dev_set_name(&ud->device, "%s-%u", dev_name(&ne->device), ud->id);
-
-       ud->unit_dev.parent = &ud->device;
-       ud->unit_dev.class = &nodemgr_ud_class;
-       dev_set_name(&ud->unit_dev, "%s-%u", dev_name(&ne->device), ud->id);
-
-       if (device_register(&ud->device))
-               goto fail_devreg;
-       if (device_register(&ud->unit_dev))
-               goto fail_classdevreg;
-       get_device(&ud->device);
-
-       nodemgr_create_ud_dev_files(ud);
-
-       return;
-
-fail_classdevreg:
-       device_unregister(&ud->device);
-fail_devreg:
-       HPSB_ERR("Failed to create unit %s", dev_name(&ud->device));
-}      
-
-
-/* This implementation currently only scans the config rom and its
- * immediate unit directories looking for software_id and
- * software_version entries, in order to get driver autoloading working. */
-static struct unit_directory *nodemgr_process_unit_directory
-       (struct node_entry *ne, struct csr1212_keyval *ud_kv,
-        unsigned int *id, struct unit_directory *parent)
-{
-       struct unit_directory *ud;
-       struct unit_directory *ud_child = NULL;
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *kv;
-       u8 last_key_id = 0;
-
-       ud = kzalloc(sizeof(*ud), GFP_KERNEL);
-       if (!ud)
-               goto unit_directory_error;
-
-       ud->ne = ne;
-       ud->ignore_driver = ignore_drivers;
-       ud->address = ud_kv->offset + CSR1212_REGISTER_SPACE_BASE;
-       ud->directory_id = ud->address & 0xffffff;
-       ud->ud_kv = ud_kv;
-       ud->id = (*id)++;
-
-       /* inherit vendor_id from root directory if none exists in unit dir */
-       ud->vendor_id = ne->vendor_id;
-
-       csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {
-               switch (kv->key.id) {
-               case CSR1212_KV_ID_VENDOR:
-                       if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
-                               ud->vendor_id = kv->value.immediate;
-                               ud->flags |= UNIT_DIRECTORY_VENDOR_ID;
-                       }
-                       break;
-
-               case CSR1212_KV_ID_MODEL:
-                       ud->model_id = kv->value.immediate;
-                       ud->flags |= UNIT_DIRECTORY_MODEL_ID;
-                       break;
-
-               case CSR1212_KV_ID_SPECIFIER_ID:
-                       ud->specifier_id = kv->value.immediate;
-                       ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID;
-                       break;
-
-               case CSR1212_KV_ID_VERSION:
-                       ud->version = kv->value.immediate;
-                       ud->flags |= UNIT_DIRECTORY_VERSION;
-                       break;
-
-               case CSR1212_KV_ID_DESCRIPTOR:
-                       if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
-                           CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
-                           CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
-                           CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
-                           CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
-                           CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
-                               switch (last_key_id) {
-                               case CSR1212_KV_ID_VENDOR:
-                                       csr1212_keep_keyval(kv);
-                                       ud->vendor_name_kv = kv;
-                                       break;
-
-                               case CSR1212_KV_ID_MODEL:
-                                       csr1212_keep_keyval(kv);
-                                       ud->model_name_kv = kv;
-                                       break;
-
-                               }
-                       } /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */
-                       break;
-
-               case CSR1212_KV_ID_DEPENDENT_INFO:
-                       /* Logical Unit Number */
-                       if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
-                               if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
-                                       ud_child = kmemdup(ud, sizeof(*ud_child), GFP_KERNEL);
-                                       if (!ud_child)
-                                               goto unit_directory_error;
-                                       nodemgr_register_device(ne, ud_child, &ne->device);
-                                       ud_child = NULL;
-                                       
-                                       ud->id = (*id)++;
-                               }
-                               ud->lun = kv->value.immediate;
-                               ud->flags |= UNIT_DIRECTORY_HAS_LUN;
-
-                       /* Logical Unit Directory */
-                       } else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
-                               /* This should really be done in SBP2 as this is
-                                * doing SBP2 specific parsing.
-                                */
-                               
-                               /* first register the parent unit */
-                               ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
-                               if (ud->device.bus != &ieee1394_bus_type)
-                                       nodemgr_register_device(ne, ud, &ne->device);
-                               
-                               /* process the child unit */
-                               ud_child = nodemgr_process_unit_directory(ne, kv, id, ud);
-
-                               if (ud_child == NULL)
-                                       break;
-                               
-                               /* inherit unspecified values, the driver core picks it up */
-                               if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
-                                   !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
-                               {
-                                       ud_child->flags |=  UNIT_DIRECTORY_MODEL_ID;
-                                       ud_child->model_id = ud->model_id;
-                               }
-                               if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
-                                   !(ud_child->flags & UNIT_DIRECTORY_SPECIFIER_ID))
-                               {
-                                       ud_child->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;
-                                       ud_child->specifier_id = ud->specifier_id;
-                               }
-                               if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
-                                   !(ud_child->flags & UNIT_DIRECTORY_VERSION))
-                               {
-                                       ud_child->flags |=  UNIT_DIRECTORY_VERSION;
-                                       ud_child->version = ud->version;
-                               }
-                               
-                               /* register the child unit */
-                               ud_child->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
-                               nodemgr_register_device(ne, ud_child, &ud->device);
-                       }
-
-                       break;
-
-               case CSR1212_KV_ID_DIRECTORY_ID:
-                       ud->directory_id = kv->value.immediate;
-                       break;
-
-               default:
-                       break;
-               }
-               last_key_id = kv->key.id;
-       }
-       
-       /* do not process child units here and only if not already registered */
-       if (!parent && ud->device.bus != &ieee1394_bus_type)
-               nodemgr_register_device(ne, ud, &ne->device);
-
-       return ud;
-
-unit_directory_error:
-       kfree(ud);
-       return NULL;
-}
-
-
-static void nodemgr_process_root_directory(struct node_entry *ne)
-{
-       unsigned int ud_id = 0;
-       struct csr1212_dentry *dentry;
-       struct csr1212_keyval *kv, *vendor_name_kv = NULL;
-       u8 last_key_id = 0;
-
-       ne->needs_probe = false;
-
-       csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) {
-               switch (kv->key.id) {
-               case CSR1212_KV_ID_VENDOR:
-                       ne->vendor_id = kv->value.immediate;
-                       break;
-
-               case CSR1212_KV_ID_NODE_CAPABILITIES:
-                       ne->capabilities = kv->value.immediate;
-                       break;
-
-               case CSR1212_KV_ID_UNIT:
-                       nodemgr_process_unit_directory(ne, kv, &ud_id, NULL);
-                       break;
-
-               case CSR1212_KV_ID_DESCRIPTOR:
-                       if (last_key_id == CSR1212_KV_ID_VENDOR) {
-                               if (kv->key.type == CSR1212_KV_TYPE_LEAF &&
-                                   CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&
-                                   CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&
-                                   CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&
-                                   CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&
-                                   CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {
-                                       csr1212_keep_keyval(kv);
-                                       vendor_name_kv = kv;
-                               }
-                       }
-                       break;
-               }
-               last_key_id = kv->key.id;
-       }
-
-       if (ne->vendor_name_kv) {
-               kv = ne->vendor_name_kv;
-               ne->vendor_name_kv = vendor_name_kv;
-               csr1212_release_keyval(kv);
-       } else if (vendor_name_kv) {
-               ne->vendor_name_kv = vendor_name_kv;
-               if (device_create_file(&ne->device,
-                                      &dev_attr_ne_vendor_name_kv) != 0)
-                       HPSB_ERR("Failed to add sysfs attribute");
-       }
-}
-
-#ifdef CONFIG_HOTPLUG
-
-static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       struct unit_directory *ud;
-       int retval = 0;
-       /* ieee1394:venNmoNspNverN */
-       char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
-
-       if (!dev)
-               return -ENODEV;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-
-       if (ud->ne->in_limbo || ud->ignore_driver)
-               return -ENODEV;
-
-#define PUT_ENVP(fmt,val)                                      \
-do {                                                           \
-       retval = add_uevent_var(env, fmt, val);         \
-       if (retval)                                             \
-               return retval;                                  \
-} while (0)
-
-       PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id);
-       PUT_ENVP("MODEL_ID=%06x", ud->model_id);
-       PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid);
-       PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id);
-       PUT_ENVP("VERSION=%06x", ud->version);
-       snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",
-                       ud->vendor_id,
-                       ud->model_id,
-                       ud->specifier_id,
-                       ud->version);
-       PUT_ENVP("MODALIAS=%s", buf);
-
-#undef PUT_ENVP
-
-       return 0;
-}
-
-#else
-
-static int nodemgr_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
-       return -ENODEV;
-}
-
-#endif /* CONFIG_HOTPLUG */
-
-
-int __hpsb_register_protocol(struct hpsb_protocol_driver *drv,
-                            struct module *owner)
-{
-       int error;
-
-       drv->driver.bus = &ieee1394_bus_type;
-       drv->driver.owner = owner;
-       drv->driver.name = drv->name;
-
-       /* This will cause a probe for devices */
-       error = driver_register(&drv->driver);
-       if (!error)
-               nodemgr_create_drv_files(drv);
-       return error;
-}
-
-void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver)
-{
-       nodemgr_remove_drv_files(driver);
-       /* This will subsequently disconnect all devices that our driver
-        * is attached to. */
-       driver_unregister(&driver->driver);
-}
-
-
-/*
- * This function updates nodes that were present on the bus before the
- * reset and still are after the reset.  The nodeid and the config rom
- * may have changed, and the drivers managing this device must be
- * informed that this device just went through a bus reset, to allow
- * the to take whatever actions required.
- */
-static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,
-                               nodeid_t nodeid, unsigned int generation)
-{
-       if (ne->nodeid != nodeid) {
-               HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,
-                          NODE_BUS_ARGS(ne->host, ne->nodeid),
-                          NODE_BUS_ARGS(ne->host, nodeid));
-               ne->nodeid = nodeid;
-       }
-
-       if (ne->busopt.generation != ((be32_to_cpu(csr->bus_info_data[2]) >> 4) & 0xf)) {
-               kfree(ne->csr->private);
-               csr1212_destroy_csr(ne->csr);
-               ne->csr = csr;
-
-               /* If the node's configrom generation has changed, we
-                * unregister all the unit directories. */
-               nodemgr_remove_uds(ne);
-
-               nodemgr_update_bus_options(ne);
-
-               /* Mark the node as new, so it gets re-probed */
-               ne->needs_probe = true;
-       } else {
-               /* old cache is valid, so update its generation */
-               struct nodemgr_csr_info *ci = ne->csr->private;
-               ci->generation = generation;
-               /* free the partially filled now unneeded new cache */
-               kfree(csr->private);
-               csr1212_destroy_csr(csr);
-       }
-
-       /* Finally, mark the node current */
-       smp_wmb();
-       ne->generation = generation;
-
-       if (ne->in_limbo) {
-               device_remove_file(&ne->device, &dev_attr_ne_in_limbo);
-               ne->in_limbo = false;
-
-               HPSB_DEBUG("Node reactivated: "
-                          "ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                          NODE_BUS_ARGS(ne->host, ne->nodeid),
-                          (unsigned long long)ne->guid);
-       }
-}
-
-static void nodemgr_node_scan_one(struct hpsb_host *host,
-                                 nodeid_t nodeid, int generation)
-{
-       struct node_entry *ne;
-       octlet_t guid;
-       struct csr1212_csr *csr;
-       struct nodemgr_csr_info *ci;
-       u8 *speed;
-
-       ci = kmalloc(sizeof(*ci), GFP_KERNEL);
-       kmemcheck_annotate_bitfield(ci, flags);
-       if (!ci)
-               return;
-
-       ci->host = host;
-       ci->nodeid = nodeid;
-       ci->generation = generation;
-
-       /* Prepare for speed probe which occurs when reading the ROM */
-       speed = &(host->speed[NODEID_TO_NODE(nodeid)]);
-       if (*speed > host->csr.lnk_spd)
-               *speed = host->csr.lnk_spd;
-       ci->speed_unverified = *speed > IEEE1394_SPEED_100;
-
-       /* We need to detect when the ConfigROM's generation has changed,
-        * so we only update the node's info when it needs to be.  */
-
-       csr = csr1212_create_csr(&nodemgr_csr_ops, 5 * sizeof(quadlet_t), ci);
-       if (!csr || csr1212_parse_csr(csr) != CSR1212_SUCCESS) {
-               HPSB_ERR("Error parsing configrom for node " NODE_BUS_FMT,
-                        NODE_BUS_ARGS(host, nodeid));
-               if (csr)
-                       csr1212_destroy_csr(csr);
-               kfree(ci);
-               return;
-       }
-
-       if (csr->bus_info_data[1] != IEEE1394_BUSID_MAGIC) {
-               /* This isn't a 1394 device, but we let it slide. There
-                * was a report of a device with broken firmware which
-                * reported '2394' instead of '1394', which is obviously a
-                * mistake. One would hope that a non-1394 device never
-                * gets connected to Firewire bus. If someone does, we
-                * shouldn't be held responsible, so we'll allow it with a
-                * warning.  */
-               HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]",
-                         NODE_BUS_ARGS(host, nodeid), csr->bus_info_data[1]);
-       }
-
-       guid = ((u64)be32_to_cpu(csr->bus_info_data[3]) << 32) | be32_to_cpu(csr->bus_info_data[4]);
-       ne = find_entry_by_guid(guid);
-
-       if (ne && ne->host != host && ne->in_limbo) {
-               /* Must have moved this device from one host to another */
-               nodemgr_remove_ne(ne);
-               ne = NULL;
-       }
-
-       if (!ne)
-               nodemgr_create_node(guid, csr, host, nodeid, generation);
-       else
-               nodemgr_update_node(ne, csr, nodeid, generation);
-}
-
-
-static void nodemgr_node_scan(struct hpsb_host *host, int generation)
-{
-       int count;
-       struct selfid *sid = (struct selfid *)host->topology_map;
-       nodeid_t nodeid = LOCAL_BUS;
-
-       /* Scan each node on the bus */
-       for (count = host->selfid_count; count; count--, sid++) {
-               if (sid->extended)
-                       continue;
-
-               if (!sid->link_active) {
-                       nodeid++;
-                       continue;
-               }
-               nodemgr_node_scan_one(host, nodeid++, generation);
-       }
-}
-
-static void nodemgr_pause_ne(struct node_entry *ne)
-{
-       HPSB_DEBUG("Node paused: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",
-                  NODE_BUS_ARGS(ne->host, ne->nodeid),
-                  (unsigned long long)ne->guid);
-
-       ne->in_limbo = true;
-       WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));
-}
-
-static int update_pdrv(struct device *dev, void *data)
-{
-       struct unit_directory *ud;
-       struct device_driver *drv;
-       struct hpsb_protocol_driver *pdrv;
-       struct node_entry *ne = data;
-       int error;
-
-       ud = container_of(dev, struct unit_directory, unit_dev);
-       if (ud->ne == ne) {
-               drv = get_driver(ud->device.driver);
-               if (drv) {
-                       error = 0;
-                       pdrv = container_of(drv, struct hpsb_protocol_driver,
-                                           driver);
-                       if (pdrv->update) {
-                               device_lock(&ud->device);
-                               error = pdrv->update(ud);
-                               device_unlock(&ud->device);
-                       }
-                       if (error)
-                               device_release_driver(&ud->device);
-                       put_driver(drv);
-               }
-       }
-
-       return 0;
-}
-
-static void nodemgr_update_pdrv(struct node_entry *ne)
-{
-       class_for_each_device(&nodemgr_ud_class, NULL, ne, update_pdrv);
-}
-
-/* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3.  This
- * seems like an optional service but in the end it is practically mandatory
- * as a consequence of these clauses.
- *
- * Note that we cannot do a broadcast write to all nodes at once because some
- * pre-1394a devices would hang. */
-static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
-{
-       const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL);
-       quadlet_t bc_remote, bc_local;
-       int error;
-
-       if (!ne->host->is_irm || ne->generation != generation ||
-           ne->nodeid == ne->host->node_id)
-               return;
-
-       bc_local = cpu_to_be32(ne->host->csr.broadcast_channel);
-
-       /* Check if the register is implemented and 1394a compliant. */
-       error = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
-                         sizeof(bc_remote));
-       if (!error && bc_remote & cpu_to_be32(0x80000000) &&
-           bc_remote != bc_local)
-               hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local));
-}
-
-
-static void nodemgr_probe_ne(struct hpsb_host *host, struct node_entry *ne,
-                            int generation)
-{
-       struct device *dev;
-
-       if (ne->host != host || ne->in_limbo)
-               return;
-
-       dev = get_device(&ne->device);
-       if (!dev)
-               return;
-
-       nodemgr_irm_write_bc(ne, generation);
-
-       /* If "needs_probe", then this is either a new or changed node we
-        * rescan totally. If the generation matches for an existing node
-        * (one that existed prior to the bus reset) we send update calls
-        * down to the drivers. Otherwise, this is a dead node and we
-        * suspend it. */
-       if (ne->needs_probe)
-               nodemgr_process_root_directory(ne);
-       else if (ne->generation == generation)
-               nodemgr_update_pdrv(ne);
-       else
-               nodemgr_pause_ne(ne);
-
-       put_device(dev);
-}
-
-struct node_probe_parameter {
-       struct hpsb_host *host;
-       int generation;
-       bool probe_now;
-};
-
-static int node_probe(struct device *dev, void *data)
-{
-       struct node_probe_parameter *p = data;
-       struct node_entry *ne;
-
-       if (p->generation != get_hpsb_generation(p->host))
-               return -EAGAIN;
-
-       ne = container_of(dev, struct node_entry, node_dev);
-       if (ne->needs_probe == p->probe_now)
-               nodemgr_probe_ne(p->host, ne, p->generation);
-       return 0;
-}
-
-static int nodemgr_node_probe(struct hpsb_host *host, int generation)
-{
-       struct node_probe_parameter p;
-
-       p.host = host;
-       p.generation = generation;
-       /*
-        * Do some processing of the nodes we've probed. This pulls them
-        * into the sysfs layer if needed, and can result in processing of
-        * unit-directories, or just updating the node and it's
-        * unit-directories.
-        *
-        * Run updates before probes. Usually, updates are time-critical
-        * while probes are time-consuming.
-        *
-        * Meanwhile, another bus reset may have happened. In this case we
-        * skip everything here and let the next bus scan handle it.
-        * Otherwise we may prematurely remove nodes which are still there.
-        */
-       p.probe_now = false;
-       if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return 0;
-
-       p.probe_now = true;
-       if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0)
-               return 0;
-       /*
-        * Now let's tell the bus to rescan our devices. This may seem
-        * like overhead, but the driver-model core will only scan a
-        * device for a driver when either the device is added, or when a
-        * new driver is added. A bus reset is a good reason to rescan
-        * devices that were there before.  For example, an sbp2 device
-        * may become available for login, if the host that held it was
-        * just removed.
-        */
-       if (bus_rescan_devices(&ieee1394_bus_type) != 0)
-               HPSB_DEBUG("bus_rescan_devices had an error");
-
-       return 1;
-}
-
-static int remove_nodes_in_limbo(struct device *dev, void *data)
-{
-       struct node_entry *ne;
-
-       if (dev->bus != &ieee1394_bus_type)
-               return 0;
-
-       ne = container_of(dev, struct node_entry, device);
-       if (ne->in_limbo)
-               nodemgr_remove_ne(ne);
-
-       return 0;
-}
-
-static void nodemgr_remove_nodes_in_limbo(struct hpsb_host *host)
-{
-       device_for_each_child(&host->device, NULL, remove_nodes_in_limbo);
-}
-
-static int nodemgr_send_resume_packet(struct hpsb_host *host)
-{
-       struct hpsb_packet *packet;
-       int error = -ENOMEM;
-
-       packet = hpsb_make_phypacket(host,
-                       EXTPHYPACKET_TYPE_RESUME |
-                       NODEID_TO_NODE(host->node_id) << PHYPACKET_PORT_SHIFT);
-       if (packet) {
-               packet->no_waiter = 1;
-               packet->generation = get_hpsb_generation(host);
-               error = hpsb_send_packet(packet);
-       }
-       if (error)
-               HPSB_WARN("fw-host%d: Failed to broadcast resume packet",
-                         host->id);
-       return error;
-}
-
-/* Perform a few high-level IRM responsibilities. */
-static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
-{
-       quadlet_t bc;
-
-       /* if irm_id == -1 then there is no IRM on this bus */
-       if (!host->is_irm || host->irm_id == (nodeid_t)-1)
-               return 1;
-
-       /* We are a 1394a-2000 compliant IRM. Set the validity bit. */
-       host->csr.broadcast_channel |= 0x40000000;
-
-       /* If there is no bus manager then we should set the root node's
-        * force_root bit to promote bus stability per the 1394
-        * spec. (8.4.2.6) */
-       if (host->busmgr_id == 0xffff && host->node_count > 1)
-       {
-               u16 root_node = host->node_count - 1;
-
-               /* get cycle master capability flag from root node */
-               if (host->is_cycmst ||
-                   (!hpsb_read(host, LOCAL_BUS | root_node, get_hpsb_generation(host),
-                               (CSR_REGISTER_BASE + CSR_CONFIG_ROM + 2 * sizeof(quadlet_t)),
-                               &bc, sizeof(quadlet_t)) &&
-                    be32_to_cpu(bc) & 1 << CSR_CMC_SHIFT))
-                       hpsb_send_phy_config(host, root_node, -1);
-               else {
-                       HPSB_DEBUG("The root node is not cycle master capable; "
-                                  "selecting a new root node and resetting...");
-
-                       if (cycles >= 5) {
-                               /* Oh screw it! Just leave the bus as it is */
-                               HPSB_DEBUG("Stopping reset loop for IRM sanity");
-                               return 1;
-                       }
-
-                       hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1);
-                       hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
-
-                       return 0;
-               }
-       }
-
-       /* Some devices suspend their ports while being connected to an inactive
-        * host adapter, i.e. if connected before the low-level driver is
-        * loaded.  They become visible either when physically unplugged and
-        * replugged, or when receiving a resume packet.  Send one once. */
-       if (!host->resume_packet_sent && !nodemgr_send_resume_packet(host))
-               host->resume_packet_sent = 1;
-
-       return 1;
-}
-
-/* We need to ensure that if we are not the IRM, that the IRM node is capable of
- * everything we can do, otherwise issue a bus reset and try to become the IRM
- * ourselves. */
-static int nodemgr_check_irm_capability(struct hpsb_host *host, int cycles)
-{
-       quadlet_t bc;
-       int status;
-
-       if (hpsb_disable_irm || host->is_irm)
-               return 1;
-
-       status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
-                          get_hpsb_generation(host),
-                          (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
-                          &bc, sizeof(quadlet_t));
-
-       if (status < 0 || !(be32_to_cpu(bc) & 0x80000000)) {
-               /* The current irm node does not have a valid BROADCAST_CHANNEL
-                * register and we do, so reset the bus with force_root set */
-               HPSB_DEBUG("Current remote IRM is not 1394a-2000 compliant, resetting...");
-
-               if (cycles >= 5) {
-                       /* Oh screw it! Just leave the bus as it is */
-                       HPSB_DEBUG("Stopping reset loop for IRM sanity");
-                       return 1;
-               }
-
-               hpsb_send_phy_config(host, NODEID_TO_NODE(host->node_id), -1);
-               hpsb_reset_bus(host, LONG_RESET_FORCE_ROOT);
-
-               return 0;
-       }
-
-       return 1;
-}
-
-static int nodemgr_host_thread(void *data)
-{
-       struct hpsb_host *host = data;
-       unsigned int g, generation = 0;
-       int i, reset_cycles = 0;
-
-       set_freezable();
-       /* Setup our device-model entries */
-       nodemgr_create_host_dev_files(host);
-
-       for (;;) {
-               /* Sleep until next bus reset */
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (get_hpsb_generation(host) == generation &&
-                   !kthread_should_stop())
-                       schedule();
-               __set_current_state(TASK_RUNNING);
-
-               /* Thread may have been woken up to freeze or to exit */
-               if (try_to_freeze())
-                       continue;
-               if (kthread_should_stop())
-                       goto exit;
-
-               /* Pause for 1/4 second in 1/16 second intervals,
-                * to make sure things settle down. */
-               g = get_hpsb_generation(host);
-               for (i = 0; i < 4 ; i++) {
-                       msleep_interruptible(63);
-                       try_to_freeze();
-                       if (kthread_should_stop())
-                               goto exit;
-
-                       /* Now get the generation in which the node ID's we collect
-                        * are valid.  During the bus scan we will use this generation
-                        * for the read transactions, so that if another reset occurs
-                        * during the scan the transactions will fail instead of
-                        * returning bogus data. */
-                       generation = get_hpsb_generation(host);
-
-                       /* If we get a reset before we are done waiting, then
-                        * start the waiting over again */
-                       if (generation != g)
-                               g = generation, i = 0;
-               }
-
-               if (!nodemgr_check_irm_capability(host, reset_cycles) ||
-                   !nodemgr_do_irm_duties(host, reset_cycles)) {
-                       reset_cycles++;
-                       continue;
-               }
-               reset_cycles = 0;
-
-               /* Scan our nodes to get the bus options and create node
-                * entries. This does not do the sysfs stuff, since that
-                * would trigger uevents and such, which is a bad idea at
-                * this point. */
-               nodemgr_node_scan(host, generation);
-
-               /* This actually does the full probe, with sysfs
-                * registration. */
-               if (!nodemgr_node_probe(host, generation))
-                       continue;
-
-               /* Update some of our sysfs symlinks */
-               nodemgr_update_host_dev_links(host);
-
-               /* Sleep 3 seconds */
-               for (i = 3000/200; i; i--) {
-                       msleep_interruptible(200);
-                       try_to_freeze();
-                       if (kthread_should_stop())
-                               goto exit;
-
-                       if (generation != get_hpsb_generation(host))
-                               break;
-               }
-               /* Remove nodes which are gone, unless a bus reset happened */
-               if (!i)
-                       nodemgr_remove_nodes_in_limbo(host);
-       }
-exit:
-       HPSB_VERBOSE("NodeMgr: Exiting thread");
-       return 0;
-}
-
-struct per_host_parameter {
-       void *data;
-       int (*cb)(struct hpsb_host *, void *);
-};
-
-static int per_host(struct device *dev, void *data)
-{
-       struct hpsb_host *host;
-       struct per_host_parameter *p = data;
-
-       host = container_of(dev, struct hpsb_host, host_dev);
-       return p->cb(host, p->data);
-}
-
-/**
- * nodemgr_for_each_host - call a function for each IEEE 1394 host
- * @data: an address to supply to the callback
- * @cb: function to call for each host
- *
- * Iterate the hosts, calling a given function with supplied data for each host.
- * If the callback fails on a host, i.e. if it returns a non-zero value, the
- * iteration is stopped.
- *
- * Return value: 0 on success, non-zero on failure (same as returned by last run
- * of the callback).
- */
-int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *))
-{
-       struct per_host_parameter p;
-
-       p.cb = cb;
-       p.data = data;
-       return class_for_each_device(&hpsb_host_class, NULL, &p, per_host);
-}
-
-/* The following two convenience functions use a struct node_entry
- * for addressing a node on the bus.  They are intended for use by any
- * process context, not just the nodemgr thread, so we need to be a
- * little careful when reading out the node ID and generation.  The
- * thing that can go wrong is that we get the node ID, then a bus
- * reset occurs, and then we read the generation.  The node ID is
- * possibly invalid, but the generation is current, and we end up
- * sending a packet to a the wrong node.
- *
- * The solution is to make sure we read the generation first, so that
- * if a reset occurs in the process, we end up with a stale generation
- * and the transactions will fail instead of silently using wrong node
- * ID's.
- */
-
-/**
- * hpsb_node_fill_packet - fill some destination information into a packet
- * @ne: destination node
- * @packet: packet to fill in
- *
- * This will fill in the given, pre-initialised hpsb_packet with the current
- * information from the node entry (host, node ID, bus generation number).
- */
-void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet)
-{
-       packet->host = ne->host;
-       packet->generation = ne->generation;
-       smp_rmb();
-       packet->node_id = ne->nodeid;
-}
-
-int hpsb_node_write(struct node_entry *ne, u64 addr,
-                   quadlet_t *buffer, size_t length)
-{
-       unsigned int generation = ne->generation;
-
-       smp_rmb();
-       return hpsb_write(ne->host, ne->nodeid, generation,
-                         addr, buffer, length);
-}
-
-static void nodemgr_add_host(struct hpsb_host *host)
-{
-       struct host_info *hi;
-
-       hi = hpsb_create_hostinfo(&nodemgr_highlevel, host, sizeof(*hi));
-       if (!hi) {
-               HPSB_ERR("NodeMgr: out of memory in add host");
-               return;
-       }
-       hi->host = host;
-       hi->thread = kthread_run(nodemgr_host_thread, host, "knodemgrd_%d",
-                                host->id);
-       if (IS_ERR(hi->thread)) {
-               HPSB_ERR("NodeMgr: cannot start thread for host %d", host->id);
-               hpsb_destroy_hostinfo(&nodemgr_highlevel, host);
-       }
-}
-
-static void nodemgr_host_reset(struct hpsb_host *host)
-{
-       struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
-
-       if (hi) {
-               HPSB_VERBOSE("NodeMgr: Processing reset for host %d", host->id);
-               wake_up_process(hi->thread);
-       }
-}
-
-static void nodemgr_remove_host(struct hpsb_host *host)
-{
-       struct host_info *hi = hpsb_get_hostinfo(&nodemgr_highlevel, host);
-
-       if (hi) {
-               kthread_stop(hi->thread);
-               nodemgr_remove_host_dev(&host->device);
-       }
-}
-
-static struct hpsb_highlevel nodemgr_highlevel = {
-       .name =         "Node manager",
-       .add_host =     nodemgr_add_host,
-       .host_reset =   nodemgr_host_reset,
-       .remove_host =  nodemgr_remove_host,
-};
-
-int init_ieee1394_nodemgr(void)
-{
-       int error;
-
-       error = class_register(&nodemgr_ne_class);
-       if (error)
-               goto fail_ne;
-       error = class_register(&nodemgr_ud_class);
-       if (error)
-               goto fail_ud;
-       error = driver_register(&nodemgr_mid_layer_driver);
-       if (error)
-               goto fail_ml;
-       /* This driver is not used if nodemgr is off (disable_nodemgr=1). */
-       nodemgr_dev_template_host.driver = &nodemgr_mid_layer_driver;
-
-       hpsb_register_highlevel(&nodemgr_highlevel);
-       return 0;
-
-fail_ml:
-       class_unregister(&nodemgr_ud_class);
-fail_ud:
-       class_unregister(&nodemgr_ne_class);
-fail_ne:
-       return error;
-}
-
-void cleanup_ieee1394_nodemgr(void)
-{
-       hpsb_unregister_highlevel(&nodemgr_highlevel);
-       driver_unregister(&nodemgr_mid_layer_driver);
-       class_unregister(&nodemgr_ud_class);
-       class_unregister(&nodemgr_ne_class);
-}
diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
deleted file mode 100644 (file)
index 749b271..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2000  Andreas E. Bombe
- *               2001  Ben Collins <bcollins@debian.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _IEEE1394_NODEMGR_H
-#define _IEEE1394_NODEMGR_H
-
-#include <linux/device.h>
-#include <asm/system.h>
-#include <asm/types.h>
-
-#include "ieee1394_core.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-
-struct csr1212_csr;
-struct csr1212_keyval;
-struct hpsb_host;
-struct ieee1394_device_id;
-
-/* This is the start of a Node entry structure. It should be a stable API
- * for which to gather info from the Node Manager about devices attached
- * to the bus.  */
-struct bus_options {
-       u8      irmc;           /* Iso Resource Manager Capable */
-       u8      cmc;            /* Cycle Master Capable */
-       u8      isc;            /* Iso Capable */
-       u8      bmc;            /* Bus Master Capable */
-       u8      pmc;            /* Power Manager Capable (PNP spec) */
-       u8      cyc_clk_acc;    /* Cycle clock accuracy */
-       u8      max_rom;        /* Maximum block read supported in the CSR */
-       u8      generation;     /* Incremented when configrom changes */
-       u8      lnkspd;         /* Link speed */
-       u16     max_rec;        /* Maximum packet size node can receive */
-};
-
-#define UNIT_DIRECTORY_VENDOR_ID               0x01
-#define UNIT_DIRECTORY_MODEL_ID                        0x02
-#define UNIT_DIRECTORY_SPECIFIER_ID            0x04
-#define UNIT_DIRECTORY_VERSION                 0x08
-#define UNIT_DIRECTORY_HAS_LUN_DIRECTORY       0x10
-#define UNIT_DIRECTORY_LUN_DIRECTORY           0x20
-#define UNIT_DIRECTORY_HAS_LUN                 0x40
-
-/*
- * A unit directory corresponds to a protocol supported by the
- * node. If a node supports eg. IP/1394 and AV/C, its config rom has a
- * unit directory for each of these protocols.
- */
-struct unit_directory {
-       struct node_entry *ne;  /* The node which this directory belongs to */
-       octlet_t address;       /* Address of the unit directory on the node */
-       u8 flags;               /* Indicates which entries were read */
-
-       quadlet_t vendor_id;
-       struct csr1212_keyval *vendor_name_kv;
-
-       quadlet_t model_id;
-       struct csr1212_keyval *model_name_kv;
-       quadlet_t specifier_id;
-       quadlet_t version;
-       quadlet_t directory_id;
-
-       unsigned int id;
-
-       int ignore_driver;
-
-       int length;             /* Number of quadlets */
-
-       struct device device;
-       struct device unit_dev;
-
-       struct csr1212_keyval *ud_kv;
-       u32 lun;                /* logical unit number immediate value */
-};
-
-struct node_entry {
-       u64 guid;                       /* GUID of this node */
-       u32 guid_vendor_id;             /* Top 24bits of guid */
-
-       struct hpsb_host *host;         /* Host this node is attached to */
-       nodeid_t nodeid;                /* NodeID */
-       struct bus_options busopt;      /* Bus Options */
-       bool needs_probe;
-       unsigned int generation;        /* Synced with hpsb generation */
-
-       /* The following is read from the config rom */
-       u32 vendor_id;
-       struct csr1212_keyval *vendor_name_kv;
-
-       u32 capabilities;
-
-       struct device device;
-       struct device node_dev;
-
-       /* Means this node is not attached anymore */
-       bool in_limbo;
-
-       struct csr1212_csr *csr;
-};
-
-struct hpsb_protocol_driver {
-       /* The name of the driver, e.g. SBP2 or IP1394 */
-       const char *name;
-
-       /*
-        * The device id table describing the protocols and/or devices
-        * supported by this driver.  This is used by the nodemgr to
-        * decide if a driver could support a given node, but the
-        * probe function below can implement further protocol
-        * dependent or vendor dependent checking.
-        */
-       const struct ieee1394_device_id *id_table;
-
-       /*
-        * The update function is called when the node has just
-        * survived a bus reset, i.e. it is still present on the bus.
-        * However, it may be necessary to reestablish the connection
-        * or login into the node again, depending on the protocol. If the
-        * probe fails (returns non-zero), we unbind the driver from this
-        * device.
-        */
-       int (*update)(struct unit_directory *ud);
-
-       /* Our LDM structure */
-       struct device_driver driver;
-};
-
-int __hpsb_register_protocol(struct hpsb_protocol_driver *, struct module *);
-static inline int hpsb_register_protocol(struct hpsb_protocol_driver *driver)
-{
-       return __hpsb_register_protocol(driver, THIS_MODULE);
-}
-
-void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver);
-
-static inline int hpsb_node_entry_valid(struct node_entry *ne)
-{
-       return ne->generation == get_hpsb_generation(ne->host);
-}
-void hpsb_node_fill_packet(struct node_entry *ne, struct hpsb_packet *packet);
-int hpsb_node_write(struct node_entry *ne, u64 addr,
-                   quadlet_t *buffer, size_t length);
-static inline int hpsb_node_read(struct node_entry *ne, u64 addr,
-                                quadlet_t *buffer, size_t length)
-{
-       unsigned int g = ne->generation;
-
-       smp_rmb();
-       return hpsb_read(ne->host, ne->nodeid, g, addr, buffer, length);
-}
-static inline int hpsb_node_lock(struct node_entry *ne, u64 addr, int extcode,
-                                quadlet_t *buffer, quadlet_t arg)
-{
-       unsigned int g = ne->generation;
-
-       smp_rmb();
-       return hpsb_lock(ne->host, ne->nodeid, g, addr, extcode, buffer, arg);
-}
-int nodemgr_for_each_host(void *data, int (*cb)(struct hpsb_host *, void *));
-
-int init_ieee1394_nodemgr(void);
-void cleanup_ieee1394_nodemgr(void);
-
-/* The template for a host device */
-extern struct device nodemgr_dev_template_host;
-
-/* Bus attributes we export */
-extern struct bus_attribute *const fw_bus_attrs[];
-
-#endif /* _IEEE1394_NODEMGR_H */
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
deleted file mode 100644 (file)
index 5081502..0000000
+++ /dev/null
@@ -1,3590 +0,0 @@
-/*
- * ohci1394.c - driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Gord Peters <GordPeters@smarttech.com>
- *              2001      Ben Collins <bcollins@debian.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.
- *
- * 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.
- */
-
-/*
- * Things known to be working:
- * . Async Request Transmit
- * . Async Response Receive
- * . Async Request Receive
- * . Async Response Transmit
- * . Iso Receive
- * . DMA mmap for iso receive
- * . Config ROM generation
- *
- * Things implemented, but still in test phase:
- * . Iso Transmit
- * . Async Stream Packets Transmit (Receive done via Iso interface)
- *
- * Things not implemented:
- * . DMA error recovery
- *
- * Known bugs:
- * . devctl BUS_RESET arg confusion (reset type or root holdoff?)
- *   added LONG_RESET_ROOT and SHORT_RESET_ROOT for root holdoff --kk
- */
-
-/*
- * Acknowledgments:
- *
- * Adam J Richter <adam@yggdrasil.com>
- *  . Use of pci_class to find device
- *
- * Emilie Chung        <emilie.chung@axis.com>
- *  . Tip on Async Request Filter
- *
- * Pascal Drolet <pascal.drolet@informission.ca>
- *  . Various tips for optimization and functionnalities
- *
- * Robert Ficklin <rficklin@westengineering.com>
- *  . Loop in irq_handler
- *
- * James Goodwin <jamesg@Filanet.com>
- *  . Various tips on initialization, self-id reception, etc.
- *
- * Albrecht Dress <ad@mpifr-bonn.mpg.de>
- *  . Apple PowerBook detection
- *
- * Daniel Kobras <daniel.kobras@student.uni-tuebingen.de>
- *  . Reset the board properly before leaving + misc cleanups
- *
- * Leon van Stuivenberg <leonvs@iae.nl>
- *  . Bug fixes
- *
- * Ben Collins <bcollins@debian.org>
- *  . Working big-endian support
- *  . Updated to 2.4.x module scheme (PCI aswell)
- *  . Config ROM generation
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *  . Reworked code for initiating bus resets
- *    (long, short, with or without hold-off)
- *
- * Nandu Santhi <contactnandu@users.sourceforge.net>
- *  . Added support for nVidia nForce2 onboard Firewire chipset
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/uaccess.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/irq.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-
-#ifdef CONFIG_PPC_PMAC
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#endif
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "dma.h"
-#include "iso.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "ohci1394.h"
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define OHCI1394_DEBUG
-#endif
-
-#ifdef DBGMSG
-#undef DBGMSG
-#endif
-
-#ifdef OHCI1394_DEBUG
-#define DBGMSG(fmt, args...) \
-printk(KERN_INFO "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
-#else
-#define DBGMSG(fmt, args...) do {} while (0)
-#endif
-
-/* print general (card independent) information */
-#define PRINT_G(level, fmt, args...) \
-printk(level "%s: " fmt "\n" , OHCI1394_DRIVER_NAME , ## args)
-
-/* print card specific information */
-#define PRINT(level, fmt, args...) \
-printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
-
-/* Module Parameters */
-static int phys_dma = 1;
-module_param(phys_dma, int, 0444);
-MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 1).");
-
-static void dma_trm_tasklet(unsigned long data);
-static void dma_trm_reset(struct dma_trm_ctx *d);
-
-static int alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
-                            enum context_type type, int ctx, int num_desc,
-                            int buf_size, int split_buf_size, int context_base);
-static void free_dma_rcv_ctx(struct dma_rcv_ctx *d);
-
-static int alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
-                            enum context_type type, int ctx, int num_desc,
-                            int context_base);
-
-static void ohci1394_pci_remove(struct pci_dev *pdev);
-
-#ifndef __LITTLE_ENDIAN
-static const size_t hdr_sizes[] = {
-       3,      /* TCODE_WRITEQ */
-       4,      /* TCODE_WRITEB */
-       3,      /* TCODE_WRITE_RESPONSE */
-       0,      /* reserved */
-       3,      /* TCODE_READQ */
-       4,      /* TCODE_READB */
-       3,      /* TCODE_READQ_RESPONSE */
-       4,      /* TCODE_READB_RESPONSE */
-       1,      /* TCODE_CYCLE_START */
-       4,      /* TCODE_LOCK_REQUEST */
-       2,      /* TCODE_ISO_DATA */
-       4,      /* TCODE_LOCK_RESPONSE */
-               /* rest is reserved or link-internal */
-};
-
-static inline void header_le32_to_cpu(quadlet_t *data, unsigned char tcode)
-{
-       size_t size;
-
-       if (unlikely(tcode >= ARRAY_SIZE(hdr_sizes)))
-               return;
-
-       size = hdr_sizes[tcode];
-       while (size--)
-               data[size] = le32_to_cpu(data[size]);
-}
-#else
-#define header_le32_to_cpu(w,x) do {} while (0)
-#endif /* !LITTLE_ENDIAN */
-
-/***********************************
- * IEEE-1394 functionality section *
- ***********************************/
-
-static u8 get_phy_reg(struct ti_ohci *ohci, u8 addr)
-{
-       int i;
-       unsigned long flags;
-       quadlet_t r;
-
-       spin_lock_irqsave (&ohci->phy_reg_lock, flags);
-
-       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
-                       break;
-
-               mdelay(1);
-       }
-
-       r = reg_read(ohci, OHCI1394_PhyControl);
-
-       if (i >= OHCI_LOOP_COUNT)
-               PRINT (KERN_ERR, "Get PHY Reg timeout [0x%08x/0x%08x/%d]",
-                      r, r & 0x80000000, i);
-
-       spin_unlock_irqrestore (&ohci->phy_reg_lock, flags);
-
-       return (r & 0x00ff0000) >> 16;
-}
-
-static void set_phy_reg(struct ti_ohci *ohci, u8 addr, u8 data)
-{
-       int i;
-       unsigned long flags;
-       u32 r = 0;
-
-       spin_lock_irqsave (&ohci->phy_reg_lock, flags);
-
-       reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               r = reg_read(ohci, OHCI1394_PhyControl);
-               if (!(r & 0x00004000))
-                       break;
-
-               mdelay(1);
-       }
-
-       if (i == OHCI_LOOP_COUNT)
-               PRINT (KERN_ERR, "Set PHY Reg timeout [0x%08x/0x%08x/%d]",
-                      r, r & 0x00004000, i);
-
-       spin_unlock_irqrestore (&ohci->phy_reg_lock, flags);
-
-       return;
-}
-
-/* Or's our value into the current value */
-static void set_phy_reg_mask(struct ti_ohci *ohci, u8 addr, u8 data)
-{
-       u8 old;
-
-       old = get_phy_reg (ohci, addr);
-       old |= data;
-       set_phy_reg (ohci, addr, old);
-
-       return;
-}
-
-static void handle_selfid(struct ti_ohci *ohci, struct hpsb_host *host,
-                               int phyid, int isroot)
-{
-       quadlet_t *q = ohci->selfid_buf_cpu;
-       quadlet_t self_id_count=reg_read(ohci, OHCI1394_SelfIDCount);
-       size_t size;
-       quadlet_t q0, q1;
-
-       /* Check status of self-id reception */
-
-       if (ohci->selfid_swap)
-               q0 = le32_to_cpu(q[0]);
-       else
-               q0 = q[0];
-
-       if ((self_id_count & 0x80000000) ||
-           ((self_id_count & 0x00FF0000) != (q0 & 0x00FF0000))) {
-               PRINT(KERN_ERR,
-                     "Error in reception of SelfID packets [0x%08x/0x%08x] (count: %d)",
-                     self_id_count, q0, ohci->self_id_errors);
-
-               /* Tip by James Goodwin <jamesg@Filanet.com>:
-                * We had an error, generate another bus reset in response.  */
-               if (ohci->self_id_errors<OHCI1394_MAX_SELF_ID_ERRORS) {
-                       set_phy_reg_mask (ohci, 1, 0x40);
-                       ohci->self_id_errors++;
-               } else {
-                       PRINT(KERN_ERR,
-                             "Too many errors on SelfID error reception, giving up!");
-               }
-               return;
-       }
-
-       /* SelfID Ok, reset error counter. */
-       ohci->self_id_errors = 0;
-
-       size = ((self_id_count & 0x00001FFC) >> 2) - 1;
-       q++;
-
-       while (size > 0) {
-               if (ohci->selfid_swap) {
-                       q0 = le32_to_cpu(q[0]);
-                       q1 = le32_to_cpu(q[1]);
-               } else {
-                       q0 = q[0];
-                       q1 = q[1];
-               }
-
-               if (q0 == ~q1) {
-                       DBGMSG ("SelfID packet 0x%x received", q0);
-                       hpsb_selfid_received(host, cpu_to_be32(q0));
-                       if (((q0 & 0x3f000000) >> 24) == phyid)
-                               DBGMSG ("SelfID for this node is 0x%08x", q0);
-               } else {
-                       PRINT(KERN_ERR,
-                             "SelfID is inconsistent [0x%08x/0x%08x]", q0, q1);
-               }
-               q += 2;
-               size -= 2;
-       }
-
-       DBGMSG("SelfID complete");
-
-       return;
-}
-
-static void ohci_soft_reset(struct ti_ohci *ohci) {
-       int i;
-
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (!(reg_read(ohci, OHCI1394_HCControlSet) & OHCI1394_HCControl_softReset))
-                       break;
-               mdelay(1);
-       }
-       DBGMSG ("Soft reset finished");
-}
-
-
-/* Generate the dma receive prgs and start the context */
-static void initialize_dma_rcv_ctx(struct dma_rcv_ctx *d, int generate_irq)
-{
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       int i;
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       for (i=0; i<d->num_desc; i++) {
-               u32 c;
-
-               c = DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE | DMA_CTL_BRANCH;
-               if (generate_irq)
-                       c |= DMA_CTL_IRQ;
-
-               d->prg_cpu[i]->control = cpu_to_le32(c | d->buf_size);
-
-               /* End of descriptor list? */
-               if (i + 1 < d->num_desc) {
-                       d->prg_cpu[i]->branchAddress =
-                               cpu_to_le32((d->prg_bus[i+1] & 0xfffffff0) | 0x1);
-               } else {
-                       d->prg_cpu[i]->branchAddress =
-                               cpu_to_le32((d->prg_bus[0] & 0xfffffff0));
-               }
-
-               d->prg_cpu[i]->address = cpu_to_le32(d->buf_bus[i]);
-               d->prg_cpu[i]->status = cpu_to_le32(d->buf_size);
-       }
-
-        d->buf_ind = 0;
-        d->buf_offset = 0;
-
-       if (d->type == DMA_CTX_ISO) {
-               /* Clear contextControl */
-               reg_write(ohci, d->ctrlClear, 0xffffffff);
-
-               /* Set bufferFill, isochHeader, multichannel for IR context */
-               reg_write(ohci, d->ctrlSet, 0xd0000000);
-
-               /* Set the context match register to match on all tags */
-               reg_write(ohci, d->ctxtMatch, 0xf0000000);
-
-               /* Clear the multi channel mask high and low registers */
-               reg_write(ohci, OHCI1394_IRMultiChanMaskHiClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IRMultiChanMaskLoClear, 0xffffffff);
-
-               /* Set up isoRecvIntMask to generate interrupts */
-               reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1 << d->ctx);
-       }
-
-       /* Tell the controller where the first AR program is */
-       reg_write(ohci, d->cmdPtr, d->prg_bus[0] | 0x1);
-
-       /* Run context */
-       reg_write(ohci, d->ctrlSet, 0x00008000);
-
-       DBGMSG("Receive DMA ctx=%d initialized", d->ctx);
-}
-
-/* Initialize the dma transmit context */
-static void initialize_dma_trm_ctx(struct dma_trm_ctx *d)
-{
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-
-       /* Stop the context */
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-        d->prg_ind = 0;
-       d->sent_ind = 0;
-       d->free_prgs = d->num_desc;
-        d->branchAddrPtr = NULL;
-       INIT_LIST_HEAD(&d->fifo_list);
-       INIT_LIST_HEAD(&d->pending_list);
-
-       if (d->type == DMA_CTX_ISO) {
-               /* enable interrupts */
-               reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << d->ctx);
-       }
-
-       DBGMSG("Transmit DMA ctx=%d initialized", d->ctx);
-}
-
-/* Count the number of available iso contexts */
-static int get_nb_iso_ctx(struct ti_ohci *ohci, int reg)
-{
-       u32 tmp;
-
-       reg_write(ohci, reg, 0xffffffff);
-       tmp = reg_read(ohci, reg);
-
-       DBGMSG("Iso contexts reg: %08x implemented: %08x", reg, tmp);
-
-       /* Count the number of contexts */
-       return hweight32(tmp);
-}
-
-/* Global initialization */
-static void ohci_initialize(struct ti_ohci *ohci)
-{
-       quadlet_t buf;
-       int num_ports, i;
-
-       spin_lock_init(&ohci->phy_reg_lock);
-
-       /* Put some defaults to these undefined bus options */
-       buf = reg_read(ohci, OHCI1394_BusOptions);
-       buf |=  0x60000000; /* Enable CMC and ISC */
-       if (hpsb_disable_irm)
-               buf &= ~0x80000000;
-       else
-               buf |=  0x80000000; /* Enable IRMC */
-       buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
-       buf &= ~0x18000000; /* Disable PMC and BMC */
-       reg_write(ohci, OHCI1394_BusOptions, buf);
-
-       /* Set the bus number */
-       reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
-
-       /* Enable posted writes */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_postedWriteEnable);
-
-       /* Clear link control register */
-       reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
-
-       /* Enable cycle timer and cycle master and set the IRM
-        * contender bit in our self ID packets if appropriate. */
-       reg_write(ohci, OHCI1394_LinkControlSet,
-                 OHCI1394_LinkControl_CycleTimerEnable |
-                 OHCI1394_LinkControl_CycleMaster);
-       i = get_phy_reg(ohci, 4) | PHY_04_LCTRL;
-       if (hpsb_disable_irm)
-               i &= ~PHY_04_CONTENDER;
-       else
-               i |= PHY_04_CONTENDER;
-       set_phy_reg(ohci, 4, i);
-
-       /* Set up self-id dma buffer */
-       reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
-
-       /* enable self-id */
-       reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_RcvSelfID);
-
-       /* Set the Config ROM mapping register */
-       reg_write(ohci, OHCI1394_ConfigROMmap, ohci->csr_config_rom_bus);
-
-       /* Now get our max packet size */
-       ohci->max_packet_size =
-               1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
-               
-       /* Clear the interrupt mask */
-       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-
-       /* Clear the interrupt mask */
-       reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
-
-       /* Initialize AR dma */
-       initialize_dma_rcv_ctx(&ohci->ar_req_context, 0);
-       initialize_dma_rcv_ctx(&ohci->ar_resp_context, 0);
-
-       /* Initialize AT dma */
-       initialize_dma_trm_ctx(&ohci->at_req_context);
-       initialize_dma_trm_ctx(&ohci->at_resp_context);
-       
-       /* Accept AR requests from all nodes */
-       reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
-
-       /* Set the address range of the physical response unit.
-        * Most controllers do not implement it as a writable register though.
-        * They will keep a hardwired offset of 0x00010000 and show 0x0 as
-        * register content.
-        * To actually enable physical responses is the job of our interrupt
-        * handler which programs the physical request filter. */
-       reg_write(ohci, OHCI1394_PhyUpperBound,
-                 OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED >> 16);
-
-       DBGMSG("physUpperBoundOffset=%08x",
-              reg_read(ohci, OHCI1394_PhyUpperBound));
-
-       /* Specify AT retries */
-       reg_write(ohci, OHCI1394_ATRetries,
-                 OHCI1394_MAX_AT_REQ_RETRIES |
-                 (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
-                 (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
-
-       /* We don't want hardware swapping */
-       reg_write(ohci, OHCI1394_HCControlClear, OHCI1394_HCControl_noByteSwap);
-
-       /* Enable interrupts */
-       reg_write(ohci, OHCI1394_IntMaskSet,
-                 OHCI1394_unrecoverableError |
-                 OHCI1394_masterIntEnable |
-                 OHCI1394_busReset |
-                 OHCI1394_selfIDComplete |
-                 OHCI1394_RSPkt |
-                 OHCI1394_RQPkt |
-                 OHCI1394_respTxComplete |
-                 OHCI1394_reqTxComplete |
-                 OHCI1394_isochRx |
-                 OHCI1394_isochTx |
-                 OHCI1394_postedWriteErr |
-                 OHCI1394_cycleTooLong |
-                 OHCI1394_cycleInconsistent);
-
-       /* Enable link */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
-
-       buf = reg_read(ohci, OHCI1394_Version);
-       PRINT(KERN_INFO, "OHCI-1394 %d.%d (PCI): IRQ=[%d]  "
-             "MMIO=[%llx-%llx]  Max Packet=[%d]  IR/IT contexts=[%d/%d]",
-             ((((buf) >> 16) & 0xf) + (((buf) >> 20) & 0xf) * 10),
-             ((((buf) >> 4) & 0xf) + ((buf) & 0xf) * 10), ohci->dev->irq,
-             (unsigned long long)pci_resource_start(ohci->dev, 0),
-             (unsigned long long)pci_resource_start(ohci->dev, 0) + OHCI1394_REGISTER_SIZE - 1,
-             ohci->max_packet_size,
-             ohci->nb_iso_rcv_ctx, ohci->nb_iso_xmit_ctx);
-
-       /* Check all of our ports to make sure that if anything is
-        * connected, we enable that port. */
-       num_ports = get_phy_reg(ohci, 2) & 0xf;
-       for (i = 0; i < num_ports; i++) {
-               unsigned int status;
-
-               set_phy_reg(ohci, 7, i);
-               status = get_phy_reg(ohci, 8);
-
-               if (status & 0x20)
-                       set_phy_reg(ohci, 8, status & ~1);
-       }
-
-        /* Serial EEPROM Sanity check. */
-        if ((ohci->max_packet_size < 512) ||
-           (ohci->max_packet_size > 4096)) {
-               /* Serial EEPROM contents are suspect, set a sane max packet
-                * size and print the raw contents for bug reports if verbose
-                * debug is enabled. */
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-               int i;
-#endif
-
-               PRINT(KERN_DEBUG, "Serial EEPROM has suspicious values, "
-                      "attempting to set max_packet_size to 512 bytes");
-               reg_write(ohci, OHCI1394_BusOptions,
-                         (reg_read(ohci, OHCI1394_BusOptions) & 0xf007) | 0x8002);
-               ohci->max_packet_size = 512;
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-               PRINT(KERN_DEBUG, "    EEPROM Present: %d",
-                     (reg_read(ohci, OHCI1394_Version) >> 24) & 0x1);
-               reg_write(ohci, OHCI1394_GUID_ROM, 0x80000000);
-
-               for (i = 0;
-                    ((i < 1000) &&
-                     (reg_read(ohci, OHCI1394_GUID_ROM) & 0x80000000)); i++)
-                       udelay(10);
-
-               for (i = 0; i < 0x20; i++) {
-                       reg_write(ohci, OHCI1394_GUID_ROM, 0x02000000);
-                       PRINT(KERN_DEBUG, "    EEPROM %02x: %02x", i,
-                             (reg_read(ohci, OHCI1394_GUID_ROM) >> 16) & 0xff);
-               }
-#endif
-       }
-}
-
-/*
- * Insert a packet in the DMA fifo and generate the DMA prg
- * FIXME: rewrite the program in order to accept packets crossing
- *        page boundaries.
- *        check also that a single dma descriptor doesn't cross a
- *        page boundary.
- */
-static void insert_packet(struct ti_ohci *ohci,
-                         struct dma_trm_ctx *d, struct hpsb_packet *packet)
-{
-       u32 cycleTimer;
-       int idx = d->prg_ind;
-
-       DBGMSG("Inserting packet for node " NODE_BUS_FMT
-              ", tlabel=%d, tcode=0x%x, speed=%d",
-              NODE_BUS_ARGS(ohci->host, packet->node_id), packet->tlabel,
-              packet->tcode, packet->speed_code);
-
-       d->prg_cpu[idx]->begin.address = 0;
-       d->prg_cpu[idx]->begin.branchAddress = 0;
-
-       if (d->type == DMA_CTX_ASYNC_RESP) {
-               /*
-                * For response packets, we need to put a timeout value in
-                * the 16 lower bits of the status... let's try 1 sec timeout
-                */
-               cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-               d->prg_cpu[idx]->begin.status = cpu_to_le32(
-                       (((((cycleTimer>>25)&0x7)+1)&0x7)<<13) |
-                       ((cycleTimer&0x01fff000)>>12));
-
-               DBGMSG("cycleTimer: %08x timeStamp: %08x",
-                      cycleTimer, d->prg_cpu[idx]->begin.status);
-       } else 
-               d->prg_cpu[idx]->begin.status = 0;
-
-        if ( (packet->type == hpsb_async) || (packet->type == hpsb_raw) ) {
-
-                if (packet->type == hpsb_raw) {
-                       d->prg_cpu[idx]->data[0] = cpu_to_le32(OHCI1394_TCODE_PHY<<4);
-                        d->prg_cpu[idx]->data[1] = cpu_to_le32(packet->header[0]);
-                        d->prg_cpu[idx]->data[2] = cpu_to_le32(packet->header[1]);
-                } else {
-                        d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
-                                (packet->header[0] & 0xFFFF);
-
-                       if (packet->tcode == TCODE_ISO_DATA) {
-                               /* Sending an async stream packet */
-                               d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
-                       } else {
-                               /* Sending a normal async request or response */
-                               d->prg_cpu[idx]->data[1] =
-                                       (packet->header[1] & 0xFFFF) |
-                                       (packet->header[0] & 0xFFFF0000);
-                               d->prg_cpu[idx]->data[2] = packet->header[2];
-                               d->prg_cpu[idx]->data[3] = packet->header[3];
-                       }
-                       header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode);
-                }
-
-                if (packet->data_size) { /* block transmit */
-                       if (packet->tcode == TCODE_STREAM_DATA){
-                               d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                                                   DMA_CTL_IMMEDIATE | 0x8);
-                       } else {
-                               d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                                                   DMA_CTL_IMMEDIATE | 0x10);
-                       }
-                        d->prg_cpu[idx]->end.control =
-                                cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                           DMA_CTL_IRQ |
-                                           DMA_CTL_BRANCH |
-                                           packet->data_size);
-                        /*
-                         * Check that the packet data buffer
-                         * does not cross a page boundary.
-                        *
-                        * XXX Fix this some day. eth1394 seems to trigger
-                        * it, but ignoring it doesn't seem to cause a
-                        * problem.
-                         */
-#if 0
-                        if (cross_bound((unsigned long)packet->data,
-                                        packet->data_size)>0) {
-                                /* FIXME: do something about it */
-                                PRINT(KERN_ERR,
-                                      "%s: packet data addr: %p size %Zd bytes "
-                                     "cross page boundary", __func__,
-                                      packet->data, packet->data_size);
-                        }
-#endif
-                        d->prg_cpu[idx]->end.address = cpu_to_le32(
-                                pci_map_single(ohci->dev, packet->data,
-                                               packet->data_size,
-                                               PCI_DMA_TODEVICE));
-
-                        d->prg_cpu[idx]->end.branchAddress = 0;
-                        d->prg_cpu[idx]->end.status = 0;
-                        if (d->branchAddrPtr)
-                                *(d->branchAddrPtr) =
-                                       cpu_to_le32(d->prg_bus[idx] | 0x3);
-                        d->branchAddrPtr =
-                                &(d->prg_cpu[idx]->end.branchAddress);
-                } else { /* quadlet transmit */
-                        if (packet->type == hpsb_raw)
-                                d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                                   DMA_CTL_IMMEDIATE |
-                                                   DMA_CTL_IRQ |
-                                                   DMA_CTL_BRANCH |
-                                                   (packet->header_size + 4));
-                        else
-                                d->prg_cpu[idx]->begin.control =
-                                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                                   DMA_CTL_IMMEDIATE |
-                                                   DMA_CTL_IRQ |
-                                                   DMA_CTL_BRANCH |
-                                                   packet->header_size);
-
-                        if (d->branchAddrPtr)
-                                *(d->branchAddrPtr) =
-                                       cpu_to_le32(d->prg_bus[idx] | 0x2);
-                        d->branchAddrPtr =
-                                &(d->prg_cpu[idx]->begin.branchAddress);
-                }
-
-        } else { /* iso packet */
-                d->prg_cpu[idx]->data[0] = packet->speed_code<<16 |
-                        (packet->header[0] & 0xFFFF);
-                d->prg_cpu[idx]->data[1] = packet->header[0] & 0xFFFF0000;
-               header_le32_to_cpu(d->prg_cpu[idx]->data, packet->tcode);
-
-                d->prg_cpu[idx]->begin.control =
-                       cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                                   DMA_CTL_IMMEDIATE | 0x8);
-                d->prg_cpu[idx]->end.control =
-                       cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                   DMA_CTL_UPDATE |
-                                   DMA_CTL_IRQ |
-                                   DMA_CTL_BRANCH |
-                                   packet->data_size);
-                d->prg_cpu[idx]->end.address = cpu_to_le32(
-                               pci_map_single(ohci->dev, packet->data,
-                               packet->data_size, PCI_DMA_TODEVICE));
-
-                d->prg_cpu[idx]->end.branchAddress = 0;
-                d->prg_cpu[idx]->end.status = 0;
-                DBGMSG("Iso xmit context info: header[%08x %08x]\n"
-                       "                       begin=%08x %08x %08x %08x\n"
-                       "                             %08x %08x %08x %08x\n"
-                       "                       end  =%08x %08x %08x %08x",
-                       d->prg_cpu[idx]->data[0], d->prg_cpu[idx]->data[1],
-                       d->prg_cpu[idx]->begin.control,
-                       d->prg_cpu[idx]->begin.address,
-                       d->prg_cpu[idx]->begin.branchAddress,
-                       d->prg_cpu[idx]->begin.status,
-                       d->prg_cpu[idx]->data[0],
-                       d->prg_cpu[idx]->data[1],
-                       d->prg_cpu[idx]->data[2],
-                       d->prg_cpu[idx]->data[3],
-                       d->prg_cpu[idx]->end.control,
-                       d->prg_cpu[idx]->end.address,
-                       d->prg_cpu[idx]->end.branchAddress,
-                       d->prg_cpu[idx]->end.status);
-                if (d->branchAddrPtr)
-                       *(d->branchAddrPtr) = cpu_to_le32(d->prg_bus[idx] | 0x3);
-                d->branchAddrPtr = &(d->prg_cpu[idx]->end.branchAddress);
-        }
-       d->free_prgs--;
-
-       /* queue the packet in the appropriate context queue */
-       list_add_tail(&packet->driver_list, &d->fifo_list);
-       d->prg_ind = (d->prg_ind + 1) % d->num_desc;
-}
-
-/*
- * This function fills the FIFO with the (eventual) pending packets
- * and runs or wakes up the DMA prg if necessary.
- *
- * The function MUST be called with the d->lock held.
- */
-static void dma_trm_flush(struct ti_ohci *ohci, struct dma_trm_ctx *d)
-{
-       struct hpsb_packet *packet, *ptmp;
-       int idx = d->prg_ind;
-       int z = 0;
-
-       /* insert the packets into the dma fifo */
-       list_for_each_entry_safe(packet, ptmp, &d->pending_list, driver_list) {
-               if (!d->free_prgs)
-                       break;
-
-               /* For the first packet only */
-               if (!z)
-                       z = (packet->data_size) ? 3 : 2;
-
-               /* Insert the packet */
-               list_del_init(&packet->driver_list);
-               insert_packet(ohci, d, packet);
-       }
-
-       /* Nothing must have been done, either no free_prgs or no packets */
-       if (z == 0)
-               return;
-
-       /* Is the context running ? (should be unless it is
-          the first packet to be sent in this context) */
-       if (!(reg_read(ohci, d->ctrlSet) & 0x8000)) {
-               u32 nodeId = reg_read(ohci, OHCI1394_NodeID);
-
-               DBGMSG("Starting transmit DMA ctx=%d",d->ctx);
-               reg_write(ohci, d->cmdPtr, d->prg_bus[idx] | z);
-
-               /* Check that the node id is valid, and not 63 */
-               if (!(nodeId & 0x80000000) || (nodeId & 0x3f) == 63)
-                       PRINT(KERN_ERR, "Running dma failed because Node ID is not valid");
-               else
-                       reg_write(ohci, d->ctrlSet, 0x8000);
-       } else {
-               /* Wake up the dma context if necessary */
-               if (!(reg_read(ohci, d->ctrlSet) & 0x400))
-                       DBGMSG("Waking transmit DMA ctx=%d",d->ctx);
-
-               /* do this always, to avoid race condition */
-               reg_write(ohci, d->ctrlSet, 0x1000);
-       }
-
-       return;
-}
-
-/* Transmission of an async or iso packet */
-static int ohci_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
-{
-       struct ti_ohci *ohci = host->hostdata;
-       struct dma_trm_ctx *d;
-       unsigned long flags;
-
-       if (packet->data_size > ohci->max_packet_size) {
-               PRINT(KERN_ERR,
-                     "Transmit packet size %Zd is too big",
-                     packet->data_size);
-               return -EOVERFLOW;
-       }
-
-       if (packet->type == hpsb_raw)
-               d = &ohci->at_req_context;
-       else if ((packet->tcode & 0x02) && (packet->tcode != TCODE_ISO_DATA))
-               d = &ohci->at_resp_context;
-       else
-               d = &ohci->at_req_context;
-
-       spin_lock_irqsave(&d->lock,flags);
-
-       list_add_tail(&packet->driver_list, &d->pending_list);
-
-       dma_trm_flush(ohci, d);
-
-       spin_unlock_irqrestore(&d->lock,flags);
-
-       return 0;
-}
-
-static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
-{
-       struct ti_ohci *ohci = host->hostdata;
-       int retval = 0, phy_reg;
-
-       switch (cmd) {
-       case RESET_BUS:
-               switch (arg) {
-               case SHORT_RESET:
-                       phy_reg = get_phy_reg(ohci, 5);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 5, phy_reg); /* set ISBR */
-                       break;
-               case LONG_RESET:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 1, phy_reg); /* set IBR */
-                       break;
-               case SHORT_RESET_NO_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       if (phy_reg & 0x80) {
-                               phy_reg &= ~0x80;
-                               set_phy_reg(ohci, 1, phy_reg); /* clear RHB */
-                       }
-
-                       phy_reg = get_phy_reg(ohci, 5);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 5, phy_reg); /* set ISBR */
-                       break;
-               case LONG_RESET_NO_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       phy_reg &= ~0x80;
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 1, phy_reg); /* clear RHB, set IBR */
-                       break;
-               case SHORT_RESET_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       if (!(phy_reg & 0x80)) {
-                               phy_reg |= 0x80;
-                               set_phy_reg(ohci, 1, phy_reg); /* set RHB */
-                       }
-
-                       phy_reg = get_phy_reg(ohci, 5);
-                       phy_reg |= 0x40;
-                       set_phy_reg(ohci, 5, phy_reg); /* set ISBR */
-                       break;
-               case LONG_RESET_FORCE_ROOT:
-                       phy_reg = get_phy_reg(ohci, 1);
-                       phy_reg |= 0xc0;
-                       set_phy_reg(ohci, 1, phy_reg); /* set RHB and IBR */
-                       break;
-               default:
-                       retval = -1;
-               }
-               break;
-
-       case GET_CYCLE_COUNTER:
-               retval = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-               break;
-
-       case SET_CYCLE_COUNTER:
-               reg_write(ohci, OHCI1394_IsochronousCycleTimer, arg);
-               break;
-
-       case SET_BUS_ID:
-               PRINT(KERN_ERR, "devctl command SET_BUS_ID err");
-               break;
-
-       case ACT_CYCLE_MASTER:
-               if (arg) {
-                       /* check if we are root and other nodes are present */
-                       u32 nodeId = reg_read(ohci, OHCI1394_NodeID);
-                       if ((nodeId & (1<<30)) && (nodeId & 0x3f)) {
-                               /*
-                                * enable cycleTimer, cycleMaster
-                                */
-                               DBGMSG("Cycle master enabled");
-                               reg_write(ohci, OHCI1394_LinkControlSet,
-                                         OHCI1394_LinkControl_CycleTimerEnable |
-                                         OHCI1394_LinkControl_CycleMaster);
-                       }
-               } else {
-                       /* disable cycleTimer, cycleMaster, cycleSource */
-                       reg_write(ohci, OHCI1394_LinkControlClear,
-                                 OHCI1394_LinkControl_CycleTimerEnable |
-                                 OHCI1394_LinkControl_CycleMaster |
-                                 OHCI1394_LinkControl_CycleSource);
-               }
-               break;
-
-       case CANCEL_REQUESTS:
-               DBGMSG("Cancel request received");
-               dma_trm_reset(&ohci->at_req_context);
-               dma_trm_reset(&ohci->at_resp_context);
-               break;
-
-       default:
-               PRINT_G(KERN_ERR, "ohci_devctl cmd %d not implemented yet",
-                       cmd);
-               break;
-       }
-       return retval;
-}
-
-/***********************************
- * rawiso ISO reception            *
- ***********************************/
-
-/*
-  We use either buffer-fill or packet-per-buffer DMA mode. The DMA
-  buffer is split into "blocks" (regions described by one DMA
-  descriptor). Each block must be one page or less in size, and
-  must not cross a page boundary.
-
-  There is one little wrinkle with buffer-fill mode: a packet that
-  starts in the final block may wrap around into the first block. But
-  the user API expects all packets to be contiguous. Our solution is
-  to keep the very last page of the DMA buffer in reserve - if a
-  packet spans the gap, we copy its tail into this page.
-*/
-
-struct ohci_iso_recv {
-       struct ti_ohci *ohci;
-
-       struct ohci1394_iso_tasklet task;
-       int task_active;
-
-       enum { BUFFER_FILL_MODE = 0,
-              PACKET_PER_BUFFER_MODE = 1 } dma_mode;
-
-       /* memory and PCI mapping for the DMA descriptors */
-       struct dma_prog_region prog;
-       struct dma_cmd *block; /* = (struct dma_cmd*) prog.virt */
-
-       /* how many DMA blocks fit in the buffer */
-       unsigned int nblocks;
-
-       /* stride of DMA blocks */
-       unsigned int buf_stride;
-
-       /* number of blocks to batch between interrupts */
-       int block_irq_interval;
-
-       /* block that DMA will finish next */
-       int block_dma;
-
-       /* (buffer-fill only) block that the reader will release next */
-       int block_reader;
-
-       /* (buffer-fill only) bytes of buffer the reader has released,
-          less than one block */
-       int released_bytes;
-
-       /* (buffer-fill only) buffer offset at which the next packet will appear */
-       int dma_offset;
-
-       /* OHCI DMA context control registers */
-       u32 ContextControlSet;
-       u32 ContextControlClear;
-       u32 CommandPtr;
-       u32 ContextMatch;
-};
-
-static void ohci_iso_recv_task(unsigned long data);
-static void ohci_iso_recv_stop(struct hpsb_iso *iso);
-static void ohci_iso_recv_shutdown(struct hpsb_iso *iso);
-static int  ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync);
-static void ohci_iso_recv_program(struct hpsb_iso *iso);
-
-static int ohci_iso_recv_init(struct hpsb_iso *iso)
-{
-       struct ti_ohci *ohci = iso->host->hostdata;
-       struct ohci_iso_recv *recv;
-       int ctx;
-       int ret = -ENOMEM;
-
-       recv = kmalloc(sizeof(*recv), GFP_KERNEL);
-       if (!recv)
-               return -ENOMEM;
-
-       iso->hostdata = recv;
-       recv->ohci = ohci;
-       recv->task_active = 0;
-       dma_prog_region_init(&recv->prog);
-       recv->block = NULL;
-
-       /* use buffer-fill mode, unless irq_interval is 1
-          (note: multichannel requires buffer-fill) */
-
-       if (((iso->irq_interval == 1 && iso->dma_mode == HPSB_ISO_DMA_OLD_ABI) ||
-            iso->dma_mode == HPSB_ISO_DMA_PACKET_PER_BUFFER) && iso->channel != -1) {
-               recv->dma_mode = PACKET_PER_BUFFER_MODE;
-       } else {
-               recv->dma_mode = BUFFER_FILL_MODE;
-       }
-
-       /* set nblocks, buf_stride, block_irq_interval */
-
-       if (recv->dma_mode == BUFFER_FILL_MODE) {
-               recv->buf_stride = PAGE_SIZE;
-
-               /* one block per page of data in the DMA buffer, minus the final guard page */
-               recv->nblocks = iso->buf_size/PAGE_SIZE - 1;
-               if (recv->nblocks < 3) {
-                       DBGMSG("ohci_iso_recv_init: DMA buffer too small");
-                       goto err;
-               }
-
-               /* iso->irq_interval is in packets - translate that to blocks */
-               if (iso->irq_interval == 1)
-                       recv->block_irq_interval = 1;
-               else
-                       recv->block_irq_interval = iso->irq_interval *
-                                                       ((recv->nblocks+1)/iso->buf_packets);
-               if (recv->block_irq_interval*4 > recv->nblocks)
-                       recv->block_irq_interval = recv->nblocks/4;
-               if (recv->block_irq_interval < 1)
-                       recv->block_irq_interval = 1;
-
-       } else {
-               int max_packet_size;
-
-               recv->nblocks = iso->buf_packets;
-               recv->block_irq_interval = iso->irq_interval;
-               if (recv->block_irq_interval * 4 > iso->buf_packets)
-                       recv->block_irq_interval = iso->buf_packets / 4;
-               if (recv->block_irq_interval < 1)
-                       recv->block_irq_interval = 1;
-
-               /* choose a buffer stride */
-               /* must be a power of 2, and <= PAGE_SIZE */
-
-               max_packet_size = iso->buf_size / iso->buf_packets;
-
-               for (recv->buf_stride = 8; recv->buf_stride < max_packet_size;
-                   recv->buf_stride *= 2);
-
-               if (recv->buf_stride*iso->buf_packets > iso->buf_size ||
-                  recv->buf_stride > PAGE_SIZE) {
-                       /* this shouldn't happen, but anyway... */
-                       DBGMSG("ohci_iso_recv_init: problem choosing a buffer stride");
-                       goto err;
-               }
-       }
-
-       recv->block_reader = 0;
-       recv->released_bytes = 0;
-       recv->block_dma = 0;
-       recv->dma_offset = 0;
-
-       /* size of DMA program = one descriptor per block */
-       if (dma_prog_region_alloc(&recv->prog,
-                                sizeof(struct dma_cmd) * recv->nblocks,
-                                recv->ohci->dev))
-               goto err;
-
-       recv->block = (struct dma_cmd*) recv->prog.kvirt;
-
-       ohci1394_init_iso_tasklet(&recv->task,
-                                 iso->channel == -1 ? OHCI_ISO_MULTICHANNEL_RECEIVE :
-                                                      OHCI_ISO_RECEIVE,
-                                 ohci_iso_recv_task, (unsigned long) iso);
-
-       if (ohci1394_register_iso_tasklet(recv->ohci, &recv->task) < 0) {
-               ret = -EBUSY;
-               goto err;
-       }
-
-       recv->task_active = 1;
-
-       /* recv context registers are spaced 32 bytes apart */
-       ctx = recv->task.context;
-       recv->ContextControlSet = OHCI1394_IsoRcvContextControlSet + 32 * ctx;
-       recv->ContextControlClear = OHCI1394_IsoRcvContextControlClear + 32 * ctx;
-       recv->CommandPtr = OHCI1394_IsoRcvCommandPtr + 32 * ctx;
-       recv->ContextMatch = OHCI1394_IsoRcvContextMatch + 32 * ctx;
-
-       if (iso->channel == -1) {
-               /* clear multi-channel selection mask */
-               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, 0xFFFFFFFF);
-               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, 0xFFFFFFFF);
-       }
-
-       /* write the DMA program */
-       ohci_iso_recv_program(iso);
-
-       DBGMSG("ohci_iso_recv_init: %s mode, DMA buffer is %lu pages"
-              " (%u bytes), using %u blocks, buf_stride %u, block_irq_interval %d",
-              recv->dma_mode == BUFFER_FILL_MODE ?
-              "buffer-fill" : "packet-per-buffer",
-              iso->buf_size/PAGE_SIZE, iso->buf_size,
-              recv->nblocks, recv->buf_stride, recv->block_irq_interval);
-
-       return 0;
-
-err:
-       ohci_iso_recv_shutdown(iso);
-       return ret;
-}
-
-static void ohci_iso_recv_stop(struct hpsb_iso *iso)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-
-       /* disable interrupts */
-       reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskClear, 1 << recv->task.context);
-
-       /* halt DMA */
-       ohci1394_stop_context(recv->ohci, recv->ContextControlClear, NULL);
-}
-
-static void ohci_iso_recv_shutdown(struct hpsb_iso *iso)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-
-       if (recv->task_active) {
-               ohci_iso_recv_stop(iso);
-               ohci1394_unregister_iso_tasklet(recv->ohci, &recv->task);
-               recv->task_active = 0;
-       }
-
-       dma_prog_region_free(&recv->prog);
-       kfree(recv);
-       iso->hostdata = NULL;
-}
-
-/* set up a "gapped" ring buffer DMA program */
-static void ohci_iso_recv_program(struct hpsb_iso *iso)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       int blk;
-
-       /* address of 'branch' field in previous DMA descriptor */
-       u32 *prev_branch = NULL;
-
-       for (blk = 0; blk < recv->nblocks; blk++) {
-               u32 control;
-
-               /* the DMA descriptor */
-               struct dma_cmd *cmd = &recv->block[blk];
-
-               /* offset of the DMA descriptor relative to the DMA prog buffer */
-               unsigned long prog_offset = blk * sizeof(struct dma_cmd);
-
-               /* offset of this packet's data within the DMA buffer */
-               unsigned long buf_offset = blk * recv->buf_stride;
-
-               if (recv->dma_mode == BUFFER_FILL_MODE) {
-                       control = 2 << 28; /* INPUT_MORE */
-               } else {
-                       control = 3 << 28; /* INPUT_LAST */
-               }
-
-               control |= 8 << 24; /* s = 1, update xferStatus and resCount */
-
-               /* interrupt on last block, and at intervals */
-               if (blk == recv->nblocks-1 || (blk % recv->block_irq_interval) == 0) {
-                       control |= 3 << 20; /* want interrupt */
-               }
-
-               control |= 3 << 18; /* enable branch to address */
-               control |= recv->buf_stride;
-
-               cmd->control = cpu_to_le32(control);
-               cmd->address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, buf_offset));
-               cmd->branchAddress = 0; /* filled in on next loop */
-               cmd->status = cpu_to_le32(recv->buf_stride);
-
-               /* link the previous descriptor to this one */
-               if (prev_branch) {
-                       *prev_branch = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog, prog_offset) | 1);
-               }
-
-               prev_branch = &cmd->branchAddress;
-       }
-
-       /* the final descriptor's branch address and Z should be left at 0 */
-}
-
-/* listen or unlisten to a specific channel (multi-channel mode only) */
-static void ohci_iso_recv_change_channel(struct hpsb_iso *iso, unsigned char channel, int listen)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       int reg, i;
-
-       if (channel < 32) {
-               reg = listen ? OHCI1394_IRMultiChanMaskLoSet : OHCI1394_IRMultiChanMaskLoClear;
-               i = channel;
-       } else {
-               reg = listen ? OHCI1394_IRMultiChanMaskHiSet : OHCI1394_IRMultiChanMaskHiClear;
-               i = channel - 32;
-       }
-
-       reg_write(recv->ohci, reg, (1 << i));
-
-       /* issue a dummy read to force all PCI writes to be posted immediately */
-       mb();
-       reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
-}
-
-static void ohci_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       int i;
-
-       for (i = 0; i < 64; i++) {
-               if (mask & (1ULL << i)) {
-                       if (i < 32)
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoSet, (1 << i));
-                       else
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiSet, (1 << (i-32)));
-               } else {
-                       if (i < 32)
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskLoClear, (1 << i));
-                       else
-                               reg_write(recv->ohci, OHCI1394_IRMultiChanMaskHiClear, (1 << (i-32)));
-               }
-       }
-
-       /* issue a dummy read to force all PCI writes to be posted immediately */
-       mb();
-       reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
-}
-
-static int ohci_iso_recv_start(struct hpsb_iso *iso, int cycle, int tag_mask, int sync)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       struct ti_ohci *ohci = recv->ohci;
-       u32 command, contextMatch;
-
-       reg_write(recv->ohci, recv->ContextControlClear, 0xFFFFFFFF);
-       wmb();
-
-       /* always keep ISO headers */
-       command = (1 << 30);
-
-       if (recv->dma_mode == BUFFER_FILL_MODE)
-               command |= (1 << 31);
-
-       reg_write(recv->ohci, recv->ContextControlSet, command);
-
-       /* match on specified tags */
-       contextMatch = tag_mask << 28;
-
-       if (iso->channel == -1) {
-               /* enable multichannel reception */
-               reg_write(recv->ohci, recv->ContextControlSet, (1 << 28));
-       } else {
-               /* listen on channel */
-               contextMatch |= iso->channel;
-       }
-
-       if (cycle != -1) {
-               u32 seconds;
-
-               /* enable cycleMatch */
-               reg_write(recv->ohci, recv->ContextControlSet, (1 << 29));
-
-               /* set starting cycle */
-               cycle &= 0x1FFF;
-
-               /* 'cycle' is only mod 8000, but we also need two 'seconds' bits -
-                  just snarf them from the current time */
-               seconds = reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer) >> 25;
-
-               /* advance one second to give some extra time for DMA to start */
-               seconds += 1;
-
-               cycle |= (seconds & 3) << 13;
-
-               contextMatch |= cycle << 12;
-       }
-
-       if (sync != -1) {
-               /* set sync flag on first DMA descriptor */
-               struct dma_cmd *cmd = &recv->block[recv->block_dma];
-               cmd->control |= cpu_to_le32(DMA_CTL_WAIT);
-
-               /* match sync field */
-               contextMatch |= (sync&0xf)<<8;
-       }
-
-       reg_write(recv->ohci, recv->ContextMatch, contextMatch);
-
-       /* address of first descriptor block */
-       command = dma_prog_region_offset_to_bus(&recv->prog,
-                                               recv->block_dma * sizeof(struct dma_cmd));
-       command |= 1; /* Z=1 */
-
-       reg_write(recv->ohci, recv->CommandPtr, command);
-
-       /* enable interrupts */
-       reg_write(recv->ohci, OHCI1394_IsoRecvIntMaskSet, 1 << recv->task.context);
-
-       wmb();
-
-       /* run */
-       reg_write(recv->ohci, recv->ContextControlSet, 0x8000);
-
-       /* issue a dummy read of the cycle timer register to force
-          all PCI writes to be posted immediately */
-       mb();
-       reg_read(recv->ohci, OHCI1394_IsochronousCycleTimer);
-
-       /* check RUN */
-       if (!(reg_read(recv->ohci, recv->ContextControlSet) & 0x8000)) {
-               PRINT(KERN_ERR,
-                     "Error starting IR DMA (ContextControl 0x%08x)\n",
-                     reg_read(recv->ohci, recv->ContextControlSet));
-               return -1;
-       }
-
-       return 0;
-}
-
-static void ohci_iso_recv_release_block(struct ohci_iso_recv *recv, int block)
-{
-       /* re-use the DMA descriptor for the block */
-       /* by linking the previous descriptor to it */
-
-       int next_i = block;
-       int prev_i = (next_i == 0) ? (recv->nblocks - 1) : (next_i - 1);
-
-       struct dma_cmd *next = &recv->block[next_i];
-       struct dma_cmd *prev = &recv->block[prev_i];
-       
-       /* ignore out-of-range requests */
-       if ((block < 0) || (block > recv->nblocks))
-               return;
-
-       /* 'next' becomes the new end of the DMA chain,
-          so disable branch and enable interrupt */
-       next->branchAddress = 0;
-       next->control |= cpu_to_le32(3 << 20);
-       next->status = cpu_to_le32(recv->buf_stride);
-
-       /* link prev to next */
-       prev->branchAddress = cpu_to_le32(dma_prog_region_offset_to_bus(&recv->prog,
-                                                                       sizeof(struct dma_cmd) * next_i)
-                                         | 1); /* Z=1 */
-
-       /* disable interrupt on previous DMA descriptor, except at intervals */
-       if ((prev_i % recv->block_irq_interval) == 0) {
-               prev->control |= cpu_to_le32(3 << 20); /* enable interrupt */
-       } else {
-               prev->control &= cpu_to_le32(~(3<<20)); /* disable interrupt */
-       }
-       wmb();
-
-       /* wake up DMA in case it fell asleep */
-       reg_write(recv->ohci, recv->ContextControlSet, (1 << 12));
-}
-
-static void ohci_iso_recv_bufferfill_release(struct ohci_iso_recv *recv,
-                                            struct hpsb_iso_packet_info *info)
-{
-       /* release the memory where the packet was */
-       recv->released_bytes += info->total_len;
-
-       /* have we released enough memory for one block? */
-       while (recv->released_bytes > recv->buf_stride) {
-               ohci_iso_recv_release_block(recv, recv->block_reader);
-               recv->block_reader = (recv->block_reader + 1) % recv->nblocks;
-               recv->released_bytes -= recv->buf_stride;
-       }
-}
-
-static inline void ohci_iso_recv_release(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info)
-{
-       struct ohci_iso_recv *recv = iso->hostdata;
-       if (recv->dma_mode == BUFFER_FILL_MODE) {
-               ohci_iso_recv_bufferfill_release(recv, info);
-       } else {
-               ohci_iso_recv_release_block(recv, info - iso->infos);
-       }
-}
-
-/* parse all packets from blocks that have been fully received */
-static void ohci_iso_recv_bufferfill_parse(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
-{
-       int wake = 0;
-       int runaway = 0;
-       struct ti_ohci *ohci = recv->ohci;
-
-       while (1) {
-               /* we expect the next parsable packet to begin at recv->dma_offset */
-               /* note: packet layout is as shown in section 10.6.1.1 of the OHCI spec */
-
-               unsigned int offset;
-               unsigned short len, cycle, total_len;
-               unsigned char channel, tag, sy;
-
-               unsigned char *p = iso->data_buf.kvirt;
-
-               unsigned int this_block = recv->dma_offset/recv->buf_stride;
-
-               /* don't loop indefinitely */
-               if (runaway++ > 100000) {
-                       atomic_inc(&iso->overflows);
-                       PRINT(KERN_ERR,
-                             "IR DMA error - Runaway during buffer parsing!\n");
-                       break;
-               }
-
-               /* stop parsing once we arrive at block_dma (i.e. don't get ahead of DMA) */
-               if (this_block == recv->block_dma)
-                       break;
-
-               wake = 1;
-
-               /* parse data length, tag, channel, and sy */
-
-               /* note: we keep our own local copies of 'len' and 'offset'
-                  so the user can't mess with them by poking in the mmap area */
-
-               len = p[recv->dma_offset+2] | (p[recv->dma_offset+3] << 8);
-
-               if (len > 4096) {
-                       PRINT(KERN_ERR,
-                             "IR DMA error - bogus 'len' value %u\n", len);
-               }
-
-               channel = p[recv->dma_offset+1] & 0x3F;
-               tag = p[recv->dma_offset+1] >> 6;
-               sy = p[recv->dma_offset+0] & 0xF;
-
-               /* advance to data payload */
-               recv->dma_offset += 4;
-
-               /* check for wrap-around */
-               if (recv->dma_offset >= recv->buf_stride*recv->nblocks) {
-                       recv->dma_offset -= recv->buf_stride*recv->nblocks;
-               }
-
-               /* dma_offset now points to the first byte of the data payload */
-               offset = recv->dma_offset;
-
-               /* advance to xferStatus/timeStamp */
-               recv->dma_offset += len;
-
-               total_len = len + 8; /* 8 bytes header+trailer in OHCI packet */
-               /* payload is padded to 4 bytes */
-               if (len % 4) {
-                       recv->dma_offset += 4 - (len%4);
-                       total_len += 4 - (len%4);
-               }
-
-               /* check for wrap-around */
-               if (recv->dma_offset >= recv->buf_stride*recv->nblocks) {
-                       /* uh oh, the packet data wraps from the last
-                           to the first DMA block - make the packet
-                           contiguous by copying its "tail" into the
-                           guard page */
-
-                       int guard_off = recv->buf_stride*recv->nblocks;
-                       int tail_len = len - (guard_off - offset);
-
-                       if (tail_len > 0  && tail_len < recv->buf_stride) {
-                               memcpy(iso->data_buf.kvirt + guard_off,
-                                      iso->data_buf.kvirt,
-                                      tail_len);
-                       }
-
-                       recv->dma_offset -= recv->buf_stride*recv->nblocks;
-               }
-
-               /* parse timestamp */
-               cycle = p[recv->dma_offset+0] | (p[recv->dma_offset+1]<<8);
-               cycle &= 0x1FFF;
-
-               /* advance to next packet */
-               recv->dma_offset += 4;
-
-               /* check for wrap-around */
-               if (recv->dma_offset >= recv->buf_stride*recv->nblocks) {
-                       recv->dma_offset -= recv->buf_stride*recv->nblocks;
-               }
-
-               hpsb_iso_packet_received(iso, offset, len, total_len, cycle, channel, tag, sy);
-       }
-
-       if (wake)
-               hpsb_iso_wake(iso);
-}
-
-static void ohci_iso_recv_bufferfill_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
-{
-       int loop;
-       struct ti_ohci *ohci = recv->ohci;
-
-       /* loop over all blocks */
-       for (loop = 0; loop < recv->nblocks; loop++) {
-
-               /* check block_dma to see if it's done */
-               struct dma_cmd *im = &recv->block[recv->block_dma];
-
-               /* check the DMA descriptor for new writes to xferStatus */
-               u16 xferstatus = le32_to_cpu(im->status) >> 16;
-
-               /* rescount is the number of bytes *remaining to be written* in the block */
-               u16 rescount = le32_to_cpu(im->status) & 0xFFFF;
-
-               unsigned char event = xferstatus & 0x1F;
-
-               if (!event) {
-                       /* nothing has happened to this block yet */
-                       break;
-               }
-
-               if (event != 0x11) {
-                       atomic_inc(&iso->overflows);
-                       PRINT(KERN_ERR,
-                             "IR DMA error - OHCI error code 0x%02x\n", event);
-               }
-
-               if (rescount != 0) {
-                       /* the card is still writing to this block;
-                          we can't touch it until it's done */
-                       break;
-               }
-
-               /* OK, the block is finished... */
-
-               /* sync our view of the block */
-               dma_region_sync_for_cpu(&iso->data_buf, recv->block_dma*recv->buf_stride, recv->buf_stride);
-
-               /* reset the DMA descriptor */
-               im->status = recv->buf_stride;
-
-               /* advance block_dma */
-               recv->block_dma = (recv->block_dma + 1) % recv->nblocks;
-
-               if ((recv->block_dma+1) % recv->nblocks == recv->block_reader) {
-                       atomic_inc(&iso->overflows);
-                       DBGMSG("ISO reception overflow - "
-                              "ran out of DMA blocks");
-               }
-       }
-
-       /* parse any packets that have arrived */
-       ohci_iso_recv_bufferfill_parse(iso, recv);
-}
-
-static void ohci_iso_recv_packetperbuf_task(struct hpsb_iso *iso, struct ohci_iso_recv *recv)
-{
-       int count;
-       int wake = 0;
-       struct ti_ohci *ohci = recv->ohci;
-
-       /* loop over the entire buffer */
-       for (count = 0; count < recv->nblocks; count++) {
-               u32 packet_len = 0;
-
-               /* pointer to the DMA descriptor */
-               struct dma_cmd *il = ((struct dma_cmd*) recv->prog.kvirt) + iso->pkt_dma;
-
-               /* check the DMA descriptor for new writes to xferStatus */
-               u16 xferstatus = le32_to_cpu(il->status) >> 16;
-               u16 rescount = le32_to_cpu(il->status) & 0xFFFF;
-
-               unsigned char event = xferstatus & 0x1F;
-
-               if (!event) {
-                       /* this packet hasn't come in yet; we are done for now */
-                       goto out;
-               }
-
-               if (event == 0x11) {
-                       /* packet received successfully! */
-
-                       /* rescount is the number of bytes *remaining* in the packet buffer,
-                          after the packet was written */
-                       packet_len = recv->buf_stride - rescount;
-
-               } else if (event == 0x02) {
-                       PRINT(KERN_ERR, "IR DMA error - packet too long for buffer\n");
-               } else if (event) {
-                       PRINT(KERN_ERR, "IR DMA error - OHCI error code 0x%02x\n", event);
-               }
-
-               /* sync our view of the buffer */
-               dma_region_sync_for_cpu(&iso->data_buf, iso->pkt_dma * recv->buf_stride, recv->buf_stride);
-
-               /* record the per-packet info */
-               {
-                       /* iso header is 8 bytes ahead of the data payload */
-                       unsigned char *hdr;
-
-                       unsigned int offset;
-                       unsigned short cycle;
-                       unsigned char channel, tag, sy;
-
-                       offset = iso->pkt_dma * recv->buf_stride;
-                       hdr = iso->data_buf.kvirt + offset;
-
-                       /* skip iso header */
-                       offset += 8;
-                       packet_len -= 8;
-
-                       cycle = (hdr[0] | (hdr[1] << 8)) & 0x1FFF;
-                       channel = hdr[5] & 0x3F;
-                       tag = hdr[5] >> 6;
-                       sy = hdr[4] & 0xF;
-
-                       hpsb_iso_packet_received(iso, offset, packet_len,
-                                       recv->buf_stride, cycle, channel, tag, sy);
-               }
-
-               /* reset the DMA descriptor */
-               il->status = recv->buf_stride;
-
-               wake = 1;
-               recv->block_dma = iso->pkt_dma;
-       }
-
-out:
-       if (wake)
-               hpsb_iso_wake(iso);
-}
-
-static void ohci_iso_recv_task(unsigned long data)
-{
-       struct hpsb_iso *iso = (struct hpsb_iso*) data;
-       struct ohci_iso_recv *recv = iso->hostdata;
-
-       if (recv->dma_mode == BUFFER_FILL_MODE)
-               ohci_iso_recv_bufferfill_task(iso, recv);
-       else
-               ohci_iso_recv_packetperbuf_task(iso, recv);
-}
-
-/***********************************
- * rawiso ISO transmission         *
- ***********************************/
-
-struct ohci_iso_xmit {
-       struct ti_ohci *ohci;
-       struct dma_prog_region prog;
-       struct ohci1394_iso_tasklet task;
-       int task_active;
-       int last_cycle;
-       atomic_t skips;
-
-       u32 ContextControlSet;
-       u32 ContextControlClear;
-       u32 CommandPtr;
-};
-
-/* transmission DMA program:
-   one OUTPUT_MORE_IMMEDIATE for the IT header
-   one OUTPUT_LAST for the buffer data */
-
-struct iso_xmit_cmd {
-       struct dma_cmd output_more_immediate;
-       u8 iso_hdr[8];
-       u32 unused[2];
-       struct dma_cmd output_last;
-};
-
-static int ohci_iso_xmit_init(struct hpsb_iso *iso);
-static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle);
-static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso);
-static void ohci_iso_xmit_task(unsigned long data);
-
-static int ohci_iso_xmit_init(struct hpsb_iso *iso)
-{
-       struct ohci_iso_xmit *xmit;
-       unsigned int prog_size;
-       int ctx;
-       int ret = -ENOMEM;
-
-       xmit = kmalloc(sizeof(*xmit), GFP_KERNEL);
-       if (!xmit)
-               return -ENOMEM;
-
-       iso->hostdata = xmit;
-       xmit->ohci = iso->host->hostdata;
-       xmit->task_active = 0;
-       xmit->last_cycle = -1;
-       atomic_set(&iso->skips, 0);
-
-       dma_prog_region_init(&xmit->prog);
-
-       prog_size = sizeof(struct iso_xmit_cmd) * iso->buf_packets;
-
-       if (dma_prog_region_alloc(&xmit->prog, prog_size, xmit->ohci->dev))
-               goto err;
-
-       ohci1394_init_iso_tasklet(&xmit->task, OHCI_ISO_TRANSMIT,
-                                 ohci_iso_xmit_task, (unsigned long) iso);
-
-       if (ohci1394_register_iso_tasklet(xmit->ohci, &xmit->task) < 0) {
-               ret = -EBUSY;
-               goto err;
-       }
-
-       xmit->task_active = 1;
-
-       /* xmit context registers are spaced 16 bytes apart */
-       ctx = xmit->task.context;
-       xmit->ContextControlSet = OHCI1394_IsoXmitContextControlSet + 16 * ctx;
-       xmit->ContextControlClear = OHCI1394_IsoXmitContextControlClear + 16 * ctx;
-       xmit->CommandPtr = OHCI1394_IsoXmitCommandPtr + 16 * ctx;
-
-       return 0;
-
-err:
-       ohci_iso_xmit_shutdown(iso);
-       return ret;
-}
-
-static void ohci_iso_xmit_stop(struct hpsb_iso *iso)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-
-       /* disable interrupts */
-       reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskClear, 1 << xmit->task.context);
-
-       /* halt DMA */
-       if (ohci1394_stop_context(xmit->ohci, xmit->ContextControlClear, NULL)) {
-               /* XXX the DMA context will lock up if you try to send too much data! */
-               PRINT(KERN_ERR,
-                     "you probably exceeded the OHCI card's bandwidth limit - "
-                     "reload the module and reduce xmit bandwidth");
-       }
-}
-
-static void ohci_iso_xmit_shutdown(struct hpsb_iso *iso)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-
-       if (xmit->task_active) {
-               ohci_iso_xmit_stop(iso);
-               ohci1394_unregister_iso_tasklet(xmit->ohci, &xmit->task);
-               xmit->task_active = 0;
-       }
-
-       dma_prog_region_free(&xmit->prog);
-       kfree(xmit);
-       iso->hostdata = NULL;
-}
-
-static void ohci_iso_xmit_task(unsigned long data)
-{
-       struct hpsb_iso *iso = (struct hpsb_iso*) data;
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-       int wake = 0;
-       int count;
-
-       /* check the whole buffer if necessary, starting at pkt_dma */
-       for (count = 0; count < iso->buf_packets; count++) {
-               int cycle;
-
-               /* DMA descriptor */
-               struct iso_xmit_cmd *cmd = dma_region_i(&xmit->prog, struct iso_xmit_cmd, iso->pkt_dma);
-
-               /* check for new writes to xferStatus */
-               u16 xferstatus = le32_to_cpu(cmd->output_last.status) >> 16;
-               u8  event = xferstatus & 0x1F;
-
-               if (!event) {
-                       /* packet hasn't been sent yet; we are done for now */
-                       break;
-               }
-
-               if (event != 0x11)
-                       PRINT(KERN_ERR,
-                             "IT DMA error - OHCI error code 0x%02x\n", event);
-
-               /* at least one packet went out, so wake up the writer */
-               wake = 1;
-
-               /* parse cycle */
-               cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF;
-
-               if (xmit->last_cycle > -1) {
-                       int cycle_diff = cycle - xmit->last_cycle;
-                       int skip;
-
-                       /* unwrap */
-                       if (cycle_diff < 0) {
-                               cycle_diff += 8000;
-                               if (cycle_diff < 0)
-                                       PRINT(KERN_ERR, "bogus cycle diff %d\n",
-                                             cycle_diff);
-                       }
-
-                       skip = cycle_diff - 1;
-                       if (skip > 0) {
-                               DBGMSG("skipped %d cycles without packet loss", skip);
-                               atomic_add(skip, &iso->skips);
-                       }
-               }
-               xmit->last_cycle = cycle;
-
-               /* tell the subsystem the packet has gone out */
-               hpsb_iso_packet_sent(iso, cycle, event != 0x11);
-
-               /* reset the DMA descriptor for next time */
-               cmd->output_last.status = 0;
-       }
-
-       if (wake)
-               hpsb_iso_wake(iso);
-}
-
-static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info *info)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-
-       int next_i, prev_i;
-       struct iso_xmit_cmd *next, *prev;
-
-       unsigned int offset;
-       unsigned short len;
-       unsigned char tag, sy;
-
-       /* check that the packet doesn't cross a page boundary
-          (we could allow this if we added OUTPUT_MORE descriptor support) */
-       if (cross_bound(info->offset, info->len)) {
-               PRINT(KERN_ERR,
-                     "rawiso xmit: packet %u crosses a page boundary",
-                     iso->first_packet);
-               return -EINVAL;
-       }
-
-       offset = info->offset;
-       len = info->len;
-       tag = info->tag;
-       sy = info->sy;
-
-       /* sync up the card's view of the buffer */
-       dma_region_sync_for_device(&iso->data_buf, offset, len);
-
-       /* append first_packet to the DMA chain */
-       /* by linking the previous descriptor to it */
-       /* (next will become the new end of the DMA chain) */
-
-       next_i = iso->first_packet;
-       prev_i = (next_i == 0) ? (iso->buf_packets - 1) : (next_i - 1);
-
-       next = dma_region_i(&xmit->prog, struct iso_xmit_cmd, next_i);
-       prev = dma_region_i(&xmit->prog, struct iso_xmit_cmd, prev_i);
-
-       /* set up the OUTPUT_MORE_IMMEDIATE descriptor */
-       memset(next, 0, sizeof(struct iso_xmit_cmd));
-       next->output_more_immediate.control = cpu_to_le32(0x02000008);
-
-       /* ISO packet header is embedded in the OUTPUT_MORE_IMMEDIATE */
-
-       /* tcode = 0xA, and sy */
-       next->iso_hdr[0] = 0xA0 | (sy & 0xF);
-
-       /* tag and channel number */
-       next->iso_hdr[1] = (tag << 6) | (iso->channel & 0x3F);
-
-       /* transmission speed */
-       next->iso_hdr[2] = iso->speed & 0x7;
-
-       /* payload size */
-       next->iso_hdr[6] = len & 0xFF;
-       next->iso_hdr[7] = len >> 8;
-
-       /* set up the OUTPUT_LAST */
-       next->output_last.control = cpu_to_le32(1 << 28);
-       next->output_last.control |= cpu_to_le32(1 << 27); /* update timeStamp */
-       next->output_last.control |= cpu_to_le32(3 << 20); /* want interrupt */
-       next->output_last.control |= cpu_to_le32(3 << 18); /* enable branch */
-       next->output_last.control |= cpu_to_le32(len);
-
-       /* payload bus address */
-       next->output_last.address = cpu_to_le32(dma_region_offset_to_bus(&iso->data_buf, offset));
-
-       /* leave branchAddress at zero for now */
-
-       /* re-write the previous DMA descriptor to chain to this one */
-
-       /* set prev branch address to point to next (Z=3) */
-       prev->output_last.branchAddress = cpu_to_le32(
-               dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3);
-
-       /*
-        * Link the skip address to this descriptor itself. This causes a
-        * context to skip a cycle whenever lost cycles or FIFO overruns occur,
-        * without dropping the data at that point the application should then
-        * decide whether this is an error condition or not. Some protocols
-        * can deal with this by dropping some rate-matching padding packets.
-        */
-       next->output_more_immediate.branchAddress =
-                       prev->output_last.branchAddress;
-
-       /* disable interrupt, unless required by the IRQ interval */
-       if (prev_i % iso->irq_interval) {
-               prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */
-       } else {
-               prev->output_last.control |= cpu_to_le32(3 << 20); /* enable interrupt */
-       }
-
-       wmb();
-
-       /* wake DMA in case it is sleeping */
-       reg_write(xmit->ohci, xmit->ContextControlSet, 1 << 12);
-
-       /* issue a dummy read of the cycle timer to force all PCI
-          writes to be posted immediately */
-       mb();
-       reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer);
-
-       return 0;
-}
-
-static int ohci_iso_xmit_start(struct hpsb_iso *iso, int cycle)
-{
-       struct ohci_iso_xmit *xmit = iso->hostdata;
-       struct ti_ohci *ohci = xmit->ohci;
-
-       /* clear out the control register */
-       reg_write(xmit->ohci, xmit->ContextControlClear, 0xFFFFFFFF);
-       wmb();
-
-       /* address and length of first descriptor block (Z=3) */
-       reg_write(xmit->ohci, xmit->CommandPtr,
-                 dma_prog_region_offset_to_bus(&xmit->prog, iso->pkt_dma * sizeof(struct iso_xmit_cmd)) | 3);
-
-       /* cycle match */
-       if (cycle != -1) {
-               u32 start = cycle & 0x1FFF;
-
-               /* 'cycle' is only mod 8000, but we also need two 'seconds' bits -
-                  just snarf them from the current time */
-               u32 seconds = reg_read(xmit->ohci, OHCI1394_IsochronousCycleTimer) >> 25;
-
-               /* advance one second to give some extra time for DMA to start */
-               seconds += 1;
-
-               start |= (seconds & 3) << 13;
-
-               reg_write(xmit->ohci, xmit->ContextControlSet, 0x80000000 | (start << 16));
-       }
-
-       /* enable interrupts */
-       reg_write(xmit->ohci, OHCI1394_IsoXmitIntMaskSet, 1 << xmit->task.context);
-
-       /* run */
-       reg_write(xmit->ohci, xmit->ContextControlSet, 0x8000);
-       mb();
-
-       /* wait 100 usec to give the card time to go active */
-       udelay(100);
-
-       /* check the RUN bit */
-       if (!(reg_read(xmit->ohci, xmit->ContextControlSet) & 0x8000)) {
-               PRINT(KERN_ERR, "Error starting IT DMA (ContextControl 0x%08x)\n",
-                     reg_read(xmit->ohci, xmit->ContextControlSet));
-               return -1;
-       }
-
-       return 0;
-}
-
-static int ohci_isoctl(struct hpsb_iso *iso, enum isoctl_cmd cmd, unsigned long arg)
-{
-
-       switch(cmd) {
-       case XMIT_INIT:
-               return ohci_iso_xmit_init(iso);
-       case XMIT_START:
-               return ohci_iso_xmit_start(iso, arg);
-       case XMIT_STOP:
-               ohci_iso_xmit_stop(iso);
-               return 0;
-       case XMIT_QUEUE:
-               return ohci_iso_xmit_queue(iso, (struct hpsb_iso_packet_info*) arg);
-       case XMIT_SHUTDOWN:
-               ohci_iso_xmit_shutdown(iso);
-               return 0;
-
-       case RECV_INIT:
-               return ohci_iso_recv_init(iso);
-       case RECV_START: {
-               int *args = (int*) arg;
-               return ohci_iso_recv_start(iso, args[0], args[1], args[2]);
-       }
-       case RECV_STOP:
-               ohci_iso_recv_stop(iso);
-               return 0;
-       case RECV_RELEASE:
-               ohci_iso_recv_release(iso, (struct hpsb_iso_packet_info*) arg);
-               return 0;
-       case RECV_FLUSH:
-               ohci_iso_recv_task((unsigned long) iso);
-               return 0;
-       case RECV_SHUTDOWN:
-               ohci_iso_recv_shutdown(iso);
-               return 0;
-       case RECV_LISTEN_CHANNEL:
-               ohci_iso_recv_change_channel(iso, arg, 1);
-               return 0;
-       case RECV_UNLISTEN_CHANNEL:
-               ohci_iso_recv_change_channel(iso, arg, 0);
-               return 0;
-       case RECV_SET_CHANNEL_MASK:
-               ohci_iso_recv_set_channel_mask(iso, *((u64*) arg));
-               return 0;
-
-       default:
-               PRINT_G(KERN_ERR, "ohci_isoctl cmd %d not implemented yet",
-                       cmd);
-               break;
-       }
-       return -EINVAL;
-}
-
-/***************************************
- * IEEE-1394 functionality section END *
- ***************************************/
-
-
-/********************************************************
- * Global stuff (interrupt handler, init/shutdown code) *
- ********************************************************/
-
-static void dma_trm_reset(struct dma_trm_ctx *d)
-{
-       unsigned long flags;
-       LIST_HEAD(packet_list);
-       struct ti_ohci *ohci = d->ohci;
-       struct hpsb_packet *packet, *ptmp;
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       /* Lock the context, reset it and release it. Move the packets
-        * that were pending in the context to packet_list and free
-        * them after releasing the lock. */
-
-       spin_lock_irqsave(&d->lock, flags);
-
-       list_splice_init(&d->fifo_list, &packet_list);
-       list_splice_init(&d->pending_list, &packet_list);
-
-       d->branchAddrPtr = NULL;
-       d->sent_ind = d->prg_ind;
-       d->free_prgs = d->num_desc;
-
-       spin_unlock_irqrestore(&d->lock, flags);
-
-       if (list_empty(&packet_list))
-               return;
-
-       PRINT(KERN_INFO, "AT dma reset ctx=%d, aborting transmission", d->ctx);
-
-       /* Now process subsystem callbacks for the packets from this
-        * context. */
-       list_for_each_entry_safe(packet, ptmp, &packet_list, driver_list) {
-               list_del_init(&packet->driver_list);
-               hpsb_packet_sent(ohci->host, packet, ACKX_ABORTED);
-       }
-}
-
-static void ohci_schedule_iso_tasklets(struct ti_ohci *ohci,
-                                      quadlet_t rx_event,
-                                      quadlet_t tx_event)
-{
-       struct ohci1394_iso_tasklet *t;
-       unsigned long mask;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
-
-       list_for_each_entry(t, &ohci->iso_tasklet_list, link) {
-               mask = 1 << t->context;
-
-               if (t->type == OHCI_ISO_TRANSMIT) {
-                       if (tx_event & mask)
-                               tasklet_schedule(&t->tasklet);
-               } else {
-                       /* OHCI_ISO_RECEIVE or OHCI_ISO_MULTICHANNEL_RECEIVE */
-                       if (rx_event & mask)
-                               tasklet_schedule(&t->tasklet);
-               }
-       }
-
-       spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-}
-
-static irqreturn_t ohci_irq_handler(int irq, void *dev_id)
-{
-       quadlet_t event, node_id;
-       struct ti_ohci *ohci = (struct ti_ohci *)dev_id;
-       struct hpsb_host *host = ohci->host;
-       int phyid = -1, isroot = 0;
-       unsigned long flags;
-
-       /* Read and clear the interrupt event register.  Don't clear
-        * the busReset event, though. This is done when we get the
-        * selfIDComplete interrupt. */
-       spin_lock_irqsave(&ohci->event_lock, flags);
-       event = reg_read(ohci, OHCI1394_IntEventClear);
-       reg_write(ohci, OHCI1394_IntEventClear, event & ~OHCI1394_busReset);
-       spin_unlock_irqrestore(&ohci->event_lock, flags);
-
-       if (!event)
-               return IRQ_NONE;
-
-       /* If event is ~(u32)0 cardbus card was ejected.  In this case
-        * we just return, and clean up in the ohci1394_pci_remove
-        * function. */
-       if (event == ~(u32) 0) {
-               DBGMSG("Device removed.");
-               return IRQ_NONE;
-       }
-
-       DBGMSG("IntEvent: %08x", event);
-
-       if (event & OHCI1394_unrecoverableError) {
-               int ctx;
-               PRINT(KERN_ERR, "Unrecoverable error!");
-
-               if (reg_read(ohci, OHCI1394_AsReqTrContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Req Tx Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsReqTrContextControlSet),
-                               reg_read(ohci, OHCI1394_AsReqTrCommandPtr));
-
-               if (reg_read(ohci, OHCI1394_AsRspTrContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Rsp Tx Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsRspTrContextControlSet),
-                               reg_read(ohci, OHCI1394_AsRspTrCommandPtr));
-
-               if (reg_read(ohci, OHCI1394_AsReqRcvContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Req Rcv Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsReqRcvContextControlSet),
-                               reg_read(ohci, OHCI1394_AsReqRcvCommandPtr));
-
-               if (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x800)
-                       PRINT(KERN_ERR, "Async Rsp Rcv Context died: "
-                               "ctrl[%08x] cmdptr[%08x]",
-                               reg_read(ohci, OHCI1394_AsRspRcvContextControlSet),
-                               reg_read(ohci, OHCI1394_AsRspRcvCommandPtr));
-
-               for (ctx = 0; ctx < ohci->nb_iso_xmit_ctx; ctx++) {
-                       if (reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)) & 0x800)
-                               PRINT(KERN_ERR, "Iso Xmit %d Context died: "
-                                       "ctrl[%08x] cmdptr[%08x]", ctx,
-                                       reg_read(ohci, OHCI1394_IsoXmitContextControlSet + (16 * ctx)),
-                                       reg_read(ohci, OHCI1394_IsoXmitCommandPtr + (16 * ctx)));
-               }
-
-               for (ctx = 0; ctx < ohci->nb_iso_rcv_ctx; ctx++) {
-                       if (reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)) & 0x800)
-                               PRINT(KERN_ERR, "Iso Recv %d Context died: "
-                                       "ctrl[%08x] cmdptr[%08x] match[%08x]", ctx,
-                                       reg_read(ohci, OHCI1394_IsoRcvContextControlSet + (32 * ctx)),
-                                       reg_read(ohci, OHCI1394_IsoRcvCommandPtr + (32 * ctx)),
-                                       reg_read(ohci, OHCI1394_IsoRcvContextMatch + (32 * ctx)));
-               }
-
-               event &= ~OHCI1394_unrecoverableError;
-       }
-       if (event & OHCI1394_postedWriteErr) {
-               PRINT(KERN_ERR, "physical posted write error");
-               /* no recovery strategy yet, had to involve protocol drivers */
-               event &= ~OHCI1394_postedWriteErr;
-       }
-       if (event & OHCI1394_cycleTooLong) {
-               if(printk_ratelimit())
-                       PRINT(KERN_WARNING, "isochronous cycle too long");
-               else
-                       DBGMSG("OHCI1394_cycleTooLong");
-               reg_write(ohci, OHCI1394_LinkControlSet,
-                         OHCI1394_LinkControl_CycleMaster);
-               event &= ~OHCI1394_cycleTooLong;
-       }
-       if (event & OHCI1394_cycleInconsistent) {
-               /* We subscribe to the cycleInconsistent event only to
-                * clear the corresponding event bit... otherwise,
-                * isochronous cycleMatch DMA won't work. */
-               DBGMSG("OHCI1394_cycleInconsistent");
-               event &= ~OHCI1394_cycleInconsistent;
-       }
-       if (event & OHCI1394_busReset) {
-               /* The busReset event bit can't be cleared during the
-                * selfID phase, so we disable busReset interrupts, to
-                * avoid burying the cpu in interrupt requests. */
-               spin_lock_irqsave(&ohci->event_lock, flags);
-               reg_write(ohci, OHCI1394_IntMaskClear, OHCI1394_busReset);
-
-               if (ohci->check_busreset) {
-                       int loop_count = 0;
-
-                       udelay(10);
-
-                       while (reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
-                               reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
-
-                               spin_unlock_irqrestore(&ohci->event_lock, flags);
-                               udelay(10);
-                               spin_lock_irqsave(&ohci->event_lock, flags);
-
-                               /* The loop counter check is to prevent the driver
-                                * from remaining in this state forever. For the
-                                * initial bus reset, the loop continues for ever
-                                * and the system hangs, until some device is plugged-in
-                                * or out manually into a port! The forced reset seems
-                                * to solve this problem. This mainly effects nForce2. */
-                               if (loop_count > 10000) {
-                                       ohci_devctl(host, RESET_BUS, LONG_RESET);
-                                       DBGMSG("Detected bus-reset loop. Forced a bus reset!");
-                                       loop_count = 0;
-                               }
-
-                               loop_count++;
-                       }
-               }
-               spin_unlock_irqrestore(&ohci->event_lock, flags);
-               if (!host->in_bus_reset) {
-                       DBGMSG("irq_handler: Bus reset requested");
-
-                       /* Subsystem call */
-                       hpsb_bus_reset(ohci->host);
-               }
-               event &= ~OHCI1394_busReset;
-       }
-       if (event & OHCI1394_reqTxComplete) {
-               struct dma_trm_ctx *d = &ohci->at_req_context;
-               DBGMSG("Got reqTxComplete interrupt "
-                      "status=0x%08X", reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear,
-                                             "reqTxComplete");
-               else
-                       dma_trm_tasklet((unsigned long)d);
-                       //tasklet_schedule(&d->task);
-               event &= ~OHCI1394_reqTxComplete;
-       }
-       if (event & OHCI1394_respTxComplete) {
-               struct dma_trm_ctx *d = &ohci->at_resp_context;
-               DBGMSG("Got respTxComplete interrupt "
-                      "status=0x%08X", reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear,
-                                             "respTxComplete");
-               else
-                       tasklet_schedule(&d->task);
-               event &= ~OHCI1394_respTxComplete;
-       }
-       if (event & OHCI1394_RQPkt) {
-               struct dma_rcv_ctx *d = &ohci->ar_req_context;
-               DBGMSG("Got RQPkt interrupt status=0x%08X",
-                      reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear, "RQPkt");
-               else
-                       tasklet_schedule(&d->task);
-               event &= ~OHCI1394_RQPkt;
-       }
-       if (event & OHCI1394_RSPkt) {
-               struct dma_rcv_ctx *d = &ohci->ar_resp_context;
-               DBGMSG("Got RSPkt interrupt status=0x%08X",
-                      reg_read(ohci, d->ctrlSet));
-               if (reg_read(ohci, d->ctrlSet) & 0x800)
-                       ohci1394_stop_context(ohci, d->ctrlClear, "RSPkt");
-               else
-                       tasklet_schedule(&d->task);
-               event &= ~OHCI1394_RSPkt;
-       }
-       if (event & OHCI1394_isochRx) {
-               quadlet_t rx_event;
-
-               rx_event = reg_read(ohci, OHCI1394_IsoRecvIntEventSet);
-               reg_write(ohci, OHCI1394_IsoRecvIntEventClear, rx_event);
-               ohci_schedule_iso_tasklets(ohci, rx_event, 0);
-               event &= ~OHCI1394_isochRx;
-       }
-       if (event & OHCI1394_isochTx) {
-               quadlet_t tx_event;
-
-               tx_event = reg_read(ohci, OHCI1394_IsoXmitIntEventSet);
-               reg_write(ohci, OHCI1394_IsoXmitIntEventClear, tx_event);
-               ohci_schedule_iso_tasklets(ohci, 0, tx_event);
-               event &= ~OHCI1394_isochTx;
-       }
-       if (event & OHCI1394_selfIDComplete) {
-               if (host->in_bus_reset) {
-                       node_id = reg_read(ohci, OHCI1394_NodeID);
-
-                       if (!(node_id & 0x80000000)) {
-                               PRINT(KERN_ERR,
-                                     "SelfID received, but NodeID invalid "
-                                     "(probably new bus reset occurred): %08X",
-                                     node_id);
-                               goto selfid_not_valid;
-                       }
-
-                       phyid =  node_id & 0x0000003f;
-                       isroot = (node_id & 0x40000000) != 0;
-
-                       DBGMSG("SelfID interrupt received "
-                             "(phyid %d, %s)", phyid,
-                             (isroot ? "root" : "not root"));
-
-                       handle_selfid(ohci, host, phyid, isroot);
-
-                       /* Clear the bus reset event and re-enable the
-                        * busReset interrupt.  */
-                       spin_lock_irqsave(&ohci->event_lock, flags);
-                       reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_busReset);
-                       reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset);
-                       spin_unlock_irqrestore(&ohci->event_lock, flags);
-
-                       /* Turn on phys dma reception.
-                        *
-                        * TODO: Enable some sort of filtering management.
-                        */
-                       if (phys_dma) {
-                               reg_write(ohci, OHCI1394_PhyReqFilterHiSet,
-                                         0xffffffff);
-                               reg_write(ohci, OHCI1394_PhyReqFilterLoSet,
-                                         0xffffffff);
-                       }
-
-                       DBGMSG("PhyReqFilter=%08x%08x",
-                              reg_read(ohci, OHCI1394_PhyReqFilterHiSet),
-                              reg_read(ohci, OHCI1394_PhyReqFilterLoSet));
-
-                       hpsb_selfid_complete(host, phyid, isroot);
-               } else
-                       PRINT(KERN_ERR,
-                             "SelfID received outside of bus reset sequence");
-
-selfid_not_valid:
-               event &= ~OHCI1394_selfIDComplete;
-       }
-
-       /* Make sure we handle everything, just in case we accidentally
-        * enabled an interrupt that we didn't write a handler for.  */
-       if (event)
-               PRINT(KERN_ERR, "Unhandled interrupt(s) 0x%08x",
-                     event);
-
-       return IRQ_HANDLED;
-}
-
-/* Put the buffer back into the dma context */
-static void insert_dma_buffer(struct dma_rcv_ctx *d, int idx)
-{
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       DBGMSG("Inserting dma buf ctx=%d idx=%d", d->ctx, idx);
-
-       d->prg_cpu[idx]->status = cpu_to_le32(d->buf_size);
-       d->prg_cpu[idx]->branchAddress &= le32_to_cpu(0xfffffff0);
-       idx = (idx + d->num_desc - 1 ) % d->num_desc;
-       d->prg_cpu[idx]->branchAddress |= le32_to_cpu(0x00000001);
-
-       /* To avoid a race, ensure 1394 interface hardware sees the inserted
-        * context program descriptors before it sees the wakeup bit set. */
-       wmb();
-       
-       /* wake up the dma context if necessary */
-       if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-               PRINT(KERN_INFO,
-                     "Waking dma ctx=%d ... processing is probably too slow",
-                     d->ctx);
-       }
-
-       /* do this always, to avoid race condition */
-       reg_write(ohci, d->ctrlSet, 0x1000);
-}
-
-#define cond_le32_to_cpu(data, noswap) \
-       (noswap ? data : le32_to_cpu(data))
-
-static const int TCODE_SIZE[16] = {20, 0, 16, -1, 16, 20, 20, 0,
-                           -1, 0, -1, 0, -1, -1, 16, -1};
-
-/*
- * Determine the length of a packet in the buffer
- * Optimization suggested by Pascal Drolet <pascal.drolet@informission.ca>
- */
-static inline int packet_length(struct dma_rcv_ctx *d, int idx,
-                               quadlet_t *buf_ptr, int offset,
-                               unsigned char tcode, int noswap)
-{
-       int length = -1;
-
-       if (d->type == DMA_CTX_ASYNC_REQ || d->type == DMA_CTX_ASYNC_RESP) {
-               length = TCODE_SIZE[tcode];
-               if (length == 0) {
-                       if (offset + 12 >= d->buf_size) {
-                               length = (cond_le32_to_cpu(d->buf_cpu[(idx + 1) % d->num_desc]
-                                               [3 - ((d->buf_size - offset) >> 2)], noswap) >> 16);
-                       } else {
-                               length = (cond_le32_to_cpu(buf_ptr[3], noswap) >> 16);
-                       }
-                       length += 20;
-               }
-       } else if (d->type == DMA_CTX_ISO) {
-               /* Assumption: buffer fill mode with header/trailer */
-               length = (cond_le32_to_cpu(buf_ptr[0], noswap) >> 16) + 8;
-       }
-
-       if (length > 0 && length % 4)
-               length += 4 - (length % 4);
-
-       return length;
-}
-
-/* Tasklet that processes dma receive buffers */
-static void dma_rcv_tasklet (unsigned long data)
-{
-       struct dma_rcv_ctx *d = (struct dma_rcv_ctx*)data;
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       unsigned int split_left, idx, offset, rescount;
-       unsigned char tcode;
-       int length, bytes_left, ack;
-       unsigned long flags;
-       quadlet_t *buf_ptr;
-       char *split_ptr;
-       char msg[256];
-
-       spin_lock_irqsave(&d->lock, flags);
-
-       idx = d->buf_ind;
-       offset = d->buf_offset;
-       buf_ptr = d->buf_cpu[idx] + offset/4;
-
-       rescount = le32_to_cpu(d->prg_cpu[idx]->status) & 0xffff;
-       bytes_left = d->buf_size - rescount - offset;
-
-       while (bytes_left > 0) {
-               tcode = (cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming) >> 4) & 0xf;
-
-               /* packet_length() will return < 4 for an error */
-               length = packet_length(d, idx, buf_ptr, offset, tcode, ohci->no_swap_incoming);
-
-               if (length < 4) { /* something is wrong */
-                       sprintf(msg,"Unexpected tcode 0x%x(0x%08x) in AR ctx=%d, length=%d",
-                               tcode, cond_le32_to_cpu(buf_ptr[0], ohci->no_swap_incoming),
-                               d->ctx, length);
-                       ohci1394_stop_context(ohci, d->ctrlClear, msg);
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       return;
-               }
-
-               /* The first case is where we have a packet that crosses
-                * over more than one descriptor. The next case is where
-                * it's all in the first descriptor.  */
-               if ((offset + length) > d->buf_size) {
-                       DBGMSG("Split packet rcv'd");
-                       if (length > d->split_buf_size) {
-                               ohci1394_stop_context(ohci, d->ctrlClear,
-                                            "Split packet size exceeded");
-                               d->buf_ind = idx;
-                               d->buf_offset = offset;
-                               spin_unlock_irqrestore(&d->lock, flags);
-                               return;
-                       }
-
-                       if (le32_to_cpu(d->prg_cpu[(idx+1)%d->num_desc]->status)
-                           == d->buf_size) {
-                               /* Other part of packet not written yet.
-                                * this should never happen I think
-                                * anyway we'll get it on the next call.  */
-                               PRINT(KERN_INFO,
-                                     "Got only half a packet!");
-                               d->buf_ind = idx;
-                               d->buf_offset = offset;
-                               spin_unlock_irqrestore(&d->lock, flags);
-                               return;
-                       }
-
-                       split_left = length;
-                       split_ptr = (char *)d->spb;
-                       memcpy(split_ptr,buf_ptr,d->buf_size-offset);
-                       split_left -= d->buf_size-offset;
-                       split_ptr += d->buf_size-offset;
-                       insert_dma_buffer(d, idx);
-                       idx = (idx+1) % d->num_desc;
-                       buf_ptr = d->buf_cpu[idx];
-                       offset=0;
-
-                       while (split_left >= d->buf_size) {
-                               memcpy(split_ptr,buf_ptr,d->buf_size);
-                               split_ptr += d->buf_size;
-                               split_left -= d->buf_size;
-                               insert_dma_buffer(d, idx);
-                               idx = (idx+1) % d->num_desc;
-                               buf_ptr = d->buf_cpu[idx];
-                       }
-
-                       if (split_left > 0) {
-                               memcpy(split_ptr, buf_ptr, split_left);
-                               offset = split_left;
-                               buf_ptr += offset/4;
-                       }
-               } else {
-                       DBGMSG("Single packet rcv'd");
-                       memcpy(d->spb, buf_ptr, length);
-                       offset += length;
-                       buf_ptr += length/4;
-                       if (offset==d->buf_size) {
-                               insert_dma_buffer(d, idx);
-                               idx = (idx+1) % d->num_desc;
-                               buf_ptr = d->buf_cpu[idx];
-                               offset=0;
-                       }
-               }
-
-               /* We get one phy packet to the async descriptor for each
-                * bus reset. We always ignore it.  */
-               if (tcode != OHCI1394_TCODE_PHY) {
-                       if (!ohci->no_swap_incoming)
-                               header_le32_to_cpu(d->spb, tcode);
-                       DBGMSG("Packet received from node"
-                               " %d ack=0x%02X spd=%d tcode=0x%X"
-                               " length=%d ctx=%d tlabel=%d",
-                               (d->spb[1]>>16)&0x3f,
-                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f,
-                               (cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>21)&0x3,
-                               tcode, length, d->ctx,
-                               (d->spb[0]>>10)&0x3f);
-
-                       ack = (((cond_le32_to_cpu(d->spb[length/4-1], ohci->no_swap_incoming)>>16)&0x1f)
-                               == 0x11) ? 1 : 0;
-
-                       hpsb_packet_received(ohci->host, d->spb,
-                                            length-4, ack);
-               }
-#ifdef OHCI1394_DEBUG
-               else
-                       PRINT (KERN_DEBUG, "Got phy packet ctx=%d ... discarded",
-                              d->ctx);
-#endif
-
-               rescount = le32_to_cpu(d->prg_cpu[idx]->status) & 0xffff;
-
-               bytes_left = d->buf_size - rescount - offset;
-
-       }
-
-       d->buf_ind = idx;
-       d->buf_offset = offset;
-
-       spin_unlock_irqrestore(&d->lock, flags);
-}
-
-/* Bottom half that processes sent packets */
-static void dma_trm_tasklet (unsigned long data)
-{
-       struct dma_trm_ctx *d = (struct dma_trm_ctx*)data;
-       struct ti_ohci *ohci = (struct ti_ohci*)(d->ohci);
-       struct hpsb_packet *packet, *ptmp;
-       unsigned long flags;
-       u32 status, ack;
-        size_t datasize;
-
-       spin_lock_irqsave(&d->lock, flags);
-
-       list_for_each_entry_safe(packet, ptmp, &d->fifo_list, driver_list) {
-                datasize = packet->data_size;
-               if (datasize && packet->type != hpsb_raw)
-                       status = le32_to_cpu(
-                               d->prg_cpu[d->sent_ind]->end.status) >> 16;
-               else
-                       status = le32_to_cpu(
-                               d->prg_cpu[d->sent_ind]->begin.status) >> 16;
-
-               if (status == 0)
-                       /* this packet hasn't been sent yet*/
-                       break;
-
-#ifdef OHCI1394_DEBUG
-               if (datasize)
-                       if (((le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf) == 0xa)
-                               DBGMSG("Stream packet sent to channel %d tcode=0x%X "
-                                      "ack=0x%X spd=%d dataLength=%d ctx=%d",
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>8)&0x3f,
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
-                                      status&0x1f, (status>>5)&0x3,
-                                      le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16,
-                                      d->ctx);
-                       else
-                               DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
-                                      "%d ack=0x%X spd=%d dataLength=%d ctx=%d",
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])>>16)&0x3f,
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>4)&0xf,
-                                      (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])>>10)&0x3f,
-                                      status&0x1f, (status>>5)&0x3,
-                                      le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3])>>16,
-                                      d->ctx);
-               else
-                       DBGMSG("Packet sent to node %d tcode=0x%X tLabel="
-                              "%d ack=0x%X spd=%d data=0x%08X ctx=%d",
-                                (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[1])
-                                        >>16)&0x3f,
-                                (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
-                                        >>4)&0xf,
-                                (le32_to_cpu(d->prg_cpu[d->sent_ind]->data[0])
-                                        >>10)&0x3f,
-                                status&0x1f, (status>>5)&0x3,
-                                le32_to_cpu(d->prg_cpu[d->sent_ind]->data[3]),
-                                d->ctx);
-#endif
-
-               if (status & 0x10) {
-                       ack = status & 0xf;
-               } else {
-                       switch (status & 0x1f) {
-                       case EVT_NO_STATUS: /* that should never happen */
-                       case EVT_RESERVED_A: /* that should never happen */
-                       case EVT_LONG_PACKET: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_MISSING_ACK:
-                               ack = ACKX_TIMEOUT;
-                               break;
-                       case EVT_UNDERRUN:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_OVERRUN: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_DESCRIPTOR_READ:
-                       case EVT_DATA_READ:
-                       case EVT_DATA_WRITE:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_BUS_RESET: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_TIMEOUT:
-                               ack = ACKX_TIMEOUT;
-                               break;
-                       case EVT_TCODE_ERR:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_RESERVED_B: /* that should never happen */
-                       case EVT_RESERVED_C: /* that should never happen */
-                               PRINT(KERN_WARNING, "Received OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       case EVT_UNKNOWN:
-                       case EVT_FLUSHED:
-                               ack = ACKX_SEND_ERROR;
-                               break;
-                       default:
-                               PRINT(KERN_ERR, "Unhandled OHCI evt_* error 0x%x", status & 0x1f);
-                               ack = ACKX_SEND_ERROR;
-                               BUG();
-                       }
-               }
-
-               list_del_init(&packet->driver_list);
-               hpsb_packet_sent(ohci->host, packet, ack);
-
-               if (datasize)
-                       pci_unmap_single(ohci->dev,
-                                        cpu_to_le32(d->prg_cpu[d->sent_ind]->end.address),
-                                        datasize, PCI_DMA_TODEVICE);
-
-               d->sent_ind = (d->sent_ind+1)%d->num_desc;
-               d->free_prgs++;
-       }
-
-       dma_trm_flush(ohci, d);
-
-       spin_unlock_irqrestore(&d->lock, flags);
-}
-
-static void free_dma_rcv_ctx(struct dma_rcv_ctx *d)
-{
-       int i;
-       struct ti_ohci *ohci = d->ohci;
-
-       if (ohci == NULL)
-               return;
-
-       DBGMSG("Freeing dma_rcv_ctx %d", d->ctx);
-
-       if (d->buf_cpu) {
-               for (i=0; i<d->num_desc; i++)
-                       if (d->buf_cpu[i] && d->buf_bus[i])
-                               pci_free_consistent(
-                                       ohci->dev, d->buf_size,
-                                       d->buf_cpu[i], d->buf_bus[i]);
-               kfree(d->buf_cpu);
-               kfree(d->buf_bus);
-       }
-       if (d->prg_cpu) {
-               for (i=0; i<d->num_desc; i++)
-                       if (d->prg_cpu[i] && d->prg_bus[i])
-                               pci_pool_free(d->prg_pool, d->prg_cpu[i],
-                                             d->prg_bus[i]);
-               pci_pool_destroy(d->prg_pool);
-               kfree(d->prg_cpu);
-               kfree(d->prg_bus);
-       }
-       kfree(d->spb);
-
-       /* Mark this context as freed. */
-       d->ohci = NULL;
-}
-
-static int
-alloc_dma_rcv_ctx(struct ti_ohci *ohci, struct dma_rcv_ctx *d,
-                 enum context_type type, int ctx, int num_desc,
-                 int buf_size, int split_buf_size, int context_base)
-{
-       int i, len;
-       static int num_allocs;
-       static char pool_name[20];
-
-       d->ohci = ohci;
-       d->type = type;
-       d->ctx = ctx;
-
-       d->num_desc = num_desc;
-       d->buf_size = buf_size;
-       d->split_buf_size = split_buf_size;
-
-       d->ctrlSet = 0;
-       d->ctrlClear = 0;
-       d->cmdPtr = 0;
-
-       d->buf_cpu = kzalloc(d->num_desc * sizeof(*d->buf_cpu), GFP_ATOMIC);
-       d->buf_bus = kzalloc(d->num_desc * sizeof(*d->buf_bus), GFP_ATOMIC);
-
-       if (d->buf_cpu == NULL || d->buf_bus == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "DMA buffer");
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-
-       d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_ATOMIC);
-       d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_ATOMIC);
-
-       if (d->prg_cpu == NULL || d->prg_bus == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "DMA prg");
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-
-       d->spb = kmalloc(d->split_buf_size, GFP_ATOMIC);
-
-       if (d->spb == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "split buffer");
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-       
-       len = sprintf(pool_name, "ohci1394_rcv_prg");
-       sprintf(pool_name+len, "%d", num_allocs);
-       d->prg_pool = pci_pool_create(pool_name, ohci->dev,
-                               sizeof(struct dma_cmd), 4, 0);
-       if(d->prg_pool == NULL)
-       {
-               PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
-               free_dma_rcv_ctx(d);
-               return -ENOMEM;
-       }
-       num_allocs++;
-
-       for (i=0; i<d->num_desc; i++) {
-               d->buf_cpu[i] = pci_alloc_consistent(ohci->dev,
-                                                    d->buf_size,
-                                                    d->buf_bus+i);
-
-               if (d->buf_cpu[i] != NULL) {
-                       memset(d->buf_cpu[i], 0, d->buf_size);
-               } else {
-                       PRINT(KERN_ERR,
-                             "Failed to allocate %s", "DMA buffer");
-                       free_dma_rcv_ctx(d);
-                       return -ENOMEM;
-               }
-
-               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-
-                if (d->prg_cpu[i] != NULL) {
-                        memset(d->prg_cpu[i], 0, sizeof(struct dma_cmd));
-               } else {
-                       PRINT(KERN_ERR,
-                             "Failed to allocate %s", "DMA prg");
-                       free_dma_rcv_ctx(d);
-                       return -ENOMEM;
-               }
-       }
-
-        spin_lock_init(&d->lock);
-
-       d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-       d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-       d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-
-       tasklet_init(&d->task, dma_rcv_tasklet, (unsigned long) d);
-       return 0;
-}
-
-static void free_dma_trm_ctx(struct dma_trm_ctx *d)
-{
-       int i;
-       struct ti_ohci *ohci = d->ohci;
-
-       if (ohci == NULL)
-               return;
-
-       DBGMSG("Freeing dma_trm_ctx %d", d->ctx);
-
-       if (d->prg_cpu) {
-               for (i=0; i<d->num_desc; i++)
-                       if (d->prg_cpu[i] && d->prg_bus[i])
-                               pci_pool_free(d->prg_pool, d->prg_cpu[i],
-                                             d->prg_bus[i]);
-               pci_pool_destroy(d->prg_pool);
-               kfree(d->prg_cpu);
-               kfree(d->prg_bus);
-       }
-
-       /* Mark this context as freed. */
-       d->ohci = NULL;
-}
-
-static int
-alloc_dma_trm_ctx(struct ti_ohci *ohci, struct dma_trm_ctx *d,
-                 enum context_type type, int ctx, int num_desc,
-                 int context_base)
-{
-       int i, len;
-       static char pool_name[20];
-       static int num_allocs=0;
-
-       d->ohci = ohci;
-       d->type = type;
-       d->ctx = ctx;
-       d->num_desc = num_desc;
-       d->ctrlSet = 0;
-       d->ctrlClear = 0;
-       d->cmdPtr = 0;
-
-       d->prg_cpu = kzalloc(d->num_desc * sizeof(*d->prg_cpu), GFP_KERNEL);
-       d->prg_bus = kzalloc(d->num_desc * sizeof(*d->prg_bus), GFP_KERNEL);
-
-       if (d->prg_cpu == NULL || d->prg_bus == NULL) {
-               PRINT(KERN_ERR, "Failed to allocate %s", "AT DMA prg");
-               free_dma_trm_ctx(d);
-               return -ENOMEM;
-       }
-
-       len = sprintf(pool_name, "ohci1394_trm_prg");
-       sprintf(pool_name+len, "%d", num_allocs);
-       d->prg_pool = pci_pool_create(pool_name, ohci->dev,
-                               sizeof(struct at_dma_prg), 4, 0);
-       if (d->prg_pool == NULL) {
-               PRINT(KERN_ERR, "pci_pool_create failed for %s", pool_name);
-               free_dma_trm_ctx(d);
-               return -ENOMEM;
-       }
-       num_allocs++;
-
-       for (i = 0; i < d->num_desc; i++) {
-               d->prg_cpu[i] = pci_pool_alloc(d->prg_pool, GFP_KERNEL, d->prg_bus+i);
-
-                if (d->prg_cpu[i] != NULL) {
-                        memset(d->prg_cpu[i], 0, sizeof(struct at_dma_prg));
-               } else {
-                       PRINT(KERN_ERR,
-                             "Failed to allocate %s", "AT DMA prg");
-                       free_dma_trm_ctx(d);
-                       return -ENOMEM;
-               }
-       }
-
-        spin_lock_init(&d->lock);
-
-       /* initialize tasklet */
-       d->ctrlSet = context_base + OHCI1394_ContextControlSet;
-       d->ctrlClear = context_base + OHCI1394_ContextControlClear;
-       d->cmdPtr = context_base + OHCI1394_ContextCommandPtr;
-       tasklet_init(&d->task, dma_trm_tasklet, (unsigned long)d);
-       return 0;
-}
-
-static void ohci_set_hw_config_rom(struct hpsb_host *host, __be32 *config_rom)
-{
-       struct ti_ohci *ohci = host->hostdata;
-
-       reg_write(ohci, OHCI1394_ConfigROMhdr, be32_to_cpu(config_rom[0]));
-       reg_write(ohci, OHCI1394_BusOptions, be32_to_cpu(config_rom[2]));
-
-       memcpy(ohci->csr_config_rom_cpu, config_rom, OHCI_CONFIG_ROM_LEN);
-}
-
-
-static quadlet_t ohci_hw_csr_reg(struct hpsb_host *host, int reg,
-                                 quadlet_t data, quadlet_t compare)
-{
-       struct ti_ohci *ohci = host->hostdata;
-       int i;
-
-       reg_write(ohci, OHCI1394_CSRData, data);
-       reg_write(ohci, OHCI1394_CSRCompareData, compare);
-       reg_write(ohci, OHCI1394_CSRControl, reg & 0x3);
-
-       for (i = 0; i < OHCI_LOOP_COUNT; i++) {
-               if (reg_read(ohci, OHCI1394_CSRControl) & 0x80000000)
-                       break;
-
-               mdelay(1);
-       }
-
-       return reg_read(ohci, OHCI1394_CSRData);
-}
-
-static struct hpsb_host_driver ohci1394_driver = {
-       .owner =                THIS_MODULE,
-       .name =                 OHCI1394_DRIVER_NAME,
-       .set_hw_config_rom =    ohci_set_hw_config_rom,
-       .transmit_packet =      ohci_transmit,
-       .devctl =               ohci_devctl,
-       .isoctl =               ohci_isoctl,
-       .hw_csr_reg =           ohci_hw_csr_reg,
-};
-
-/***********************************
- * PCI Driver Interface functions  *
- ***********************************/
-
-#ifdef CONFIG_PPC_PMAC
-static void ohci1394_pmac_on(struct pci_dev *dev)
-{
-       if (machine_is(powermac)) {
-               struct device_node *ofn = pci_device_to_OF_node(dev);
-
-               if (ofn) {
-                       pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 1);
-                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 1);
-               }
-       }
-}
-
-static void ohci1394_pmac_off(struct pci_dev *dev)
-{
-       if (machine_is(powermac)) {
-               struct device_node *ofn = pci_device_to_OF_node(dev);
-
-               if (ofn) {
-                       pmac_call_feature(PMAC_FTR_1394_ENABLE, ofn, 0, 0);
-                       pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, ofn, 0, 0);
-               }
-       }
-}
-#else
-#define ohci1394_pmac_on(dev)
-#define ohci1394_pmac_off(dev)
-#endif /* CONFIG_PPC_PMAC */
-
-static int __devinit ohci1394_pci_probe(struct pci_dev *dev,
-                                       const struct pci_device_id *ent)
-{
-       struct hpsb_host *host;
-       struct ti_ohci *ohci;   /* shortcut to currently handled device */
-       resource_size_t ohci_base;
-       int err = -ENOMEM;
-
-       ohci1394_pmac_on(dev);
-       if (pci_enable_device(dev)) {
-               PRINT_G(KERN_ERR, "Failed to enable OHCI hardware");
-               err = -ENXIO;
-               goto err;
-       }
-        pci_set_master(dev);
-
-       host = hpsb_alloc_host(&ohci1394_driver, sizeof(struct ti_ohci), &dev->dev);
-       if (!host) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "host structure");
-               goto err;
-       }
-       ohci = host->hostdata;
-       ohci->dev = dev;
-       ohci->host = host;
-       ohci->init_state = OHCI_INIT_ALLOC_HOST;
-       host->pdev = dev;
-       pci_set_drvdata(dev, ohci);
-
-       /* We don't want hardware swapping */
-       pci_write_config_dword(dev, OHCI1394_PCI_HCI_Control, 0);
-
-       /* Some oddball Apple controllers do not order the selfid
-        * properly, so we make up for it here.  */
-#ifndef __LITTLE_ENDIAN
-       /* XXX: Need a better way to check this. I'm wondering if we can
-        * read the values of the OHCI1394_PCI_HCI_Control and the
-        * noByteSwapData registers to see if they were not cleared to
-        * zero. Should this work? Obviously it's not defined what these
-        * registers will read when they aren't supported. Bleh! */
-       if (dev->vendor == PCI_VENDOR_ID_APPLE &&
-           dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) {
-               ohci->no_swap_incoming = 1;
-               ohci->selfid_swap = 0;
-       } else
-               ohci->selfid_swap = 1;
-#endif
-
-
-#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE2_FW
-#define PCI_DEVICE_ID_NVIDIA_NFORCE2_FW 0x006e
-#endif
-
-       /* These chipsets require a bit of extra care when checking after
-        * a busreset.  */
-       if ((dev->vendor == PCI_VENDOR_ID_APPLE &&
-            dev->device == PCI_DEVICE_ID_APPLE_UNI_N_FW) ||
-           (dev->vendor ==  PCI_VENDOR_ID_NVIDIA &&
-            dev->device == PCI_DEVICE_ID_NVIDIA_NFORCE2_FW))
-               ohci->check_busreset = 1;
-
-       /* We hardwire the MMIO length, since some CardBus adaptors
-        * fail to report the right length.  Anyway, the ohci spec
-        * clearly says it's 2kb, so this shouldn't be a problem. */
-       ohci_base = pci_resource_start(dev, 0);
-       if (pci_resource_len(dev, 0) < OHCI1394_REGISTER_SIZE)
-               PRINT(KERN_WARNING, "PCI resource length of 0x%llx too small!",
-                     (unsigned long long)pci_resource_len(dev, 0));
-
-       if (!request_mem_region(ohci_base, OHCI1394_REGISTER_SIZE,
-                               OHCI1394_DRIVER_NAME)) {
-               PRINT_G(KERN_ERR, "MMIO resource (0x%llx - 0x%llx) unavailable",
-                       (unsigned long long)ohci_base,
-                       (unsigned long long)ohci_base + OHCI1394_REGISTER_SIZE);
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_MEM_REGION;
-
-       ohci->registers = ioremap(ohci_base, OHCI1394_REGISTER_SIZE);
-       if (ohci->registers == NULL) {
-               PRINT_G(KERN_ERR, "Failed to remap registers");
-               err = -ENXIO;
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_IOMAPPING;
-       DBGMSG("Remapped memory spaces reg 0x%p", ohci->registers);
-
-       /* csr_config rom allocation */
-       ohci->csr_config_rom_cpu =
-               pci_alloc_consistent(ohci->dev, OHCI_CONFIG_ROM_LEN,
-                                    &ohci->csr_config_rom_bus);
-       if (ohci->csr_config_rom_cpu == NULL) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "buffer config rom");
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_CONFIG_ROM_BUFFER;
-
-       /* self-id dma buffer allocation */
-       ohci->selfid_buf_cpu =
-               pci_alloc_consistent(ohci->dev, OHCI1394_SI_DMA_BUF_SIZE,
-                      &ohci->selfid_buf_bus);
-       if (ohci->selfid_buf_cpu == NULL) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "self-ID buffer");
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_SELFID_BUFFER;
-
-       if ((unsigned long)ohci->selfid_buf_cpu & 0x1fff)
-               PRINT(KERN_INFO, "SelfID buffer %p is not aligned on "
-                     "8Kb boundary... may cause problems on some CXD3222 chip",
-                     ohci->selfid_buf_cpu);
-
-       /* No self-id errors at startup */
-       ohci->self_id_errors = 0;
-
-       ohci->init_state = OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE;
-       /* AR DMA request context allocation */
-       if (alloc_dma_rcv_ctx(ohci, &ohci->ar_req_context,
-                             DMA_CTX_ASYNC_REQ, 0, AR_REQ_NUM_DESC,
-                             AR_REQ_BUF_SIZE, AR_REQ_SPLIT_BUF_SIZE,
-                             OHCI1394_AsReqRcvContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Req context");
-               goto err;
-       }
-       /* AR DMA response context allocation */
-       if (alloc_dma_rcv_ctx(ohci, &ohci->ar_resp_context,
-                             DMA_CTX_ASYNC_RESP, 0, AR_RESP_NUM_DESC,
-                             AR_RESP_BUF_SIZE, AR_RESP_SPLIT_BUF_SIZE,
-                             OHCI1394_AsRspRcvContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AR Resp context");
-               goto err;
-       }
-       /* AT DMA request context */
-       if (alloc_dma_trm_ctx(ohci, &ohci->at_req_context,
-                             DMA_CTX_ASYNC_REQ, 0, AT_REQ_NUM_DESC,
-                             OHCI1394_AsReqTrContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Req context");
-               goto err;
-       }
-       /* AT DMA response context */
-       if (alloc_dma_trm_ctx(ohci, &ohci->at_resp_context,
-                             DMA_CTX_ASYNC_RESP, 1, AT_RESP_NUM_DESC,
-                             OHCI1394_AsRspTrContextBase) < 0) {
-               PRINT_G(KERN_ERR, "Failed to allocate %s", "AT Resp context");
-               goto err;
-       }
-       /* Start off with a soft reset, to clear everything to a sane
-        * state. */
-       ohci_soft_reset(ohci);
-
-       /* Now enable LPS, which we need in order to start accessing
-        * most of the registers.  In fact, on some cards (ALI M5251),
-        * accessing registers in the SClk domain without LPS enabled
-        * will lock up the machine. */
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
-
-       /* Disable and clear interrupts */
-       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-
-       /* Flush MMIO writes and wait to make sure we have full link enabled. */
-       reg_read(ohci, OHCI1394_Version);
-       msleep(50);
-
-       /* Determine the number of available IR and IT contexts. */
-       ohci->nb_iso_rcv_ctx =
-               get_nb_iso_ctx(ohci, OHCI1394_IsoRecvIntMaskSet);
-       ohci->nb_iso_xmit_ctx =
-               get_nb_iso_ctx(ohci, OHCI1394_IsoXmitIntMaskSet);
-
-       /* Set the usage bits for non-existent contexts so they can't
-        * be allocated */
-       ohci->ir_ctx_usage = ~0 << ohci->nb_iso_rcv_ctx;
-       ohci->it_ctx_usage = ~0 << ohci->nb_iso_xmit_ctx;
-
-       INIT_LIST_HEAD(&ohci->iso_tasklet_list);
-       spin_lock_init(&ohci->iso_tasklet_list_lock);
-       ohci->ISO_channel_usage = 0;
-        spin_lock_init(&ohci->IR_channel_lock);
-
-       spin_lock_init(&ohci->event_lock);
-
-       /*
-        * interrupts are disabled, all right, but... due to IRQF_SHARED we
-        * might get called anyway.  We'll see no event, of course, but
-        * we need to get to that "no event", so enough should be initialized
-        * by that point.
-        */
-       err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
-                         OHCI1394_DRIVER_NAME, ohci);
-       if (err) {
-               PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_HAVE_IRQ;
-       ohci_initialize(ohci);
-
-       /* Set certain csr values */
-       host->csr.guid_hi = reg_read(ohci, OHCI1394_GUIDHi);
-       host->csr.guid_lo = reg_read(ohci, OHCI1394_GUIDLo);
-       host->csr.cyc_clk_acc = 100;  /* how do we determine clk accuracy? */
-       host->csr.max_rec = (reg_read(ohci, OHCI1394_BusOptions) >> 12) & 0xf;
-       host->csr.lnk_spd = reg_read(ohci, OHCI1394_BusOptions) & 0x7;
-
-       if (phys_dma) {
-               host->low_addr_space =
-                       (u64) reg_read(ohci, OHCI1394_PhyUpperBound) << 16;
-               if (!host->low_addr_space)
-                       host->low_addr_space = OHCI1394_PHYS_UPPER_BOUND_FIXED;
-       }
-       host->middle_addr_space = OHCI1394_MIDDLE_ADDRESS_SPACE;
-
-       /* Tell the highlevel this host is ready */
-       if (hpsb_add_host(host)) {
-               PRINT_G(KERN_ERR, "Failed to register host with highlevel");
-               goto err;
-       }
-       ohci->init_state = OHCI_INIT_DONE;
-
-       return 0;
-err:
-       ohci1394_pci_remove(dev);
-       return err;
-}
-
-static void ohci1394_pci_remove(struct pci_dev *dev)
-{
-       struct ti_ohci *ohci;
-       struct device *device;
-
-       ohci = pci_get_drvdata(dev);
-       if (!ohci)
-               goto out;
-
-       device = get_device(&ohci->host->device);
-
-       switch (ohci->init_state) {
-       case OHCI_INIT_DONE:
-               hpsb_remove_host(ohci->host);
-
-               /* Clear out BUS Options */
-               reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
-               reg_write(ohci, OHCI1394_BusOptions,
-                         (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
-                         0x00ff0000);
-               memset(ohci->csr_config_rom_cpu, 0, OHCI_CONFIG_ROM_LEN);
-
-       case OHCI_INIT_HAVE_IRQ:
-               /* Clear interrupt registers */
-               reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-               reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-
-               /* Disable IRM Contender */
-               set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
-
-               /* Clear link control register */
-               reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
-
-               /* Let all other nodes know to ignore us */
-               ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
-
-               /* Soft reset before we start - this disables
-                * interrupts and clears linkEnable and LPS. */
-               ohci_soft_reset(ohci);
-               free_irq(dev->irq, ohci);
-
-       case OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE:
-               /* The ohci_soft_reset() stops all DMA contexts, so we
-                * dont need to do this.  */
-               free_dma_rcv_ctx(&ohci->ar_req_context);
-               free_dma_rcv_ctx(&ohci->ar_resp_context);
-               free_dma_trm_ctx(&ohci->at_req_context);
-               free_dma_trm_ctx(&ohci->at_resp_context);
-
-       case OHCI_INIT_HAVE_SELFID_BUFFER:
-               pci_free_consistent(dev, OHCI1394_SI_DMA_BUF_SIZE,
-                                   ohci->selfid_buf_cpu,
-                                   ohci->selfid_buf_bus);
-
-       case OHCI_INIT_HAVE_CONFIG_ROM_BUFFER:
-               pci_free_consistent(dev, OHCI_CONFIG_ROM_LEN,
-                                   ohci->csr_config_rom_cpu,
-                                   ohci->csr_config_rom_bus);
-
-       case OHCI_INIT_HAVE_IOMAPPING:
-               iounmap(ohci->registers);
-
-       case OHCI_INIT_HAVE_MEM_REGION:
-               release_mem_region(pci_resource_start(dev, 0),
-                                  OHCI1394_REGISTER_SIZE);
-
-       case OHCI_INIT_ALLOC_HOST:
-               pci_set_drvdata(dev, NULL);
-       }
-
-       if (device)
-               put_device(device);
-out:
-       ohci1394_pmac_off(dev);
-}
-
-#ifdef CONFIG_PM
-static int ohci1394_pci_suspend(struct pci_dev *dev, pm_message_t state)
-{
-       int err;
-       struct ti_ohci *ohci = pci_get_drvdata(dev);
-
-       if (!ohci) {
-               printk(KERN_ERR "%s: tried to suspend nonexisting host\n",
-                      OHCI1394_DRIVER_NAME);
-               return -ENXIO;
-       }
-       DBGMSG("suspend called");
-
-       /* Clear the async DMA contexts and stop using the controller */
-       hpsb_bus_reset(ohci->host);
-
-       /* See ohci1394_pci_remove() for comments on this sequence */
-       reg_write(ohci, OHCI1394_ConfigROMhdr, 0);
-       reg_write(ohci, OHCI1394_BusOptions,
-                 (reg_read(ohci, OHCI1394_BusOptions) & 0x0000f007) |
-                 0x00ff0000);
-       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
-       set_phy_reg(ohci, 4, ~0xc0 & get_phy_reg(ohci, 4));
-       reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
-       ohci_devctl(ohci->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
-       ohci_soft_reset(ohci);
-
-       free_irq(dev->irq, ohci);
-       err = pci_save_state(dev);
-       if (err) {
-               PRINT(KERN_ERR, "pci_save_state failed with %d", err);
-               return err;
-       }
-       err = pci_set_power_state(dev, pci_choose_state(dev, state));
-       if (err)
-               DBGMSG("pci_set_power_state failed with %d", err);
-       ohci1394_pmac_off(dev);
-
-       return 0;
-}
-
-static int ohci1394_pci_resume(struct pci_dev *dev)
-{
-       int err;
-       struct ti_ohci *ohci = pci_get_drvdata(dev);
-
-       if (!ohci) {
-               printk(KERN_ERR "%s: tried to resume nonexisting host\n",
-                      OHCI1394_DRIVER_NAME);
-               return -ENXIO;
-       }
-       DBGMSG("resume called");
-
-       ohci1394_pmac_on(dev);
-       pci_set_power_state(dev, PCI_D0);
-       pci_restore_state(dev);
-       err = pci_enable_device(dev);
-       if (err) {
-               PRINT(KERN_ERR, "pci_enable_device failed with %d", err);
-               return err;
-       }
-
-       /* See ohci1394_pci_probe() for comments on this sequence */
-       ohci_soft_reset(ohci);
-       reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
-       reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
-       reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
-       reg_read(ohci, OHCI1394_Version);
-       msleep(50);
-
-       err = request_irq(dev->irq, ohci_irq_handler, IRQF_SHARED,
-                         OHCI1394_DRIVER_NAME, ohci);
-       if (err) {
-               PRINT_G(KERN_ERR, "Failed to allocate interrupt %d", dev->irq);
-               return err;
-       }
-
-       ohci_initialize(ohci);
-
-       hpsb_resume_host(ohci->host);
-       return 0;
-}
-#endif /* CONFIG_PM */
-
-static struct pci_device_id ohci1394_pci_tbl[] = {
-       {
-               .class =        PCI_CLASS_SERIAL_FIREWIRE_OHCI,
-               .class_mask =   PCI_ANY_ID,
-               .vendor =       PCI_ANY_ID,
-               .device =       PCI_ANY_ID,
-               .subvendor =    PCI_ANY_ID,
-               .subdevice =    PCI_ANY_ID,
-       },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl);
-
-static struct pci_driver ohci1394_pci_driver = {
-       .name =         OHCI1394_DRIVER_NAME,
-       .id_table =     ohci1394_pci_tbl,
-       .probe =        ohci1394_pci_probe,
-       .remove =       ohci1394_pci_remove,
-#ifdef CONFIG_PM
-       .resume =       ohci1394_pci_resume,
-       .suspend =      ohci1394_pci_suspend,
-#endif
-};
-
-/***********************************
- * OHCI1394 Video Interface        *
- ***********************************/
-
-/* essentially the only purpose of this code is to allow another
-   module to hook into ohci's interrupt handler */
-
-/* returns zero if successful, one if DMA context is locked up */
-int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg)
-{
-       int i=0;
-
-       /* stop the channel program if it's still running */
-       reg_write(ohci, reg, 0x8000);
-
-       /* Wait until it effectively stops */
-       while (reg_read(ohci, reg) & 0x400) {
-               i++;
-               if (i>5000) {
-                       PRINT(KERN_ERR,
-                             "Runaway loop while stopping context: %s...", msg ? msg : "");
-                       return 1;
-               }
-
-               mb();
-               udelay(10);
-       }
-       if (msg) PRINT(KERN_ERR, "%s: dma prg stopped", msg);
-       return 0;
-}
-
-void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet, int type,
-                              void (*func)(unsigned long), unsigned long data)
-{
-       tasklet_init(&tasklet->tasklet, func, data);
-       tasklet->type = type;
-       /* We init the tasklet->link field, so we can list_del() it
-        * without worrying whether it was added to the list or not. */
-       INIT_LIST_HEAD(&tasklet->link);
-}
-
-int ohci1394_register_iso_tasklet(struct ti_ohci *ohci,
-                                 struct ohci1394_iso_tasklet *tasklet)
-{
-       unsigned long flags, *usage;
-       int n, i, r = -EBUSY;
-
-       if (tasklet->type == OHCI_ISO_TRANSMIT) {
-               n = ohci->nb_iso_xmit_ctx;
-               usage = &ohci->it_ctx_usage;
-       }
-       else {
-               n = ohci->nb_iso_rcv_ctx;
-               usage = &ohci->ir_ctx_usage;
-
-               /* only one receive context can be multichannel (OHCI sec 10.4.1) */
-               if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) {
-                       if (test_and_set_bit(0, &ohci->ir_multichannel_used)) {
-                               return r;
-                       }
-               }
-       }
-
-       spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
-
-       for (i = 0; i < n; i++)
-               if (!test_and_set_bit(i, usage)) {
-                       tasklet->context = i;
-                       list_add_tail(&tasklet->link, &ohci->iso_tasklet_list);
-                       r = 0;
-                       break;
-               }
-
-       spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-
-       return r;
-}
-
-void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
-                                    struct ohci1394_iso_tasklet *tasklet)
-{
-       unsigned long flags;
-
-       tasklet_kill(&tasklet->tasklet);
-
-       spin_lock_irqsave(&ohci->iso_tasklet_list_lock, flags);
-
-       if (tasklet->type == OHCI_ISO_TRANSMIT)
-               clear_bit(tasklet->context, &ohci->it_ctx_usage);
-       else {
-               clear_bit(tasklet->context, &ohci->ir_ctx_usage);
-
-               if (tasklet->type == OHCI_ISO_MULTICHANNEL_RECEIVE) {
-                       clear_bit(0, &ohci->ir_multichannel_used);
-               }
-       }
-
-       list_del(&tasklet->link);
-
-       spin_unlock_irqrestore(&ohci->iso_tasklet_list_lock, flags);
-}
-
-EXPORT_SYMBOL(ohci1394_stop_context);
-EXPORT_SYMBOL(ohci1394_init_iso_tasklet);
-EXPORT_SYMBOL(ohci1394_register_iso_tasklet);
-EXPORT_SYMBOL(ohci1394_unregister_iso_tasklet);
-
-/***********************************
- * General module initialization   *
- ***********************************/
-
-MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>");
-MODULE_DESCRIPTION("Driver for PCI OHCI IEEE-1394 controllers");
-MODULE_LICENSE("GPL");
-
-static void __exit ohci1394_cleanup (void)
-{
-       pci_unregister_driver(&ohci1394_pci_driver);
-}
-
-static int __init ohci1394_init(void)
-{
-       return pci_register_driver(&ohci1394_pci_driver);
-}
-
-module_init(ohci1394_init);
-module_exit(ohci1394_cleanup);
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
deleted file mode 100644 (file)
index 7fb8ab9..0000000
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- * ohci1394.h - driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Gord Peters <GordPeters@smarttech.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _OHCI1394_H
-#define _OHCI1394_H
-
-#include "ieee1394_types.h"
-#include <asm/io.h>
-
-#define OHCI1394_DRIVER_NAME      "ohci1394"
-
-#define OHCI1394_MAX_AT_REQ_RETRIES    0xf
-#define OHCI1394_MAX_AT_RESP_RETRIES   0x2
-#define OHCI1394_MAX_PHYS_RESP_RETRIES 0x8
-#define OHCI1394_MAX_SELF_ID_ERRORS    16
-
-#define AR_REQ_NUM_DESC                4               /* number of AR req descriptors */
-#define AR_REQ_BUF_SIZE                PAGE_SIZE       /* size of AR req buffers */
-#define AR_REQ_SPLIT_BUF_SIZE  PAGE_SIZE       /* split packet buffer */
-
-#define AR_RESP_NUM_DESC       4               /* number of AR resp descriptors */
-#define AR_RESP_BUF_SIZE       PAGE_SIZE       /* size of AR resp buffers */
-#define AR_RESP_SPLIT_BUF_SIZE PAGE_SIZE       /* split packet buffer */
-
-#define IR_NUM_DESC            16              /* number of IR descriptors */
-#define IR_BUF_SIZE            PAGE_SIZE       /* 4096 bytes/buffer */
-#define IR_SPLIT_BUF_SIZE      PAGE_SIZE       /* split packet buffer */
-
-#define IT_NUM_DESC            16      /* number of IT descriptors */
-
-#define AT_REQ_NUM_DESC                32      /* number of AT req descriptors */
-#define AT_RESP_NUM_DESC       32      /* number of AT resp descriptors */
-
-#define OHCI_LOOP_COUNT                100     /* Number of loops for reg read waits */
-
-#define OHCI_CONFIG_ROM_LEN    1024    /* Length of the mapped configrom space */
-
-#define OHCI1394_SI_DMA_BUF_SIZE       8192 /* length of the selfid buffer */
-
-/* PCI configuration space addresses */
-#define OHCI1394_PCI_HCI_Control 0x40
-
-struct dma_cmd {
-        u32 control;
-        u32 address;
-        u32 branchAddress;
-        u32 status;
-};
-
-/*
- * FIXME:
- * It is important that a single at_dma_prg does not cross a page boundary
- * The proper way to do it would be to do the check dynamically as the
- * programs are inserted into the AT fifo.
- */
-struct at_dma_prg {
-       struct dma_cmd begin;
-       quadlet_t data[4];
-       struct dma_cmd end;
-       quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */
-};
-
-/* identify whether a DMA context is asynchronous or isochronous */
-enum context_type { DMA_CTX_ASYNC_REQ, DMA_CTX_ASYNC_RESP, DMA_CTX_ISO };
-
-/* DMA receive context */
-struct dma_rcv_ctx {
-       struct ti_ohci *ohci;
-       enum context_type type;
-       int ctx;
-       unsigned int num_desc;
-
-       unsigned int buf_size;
-       unsigned int split_buf_size;
-
-       /* dma block descriptors */
-        struct dma_cmd **prg_cpu;
-        dma_addr_t *prg_bus;
-       struct pci_pool *prg_pool;
-
-       /* dma buffers */
-        quadlet_t **buf_cpu;
-        dma_addr_t *buf_bus;
-
-        unsigned int buf_ind;
-        unsigned int buf_offset;
-        quadlet_t *spb;
-        spinlock_t lock;
-        struct tasklet_struct task;
-       int ctrlClear;
-       int ctrlSet;
-       int cmdPtr;
-       int ctxtMatch;
-};
-
-/* DMA transmit context */
-struct dma_trm_ctx {
-       struct ti_ohci *ohci;
-       enum context_type type;
-       int ctx;
-       unsigned int num_desc;
-
-       /* dma block descriptors */
-        struct at_dma_prg **prg_cpu;
-       dma_addr_t *prg_bus;
-       struct pci_pool *prg_pool;
-
-        unsigned int prg_ind;
-        unsigned int sent_ind;
-       int free_prgs;
-        quadlet_t *branchAddrPtr;
-
-       /* list of packets inserted in the AT FIFO */
-       struct list_head fifo_list;
-
-       /* list of pending packets to be inserted in the AT FIFO */
-       struct list_head pending_list;
-
-        spinlock_t lock;
-        struct tasklet_struct task;
-       int ctrlClear;
-       int ctrlSet;
-       int cmdPtr;
-};
-
-struct ohci1394_iso_tasklet {
-       struct tasklet_struct tasklet;
-       struct list_head link;
-       int context;
-       enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE,
-              OHCI_ISO_MULTICHANNEL_RECEIVE } type;
-};
-
-struct ti_ohci {
-        struct pci_dev *dev;
-
-       enum {
-               OHCI_INIT_ALLOC_HOST,
-               OHCI_INIT_HAVE_MEM_REGION,
-               OHCI_INIT_HAVE_IOMAPPING,
-               OHCI_INIT_HAVE_CONFIG_ROM_BUFFER,
-               OHCI_INIT_HAVE_SELFID_BUFFER,
-               OHCI_INIT_HAVE_TXRX_BUFFERS__MAYBE,
-               OHCI_INIT_HAVE_IRQ,
-               OHCI_INIT_DONE,
-       } init_state;
-
-        /* remapped memory spaces */
-        void __iomem *registers;
-
-       /* dma buffer for self-id packets */
-        quadlet_t *selfid_buf_cpu;
-        dma_addr_t selfid_buf_bus;
-
-       /* buffer for csr config rom */
-        quadlet_t *csr_config_rom_cpu;
-        dma_addr_t csr_config_rom_bus;
-       int csr_config_rom_length;
-
-       unsigned int max_packet_size;
-
-        /* async receive */
-       struct dma_rcv_ctx ar_resp_context;
-       struct dma_rcv_ctx ar_req_context;
-
-       /* async transmit */
-       struct dma_trm_ctx at_resp_context;
-       struct dma_trm_ctx at_req_context;
-
-        /* iso receive */
-       int nb_iso_rcv_ctx;
-       unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */
-       unsigned long ir_multichannel_used; /* ditto */
-        spinlock_t IR_channel_lock;
-
-        /* iso transmit */
-       int nb_iso_xmit_ctx;
-       unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
-
-        u64 ISO_channel_usage;
-
-        /* IEEE-1394 part follows */
-        struct hpsb_host *host;
-
-        int phyid, isroot;
-
-        spinlock_t phy_reg_lock;
-       spinlock_t event_lock;
-
-       int self_id_errors;
-
-       /* Tasklets for iso receive and transmit, used by video1394
-        * and dv1394 */
-       struct list_head iso_tasklet_list;
-       spinlock_t iso_tasklet_list_lock;
-
-       /* Swap the selfid buffer? */
-       unsigned int selfid_swap:1;
-       /* Some Apple chipset seem to swap incoming headers for us */
-       unsigned int no_swap_incoming:1;
-
-       /* Force extra paranoia checking on bus-reset handling */
-       unsigned int check_busreset:1;
-};
-
-static inline int cross_bound(unsigned long addr, unsigned int size)
-{
-       if (size == 0)
-               return 0;
-
-       if (size > PAGE_SIZE)
-               return 1;
-
-       if (addr >> PAGE_SHIFT != (addr + size - 1) >> PAGE_SHIFT)
-               return 1;
-
-       return 0;
-}
-
-/*
- * Register read and write helper functions.
- */
-static inline void reg_write(const struct ti_ohci *ohci, int offset, u32 data)
-{
-        writel(data, ohci->registers + offset);
-}
-
-static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
-{
-        return readl(ohci->registers + offset);
-}
-
-
-/* 2 KiloBytes of register space */
-#define OHCI1394_REGISTER_SIZE                0x800
-
-/* Offsets relative to context bases defined below */
-
-#define OHCI1394_ContextControlSet            0x000
-#define OHCI1394_ContextControlClear          0x004
-#define OHCI1394_ContextCommandPtr            0x00C
-
-/* register map */
-#define OHCI1394_Version                      0x000
-#define OHCI1394_GUID_ROM                     0x004
-#define OHCI1394_ATRetries                    0x008
-#define OHCI1394_CSRData                      0x00C
-#define OHCI1394_CSRCompareData               0x010
-#define OHCI1394_CSRControl                   0x014
-#define OHCI1394_ConfigROMhdr                 0x018
-#define OHCI1394_BusID                        0x01C
-#define OHCI1394_BusOptions                   0x020
-#define OHCI1394_GUIDHi                       0x024
-#define OHCI1394_GUIDLo                       0x028
-#define OHCI1394_ConfigROMmap                 0x034
-#define OHCI1394_PostedWriteAddressLo         0x038
-#define OHCI1394_PostedWriteAddressHi         0x03C
-#define OHCI1394_VendorID                     0x040
-#define OHCI1394_HCControlSet                 0x050
-#define OHCI1394_HCControlClear               0x054
-#define  OHCI1394_HCControl_noByteSwap         0x40000000
-#define  OHCI1394_HCControl_programPhyEnable   0x00800000
-#define  OHCI1394_HCControl_aPhyEnhanceEnable  0x00400000
-#define  OHCI1394_HCControl_LPS                        0x00080000
-#define  OHCI1394_HCControl_postedWriteEnable  0x00040000
-#define  OHCI1394_HCControl_linkEnable         0x00020000
-#define  OHCI1394_HCControl_softReset          0x00010000
-#define OHCI1394_SelfIDBuffer                 0x064
-#define OHCI1394_SelfIDCount                  0x068
-#define OHCI1394_IRMultiChanMaskHiSet         0x070
-#define OHCI1394_IRMultiChanMaskHiClear       0x074
-#define OHCI1394_IRMultiChanMaskLoSet         0x078
-#define OHCI1394_IRMultiChanMaskLoClear       0x07C
-#define OHCI1394_IntEventSet                  0x080
-#define OHCI1394_IntEventClear                0x084
-#define OHCI1394_IntMaskSet                   0x088
-#define OHCI1394_IntMaskClear                 0x08C
-#define OHCI1394_IsoXmitIntEventSet           0x090
-#define OHCI1394_IsoXmitIntEventClear         0x094
-#define OHCI1394_IsoXmitIntMaskSet            0x098
-#define OHCI1394_IsoXmitIntMaskClear          0x09C
-#define OHCI1394_IsoRecvIntEventSet           0x0A0
-#define OHCI1394_IsoRecvIntEventClear         0x0A4
-#define OHCI1394_IsoRecvIntMaskSet            0x0A8
-#define OHCI1394_IsoRecvIntMaskClear          0x0AC
-#define OHCI1394_InitialBandwidthAvailable    0x0B0
-#define OHCI1394_InitialChannelsAvailableHi   0x0B4
-#define OHCI1394_InitialChannelsAvailableLo   0x0B8
-#define OHCI1394_FairnessControl              0x0DC
-#define OHCI1394_LinkControlSet               0x0E0
-#define OHCI1394_LinkControlClear             0x0E4
-#define  OHCI1394_LinkControl_RcvSelfID                0x00000200
-#define  OHCI1394_LinkControl_RcvPhyPkt                0x00000400
-#define  OHCI1394_LinkControl_CycleTimerEnable 0x00100000
-#define  OHCI1394_LinkControl_CycleMaster      0x00200000
-#define  OHCI1394_LinkControl_CycleSource      0x00400000
-#define OHCI1394_NodeID                       0x0E8
-#define OHCI1394_PhyControl                   0x0EC
-#define OHCI1394_IsochronousCycleTimer        0x0F0
-#define OHCI1394_AsReqFilterHiSet             0x100
-#define OHCI1394_AsReqFilterHiClear           0x104
-#define OHCI1394_AsReqFilterLoSet             0x108
-#define OHCI1394_AsReqFilterLoClear           0x10C
-#define OHCI1394_PhyReqFilterHiSet            0x110
-#define OHCI1394_PhyReqFilterHiClear          0x114
-#define OHCI1394_PhyReqFilterLoSet            0x118
-#define OHCI1394_PhyReqFilterLoClear          0x11C
-#define OHCI1394_PhyUpperBound                0x120
-
-#define OHCI1394_AsReqTrContextBase           0x180
-#define OHCI1394_AsReqTrContextControlSet     0x180
-#define OHCI1394_AsReqTrContextControlClear   0x184
-#define OHCI1394_AsReqTrCommandPtr            0x18C
-
-#define OHCI1394_AsRspTrContextBase           0x1A0
-#define OHCI1394_AsRspTrContextControlSet     0x1A0
-#define OHCI1394_AsRspTrContextControlClear   0x1A4
-#define OHCI1394_AsRspTrCommandPtr            0x1AC
-
-#define OHCI1394_AsReqRcvContextBase          0x1C0
-#define OHCI1394_AsReqRcvContextControlSet    0x1C0
-#define OHCI1394_AsReqRcvContextControlClear  0x1C4
-#define OHCI1394_AsReqRcvCommandPtr           0x1CC
-
-#define OHCI1394_AsRspRcvContextBase          0x1E0
-#define OHCI1394_AsRspRcvContextControlSet    0x1E0
-#define OHCI1394_AsRspRcvContextControlClear  0x1E4
-#define OHCI1394_AsRspRcvCommandPtr           0x1EC
-
-/* Isochronous transmit registers */
-/* Add (16 * n) for context n */
-#define OHCI1394_IsoXmitContextBase           0x200
-#define OHCI1394_IsoXmitContextControlSet     0x200
-#define OHCI1394_IsoXmitContextControlClear   0x204
-#define OHCI1394_IsoXmitCommandPtr            0x20C
-
-/* Isochronous receive registers */
-/* Add (32 * n) for context n */
-#define OHCI1394_IsoRcvContextBase            0x400
-#define OHCI1394_IsoRcvContextControlSet      0x400
-#define OHCI1394_IsoRcvContextControlClear    0x404
-#define OHCI1394_IsoRcvCommandPtr             0x40C
-#define OHCI1394_IsoRcvContextMatch           0x410
-
-/* Interrupts Mask/Events */
-
-#define OHCI1394_reqTxComplete           0x00000001
-#define OHCI1394_respTxComplete          0x00000002
-#define OHCI1394_ARRQ                    0x00000004
-#define OHCI1394_ARRS                    0x00000008
-#define OHCI1394_RQPkt                   0x00000010
-#define OHCI1394_RSPkt                   0x00000020
-#define OHCI1394_isochTx                 0x00000040
-#define OHCI1394_isochRx                 0x00000080
-#define OHCI1394_postedWriteErr          0x00000100
-#define OHCI1394_lockRespErr             0x00000200
-#define OHCI1394_selfIDComplete          0x00010000
-#define OHCI1394_busReset                0x00020000
-#define OHCI1394_phy                     0x00080000
-#define OHCI1394_cycleSynch              0x00100000
-#define OHCI1394_cycle64Seconds          0x00200000
-#define OHCI1394_cycleLost               0x00400000
-#define OHCI1394_cycleInconsistent       0x00800000
-#define OHCI1394_unrecoverableError      0x01000000
-#define OHCI1394_cycleTooLong            0x02000000
-#define OHCI1394_phyRegRcvd              0x04000000
-#define OHCI1394_masterIntEnable         0x80000000
-
-/* DMA Control flags */
-#define DMA_CTL_OUTPUT_MORE              0x00000000
-#define DMA_CTL_OUTPUT_LAST              0x10000000
-#define DMA_CTL_INPUT_MORE               0x20000000
-#define DMA_CTL_INPUT_LAST               0x30000000
-#define DMA_CTL_UPDATE                   0x08000000
-#define DMA_CTL_IMMEDIATE                0x02000000
-#define DMA_CTL_IRQ                      0x00300000
-#define DMA_CTL_BRANCH                   0x000c0000
-#define DMA_CTL_WAIT                     0x00030000
-
-/* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */
-#define EVT_NO_STATUS          0x0     /* No event status */
-#define EVT_RESERVED_A         0x1     /* Reserved, not used !!! */
-#define EVT_LONG_PACKET                0x2     /* The revc data was longer than the buf */
-#define EVT_MISSING_ACK                0x3     /* A subaction gap was detected before an ack
-                                          arrived, or recv'd ack had a parity error */
-#define EVT_UNDERRUN           0x4     /* Underrun on corresponding FIFO, packet
-                                          truncated */
-#define EVT_OVERRUN            0x5     /* A recv FIFO overflowed on reception of ISO
-                                          packet */
-#define EVT_DESCRIPTOR_READ    0x6     /* An unrecoverable error occurred while host was
-                                          reading a descriptor block */
-#define EVT_DATA_READ          0x7     /* An error occurred while host controller was
-                                          attempting to read from host memory in the data
-                                          stage of descriptor processing */
-#define EVT_DATA_WRITE         0x8     /* An error occurred while host controller was
-                                          attempting to write either during the data stage
-                                          of descriptor processing, or when processing a single
-                                          16-bit host memory write */
-#define EVT_BUS_RESET          0x9     /* Identifies a PHY packet in the recv buffer as
-                                          being a synthesized bus reset packet */
-#define EVT_TIMEOUT            0xa     /* Indicates that the asynchronous transmit response
-                                          packet expired and was not transmitted, or that an
-                                          IT DMA context experienced a skip processing overflow */
-#define EVT_TCODE_ERR          0xb     /* A bad tCode is associated with this packet.
-                                          The packet was flushed */
-#define EVT_RESERVED_B         0xc     /* Reserved, not used !!! */
-#define EVT_RESERVED_C         0xd     /* Reserved, not used !!! */
-#define EVT_UNKNOWN            0xe     /* An error condition has occurred that cannot be
-                                          represented by any other event codes defined herein. */
-#define EVT_FLUSHED            0xf     /* Send by the link side of output FIFO when asynchronous
-                                          packets are being flushed due to a bus reset. */
-
-#define OHCI1394_TCODE_PHY               0xE
-
-/* Node offset map (phys DMA area, posted write area).
- * The value of OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED may be modified but must
- * be lower than OHCI1394_MIDDLE_ADDRESS_SPACE.
- * OHCI1394_PHYS_UPPER_BOUND_FIXED and OHCI1394_MIDDLE_ADDRESS_SPACE are
- * constants given by the OHCI spec.
- */
-#define OHCI1394_PHYS_UPPER_BOUND_FIXED                0x000100000000ULL /* 4 GB */
-#define OHCI1394_PHYS_UPPER_BOUND_PROGRAMMED   0x010000000000ULL /* 1 TB */
-#define OHCI1394_MIDDLE_ADDRESS_SPACE          0xffff00000000ULL
-
-void ohci1394_init_iso_tasklet(struct ohci1394_iso_tasklet *tasklet,
-                              int type,
-                              void (*func)(unsigned long),
-                              unsigned long data);
-int ohci1394_register_iso_tasklet(struct ti_ohci *ohci,
-                                 struct ohci1394_iso_tasklet *tasklet);
-void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
-                                    struct ohci1394_iso_tasklet *tasklet);
-int ohci1394_stop_context(struct ti_ohci *ohci, int reg, char *msg);
-struct ti_ohci *ohci1394_get_struct(int card_num);
-
-#endif
diff --git a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
deleted file mode 100644 (file)
index bf47fee..0000000
+++ /dev/null
@@ -1,1554 +0,0 @@
-/*
- * pcilynx.c - Texas Instruments PCILynx driver
- * Copyright (C) 1999,2000 Andreas Bombe <andreas.bombe@munich.netsurf.de>,
- *                         Stephan Linz <linz@mazet.de>
- *                         Manfred Weihs <weihs@ict.tuwien.ac.at>
- *
- * 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.
- */
-
-/*
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        reading bus info block (containing GUID) from serial
- *            eeprom via i2c and storing it in config ROM
- *        Reworked code for initiating bus resets
- *            (long, short, with or without hold-off)
- *        Enhancements in async and iso send code
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/kdev_t.h>
-#include <linux/dma-mapping.h>
-#include <asm/byteorder.h>
-#include <asm/atomic.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-
-#include "csr1212.h"
-#include "ieee1394.h"
-#include "ieee1394_types.h"
-#include "hosts.h"
-#include "ieee1394_core.h"
-#include "highlevel.h"
-#include "pcilynx.h"
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-
-/* print general (card independent) information */
-#define PRINT_G(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args)
-/* print card specific information */
-#define PRINT(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args)
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define PRINT_GD(level, fmt, args...) printk(level "pcilynx: " fmt "\n" , ## args)
-#define PRINTD(level, card, fmt, args...) printk(level "pcilynx%d: " fmt "\n" , card , ## args)
-#else
-#define PRINT_GD(level, fmt, args...) do {} while (0)
-#define PRINTD(level, card, fmt, args...) do {} while (0)
-#endif
-
-
-/* Module Parameters */
-static int skip_eeprom;
-module_param(skip_eeprom, int, 0444);
-MODULE_PARM_DESC(skip_eeprom, "Use generic bus info block instead of serial eeprom (default = 0).");
-
-
-static struct hpsb_host_driver lynx_driver;
-static unsigned int card_id;
-
-
-
-/*
- * I2C stuff
- */
-
-/* the i2c stuff was inspired by i2c-philips-par.c */
-
-static void bit_setscl(void *data, int state)
-{
-       if (state) {
-                 ((struct ti_lynx *) data)->i2c_driven_state |= 0x00000040;
-       } else {
-                 ((struct ti_lynx *) data)->i2c_driven_state &= ~0x00000040;
-       }
-       reg_write((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL, ((struct ti_lynx *) data)->i2c_driven_state);
-}
-
-static void bit_setsda(void *data, int state)
-{
-       if (state) {
-                 ((struct ti_lynx *) data)->i2c_driven_state |= 0x00000010;
-       } else {
-                 ((struct ti_lynx *) data)->i2c_driven_state &= ~0x00000010;
-       }
-       reg_write((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL, ((struct ti_lynx *) data)->i2c_driven_state);
-}
-
-static int bit_getscl(void *data)
-{
-       return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000040;
-}
-
-static int bit_getsda(void *data)
-{
-       return reg_read((struct ti_lynx *) data, SERIAL_EEPROM_CONTROL) & 0x00000010;
-}
-
-static struct i2c_algo_bit_data bit_data = {
-       .setsda                 = bit_setsda,
-       .setscl                 = bit_setscl,
-       .getsda                 = bit_getsda,
-       .getscl                 = bit_getscl,
-       .udelay                 = 5,
-       .timeout                = 100,
-};
-
-
-/*
- * PCL handling functions.
- */
-
-static pcl_t alloc_pcl(struct ti_lynx *lynx)
-{
-        u8 m;
-        int i, j;
-
-        spin_lock(&lynx->lock);
-        /* FIXME - use ffz() to make this readable */
-        for (i = 0; i < (LOCALRAM_SIZE / 1024); i++) {
-                m = lynx->pcl_bmap[i];
-                for (j = 0; j < 8; j++) {
-                        if (m & 1<<j) {
-                                continue;
-                        }
-                        m |= 1<<j;
-                        lynx->pcl_bmap[i] = m;
-                        spin_unlock(&lynx->lock);
-                        return 8 * i + j;
-                }
-        }
-        spin_unlock(&lynx->lock);
-
-        return -1;
-}
-
-
-#if 0
-static void free_pcl(struct ti_lynx *lynx, pcl_t pclid)
-{
-        int off, bit;
-
-        off = pclid / 8;
-        bit = pclid % 8;
-
-        if (pclid < 0) {
-                return;
-        }
-
-        spin_lock(&lynx->lock);
-        if (lynx->pcl_bmap[off] & 1<<bit) {
-                lynx->pcl_bmap[off] &= ~(1<<bit);
-        } else {
-                PRINT(KERN_ERR, lynx->id,
-                      "attempted to free unallocated PCL %d", pclid);
-        }
-        spin_unlock(&lynx->lock);
-}
-
-/* functions useful for debugging */
-static void pretty_print_pcl(const struct ti_pcl *pcl)
-{
-        int i;
-
-        printk("PCL next %08x, userdata %08x, status %08x, remtrans %08x, nextbuf %08x\n",
-               pcl->next, pcl->user_data, pcl->pcl_status,
-               pcl->remaining_transfer_count, pcl->next_data_buffer);
-
-        printk("PCL");
-        for (i=0; i<13; i++) {
-                printk(" c%x:%08x d%x:%08x",
-                       i, pcl->buffer[i].control, i, pcl->buffer[i].pointer);
-                if (!(i & 0x3) && (i != 12)) printk("\nPCL");
-        }
-        printk("\n");
-}
-
-static void print_pcl(const struct ti_lynx *lynx, pcl_t pclid)
-{
-        struct ti_pcl pcl;
-
-        get_pcl(lynx, pclid, &pcl);
-        pretty_print_pcl(&pcl);
-}
-#endif
-
-
-
-/***********************************
- * IEEE-1394 functionality section *
- ***********************************/
-
-
-static int get_phy_reg(struct ti_lynx *lynx, int addr)
-{
-        int retval;
-        int i = 0;
-
-        unsigned long flags;
-
-        if (addr > 15) {
-                PRINT(KERN_ERR, lynx->id,
-                      "%s: PHY register address %d out of range",
-                     __func__, addr);
-                return -1;
-        }
-
-        spin_lock_irqsave(&lynx->phy_reg_lock, flags);
-
-        reg_write(lynx, LINK_PHY, LINK_PHY_READ | LINK_PHY_ADDR(addr));
-        do {
-                retval = reg_read(lynx, LINK_PHY);
-
-                if (i > 10000) {
-                        PRINT(KERN_ERR, lynx->id, "%s: runaway loop, aborting",
-                             __func__);
-                        retval = -1;
-                        break;
-                }
-                i++;
-        } while ((retval & 0xf00) != LINK_PHY_RADDR(addr));
-
-        reg_write(lynx, LINK_INT_STATUS, LINK_INT_PHY_REG_RCVD);
-        spin_unlock_irqrestore(&lynx->phy_reg_lock, flags);
-
-        if (retval != -1) {
-                return retval & 0xff;
-        } else {
-                return -1;
-        }
-}
-
-static int set_phy_reg(struct ti_lynx *lynx, int addr, int val)
-{
-        unsigned long flags;
-
-        if (addr > 15) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY register address %d out of range", __func__, addr);
-                return -1;
-        }
-
-        if (val > 0xff) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY register value %d out of range", __func__, val);
-                return -1;
-        }
-
-        spin_lock_irqsave(&lynx->phy_reg_lock, flags);
-
-        reg_write(lynx, LINK_PHY, LINK_PHY_WRITE | LINK_PHY_ADDR(addr)
-                  | LINK_PHY_WDATA(val));
-
-        spin_unlock_irqrestore(&lynx->phy_reg_lock, flags);
-
-        return 0;
-}
-
-static int sel_phy_reg_page(struct ti_lynx *lynx, int page)
-{
-        int reg;
-
-        if (page > 7) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY page %d out of range", __func__, page);
-                return -1;
-        }
-
-        reg = get_phy_reg(lynx, 7);
-        if (reg != -1) {
-                reg &= 0x1f;
-                reg |= (page << 5);
-                set_phy_reg(lynx, 7, reg);
-                return 0;
-        } else {
-                return -1;
-        }
-}
-
-#if 0 /* not needed at this time */
-static int sel_phy_reg_port(struct ti_lynx *lynx, int port)
-{
-        int reg;
-
-        if (port > 15) {
-                PRINT(KERN_ERR, lynx->id,
-                     "%s: PHY port %d out of range", __func__, port);
-                return -1;
-        }
-
-        reg = get_phy_reg(lynx, 7);
-        if (reg != -1) {
-                reg &= 0xf0;
-                reg |= port;
-                set_phy_reg(lynx, 7, reg);
-                return 0;
-        } else {
-                return -1;
-        }
-}
-#endif
-
-static u32 get_phy_vendorid(struct ti_lynx *lynx)
-{
-        u32 pvid = 0;
-        sel_phy_reg_page(lynx, 1);
-        pvid |= (get_phy_reg(lynx, 10) << 16);
-        pvid |= (get_phy_reg(lynx, 11) << 8);
-        pvid |= get_phy_reg(lynx, 12);
-        PRINT(KERN_INFO, lynx->id, "PHY vendor id 0x%06x", pvid);
-        return pvid;
-}
-
-static u32 get_phy_productid(struct ti_lynx *lynx)
-{
-        u32 id = 0;
-        sel_phy_reg_page(lynx, 1);
-        id |= (get_phy_reg(lynx, 13) << 16);
-        id |= (get_phy_reg(lynx, 14) << 8);
-        id |= get_phy_reg(lynx, 15);
-        PRINT(KERN_INFO, lynx->id, "PHY product id 0x%06x", id);
-        return id;
-}
-
-static quadlet_t generate_own_selfid(struct ti_lynx *lynx,
-                                     struct hpsb_host *host)
-{
-        quadlet_t lsid;
-        char phyreg[7];
-        int i;
-
-        phyreg[0] = lynx->phy_reg0;
-        for (i = 1; i < 7; i++) {
-                phyreg[i] = get_phy_reg(lynx, i);
-        }
-
-        /* FIXME? We assume a TSB21LV03A phy here.  This code doesn't support
-           more than 3 ports on the PHY anyway. */
-
-        lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22);
-        lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */
-        lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */
-       if (!hpsb_disable_irm)
-               lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */
-        /* lsid |= 1 << 11; *//* set contender (hack) */
-        lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */
-
-        for (i = 0; i < (phyreg[2] & 0xf); i++) { /* ports */
-                if (phyreg[3 + i] & 0x4) {
-                        lsid |= (((phyreg[3 + i] & 0x8) | 0x10) >> 3)
-                                << (6 - i*2);
-                } else {
-                        lsid |= 1 << (6 - i*2);
-                }
-        }
-
-        cpu_to_be32s(&lsid);
-        PRINT(KERN_DEBUG, lynx->id, "generated own selfid 0x%x", lsid);
-        return lsid;
-}
-
-static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host)
-{
-        quadlet_t *q = lynx->rcv_page;
-        int phyid, isroot, size;
-        quadlet_t lsid = 0;
-        int i;
-
-        if (lynx->phy_reg0 == -1 || lynx->selfid_size == -1) return;
-
-        size = lynx->selfid_size;
-        phyid = lynx->phy_reg0;
-
-        i = (size > 16 ? 16 : size) / 4 - 1;
-        while (i >= 0) {
-                cpu_to_be32s(&q[i]);
-                i--;
-        }
-
-        if (!lynx->phyic.reg_1394a) {
-                lsid = generate_own_selfid(lynx, host);
-        }
-
-        isroot = (phyid & 2) != 0;
-        phyid >>= 2;
-        PRINT(KERN_INFO, lynx->id, "SelfID process finished (phyid %d, %s)",
-              phyid, (isroot ? "root" : "not root"));
-        reg_write(lynx, LINK_ID, (0xffc0 | phyid) << 16);
-
-        if (!lynx->phyic.reg_1394a && !size) {
-                hpsb_selfid_received(host, lsid);
-        }
-
-        while (size > 0) {
-                struct selfid *sid = (struct selfid *)q;
-
-                if (!lynx->phyic.reg_1394a && !sid->extended
-                    && (sid->phy_id == (phyid + 1))) {
-                        hpsb_selfid_received(host, lsid);
-                }
-
-                if (q[0] == ~q[1]) {
-                        PRINT(KERN_DEBUG, lynx->id, "SelfID packet 0x%x rcvd",
-                              q[0]);
-                        hpsb_selfid_received(host, q[0]);
-                } else {
-                        PRINT(KERN_INFO, lynx->id,
-                              "inconsistent selfid 0x%x/0x%x", q[0], q[1]);
-                }
-                q += 2;
-                size -= 8;
-        }
-
-        if (!lynx->phyic.reg_1394a && isroot && phyid != 0) {
-                hpsb_selfid_received(host, lsid);
-        }
-
-        hpsb_selfid_complete(host, phyid, isroot);
-
-        if (host->in_bus_reset) return; /* in bus reset again */
-
-        if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER); //FIXME: I do not think, we need this here
-        reg_set_bits(lynx, LINK_CONTROL,
-                     LINK_CONTROL_RCV_CMP_VALID | LINK_CONTROL_TX_ASYNC_EN
-                     | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_CYCTIMEREN);
-}
-
-
-
-/* This must be called with the respective queue_lock held. */
-static void send_next(struct ti_lynx *lynx, int what)
-{
-        struct ti_pcl pcl;
-        struct lynx_send_data *d;
-        struct hpsb_packet *packet;
-
-#if 0 /* has been removed from ieee1394 core */
-        d = (what == hpsb_iso ? &lynx->iso_send : &lynx->async);
-#else
-       d = &lynx->async;
-#endif
-        if (!list_empty(&d->pcl_queue)) {
-                PRINT(KERN_ERR, lynx->id, "trying to queue a new packet in nonempty fifo");
-                BUG();
-        }
-
-        packet = driver_packet(d->queue.next);
-       list_move_tail(&packet->driver_list, &d->pcl_queue);
-
-        d->header_dma = pci_map_single(lynx->dev, packet->header,
-                                       packet->header_size, PCI_DMA_TODEVICE);
-        if (packet->data_size) {
-                d->data_dma = pci_map_single(lynx->dev, packet->data,
-                                             packet->data_size,
-                                             PCI_DMA_TODEVICE);
-        } else {
-                d->data_dma = 0;
-        }
-
-        pcl.next = PCL_NEXT_INVALID;
-        pcl.async_error_next = PCL_NEXT_INVALID;
-        pcl.pcl_status = 0;
-        pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size;
-#ifndef __BIG_ENDIAN
-        pcl.buffer[0].control |= PCL_BIGENDIAN;
-#endif
-        pcl.buffer[0].pointer = d->header_dma;
-        pcl.buffer[1].control = PCL_LAST_BUFF | packet->data_size;
-        pcl.buffer[1].pointer = d->data_dma;
-
-        switch (packet->type) {
-        case hpsb_async:
-                pcl.buffer[0].control |= PCL_CMD_XMT;
-                break;
-#if 0 /* has been removed from ieee1394 core */
-        case hpsb_iso:
-                pcl.buffer[0].control |= PCL_CMD_XMT | PCL_ISOMODE;
-                break;
-#endif
-        case hpsb_raw:
-                pcl.buffer[0].control |= PCL_CMD_UNFXMT;
-                break;
-        }
-
-        put_pcl(lynx, d->pcl, &pcl);
-        run_pcl(lynx, d->pcl_start, d->channel);
-}
-
-
-/* called from subsystem core */
-static int lynx_transmit(struct hpsb_host *host, struct hpsb_packet *packet)
-{
-        struct ti_lynx *lynx = host->hostdata;
-        struct lynx_send_data *d;
-        unsigned long flags;
-
-        if (packet->data_size >= 4096) {
-                PRINT(KERN_ERR, lynx->id, "transmit packet data too big (%Zd)",
-                      packet->data_size);
-                return -EOVERFLOW;
-        }
-
-        switch (packet->type) {
-        case hpsb_async:
-        case hpsb_raw:
-                d = &lynx->async;
-                break;
-#if 0 /* has been removed from ieee1394 core */
-        case hpsb_iso:
-                d = &lynx->iso_send;
-                break;
-#endif
-        default:
-                PRINT(KERN_ERR, lynx->id, "invalid packet type %d",
-                      packet->type);
-                return -EINVAL;
-        }
-
-        if (packet->tcode == TCODE_WRITEQ
-            || packet->tcode == TCODE_READQ_RESPONSE) {
-                cpu_to_be32s(&packet->header[3]);
-        }
-
-        spin_lock_irqsave(&d->queue_lock, flags);
-
-       list_add_tail(&packet->driver_list, &d->queue);
-       if (list_empty(&d->pcl_queue))
-                send_next(lynx, packet->type);
-
-        spin_unlock_irqrestore(&d->queue_lock, flags);
-
-        return 0;
-}
-
-
-/* called from subsystem core */
-static int lynx_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
-{
-        struct ti_lynx *lynx = host->hostdata;
-        int retval = 0;
-        struct hpsb_packet *packet;
-       LIST_HEAD(packet_list);
-        unsigned long flags;
-       int phy_reg;
-
-        switch (cmd) {
-        case RESET_BUS:
-                if (reg_read(lynx, LINK_INT_STATUS) & LINK_INT_PHY_BUSRESET) {
-                        retval = 0;
-                        break;
-                }
-
-               switch (arg) {
-               case SHORT_RESET:
-                       if (lynx->phyic.reg_1394a) {
-                               phy_reg = get_phy_reg(lynx, 5);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               phy_reg |= 0x40;
-
-                               PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset) on request");
-
-                               lynx->selfid_size = -1;
-                               lynx->phy_reg0 = -1;
-                               set_phy_reg(lynx, 5, phy_reg); /* set ISBR */
-                               break;
-                       } else {
-                               PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");
-                               /* fall through to long bus reset */
-                       }
-               case LONG_RESET:
-                       phy_reg = get_phy_reg(lynx, 1);
-                       if (phy_reg == -1) {
-                               PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                               retval = -1;
-                               break;
-                       }
-                       phy_reg |= 0x40;
-
-                       PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset) on request");
-
-                       lynx->selfid_size = -1;
-                       lynx->phy_reg0 = -1;
-                       set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */
-                       break;
-               case SHORT_RESET_NO_FORCE_ROOT:
-                       if (lynx->phyic.reg_1394a) {
-                               phy_reg = get_phy_reg(lynx, 1);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               if (phy_reg & 0x80) {
-                                       phy_reg &= ~0x80;
-                                       set_phy_reg(lynx, 1, phy_reg); /* clear RHB */
-                               }
-
-                               phy_reg = get_phy_reg(lynx, 5);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               phy_reg |= 0x40;
-
-                               PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, no force_root) on request");
-
-                               lynx->selfid_size = -1;
-                               lynx->phy_reg0 = -1;
-                               set_phy_reg(lynx, 5, phy_reg); /* set ISBR */
-                               break;
-                       } else {
-                               PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");
-                               /* fall through to long bus reset */
-                       }
-               case LONG_RESET_NO_FORCE_ROOT:
-                       phy_reg = get_phy_reg(lynx, 1);
-                       if (phy_reg == -1) {
-                               PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                               retval = -1;
-                               break;
-                       }
-                       phy_reg &= ~0x80;
-                       phy_reg |= 0x40;
-
-                       PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, no force_root) on request");
-
-                       lynx->selfid_size = -1;
-                       lynx->phy_reg0 = -1;
-                       set_phy_reg(lynx, 1, phy_reg); /* clear RHB, set IBR */
-                       break;
-               case SHORT_RESET_FORCE_ROOT:
-                       if (lynx->phyic.reg_1394a) {
-                               phy_reg = get_phy_reg(lynx, 1);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               if (!(phy_reg & 0x80)) {
-                                       phy_reg |= 0x80;
-                                       set_phy_reg(lynx, 1, phy_reg); /* set RHB */
-                               }
-
-                               phy_reg = get_phy_reg(lynx, 5);
-                               if (phy_reg == -1) {
-                                       PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                                       retval = -1;
-                                       break;
-                               }
-                               phy_reg |= 0x40;
-
-                               PRINT(KERN_INFO, lynx->id, "resetting bus (short bus reset, force_root set) on request");
-
-                               lynx->selfid_size = -1;
-                               lynx->phy_reg0 = -1;
-                               set_phy_reg(lynx, 5, phy_reg); /* set ISBR */
-                               break;
-                       } else {
-                               PRINT(KERN_INFO, lynx->id, "cannot do short bus reset, because of old phy");
-                               /* fall through to long bus reset */
-                       }
-               case LONG_RESET_FORCE_ROOT:
-                       phy_reg = get_phy_reg(lynx, 1);
-                       if (phy_reg == -1) {
-                               PRINT(KERN_ERR, lynx->id, "cannot reset bus, because read phy reg failed");
-                               retval = -1;
-                               break;
-                       }
-                       phy_reg |= 0xc0;
-
-                       PRINT(KERN_INFO, lynx->id, "resetting bus (long bus reset, force_root set) on request");
-
-                       lynx->selfid_size = -1;
-                       lynx->phy_reg0 = -1;
-                       set_phy_reg(lynx, 1, phy_reg); /* set IBR and RHB */
-                       break;
-               default:
-                       PRINT(KERN_ERR, lynx->id, "unknown argument for reset_bus command %d", arg);
-                       retval = -1;
-               }
-
-                break;
-
-        case GET_CYCLE_COUNTER:
-                retval = reg_read(lynx, CYCLE_TIMER);
-                break;
-
-        case SET_CYCLE_COUNTER:
-                reg_write(lynx, CYCLE_TIMER, arg);
-                break;
-
-        case SET_BUS_ID:
-                reg_write(lynx, LINK_ID,
-                          (arg << 22) | (reg_read(lynx, LINK_ID) & 0x003f0000));
-                break;
-
-        case ACT_CYCLE_MASTER:
-                if (arg) {
-                        reg_set_bits(lynx, LINK_CONTROL,
-                                     LINK_CONTROL_CYCMASTER);
-                } else {
-                        reg_clear_bits(lynx, LINK_CONTROL,
-                                       LINK_CONTROL_CYCMASTER);
-                }
-                break;
-
-        case CANCEL_REQUESTS:
-                spin_lock_irqsave(&lynx->async.queue_lock, flags);
-
-                reg_write(lynx, DMA_CHAN_CTRL(CHANNEL_ASYNC_SEND), 0);
-               list_splice_init(&lynx->async.queue, &packet_list);
-
-                if (list_empty(&lynx->async.pcl_queue)) {
-                        spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
-                        PRINTD(KERN_DEBUG, lynx->id, "no async packet in PCL to cancel");
-                } else {
-                        struct ti_pcl pcl;
-                        u32 ack;
-
-                        PRINT(KERN_INFO, lynx->id, "cancelling async packet, that was already in PCL");
-
-                        get_pcl(lynx, lynx->async.pcl, &pcl);
-
-                        packet = driver_packet(lynx->async.pcl_queue.next);
-                       list_del_init(&packet->driver_list);
-
-                        pci_unmap_single(lynx->dev, lynx->async.header_dma,
-                                         packet->header_size, PCI_DMA_TODEVICE);
-                        if (packet->data_size) {
-                                pci_unmap_single(lynx->dev, lynx->async.data_dma,
-                                                 packet->data_size, PCI_DMA_TODEVICE);
-                        }
-
-                        spin_unlock_irqrestore(&lynx->async.queue_lock, flags);
-
-                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
-                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
-                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
-                                } else {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                }
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "async packet was not completed");
-                                ack = ACKX_ABORTED;
-                        }
-                        hpsb_packet_sent(host, packet, ack);
-                }
-
-               while (!list_empty(&packet_list)) {
-                       packet = driver_packet(packet_list.next);
-                       list_del_init(&packet->driver_list);
-                       hpsb_packet_sent(host, packet, ACKX_ABORTED);
-               }
-
-                break;
-#if 0 /* has been removed from ieee1394 core */
-        case ISO_LISTEN_CHANNEL:
-                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-
-                if (lynx->iso_rcv.chan_count++ == 0) {
-                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
-                                  DMA_WORD1_CMP_ENABLE_MASTER);
-                }
-
-                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-                break;
-
-        case ISO_UNLISTEN_CHANNEL:
-                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-
-                if (--lynx->iso_rcv.chan_count == 0) {
-                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
-                                  0);
-                }
-
-                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-                break;
-#endif
-        default:
-                PRINT(KERN_ERR, lynx->id, "unknown devctl command %d", cmd);
-                retval = -1;
-        }
-
-        return retval;
-}
-
-
-/***************************************
- * IEEE-1394 functionality section END *
- ***************************************/
-
-
-/********************************************************
- * Global stuff (interrupt handler, init/shutdown code) *
- ********************************************************/
-
-
-static irqreturn_t lynx_irq_handler(int irq, void *dev_id)
-{
-        struct ti_lynx *lynx = (struct ti_lynx *)dev_id;
-        struct hpsb_host *host = lynx->host;
-        u32 intmask;
-        u32 linkint;
-
-        linkint = reg_read(lynx, LINK_INT_STATUS);
-        intmask = reg_read(lynx, PCI_INT_STATUS);
-
-        if (!(intmask & PCI_INT_INT_PEND))
-               return IRQ_NONE;
-
-        PRINTD(KERN_DEBUG, lynx->id, "interrupt: 0x%08x / 0x%08x", intmask,
-               linkint);
-
-        reg_write(lynx, LINK_INT_STATUS, linkint);
-        reg_write(lynx, PCI_INT_STATUS, intmask);
-
-        if (intmask & PCI_INT_1394) {
-                if (linkint & LINK_INT_PHY_TIMEOUT) {
-                        PRINT(KERN_INFO, lynx->id, "PHY timeout occurred");
-                }
-                if (linkint & LINK_INT_PHY_BUSRESET) {
-                        PRINT(KERN_INFO, lynx->id, "bus reset interrupt");
-                        lynx->selfid_size = -1;
-                        lynx->phy_reg0 = -1;
-                        if (!host->in_bus_reset)
-                                hpsb_bus_reset(host);
-                }
-                if (linkint & LINK_INT_PHY_REG_RCVD) {
-                        u32 reg;
-
-                        spin_lock(&lynx->phy_reg_lock);
-                        reg = reg_read(lynx, LINK_PHY);
-                        spin_unlock(&lynx->phy_reg_lock);
-
-                        if (!host->in_bus_reset) {
-                                PRINT(KERN_INFO, lynx->id,
-                                      "phy reg received without reset");
-                        } else if (reg & 0xf00) {
-                                PRINT(KERN_INFO, lynx->id,
-                                      "unsolicited phy reg %d received",
-                                      (reg >> 8) & 0xf);
-                        } else {
-                                lynx->phy_reg0 = reg & 0xff;
-                                handle_selfid(lynx, host);
-                        }
-                }
-                if (linkint & LINK_INT_ISO_STUCK) {
-                        PRINT(KERN_INFO, lynx->id, "isochronous transmitter stuck");
-                }
-                if (linkint & LINK_INT_ASYNC_STUCK) {
-                        PRINT(KERN_INFO, lynx->id, "asynchronous transmitter stuck");
-                }
-                if (linkint & LINK_INT_SENT_REJECT) {
-                        PRINT(KERN_INFO, lynx->id, "sent reject");
-                }
-                if (linkint & LINK_INT_TX_INVALID_TC) {
-                        PRINT(KERN_INFO, lynx->id, "invalid transaction code");
-                }
-                if (linkint & LINK_INT_GRF_OVERFLOW) {
-                        /* flush FIFO if overflow happens during reset */
-                        if (host->in_bus_reset)
-                                reg_write(lynx, FIFO_CONTROL,
-                                          FIFO_CONTROL_GRF_FLUSH);
-                        PRINT(KERN_INFO, lynx->id, "GRF overflow");
-                }
-                if (linkint & LINK_INT_ITF_UNDERFLOW) {
-                        PRINT(KERN_INFO, lynx->id, "ITF underflow");
-                }
-                if (linkint & LINK_INT_ATF_UNDERFLOW) {
-                        PRINT(KERN_INFO, lynx->id, "ATF underflow");
-                }
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_RCV)) {
-                PRINTD(KERN_DEBUG, lynx->id, "iso receive");
-
-                spin_lock(&lynx->iso_rcv.lock);
-
-                lynx->iso_rcv.stat[lynx->iso_rcv.next] =
-                        reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ISO_RCV));
-
-                lynx->iso_rcv.used++;
-                lynx->iso_rcv.next = (lynx->iso_rcv.next + 1) % NUM_ISORCV_PCL;
-
-                if ((lynx->iso_rcv.next == lynx->iso_rcv.last)
-                    || !lynx->iso_rcv.chan_count) {
-                        PRINTD(KERN_DEBUG, lynx->id, "stopped");
-                        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0);
-                }
-
-                run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, lynx->iso_rcv.next,
-                            CHANNEL_ISO_RCV);
-
-                spin_unlock(&lynx->iso_rcv.lock);
-
-               tasklet_schedule(&lynx->iso_rcv.tq);
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_SEND)) {
-                PRINTD(KERN_DEBUG, lynx->id, "async sent");
-                spin_lock(&lynx->async.queue_lock);
-
-                if (list_empty(&lynx->async.pcl_queue)) {
-                        spin_unlock(&lynx->async.queue_lock);
-                        PRINT(KERN_WARNING, lynx->id, "async dma halted, but no queued packet (maybe it was cancelled)");
-                } else {
-                        struct ti_pcl pcl;
-                        u32 ack;
-                        struct hpsb_packet *packet;
-
-                        get_pcl(lynx, lynx->async.pcl, &pcl);
-
-                        packet = driver_packet(lynx->async.pcl_queue.next);
-                        list_del_init(&packet->driver_list);
-
-                        pci_unmap_single(lynx->dev, lynx->async.header_dma,
-                                         packet->header_size, PCI_DMA_TODEVICE);
-                        if (packet->data_size) {
-                                pci_unmap_single(lynx->dev, lynx->async.data_dma,
-                                                 packet->data_size, PCI_DMA_TODEVICE);
-                        }
-
-                        if (!list_empty(&lynx->async.queue)) {
-                                send_next(lynx, hpsb_async);
-                        }
-
-                        spin_unlock(&lynx->async.queue_lock);
-
-                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
-                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
-                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
-                                } else {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                }
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "async packet was not completed");
-                                ack = ACKX_SEND_ERROR;
-                        }
-                        hpsb_packet_sent(host, packet, ack);
-                }
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ISO_SEND)) {
-                PRINTD(KERN_DEBUG, lynx->id, "iso sent");
-                spin_lock(&lynx->iso_send.queue_lock);
-
-                if (list_empty(&lynx->iso_send.pcl_queue)) {
-                        spin_unlock(&lynx->iso_send.queue_lock);
-                        PRINT(KERN_ERR, lynx->id, "iso send dma halted, but no queued packet");
-                } else {
-                        struct ti_pcl pcl;
-                        u32 ack;
-                        struct hpsb_packet *packet;
-
-                        get_pcl(lynx, lynx->iso_send.pcl, &pcl);
-
-                        packet = driver_packet(lynx->iso_send.pcl_queue.next);
-                        list_del_init(&packet->driver_list);
-
-                        pci_unmap_single(lynx->dev, lynx->iso_send.header_dma,
-                                         packet->header_size, PCI_DMA_TODEVICE);
-                        if (packet->data_size) {
-                                pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,
-                                                 packet->data_size, PCI_DMA_TODEVICE);
-                        }
-#if 0 /* has been removed from ieee1394 core */
-                        if (!list_empty(&lynx->iso_send.queue)) {
-                                send_next(lynx, hpsb_iso);
-                        }
-#endif
-                        spin_unlock(&lynx->iso_send.queue_lock);
-
-                        if (pcl.pcl_status & DMA_CHAN_STAT_PKTCMPL) {
-                                if (pcl.pcl_status & DMA_CHAN_STAT_SPECIALACK) {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                        PRINTD(KERN_INFO, lynx->id, "special ack %d", ack);
-                                        ack = (ack == 1 ? ACKX_TIMEOUT : ACKX_SEND_ERROR);
-                                } else {
-                                        ack = (pcl.pcl_status >> 15) & 0xf;
-                                }
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "iso send packet was not completed");
-                                ack = ACKX_SEND_ERROR;
-                        }
-
-                        hpsb_packet_sent(host, packet, ack); //FIXME: maybe we should just use ACK_COMPLETE and ACKX_SEND_ERROR
-                }
-        }
-
-        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) {
-                /* general receive DMA completed */
-                int stat = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_RCV));
-
-                PRINTD(KERN_DEBUG, lynx->id, "received packet size %d",
-                       stat & 0x1fff);
-
-                if (stat & DMA_CHAN_STAT_SELFID) {
-                        lynx->selfid_size = stat & 0x1fff;
-                        handle_selfid(lynx, host);
-                } else {
-                        quadlet_t *q_data = lynx->rcv_page;
-                        if ((*q_data >> 4 & 0xf) == TCODE_READQ_RESPONSE
-                            || (*q_data >> 4 & 0xf) == TCODE_WRITEQ) {
-                                cpu_to_be32s(q_data + 3);
-                        }
-                        hpsb_packet_received(host, q_data, stat & 0x1fff, 0);
-                }
-
-                run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);
-        }
-
-       return IRQ_HANDLED;
-}
-
-
-static void iso_rcv_bh(struct ti_lynx *lynx)
-{
-        unsigned int idx;
-        quadlet_t *data;
-        unsigned long flags;
-
-        spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-
-        while (lynx->iso_rcv.used) {
-                idx = lynx->iso_rcv.last;
-                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-
-                data = lynx->iso_rcv.page[idx / ISORCV_PER_PAGE]
-                        + (idx % ISORCV_PER_PAGE) * MAX_ISORCV_SIZE;
-
-                if ((*data >> 16) + 4 != (lynx->iso_rcv.stat[idx] & 0x1fff)) {
-                        PRINT(KERN_ERR, lynx->id,
-                              "iso length mismatch 0x%08x/0x%08x", *data,
-                              lynx->iso_rcv.stat[idx]);
-                }
-
-                if (lynx->iso_rcv.stat[idx]
-                    & (DMA_CHAN_STAT_PCIERR | DMA_CHAN_STAT_PKTERR)) {
-                        PRINT(KERN_INFO, lynx->id,
-                              "iso receive error on %d to 0x%p", idx, data);
-                } else {
-                        hpsb_packet_received(lynx->host, data,
-                                             lynx->iso_rcv.stat[idx] & 0x1fff,
-                                             0);
-                }
-
-                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);
-                lynx->iso_rcv.last = (idx + 1) % NUM_ISORCV_PCL;
-                lynx->iso_rcv.used--;
-        }
-
-        if (lynx->iso_rcv.chan_count) {
-                reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),
-                          DMA_WORD1_CMP_ENABLE_MASTER);
-        }
-        spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);
-}
-
-
-static void remove_card(struct pci_dev *dev)
-{
-        struct ti_lynx *lynx;
-       struct device *lynx_dev;
-        int i;
-
-        lynx = pci_get_drvdata(dev);
-        if (!lynx) return;
-        pci_set_drvdata(dev, NULL);
-
-       lynx_dev = get_device(&lynx->host->device);
-
-        switch (lynx->state) {
-        case is_host:
-                reg_write(lynx, PCI_INT_ENABLE, 0);
-                hpsb_remove_host(lynx->host);
-        case have_intr:
-                reg_write(lynx, PCI_INT_ENABLE, 0);
-                free_irq(lynx->dev->irq, lynx);
-
-               /* Disable IRM Contender and LCtrl */
-               if (lynx->phyic.reg_1394a)
-                       set_phy_reg(lynx, 4, ~0xc0 & get_phy_reg(lynx, 4));
-
-               /* Let all other nodes know to ignore us */
-               lynx_devctl(lynx->host, RESET_BUS, LONG_RESET_NO_FORCE_ROOT);
-
-        case have_iomappings:
-                reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
-                /* Fix buggy cards with autoboot pin not tied low: */
-                reg_write(lynx, DMA0_CHAN_CTRL, 0);
-                iounmap(lynx->registers);
-                iounmap(lynx->local_rom);
-                iounmap(lynx->local_ram);
-                iounmap(lynx->aux_port);
-        case have_1394_buffers:
-                for (i = 0; i < ISORCV_PAGES; i++) {
-                        if (lynx->iso_rcv.page[i]) {
-                                pci_free_consistent(lynx->dev, PAGE_SIZE,
-                                                    lynx->iso_rcv.page[i],
-                                                    lynx->iso_rcv.page_dma[i]);
-                        }
-                }
-                pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page,
-                                    lynx->rcv_page_dma);
-        case have_aux_buf:
-        case have_pcl_mem:
-                pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,
-                                    lynx->pcl_mem_dma);
-        case clear:
-                /* do nothing - already freed */
-                ;
-        }
-
-       tasklet_kill(&lynx->iso_rcv.tq);
-
-       if (lynx_dev)
-               put_device(lynx_dev);
-}
-
-
-static int __devinit add_card(struct pci_dev *dev,
-                              const struct pci_device_id *devid_is_unused)
-{
-#define FAIL(fmt, args...) do { \
-        PRINT_G(KERN_ERR, fmt , ## args); \
-        remove_card(dev); \
-        return error; \
-        } while (0)
-
-       char irq_buf[16];
-       struct hpsb_host *host;
-        struct ti_lynx *lynx; /* shortcut to currently handled device */
-        struct ti_pcl pcl;
-        u32 *pcli;
-        int i;
-        int error;
-
-        error = -ENXIO;
-
-        if (pci_set_dma_mask(dev, DMA_BIT_MASK(32)))
-                FAIL("DMA address limits not supported for PCILynx hardware");
-        if (pci_enable_device(dev))
-                FAIL("failed to enable PCILynx hardware");
-        pci_set_master(dev);
-
-        error = -ENOMEM;
-
-       host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx), &dev->dev);
-        if (!host) FAIL("failed to allocate control structure memory");
-
-        lynx = host->hostdata;
-       lynx->id = card_id++;
-        lynx->dev = dev;
-        lynx->state = clear;
-       lynx->host = host;
-        host->pdev = dev;
-        pci_set_drvdata(dev, lynx);
-
-        spin_lock_init(&lynx->lock);
-        spin_lock_init(&lynx->phy_reg_lock);
-
-        lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE,
-                                             &lynx->pcl_mem_dma);
-
-        if (lynx->pcl_mem != NULL) {
-                lynx->state = have_pcl_mem;
-                PRINT(KERN_INFO, lynx->id,
-                      "allocated PCL memory %d Bytes @ 0x%p", LOCALRAM_SIZE,
-                      lynx->pcl_mem);
-        } else {
-                FAIL("failed to allocate PCL memory area");
-        }
-
-        lynx->rcv_page = pci_alloc_consistent(dev, PAGE_SIZE,
-                                              &lynx->rcv_page_dma);
-        if (lynx->rcv_page == NULL) {
-                FAIL("failed to allocate receive buffer");
-        }
-        lynx->state = have_1394_buffers;
-
-        for (i = 0; i < ISORCV_PAGES; i++) {
-                lynx->iso_rcv.page[i] =
-                        pci_alloc_consistent(dev, PAGE_SIZE,
-                                             &lynx->iso_rcv.page_dma[i]);
-                if (lynx->iso_rcv.page[i] == NULL) {
-                        FAIL("failed to allocate iso receive buffers");
-                }
-        }
-
-        lynx->registers = ioremap_nocache(pci_resource_start(dev,0),
-                                          PCILYNX_MAX_REGISTER);
-        lynx->local_ram = ioremap(pci_resource_start(dev,1), PCILYNX_MAX_MEMORY);
-        lynx->aux_port  = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY);
-        lynx->local_rom = ioremap(pci_resource_start(dev,PCI_ROM_RESOURCE),
-                                  PCILYNX_MAX_MEMORY);
-        lynx->state = have_iomappings;
-
-        if (lynx->registers == NULL) {
-                FAIL("failed to remap registers - card not accessible");
-        }
-
-        reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);
-        /* Fix buggy cards with autoboot pin not tied low: */
-        reg_write(lynx, DMA0_CHAN_CTRL, 0);
-
-       sprintf (irq_buf, "%d", dev->irq);
-
-        if (!request_irq(dev->irq, lynx_irq_handler, IRQF_SHARED,
-                         PCILYNX_DRIVER_NAME, lynx)) {
-                PRINT(KERN_INFO, lynx->id, "allocated interrupt %s", irq_buf);
-                lynx->state = have_intr;
-        } else {
-                FAIL("failed to allocate shared interrupt %s", irq_buf);
-        }
-
-        /* alloc_pcl return values are not checked, it is expected that the
-         * provided PCL space is sufficient for the initial allocations */
-        lynx->rcv_pcl = alloc_pcl(lynx);
-        lynx->rcv_pcl_start = alloc_pcl(lynx);
-        lynx->async.pcl = alloc_pcl(lynx);
-        lynx->async.pcl_start = alloc_pcl(lynx);
-        lynx->iso_send.pcl = alloc_pcl(lynx);
-        lynx->iso_send.pcl_start = alloc_pcl(lynx);
-
-        for (i = 0; i < NUM_ISORCV_PCL; i++) {
-                lynx->iso_rcv.pcl[i] = alloc_pcl(lynx);
-        }
-        lynx->iso_rcv.pcl_start = alloc_pcl(lynx);
-
-        /* all allocations successful - simple init stuff follows */
-
-        reg_write(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);
-
-       tasklet_init(&lynx->iso_rcv.tq, (void (*)(unsigned long))iso_rcv_bh,
-                    (unsigned long)lynx);
-
-        spin_lock_init(&lynx->iso_rcv.lock);
-
-        spin_lock_init(&lynx->async.queue_lock);
-        lynx->async.channel = CHANNEL_ASYNC_SEND;
-        spin_lock_init(&lynx->iso_send.queue_lock);
-        lynx->iso_send.channel = CHANNEL_ISO_SEND;
-
-        PRINT(KERN_INFO, lynx->id, "remapped memory spaces reg 0x%p, rom 0x%p, "
-              "ram 0x%p, aux 0x%p", lynx->registers, lynx->local_rom,
-              lynx->local_ram, lynx->aux_port);
-
-        /* now, looking for PHY register set */
-        if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) {
-                lynx->phyic.reg_1394a = 1;
-                PRINT(KERN_INFO, lynx->id,
-                      "found 1394a conform PHY (using extended register set)");
-                lynx->phyic.vendor = get_phy_vendorid(lynx);
-                lynx->phyic.product = get_phy_productid(lynx);
-        } else {
-                lynx->phyic.reg_1394a = 0;
-                PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");
-        }
-
-        lynx->selfid_size = -1;
-        lynx->phy_reg0 = -1;
-
-       INIT_LIST_HEAD(&lynx->async.queue);
-       INIT_LIST_HEAD(&lynx->async.pcl_queue);
-       INIT_LIST_HEAD(&lynx->iso_send.queue);
-       INIT_LIST_HEAD(&lynx->iso_send.pcl_queue);
-
-        pcl.next = pcl_bus(lynx, lynx->rcv_pcl);
-        put_pcl(lynx, lynx->rcv_pcl_start, &pcl);
-
-        pcl.next = PCL_NEXT_INVALID;
-        pcl.async_error_next = PCL_NEXT_INVALID;
-
-        pcl.buffer[0].control = PCL_CMD_RCV | 16;
-#ifndef __BIG_ENDIAN
-       pcl.buffer[0].control |= PCL_BIGENDIAN;
-#endif
-       pcl.buffer[1].control = PCL_LAST_BUFF | 4080;
-
-        pcl.buffer[0].pointer = lynx->rcv_page_dma;
-        pcl.buffer[1].pointer = lynx->rcv_page_dma + 16;
-        put_pcl(lynx, lynx->rcv_pcl, &pcl);
-
-        pcl.next = pcl_bus(lynx, lynx->async.pcl);
-        pcl.async_error_next = pcl_bus(lynx, lynx->async.pcl);
-        put_pcl(lynx, lynx->async.pcl_start, &pcl);
-
-        pcl.next = pcl_bus(lynx, lynx->iso_send.pcl);
-        pcl.async_error_next = PCL_NEXT_INVALID;
-        put_pcl(lynx, lynx->iso_send.pcl_start, &pcl);
-
-        pcl.next = PCL_NEXT_INVALID;
-        pcl.async_error_next = PCL_NEXT_INVALID;
-        pcl.buffer[0].control = PCL_CMD_RCV | 4;
-#ifndef __BIG_ENDIAN
-        pcl.buffer[0].control |= PCL_BIGENDIAN;
-#endif
-        pcl.buffer[1].control = PCL_LAST_BUFF | 2044;
-
-        for (i = 0; i < NUM_ISORCV_PCL; i++) {
-                int page = i / ISORCV_PER_PAGE;
-                int sec = i % ISORCV_PER_PAGE;
-
-                pcl.buffer[0].pointer = lynx->iso_rcv.page_dma[page]
-                        + sec * MAX_ISORCV_SIZE;
-                pcl.buffer[1].pointer = pcl.buffer[0].pointer + 4;
-                put_pcl(lynx, lynx->iso_rcv.pcl[i], &pcl);
-        }
-
-        pcli = (u32 *)&pcl;
-        for (i = 0; i < NUM_ISORCV_PCL; i++) {
-                pcli[i] = pcl_bus(lynx, lynx->iso_rcv.pcl[i]);
-        }
-        put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl);
-
-        /* FIFO sizes from left to right: ITF=48 ATF=48 GRF=160 */
-        reg_write(lynx, FIFO_SIZES, 0x003030a0);
-        /* 20 byte threshold before triggering PCI transfer */
-        reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24);
-        /* threshold on both send FIFOs before transmitting:
-           FIFO size - cache line size - 1 */
-        i = reg_read(lynx, PCI_LATENCY_CACHELINE) & 0xff;
-        i = 0x30 - i - 1;
-        reg_write(lynx, FIFO_XMIT_THRESHOLD, (i << 8) | i);
-
-        reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_1394);
-
-        reg_write(lynx, LINK_INT_ENABLE, LINK_INT_PHY_TIMEOUT
-                  | LINK_INT_PHY_REG_RCVD  | LINK_INT_PHY_BUSRESET
-                  | LINK_INT_ISO_STUCK     | LINK_INT_ASYNC_STUCK
-                  | LINK_INT_SENT_REJECT   | LINK_INT_TX_INVALID_TC
-                  | LINK_INT_GRF_OVERFLOW  | LINK_INT_ITF_UNDERFLOW
-                  | LINK_INT_ATF_UNDERFLOW);
-
-        reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);
-        reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ASYNC_RCV), 0xa<<4);
-        reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);
-        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ASYNC_RCV),
-                  DMA_WORD1_CMP_MATCH_LOCAL_NODE | DMA_WORD1_CMP_MATCH_BROADCAST
-                  | DMA_WORD1_CMP_MATCH_EXACT    | DMA_WORD1_CMP_MATCH_BUS_BCAST
-                  | DMA_WORD1_CMP_ENABLE_SELF_ID | DMA_WORD1_CMP_ENABLE_MASTER);
-
-        run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);
-
-        reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ISO_RCV), 0);
-        reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ISO_RCV), 0x9<<4);
-        reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ISO_RCV), 0);
-        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0);
-
-        run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, 0, CHANNEL_ISO_RCV);
-
-        reg_write(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID
-                  | LINK_CONTROL_TX_ISO_EN   | LINK_CONTROL_RX_ISO_EN
-                  | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN
-                  | LINK_CONTROL_RESET_TX    | LINK_CONTROL_RESET_RX);
-
-       if (!lynx->phyic.reg_1394a) {
-               if (!hpsb_disable_irm) {
-                       /* attempt to enable contender bit -FIXME- would this
-                        * work elsewhere? */
-                       reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
-                       reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1);
-               }
-       } else {
-               /* set the contender (if appropriate) and LCtrl bit in the
-                * extended PHY register set. (Should check that PHY_02_EXTENDED
-                * is set in register 2?)
-                */
-               i = get_phy_reg(lynx, 4);
-               i |= PHY_04_LCTRL;
-               if (hpsb_disable_irm)
-                       i &= ~PHY_04_CONTENDER;
-               else
-                       i |= PHY_04_CONTENDER;
-               if (i != -1) set_phy_reg(lynx, 4, i);
-       }
-       
-        if (!skip_eeprom)
-        {
-               /* needed for i2c communication with serial eeprom */
-               struct i2c_adapter *i2c_ad;
-               struct i2c_algo_bit_data i2c_adapter_data;
-
-               error = -ENOMEM;
-               i2c_ad = kzalloc(sizeof(*i2c_ad), GFP_KERNEL);
-               if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
-
-               strlcpy(i2c_ad->name, "PCILynx I2C", sizeof(i2c_ad->name));
-                i2c_adapter_data = bit_data;
-                i2c_ad->algo_data = &i2c_adapter_data;
-                i2c_adapter_data.data = lynx;
-               i2c_ad->dev.parent = &dev->dev;
-
-               PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",
-                      reg_read(lynx, SERIAL_EEPROM_CONTROL));
-
-               /* reset hardware to sane state */
-               lynx->i2c_driven_state = 0x00000070;
-               reg_write(lynx, SERIAL_EEPROM_CONTROL, lynx->i2c_driven_state);
-
-               if (i2c_bit_add_bus(i2c_ad) < 0)
-               {
-                       kfree(i2c_ad);
-                       error = -ENXIO;
-                       FAIL("unable to register i2c");
-               }
-               else
-               {
-                        /* do i2c stuff */
-                        unsigned char i2c_cmd = 0x10;
-                        struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd },
-                                                  { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }
-                                                };
-
-                       /* we use i2c_transfer because we have no i2c_client
-                          at hand */
-                        if (i2c_transfer(i2c_ad, msg, 2) < 0) {
-                                PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");
-                        } else {
-                                PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom");
-                               /* FIXME: probably we should rewrite the max_rec, max_ROM(1394a),
-                                * generation(1394a) and link_spd(1394a) field and recalculate
-                                * the CRC */
-
-                                for (i = 0; i < 5 ; i++)
-                                        PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",
-                                              i, be32_to_cpu(lynx->bus_info_block[i]));
-
-                                /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */
-                               if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) &&
-                                   (lynx->bus_info_block[1] == IEEE1394_BUSID_MAGIC))
-                                {
-                                        PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");
-                                } else {
-                                       kfree(i2c_ad);
-                                       error = -ENXIO;
-                                       FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block");
-                                }
-
-                        }
-
-                       i2c_del_adapter(i2c_ad);
-                       kfree(i2c_ad);
-                }
-        }
-
-       host->csr.guid_hi = be32_to_cpu(lynx->bus_info_block[3]);
-       host->csr.guid_lo = be32_to_cpu(lynx->bus_info_block[4]);
-       host->csr.cyc_clk_acc = (be32_to_cpu(lynx->bus_info_block[2]) >> 16) & 0xff;
-       host->csr.max_rec = (be32_to_cpu(lynx->bus_info_block[2]) >> 12) & 0xf;
-       if (!lynx->phyic.reg_1394a)
-               host->csr.lnk_spd = (get_phy_reg(lynx, 2) & 0xc0) >> 6;
-       else
-               host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7;
-
-       if (hpsb_add_host(host)) {
-               error = -ENOMEM;
-               FAIL("Failed to register host with highlevel");
-       }
-
-       lynx->state = is_host;
-
-       return 0;
-#undef FAIL
-}
-
-
-static struct pci_device_id pci_table[] = {
-       {
-                .vendor =    PCI_VENDOR_ID_TI,
-                .device =    PCI_DEVICE_ID_TI_PCILYNX,
-                .subvendor = PCI_ANY_ID,
-                .subdevice = PCI_ANY_ID,
-       },
-       { }                     /* Terminating entry */
-};
-
-static struct pci_driver lynx_pci_driver = {
-        .name =     PCILYNX_DRIVER_NAME,
-        .id_table = pci_table,
-        .probe =    add_card,
-        .remove =   remove_card,
-};
-
-static struct hpsb_host_driver lynx_driver = {
-       .owner =           THIS_MODULE,
-       .name =            PCILYNX_DRIVER_NAME,
-       .set_hw_config_rom = NULL,
-        .transmit_packet = lynx_transmit,
-        .devctl =          lynx_devctl,
-       .isoctl =          NULL,
-};
-
-MODULE_AUTHOR("Andreas E. Bombe <andreas.bombe@munich.netsurf.de>");
-MODULE_DESCRIPTION("driver for Texas Instruments PCI Lynx IEEE-1394 controller");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("pcilynx");
-MODULE_DEVICE_TABLE(pci, pci_table);
-
-static int __init pcilynx_init(void)
-{
-        int ret;
-
-        ret = pci_register_driver(&lynx_pci_driver);
-        if (ret < 0) {
-                PRINT_G(KERN_ERR, "PCI module init failed");
-                return ret;
-        }
-
-        return 0;
-}
-
-static void __exit pcilynx_cleanup(void)
-{
-        pci_unregister_driver(&lynx_pci_driver);
-}
-
-
-module_init(pcilynx_init);
-module_exit(pcilynx_cleanup);
diff --git a/drivers/ieee1394/pcilynx.h b/drivers/ieee1394/pcilynx.h
deleted file mode 100644 (file)
index 693a169..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-#ifndef __PCILYNX_H__
-#define __PCILYNX_H__
-
-
-#define PCILYNX_DRIVER_NAME      "pcilynx"
-#define PCILYNX_MAJOR            177
-
-#define PCILYNX_MINOR_AUX_START  0
-#define PCILYNX_MINOR_ROM_START  16
-#define PCILYNX_MINOR_RAM_START  32
-
-#define PCILYNX_MAX_REGISTER     0xfff
-#define PCILYNX_MAX_MEMORY       0xffff
-
-#define PCI_DEVICE_ID_TI_PCILYNX 0x8000
-#define MAX_PCILYNX_CARDS        4
-#define LOCALRAM_SIZE            4096
-
-#define NUM_ISORCV_PCL           4
-#define MAX_ISORCV_SIZE          2048
-#define ISORCV_PER_PAGE          (PAGE_SIZE / MAX_ISORCV_SIZE)
-#define ISORCV_PAGES             (NUM_ISORCV_PCL / ISORCV_PER_PAGE)
-
-#define CHANNEL_LOCALBUS         0
-#define CHANNEL_ASYNC_RCV        1
-#define CHANNEL_ISO_RCV          2
-#define CHANNEL_ASYNC_SEND       3
-#define CHANNEL_ISO_SEND         4
-
-#define PCILYNX_CONFIG_ROM_LENGTH   1024
-
-typedef int pcl_t;
-
-struct ti_lynx {
-        int id; /* sequential card number */
-
-        spinlock_t lock;
-
-        struct pci_dev *dev;
-
-        struct {
-                unsigned reg_1394a:1;
-                u32 vendor;
-                u32 product;
-        } phyic;
-
-        enum { clear, have_intr, have_aux_buf, have_pcl_mem,
-               have_1394_buffers, have_iomappings, is_host } state;
-
-        /* remapped memory spaces */
-        void __iomem *registers;
-        void __iomem *local_rom;
-        void __iomem *local_ram;
-        void __iomem *aux_port;
-       __be32 bus_info_block[5];
-
-        /*
-         * use local RAM of LOCALRAM_SIZE bytes for PCLs, which allows for
-         * LOCALRAM_SIZE * 8 PCLs (each sized 128 bytes);
-         * the following is an allocation bitmap
-         */
-        u8 pcl_bmap[LOCALRAM_SIZE / 1024];
-
-       /* point to PCLs memory area if needed */
-       void *pcl_mem;
-        dma_addr_t pcl_mem_dma;
-
-        /* PCLs for local mem / aux transfers */
-        pcl_t dmem_pcl;
-
-        /* IEEE-1394 part follows */
-        struct hpsb_host *host;
-
-        int phyid, isroot;
-        int selfid_size;
-        int phy_reg0;
-
-        spinlock_t phy_reg_lock;
-
-        pcl_t rcv_pcl_start, rcv_pcl;
-        void *rcv_page;
-        dma_addr_t rcv_page_dma;
-        int rcv_active;
-
-        struct lynx_send_data {
-                pcl_t pcl_start, pcl;
-                struct list_head queue;
-                struct list_head pcl_queue; /* this queue contains at most one packet */
-                spinlock_t queue_lock;
-                dma_addr_t header_dma, data_dma;
-                int channel;
-        } async, iso_send;
-
-        struct {
-                pcl_t pcl[NUM_ISORCV_PCL];
-                u32 stat[NUM_ISORCV_PCL];
-                void *page[ISORCV_PAGES];
-                dma_addr_t page_dma[ISORCV_PAGES];
-                pcl_t pcl_start;
-                int chan_count;
-                int next, last, used, running;
-                struct tasklet_struct tq;
-                spinlock_t lock;
-        } iso_rcv;
-
-       u32 i2c_driven_state; /* the state we currently drive the Serial EEPROM Control register */
-};
-
-/* the per-file data structure for mem space access */
-struct memdata {
-        struct ti_lynx *lynx;
-        int cid;
-        atomic_t aux_intr_last_seen;
-       /* enum values are the same as LBUS_ADDR_SEL_* values below */
-        enum { rom = 0x10000, aux = 0x20000, ram = 0 } type;
-};
-
-
-
-/*
- * Register read and write helper functions.
- */
-static inline void reg_write(const struct ti_lynx *lynx, int offset, u32 data)
-{
-        writel(data, lynx->registers + offset);
-}
-
-static inline u32 reg_read(const struct ti_lynx *lynx, int offset)
-{
-        return readl(lynx->registers + offset);
-}
-
-static inline void reg_set_bits(const struct ti_lynx *lynx, int offset,
-                                u32 mask)
-{
-        reg_write(lynx, offset, (reg_read(lynx, offset) | mask));
-}
-
-static inline void reg_clear_bits(const struct ti_lynx *lynx, int offset,
-                                  u32 mask)
-{
-        reg_write(lynx, offset, (reg_read(lynx, offset) & ~mask));
-}
-
-
-
-/* chip register definitions follow */
-
-#define PCI_LATENCY_CACHELINE             0x0c
-
-#define MISC_CONTROL                      0x40
-#define MISC_CONTROL_SWRESET              (1<<0)
-
-#define SERIAL_EEPROM_CONTROL             0x44
-
-#define PCI_INT_STATUS                    0x48
-#define PCI_INT_ENABLE                    0x4c
-/* status and enable have identical bit numbers */
-#define PCI_INT_INT_PEND                  (1<<31)
-#define PCI_INT_FORCED_INT                (1<<30)
-#define PCI_INT_SLV_ADR_PERR              (1<<28)
-#define PCI_INT_SLV_DAT_PERR              (1<<27)
-#define PCI_INT_MST_DAT_PERR              (1<<26)
-#define PCI_INT_MST_DEV_TIMEOUT           (1<<25)
-#define PCI_INT_INTERNAL_SLV_TIMEOUT      (1<<23)
-#define PCI_INT_AUX_TIMEOUT               (1<<18)
-#define PCI_INT_AUX_INT                   (1<<17)
-#define PCI_INT_1394                      (1<<16)
-#define PCI_INT_DMA4_PCL                  (1<<9)
-#define PCI_INT_DMA4_HLT                  (1<<8)
-#define PCI_INT_DMA3_PCL                  (1<<7)
-#define PCI_INT_DMA3_HLT                  (1<<6)
-#define PCI_INT_DMA2_PCL                  (1<<5)
-#define PCI_INT_DMA2_HLT                  (1<<4)
-#define PCI_INT_DMA1_PCL                  (1<<3)
-#define PCI_INT_DMA1_HLT                  (1<<2)
-#define PCI_INT_DMA0_PCL                  (1<<1)
-#define PCI_INT_DMA0_HLT                  (1<<0)
-/* all DMA interrupts combined: */
-#define PCI_INT_DMA_ALL                   0x3ff
-
-#define PCI_INT_DMA_HLT(chan)             (1 << (chan * 2))
-#define PCI_INT_DMA_PCL(chan)             (1 << (chan * 2 + 1))
-
-#define LBUS_ADDR                         0xb4
-#define LBUS_ADDR_SEL_RAM                 (0x0<<16)
-#define LBUS_ADDR_SEL_ROM                 (0x1<<16)
-#define LBUS_ADDR_SEL_AUX                 (0x2<<16)
-#define LBUS_ADDR_SEL_ZV                  (0x3<<16)
-
-#define GPIO_CTRL_A                       0xb8
-#define GPIO_CTRL_B                       0xbc
-#define GPIO_DATA_BASE                    0xc0
-
-#define DMA_BREG(base, chan)              (base + chan * 0x20)
-#define DMA_SREG(base, chan)              (base + chan * 0x10)
-
-#define DMA0_PREV_PCL                     0x100
-#define DMA1_PREV_PCL                     0x120
-#define DMA2_PREV_PCL                     0x140
-#define DMA3_PREV_PCL                     0x160
-#define DMA4_PREV_PCL                     0x180
-#define DMA_PREV_PCL(chan)                (DMA_BREG(DMA0_PREV_PCL, chan))
-
-#define DMA0_CURRENT_PCL                  0x104
-#define DMA1_CURRENT_PCL                  0x124
-#define DMA2_CURRENT_PCL                  0x144
-#define DMA3_CURRENT_PCL                  0x164
-#define DMA4_CURRENT_PCL                  0x184
-#define DMA_CURRENT_PCL(chan)             (DMA_BREG(DMA0_CURRENT_PCL, chan))
-
-#define DMA0_CHAN_STAT                    0x10c
-#define DMA1_CHAN_STAT                    0x12c
-#define DMA2_CHAN_STAT                    0x14c
-#define DMA3_CHAN_STAT                    0x16c
-#define DMA4_CHAN_STAT                    0x18c
-#define DMA_CHAN_STAT(chan)               (DMA_BREG(DMA0_CHAN_STAT, chan))
-/* CHAN_STATUS registers share bits */
-#define DMA_CHAN_STAT_SELFID              (1<<31)
-#define DMA_CHAN_STAT_ISOPKT              (1<<30)
-#define DMA_CHAN_STAT_PCIERR              (1<<29)
-#define DMA_CHAN_STAT_PKTERR              (1<<28)
-#define DMA_CHAN_STAT_PKTCMPL             (1<<27)
-#define DMA_CHAN_STAT_SPECIALACK          (1<<14)
-
-
-#define DMA0_CHAN_CTRL                    0x110
-#define DMA1_CHAN_CTRL                    0x130
-#define DMA2_CHAN_CTRL                    0x150
-#define DMA3_CHAN_CTRL                    0x170
-#define DMA4_CHAN_CTRL                    0x190
-#define DMA_CHAN_CTRL(chan)               (DMA_BREG(DMA0_CHAN_CTRL, chan))
-/* CHAN_CTRL registers share bits */
-#define DMA_CHAN_CTRL_ENABLE              (1<<31)
-#define DMA_CHAN_CTRL_BUSY                (1<<30)
-#define DMA_CHAN_CTRL_LINK                (1<<29)
-
-#define DMA0_READY                        0x114
-#define DMA1_READY                        0x134
-#define DMA2_READY                        0x154
-#define DMA3_READY                        0x174
-#define DMA4_READY                        0x194
-#define DMA_READY(chan)                   (DMA_BREG(DMA0_READY, chan))
-
-#define DMA_GLOBAL_REGISTER               0x908
-
-#define FIFO_SIZES                        0xa00
-
-#define FIFO_CONTROL                      0xa10
-#define FIFO_CONTROL_GRF_FLUSH            (1<<4)
-#define FIFO_CONTROL_ITF_FLUSH            (1<<3)
-#define FIFO_CONTROL_ATF_FLUSH            (1<<2)
-
-#define FIFO_XMIT_THRESHOLD               0xa14
-
-#define DMA0_WORD0_CMP_VALUE              0xb00
-#define DMA1_WORD0_CMP_VALUE              0xb10
-#define DMA2_WORD0_CMP_VALUE              0xb20
-#define DMA3_WORD0_CMP_VALUE              0xb30
-#define DMA4_WORD0_CMP_VALUE              0xb40
-#define DMA_WORD0_CMP_VALUE(chan)         (DMA_SREG(DMA0_WORD0_CMP_VALUE, chan))
-
-#define DMA0_WORD0_CMP_ENABLE             0xb04
-#define DMA1_WORD0_CMP_ENABLE             0xb14
-#define DMA2_WORD0_CMP_ENABLE             0xb24
-#define DMA3_WORD0_CMP_ENABLE             0xb34
-#define DMA4_WORD0_CMP_ENABLE             0xb44
-#define DMA_WORD0_CMP_ENABLE(chan)        (DMA_SREG(DMA0_WORD0_CMP_ENABLE,chan))
-
-#define DMA0_WORD1_CMP_VALUE              0xb08
-#define DMA1_WORD1_CMP_VALUE              0xb18
-#define DMA2_WORD1_CMP_VALUE              0xb28
-#define DMA3_WORD1_CMP_VALUE              0xb38
-#define DMA4_WORD1_CMP_VALUE              0xb48
-#define DMA_WORD1_CMP_VALUE(chan)         (DMA_SREG(DMA0_WORD1_CMP_VALUE, chan))
-
-#define DMA0_WORD1_CMP_ENABLE             0xb0c
-#define DMA1_WORD1_CMP_ENABLE             0xb1c
-#define DMA2_WORD1_CMP_ENABLE             0xb2c
-#define DMA3_WORD1_CMP_ENABLE             0xb3c
-#define DMA4_WORD1_CMP_ENABLE             0xb4c
-#define DMA_WORD1_CMP_ENABLE(chan)        (DMA_SREG(DMA0_WORD1_CMP_ENABLE,chan))
-/* word 1 compare enable flags */
-#define DMA_WORD1_CMP_MATCH_OTHERBUS      (1<<15)
-#define DMA_WORD1_CMP_MATCH_BROADCAST     (1<<14)
-#define DMA_WORD1_CMP_MATCH_BUS_BCAST     (1<<13)
-#define DMA_WORD1_CMP_MATCH_LOCAL_NODE    (1<<12)
-#define DMA_WORD1_CMP_MATCH_EXACT         (1<<11)
-#define DMA_WORD1_CMP_ENABLE_SELF_ID      (1<<10)
-#define DMA_WORD1_CMP_ENABLE_MASTER       (1<<8)
-
-#define LINK_ID                           0xf00
-#define LINK_ID_BUS(id)                   (id<<22)
-#define LINK_ID_NODE(id)                  (id<<16)
-
-#define LINK_CONTROL                      0xf04
-#define LINK_CONTROL_BUSY                 (1<<29)
-#define LINK_CONTROL_TX_ISO_EN            (1<<26)
-#define LINK_CONTROL_RX_ISO_EN            (1<<25)
-#define LINK_CONTROL_TX_ASYNC_EN          (1<<24)
-#define LINK_CONTROL_RX_ASYNC_EN          (1<<23)
-#define LINK_CONTROL_RESET_TX             (1<<21)
-#define LINK_CONTROL_RESET_RX             (1<<20)
-#define LINK_CONTROL_CYCMASTER            (1<<11)
-#define LINK_CONTROL_CYCSOURCE            (1<<10)
-#define LINK_CONTROL_CYCTIMEREN           (1<<9)
-#define LINK_CONTROL_RCV_CMP_VALID        (1<<7)
-#define LINK_CONTROL_SNOOP_ENABLE         (1<<6)
-
-#define CYCLE_TIMER                       0xf08
-
-#define LINK_PHY                          0xf0c
-#define LINK_PHY_READ                     (1<<31)
-#define LINK_PHY_WRITE                    (1<<30)
-#define LINK_PHY_ADDR(addr)               (addr<<24)
-#define LINK_PHY_WDATA(data)              (data<<16)
-#define LINK_PHY_RADDR(addr)              (addr<<8)
-
-
-#define LINK_INT_STATUS                   0xf14
-#define LINK_INT_ENABLE                   0xf18
-/* status and enable have identical bit numbers */
-#define LINK_INT_LINK_INT                 (1<<31)
-#define LINK_INT_PHY_TIMEOUT              (1<<30)
-#define LINK_INT_PHY_REG_RCVD             (1<<29)
-#define LINK_INT_PHY_BUSRESET             (1<<28)
-#define LINK_INT_TX_RDY                   (1<<26)
-#define LINK_INT_RX_DATA_RDY              (1<<25)
-#define LINK_INT_ISO_STUCK                (1<<20)
-#define LINK_INT_ASYNC_STUCK              (1<<19)
-#define LINK_INT_SENT_REJECT              (1<<17)
-#define LINK_INT_HDR_ERR                  (1<<16)
-#define LINK_INT_TX_INVALID_TC            (1<<15)
-#define LINK_INT_CYC_SECOND               (1<<11)
-#define LINK_INT_CYC_START                (1<<10)
-#define LINK_INT_CYC_DONE                 (1<<9)
-#define LINK_INT_CYC_PENDING              (1<<8)
-#define LINK_INT_CYC_LOST                 (1<<7)
-#define LINK_INT_CYC_ARB_FAILED           (1<<6)
-#define LINK_INT_GRF_OVERFLOW             (1<<5)
-#define LINK_INT_ITF_UNDERFLOW            (1<<4)
-#define LINK_INT_ATF_UNDERFLOW            (1<<3)
-#define LINK_INT_ISOARB_FAILED            (1<<0)
-
-/* PHY specifics */
-#define PHY_VENDORID_TI                 0x800028
-#define PHY_PRODUCTID_TSB41LV03         0x000000
-
-
-/* this is the physical layout of a PCL, its size is 128 bytes */
-struct ti_pcl {
-        u32 next;
-        u32 async_error_next;
-        u32 user_data;
-        u32 pcl_status;
-        u32 remaining_transfer_count;
-        u32 next_data_buffer;
-        struct {
-                u32 control;
-                u32 pointer;
-        } buffer[13] __attribute__ ((packed));
-} __attribute__ ((packed));
-
-#include <linux/stddef.h>
-#define pcloffs(MEMBER) (offsetof(struct ti_pcl, MEMBER))
-
-
-static inline void put_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                           const struct ti_pcl *pcl)
-{
-        memcpy_le32((u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)),
-                    (u32 *)pcl, sizeof(struct ti_pcl));
-}
-
-static inline void get_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                           struct ti_pcl *pcl)
-{
-        memcpy_le32((u32 *)pcl,
-                    (u32 *)(lynx->pcl_mem + pclid * sizeof(struct ti_pcl)),
-                    sizeof(struct ti_pcl));
-}
-
-static inline u32 pcl_bus(const struct ti_lynx *lynx, pcl_t pclid)
-{
-        return lynx->pcl_mem_dma + pclid * sizeof(struct ti_pcl);
-}
-
-
-#if defined (__BIG_ENDIAN)
-typedef struct ti_pcl pcltmp_t;
-
-static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                                      pcltmp_t *tmp)
-{
-        get_pcl(lynx, pclid, tmp);
-        return tmp;
-}
-
-static inline void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                              pcltmp_t *tmp)
-{
-        put_pcl(lynx, pclid, tmp);
-}
-
-#else
-typedef int pcltmp_t; /* just a dummy */
-
-static inline struct ti_pcl *edit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                                      pcltmp_t *tmp)
-{
-        return lynx->pcl_mem + pclid * sizeof(struct ti_pcl);
-}
-
-static inline void commit_pcl(const struct ti_lynx *lynx, pcl_t pclid,
-                              pcltmp_t *tmp)
-{
-}
-#endif
-
-
-static inline void run_sub_pcl(const struct ti_lynx *lynx, pcl_t pclid, int idx,
-                               int dmachan)
-{
-        reg_write(lynx, DMA0_CURRENT_PCL + dmachan * 0x20,
-                  pcl_bus(lynx, pclid) + idx * 4);
-        reg_write(lynx, DMA0_CHAN_CTRL + dmachan * 0x20,
-                  DMA_CHAN_CTRL_ENABLE | DMA_CHAN_CTRL_LINK);
-}
-
-static inline void run_pcl(const struct ti_lynx *lynx, pcl_t pclid, int dmachan)
-{
-        run_sub_pcl(lynx, pclid, 0, dmachan);
-}
-
-#define PCL_NEXT_INVALID (1<<0)
-
-/* transfer commands */
-#define PCL_CMD_RCV            (0x1<<24)
-#define PCL_CMD_RCV_AND_UPDATE (0xa<<24)
-#define PCL_CMD_XMT            (0x2<<24)
-#define PCL_CMD_UNFXMT         (0xc<<24)
-#define PCL_CMD_PCI_TO_LBUS    (0x8<<24)
-#define PCL_CMD_LBUS_TO_PCI    (0x9<<24)
-
-/* aux commands */
-#define PCL_CMD_NOP            (0x0<<24)
-#define PCL_CMD_LOAD           (0x3<<24)
-#define PCL_CMD_STOREQ         (0x4<<24)
-#define PCL_CMD_STORED         (0xb<<24)
-#define PCL_CMD_STORE0         (0x5<<24)
-#define PCL_CMD_STORE1         (0x6<<24)
-#define PCL_CMD_COMPARE        (0xe<<24)
-#define PCL_CMD_SWAP_COMPARE   (0xf<<24)
-#define PCL_CMD_ADD            (0xd<<24)
-#define PCL_CMD_BRANCH         (0x7<<24)
-
-/* BRANCH condition codes */
-#define PCL_COND_DMARDY_SET    (0x1<<20)
-#define PCL_COND_DMARDY_CLEAR  (0x2<<20)
-
-#define PCL_GEN_INTR           (1<<19)
-#define PCL_LAST_BUFF          (1<<18)
-#define PCL_LAST_CMD           (PCL_LAST_BUFF)
-#define PCL_WAITSTAT           (1<<17)
-#define PCL_BIGENDIAN          (1<<16)
-#define PCL_ISOMODE            (1<<12)
-
-#endif
diff --git a/drivers/ieee1394/raw1394-private.h b/drivers/ieee1394/raw1394-private.h
deleted file mode 100644 (file)
index 7a225a4..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#ifndef IEEE1394_RAW1394_PRIVATE_H
-#define IEEE1394_RAW1394_PRIVATE_H
-
-/* header for definitions that are private to the raw1394 driver
-   and not visible to user-space */
-
-#define RAW1394_DEVICE_MAJOR      171
-#define RAW1394_DEVICE_NAME       "raw1394"
-
-#define RAW1394_MAX_USER_CSR_DIRS      16
-
-struct iso_block_store {
-        atomic_t refcount;
-        size_t data_size;
-        quadlet_t data[0];
-};
-
-enum raw1394_iso_state { RAW1394_ISO_INACTIVE = 0,
-                        RAW1394_ISO_RECV = 1,
-                        RAW1394_ISO_XMIT = 2 };
-
-struct file_info {
-        struct list_head list;
-
-       struct mutex state_mutex;
-        enum { opened, initialized, connected } state;
-        unsigned int protocol_version;
-
-        struct hpsb_host *host;
-
-        struct list_head req_pending;  /* protected by reqlists_lock */
-        struct list_head req_complete; /* protected by reqlists_lock */
-        spinlock_t reqlists_lock;
-        wait_queue_head_t wait_complete;
-
-        struct list_head addr_list;    /* protected by host_info_lock */
-
-        u8 __user *fcp_buffer;
-
-        u8 notification; /* (busreset-notification) RAW1394_NOTIFY_OFF/ON */
-
-       /* new rawiso API */
-       enum raw1394_iso_state iso_state;
-       struct hpsb_iso *iso_handle;
-
-       /* User space's CSR1212 dynamic ConfigROM directories */
-       struct csr1212_keyval *csr1212_dirs[RAW1394_MAX_USER_CSR_DIRS];
-
-       /* Legacy ConfigROM update flag */
-       u8 cfgrom_upd;
-};
-
-struct arm_addr {
-        struct list_head addr_list; /* file_info list */
-        u64    start, end;
-        u64    arm_tag;
-        u8     access_rights;
-        u8     notification_options;
-        u8     client_transactions;
-        u64    recvb;
-        u16    rec_length;
-        u8     *addr_space_buffer; /* accessed by read/write/lock requests */
-};
-
-struct pending_request {
-        struct list_head list;
-        struct file_info *file_info;
-        struct hpsb_packet *packet;
-        struct iso_block_store *ibs;
-        quadlet_t *data;
-        int free_data;
-        struct raw1394_request req;
-};
-
-struct host_info {
-        struct list_head list;
-        struct hpsb_host *host;
-        struct list_head file_info_list;  /* protected by host_info_lock */
-};
-
-#endif  /* IEEE1394_RAW1394_PRIVATE_H */
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
deleted file mode 100644 (file)
index f340142..0000000
+++ /dev/null
@@ -1,3096 +0,0 @@
-/*
- * IEEE 1394 for Linux
- *
- * Raw interface to the bus
- *
- * Copyright (C) 1999, 2000 Andreas E. Bombe
- *               2001, 2002 Manfred Weihs <weihs@ict.tuwien.ac.at>
- *                     2002 Christian Toegel <christian.toegel@gmx.at>
- *
- * This code is licensed under the GPL.  See the file COPYING in the root
- * directory of the kernel sources for details.
- *
- *
- * Contributions:
- *
- * Manfred Weihs <weihs@ict.tuwien.ac.at>
- *        configuration ROM manipulation
- *        address range mapping
- *        adaptation for new (transparent) loopback mechanism
- *        sending of arbitrary async packets
- * Christian Toegel <christian.toegel@gmx.at>
- *        address range mapping
- *        lock64 request
- *        transmit physical packet
- *        busreset notification control (switch on/off)
- *        busreset with selection of type (short/long)
- *        request_reply
- */
-
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/vmalloc.h>
-#include <linux/cdev.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
-#include <linux/compat.h>
-
-#include "csr1212.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-#include "iso.h"
-#include "nodemgr.h"
-#include "raw1394.h"
-#include "raw1394-private.h"
-
-#define int2ptr(x) ((void __user *)(unsigned long)x)
-#define ptr2int(x) ((u64)(unsigned long)(void __user *)x)
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define RAW1394_DEBUG
-#endif
-
-#ifdef RAW1394_DEBUG
-#define DBGMSG(fmt, args...) \
-printk(KERN_INFO "raw1394:" fmt "\n" , ## args)
-#else
-#define DBGMSG(fmt, args...) do {} while (0)
-#endif
-
-static LIST_HEAD(host_info_list);
-static int host_count;
-static DEFINE_SPINLOCK(host_info_lock);
-static atomic_t internal_generation = ATOMIC_INIT(0);
-
-static atomic_t iso_buffer_size;
-static const int iso_buffer_max = 4 * 1024 * 1024;     /* 4 MB */
-
-static struct hpsb_highlevel raw1394_highlevel;
-
-static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
-                   u64 addr, size_t length, u16 flags);
-static int arm_write(struct hpsb_host *host, int nodeid, int destid,
-                    quadlet_t * data, u64 addr, size_t length, u16 flags);
-static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                   u16 flags);
-static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                     u16 flags);
-static const struct hpsb_address_ops arm_ops = {
-       .read = arm_read,
-       .write = arm_write,
-       .lock = arm_lock,
-       .lock64 = arm_lock64,
-};
-
-static void queue_complete_cb(struct pending_request *req);
-
-static struct pending_request *__alloc_pending_request(gfp_t flags)
-{
-       struct pending_request *req;
-
-       req = kzalloc(sizeof(*req), flags);
-       if (req)
-               INIT_LIST_HEAD(&req->list);
-
-       return req;
-}
-
-static inline struct pending_request *alloc_pending_request(void)
-{
-       return __alloc_pending_request(GFP_KERNEL);
-}
-
-static void free_pending_request(struct pending_request *req)
-{
-       if (req->ibs) {
-               if (atomic_dec_and_test(&req->ibs->refcount)) {
-                       atomic_sub(req->ibs->data_size, &iso_buffer_size);
-                       kfree(req->ibs);
-               }
-       } else if (req->free_data) {
-               kfree(req->data);
-       }
-       hpsb_free_packet(req->packet);
-       kfree(req);
-}
-
-/* fi->reqlists_lock must be taken */
-static void __queue_complete_req(struct pending_request *req)
-{
-       struct file_info *fi = req->file_info;
-
-       list_move_tail(&req->list, &fi->req_complete);
-       wake_up(&fi->wait_complete);
-}
-
-static void queue_complete_req(struct pending_request *req)
-{
-       unsigned long flags;
-       struct file_info *fi = req->file_info;
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       __queue_complete_req(req);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-}
-
-static void queue_complete_cb(struct pending_request *req)
-{
-       struct hpsb_packet *packet = req->packet;
-       int rcode = (packet->header[1] >> 12) & 0xf;
-
-       switch (packet->ack_code) {
-       case ACKX_NONE:
-       case ACKX_SEND_ERROR:
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               break;
-       case ACKX_ABORTED:
-               req->req.error = RAW1394_ERROR_ABORTED;
-               break;
-       case ACKX_TIMEOUT:
-               req->req.error = RAW1394_ERROR_TIMEOUT;
-               break;
-       default:
-               req->req.error = (packet->ack_code << 16) | rcode;
-               break;
-       }
-
-       if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
-               req->req.length = 0;
-       }
-
-       if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||
-           (req->req.type == RAW1394_REQ_ASYNC_WRITE) ||
-           (req->req.type == RAW1394_REQ_ASYNC_STREAM) ||
-           (req->req.type == RAW1394_REQ_LOCK) ||
-           (req->req.type == RAW1394_REQ_LOCK64))
-               hpsb_free_tlabel(packet);
-
-       queue_complete_req(req);
-}
-
-static void add_host(struct hpsb_host *host)
-{
-       struct host_info *hi;
-       unsigned long flags;
-
-       hi = kmalloc(sizeof(*hi), GFP_KERNEL);
-
-       if (hi) {
-               INIT_LIST_HEAD(&hi->list);
-               hi->host = host;
-               INIT_LIST_HEAD(&hi->file_info_list);
-
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_add_tail(&hi->list, &host_info_list);
-               host_count++;
-               spin_unlock_irqrestore(&host_info_lock, flags);
-       }
-
-       atomic_inc(&internal_generation);
-}
-
-static struct host_info *find_host_info(struct hpsb_host *host)
-{
-       struct host_info *hi;
-
-       list_for_each_entry(hi, &host_info_list, list)
-           if (hi->host == host)
-               return hi;
-
-       return NULL;
-}
-
-static void remove_host(struct hpsb_host *host)
-{
-       struct host_info *hi;
-       unsigned long flags;
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(host);
-
-       if (hi != NULL) {
-               list_del(&hi->list);
-               host_count--;
-               /*
-                  FIXME: address ranges should be removed
-                  and fileinfo states should be initialized
-                  (including setting generation to
-                  internal-generation ...)
-                */
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       if (hi == NULL) {
-               printk(KERN_ERR "raw1394: attempt to remove unknown host "
-                      "0x%p\n", host);
-               return;
-       }
-
-       kfree(hi);
-
-       atomic_inc(&internal_generation);
-}
-
-static void host_reset(struct hpsb_host *host)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct file_info *fi;
-       struct pending_request *req;
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(host);
-
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       if (fi->notification == RAW1394_NOTIFY_ON) {
-                               req = __alloc_pending_request(GFP_ATOMIC);
-
-                               if (req != NULL) {
-                                       req->file_info = fi;
-                                       req->req.type = RAW1394_REQ_BUS_RESET;
-                                       req->req.generation =
-                                           get_hpsb_generation(host);
-                                       req->req.misc = (host->node_id << 16)
-                                           | host->node_count;
-                                       if (fi->protocol_version > 3) {
-                                               req->req.misc |=
-                                                   (NODEID_TO_NODE
-                                                    (host->irm_id)
-                                                    << 8);
-                                       }
-
-                                       queue_complete_req(req);
-                               }
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-}
-
-static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
-                       int cts, u8 * data, size_t length)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct file_info *fi;
-       struct pending_request *req, *req_next;
-       struct iso_block_store *ibs = NULL;
-       LIST_HEAD(reqs);
-
-       if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
-               HPSB_INFO("dropped fcp request");
-               return;
-       }
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(host);
-
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       if (!fi->fcp_buffer)
-                               continue;
-
-                       req = __alloc_pending_request(GFP_ATOMIC);
-                       if (!req)
-                               break;
-
-                       if (!ibs) {
-                               ibs = kmalloc(sizeof(*ibs) + length,
-                                             GFP_ATOMIC);
-                               if (!ibs) {
-                                       kfree(req);
-                                       break;
-                               }
-
-                               atomic_add(length, &iso_buffer_size);
-                               atomic_set(&ibs->refcount, 0);
-                               ibs->data_size = length;
-                               memcpy(ibs->data, data, length);
-                       }
-
-                       atomic_inc(&ibs->refcount);
-
-                       req->file_info = fi;
-                       req->ibs = ibs;
-                       req->data = ibs->data;
-                       req->req.type = RAW1394_REQ_FCP_REQUEST;
-                       req->req.generation = get_hpsb_generation(host);
-                       req->req.misc = nodeid | (direction << 16);
-                       req->req.recvb = ptr2int(fi->fcp_buffer);
-                       req->req.length = length;
-
-                       list_add_tail(&req->list, &reqs);
-               }
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       list_for_each_entry_safe(req, req_next, &reqs, list)
-           queue_complete_req(req);
-}
-
-#ifdef CONFIG_COMPAT
-struct compat_raw1394_req {
-       __u32 type;
-       __s32 error;
-       __u32 misc;
-
-       __u32 generation;
-       __u32 length;
-
-       __u64 address;
-
-       __u64 tag;
-
-       __u64 sendb;
-       __u64 recvb;
-}
-#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
-__attribute__((packed))
-#endif
-;
-
-static const char __user *raw1394_compat_write(const char __user *buf)
-{
-       struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
-       struct raw1394_request __user *r;
-
-       r = compat_alloc_user_space(sizeof(struct raw1394_request));
-
-#define C(x) __copy_in_user(&r->x, &cr->x, sizeof(r->x))
-
-       if (copy_in_user(r, cr, sizeof(struct compat_raw1394_req)) ||
-           C(address) ||
-           C(tag) ||
-           C(sendb) ||
-           C(recvb))
-               return (__force const char __user *)ERR_PTR(-EFAULT);
-
-       return (const char __user *)r;
-}
-#undef C
-
-#define P(x) __put_user(r->x, &cr->x)
-
-static int
-raw1394_compat_read(const char __user *buf, struct raw1394_request *r)
-{
-       struct compat_raw1394_req __user *cr = (typeof(cr)) buf;
-
-       if (!access_ok(VERIFY_WRITE, cr, sizeof(struct compat_raw1394_req)) ||
-           P(type) ||
-           P(error) ||
-           P(misc) ||
-           P(generation) ||
-           P(length) ||
-           P(address) ||
-           P(tag) ||
-           P(sendb) ||
-           P(recvb))
-               return -EFAULT;
-
-       return sizeof(struct compat_raw1394_req);
-}
-#undef P
-
-#endif
-
-/* get next completed request  (caller must hold fi->reqlists_lock) */
-static inline struct pending_request *__next_complete_req(struct file_info *fi)
-{
-       struct list_head *lh;
-       struct pending_request *req = NULL;
-
-       if (!list_empty(&fi->req_complete)) {
-               lh = fi->req_complete.next;
-               list_del(lh);
-               req = list_entry(lh, struct pending_request, list);
-       }
-       return req;
-}
-
-/* atomically get next completed request */
-static struct pending_request *next_complete_req(struct file_info *fi)
-{
-       unsigned long flags;
-       struct pending_request *req;
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       req = __next_complete_req(fi);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-       return req;
-}
-
-static ssize_t raw1394_read(struct file *file, char __user * buffer,
-                           size_t count, loff_t * offset_is_ignored)
-{
-       struct file_info *fi = file->private_data;
-       struct pending_request *req;
-       ssize_t ret;
-
-#ifdef CONFIG_COMPAT
-       if (count == sizeof(struct compat_raw1394_req)) {
-               /* ok */
-       } else
-#endif
-       if (count != sizeof(struct raw1394_request)) {
-               return -EINVAL;
-       }
-
-       if (!access_ok(VERIFY_WRITE, buffer, count)) {
-               return -EFAULT;
-       }
-
-       if (file->f_flags & O_NONBLOCK) {
-               if (!(req = next_complete_req(fi)))
-                       return -EAGAIN;
-       } else {
-               /*
-                * NB: We call the macro wait_event_interruptible() with a
-                * condition argument with side effect.  This is only possible
-                * because the side effect does not occur until the condition
-                * became true, and wait_event_interruptible() won't evaluate
-                * the condition again after that.
-                */
-               if (wait_event_interruptible(fi->wait_complete,
-                                            (req = next_complete_req(fi))))
-                       return -ERESTARTSYS;
-       }
-
-       if (req->req.length) {
-               if (copy_to_user(int2ptr(req->req.recvb), req->data,
-                                req->req.length)) {
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-               }
-       }
-
-#ifdef CONFIG_COMPAT
-       if (count == sizeof(struct compat_raw1394_req) &&
-           sizeof(struct compat_raw1394_req) !=
-                       sizeof(struct raw1394_request)) {
-               ret = raw1394_compat_read(buffer, &req->req);
-       } else
-#endif
-       {
-               if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
-                       ret = -EFAULT;
-                       goto out;
-               }
-               ret = (ssize_t) sizeof(struct raw1394_request);
-       }
-      out:
-       free_pending_request(req);
-       return ret;
-}
-
-static int state_opened(struct file_info *fi, struct pending_request *req)
-{
-       if (req->req.type == RAW1394_REQ_INITIALIZE) {
-               switch (req->req.misc) {
-               case RAW1394_KERNELAPI_VERSION:
-               case 3:
-                       fi->state = initialized;
-                       fi->protocol_version = req->req.misc;
-                       req->req.error = RAW1394_ERROR_NONE;
-                       req->req.generation = atomic_read(&internal_generation);
-                       break;
-
-               default:
-                       req->req.error = RAW1394_ERROR_COMPAT;
-                       req->req.misc = RAW1394_KERNELAPI_VERSION;
-               }
-       } else {
-               req->req.error = RAW1394_ERROR_STATE_ORDER;
-       }
-
-       req->req.length = 0;
-       queue_complete_req(req);
-       return 0;
-}
-
-static int state_initialized(struct file_info *fi, struct pending_request *req)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct raw1394_khost_list *khl;
-
-       if (req->req.generation != atomic_read(&internal_generation)) {
-               req->req.error = RAW1394_ERROR_GENERATION;
-               req->req.generation = atomic_read(&internal_generation);
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       switch (req->req.type) {
-       case RAW1394_REQ_LIST_CARDS:
-               spin_lock_irqsave(&host_info_lock, flags);
-               khl = kmalloc(sizeof(*khl) * host_count, GFP_ATOMIC);
-
-               if (khl) {
-                       req->req.misc = host_count;
-                       req->data = (quadlet_t *) khl;
-
-                       list_for_each_entry(hi, &host_info_list, list) {
-                               khl->nodes = hi->host->node_count;
-                               strcpy(khl->name, hi->host->driver->name);
-                               khl++;
-                       }
-               }
-               spin_unlock_irqrestore(&host_info_lock, flags);
-
-               if (khl) {
-                       req->req.error = RAW1394_ERROR_NONE;
-                       req->req.length = min(req->req.length,
-                                             (u32) (sizeof
-                                                    (struct raw1394_khost_list)
-                                                    * req->req.misc));
-                       req->free_data = 1;
-               } else {
-                       return -ENOMEM;
-               }
-               break;
-
-       case RAW1394_REQ_SET_CARD:
-               spin_lock_irqsave(&host_info_lock, flags);
-               if (req->req.misc >= host_count) {
-                       req->req.error = RAW1394_ERROR_INVALID_ARG;
-                       goto out_set_card;
-               }
-               list_for_each_entry(hi, &host_info_list, list)
-                       if (!req->req.misc--)
-                               break;
-               get_device(&hi->host->device); /* FIXME handle failure case */
-               list_add_tail(&fi->list, &hi->file_info_list);
-
-               /* prevent unloading of the host's low-level driver */
-               if (!try_module_get(hi->host->driver->owner)) {
-                       req->req.error = RAW1394_ERROR_ABORTED;
-                       goto out_set_card;
-               }
-               WARN_ON(fi->host);
-               fi->host = hi->host;
-               fi->state = connected;
-
-               req->req.error = RAW1394_ERROR_NONE;
-               req->req.generation = get_hpsb_generation(fi->host);
-               req->req.misc = (fi->host->node_id << 16)
-                               | fi->host->node_count;
-               if (fi->protocol_version > 3)
-                       req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
-out_set_card:
-               spin_unlock_irqrestore(&host_info_lock, flags);
-
-               req->req.length = 0;
-               break;
-
-       default:
-               req->req.error = RAW1394_ERROR_STATE_ORDER;
-               req->req.length = 0;
-               break;
-       }
-
-       queue_complete_req(req);
-       return 0;
-}
-
-static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
-{
-       if (req->req.misc) {
-               if (fi->fcp_buffer) {
-                       req->req.error = RAW1394_ERROR_ALREADY;
-               } else {
-                       fi->fcp_buffer = int2ptr(req->req.recvb);
-               }
-       } else {
-               if (!fi->fcp_buffer) {
-                       req->req.error = RAW1394_ERROR_ALREADY;
-               } else {
-                       fi->fcp_buffer = NULL;
-               }
-       }
-
-       req->req.length = 0;
-       queue_complete_req(req);
-}
-
-static int handle_async_request(struct file_info *fi,
-                               struct pending_request *req, int node)
-{
-       unsigned long flags;
-       struct hpsb_packet *packet = NULL;
-       u64 addr = req->req.address & 0xffffffffffffULL;
-
-       switch (req->req.type) {
-       case RAW1394_REQ_ASYNC_READ:
-               DBGMSG("read_request called");
-               packet =
-                   hpsb_make_readpacket(fi->host, node, addr, req->req.length);
-
-               if (!packet)
-                       return -ENOMEM;
-
-               if (req->req.length == 4)
-                       req->data = &packet->header[3];
-               else
-                       req->data = packet->data;
-
-               break;
-
-       case RAW1394_REQ_ASYNC_WRITE:
-               DBGMSG("write_request called");
-
-               packet = hpsb_make_writepacket(fi->host, node, addr, NULL,
-                                              req->req.length);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (req->req.length == 4) {
-                       if (copy_from_user
-                           (&packet->header[3], int2ptr(req->req.sendb),
-                            req->req.length))
-                               req->req.error = RAW1394_ERROR_MEMFAULT;
-               } else {
-                       if (copy_from_user
-                           (packet->data, int2ptr(req->req.sendb),
-                            req->req.length))
-                               req->req.error = RAW1394_ERROR_MEMFAULT;
-               }
-
-               req->req.length = 0;
-               break;
-
-       case RAW1394_REQ_ASYNC_STREAM:
-               DBGMSG("stream_request called");
-
-               packet =
-                   hpsb_make_streampacket(fi->host, NULL, req->req.length,
-                                          node & 0x3f /*channel */ ,
-                                          (req->req.misc >> 16) & 0x3,
-                                          req->req.misc & 0xf);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                  req->req.length))
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-
-               req->req.length = 0;
-               break;
-
-       case RAW1394_REQ_LOCK:
-               DBGMSG("lock_request called");
-               if ((req->req.misc == EXTCODE_FETCH_ADD)
-                   || (req->req.misc == EXTCODE_LITTLE_ADD)) {
-                       if (req->req.length != 4) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               } else {
-                       if (req->req.length != 8) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               }
-
-               packet = hpsb_make_lockpacket(fi->host, node, addr,
-                                             req->req.misc, NULL, 0);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                  req->req.length)) {
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-                       break;
-               }
-
-               req->data = packet->data;
-               req->req.length = 4;
-               break;
-
-       case RAW1394_REQ_LOCK64:
-               DBGMSG("lock64_request called");
-               if ((req->req.misc == EXTCODE_FETCH_ADD)
-                   || (req->req.misc == EXTCODE_LITTLE_ADD)) {
-                       if (req->req.length != 8) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               } else {
-                       if (req->req.length != 16) {
-                               req->req.error = RAW1394_ERROR_INVALID_ARG;
-                               break;
-                       }
-               }
-               packet = hpsb_make_lock64packet(fi->host, node, addr,
-                                               req->req.misc, NULL, 0);
-               if (!packet)
-                       return -ENOMEM;
-
-               if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                  req->req.length)) {
-                       req->req.error = RAW1394_ERROR_MEMFAULT;
-                       break;
-               }
-
-               req->data = packet->data;
-               req->req.length = 8;
-               break;
-
-       default:
-               req->req.error = RAW1394_ERROR_STATE_ORDER;
-       }
-
-       req->packet = packet;
-
-       if (req->req.error) {
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       hpsb_set_packet_complete_task(packet,
-                                     (void (*)(void *))queue_complete_cb, req);
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       list_add_tail(&req->list, &fi->req_pending);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-       packet->generation = req->req.generation;
-
-       if (hpsb_send_packet(packet) < 0) {
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               req->req.length = 0;
-               hpsb_free_tlabel(packet);
-               queue_complete_req(req);
-       }
-       return 0;
-}
-
-static int handle_async_send(struct file_info *fi, struct pending_request *req)
-{
-       unsigned long flags;
-       struct hpsb_packet *packet;
-       int header_length = req->req.misc & 0xffff;
-       int expect_response = req->req.misc >> 16;
-       size_t data_size;
-
-       if (header_length > req->req.length || header_length < 12 ||
-           header_length > FIELD_SIZEOF(struct hpsb_packet, header)) {
-               req->req.error = RAW1394_ERROR_INVALID_ARG;
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       data_size = req->req.length - header_length;
-       packet = hpsb_alloc_packet(data_size);
-       req->packet = packet;
-       if (!packet)
-               return -ENOMEM;
-
-       if (copy_from_user(packet->header, int2ptr(req->req.sendb),
-                          header_length)) {
-               req->req.error = RAW1394_ERROR_MEMFAULT;
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       if (copy_from_user
-           (packet->data, int2ptr(req->req.sendb) + header_length,
-            data_size)) {
-               req->req.error = RAW1394_ERROR_MEMFAULT;
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       packet->type = hpsb_async;
-       packet->node_id = packet->header[0] >> 16;
-       packet->tcode = (packet->header[0] >> 4) & 0xf;
-       packet->tlabel = (packet->header[0] >> 10) & 0x3f;
-       packet->host = fi->host;
-       packet->expect_response = expect_response;
-       packet->header_size = header_length;
-       packet->data_size = data_size;
-
-       req->req.length = 0;
-       hpsb_set_packet_complete_task(packet,
-                                     (void (*)(void *))queue_complete_cb, req);
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       list_add_tail(&req->list, &fi->req_pending);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-       /* Update the generation of the packet just before sending. */
-       packet->generation = req->req.generation;
-
-       if (hpsb_send_packet(packet) < 0) {
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               queue_complete_req(req);
-       }
-
-       return 0;
-}
-
-static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
-                   u64 addr, size_t length, u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       DBGMSG("arm_read  called by node: %X "
-              "addr: %4.4x %8.8x length: %Zu", nodeid,
-              (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-              length);
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search address-entry */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >= (addr + length))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_read addr_entry FOUND");
-       }
-       if (arm_addr->rec_length < length) {
-               DBGMSG("arm_read blocklength too big -> rcode_data_error");
-               rcode = RCODE_DATA_ERROR;       /* hardware error, data is unavailable */
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_READ) {
-                       if (!(arm_addr->client_transactions & ARM_READ)) {
-                               memcpy(buffer,
-                                      (arm_addr->addr_space_buffer) + (addr -
-                                                                       (arm_addr->
-                                                                        start)),
-                                      length);
-                               DBGMSG("arm_read -> (rcode_complete)");
-                               rcode = RCODE_COMPLETE;
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG("arm_read -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_READ) {
-               DBGMSG("arm_read -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       DBGMSG("arm_read -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               if (rcode == RCODE_COMPLETE) {
-                       size =
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) +
-                           length * sizeof(byte_t) +
-                           sizeof(struct arm_request_response);
-               } else {
-                       size =
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) +
-                           sizeof(struct arm_request_response);
-               }
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       DBGMSG("arm_read -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc =
-                   (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               arm_req->buffer = NULL;
-               arm_resp->buffer = NULL;
-               if (rcode == RCODE_COMPLETE) {
-                       byte_t *buf =
-                           (byte_t *) arm_resp + sizeof(struct arm_response);
-                       memcpy(buf,
-                              (arm_addr->addr_space_buffer) + (addr -
-                                                               (arm_addr->
-                                                                start)),
-                              length);
-                       arm_resp->buffer =
-                           int2ptr((arm_addr->recvb) +
-                                   sizeof(struct arm_request_response) +
-                                   sizeof(struct arm_request) +
-                                   sizeof(struct arm_response));
-               }
-               arm_resp->buffer_length =
-                   (rcode == RCODE_COMPLETE) ? length : 0;
-               arm_resp->response_code = rcode;
-               arm_req->buffer_length = 0;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = 0;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = host->node_id;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_write(struct hpsb_host *host, int nodeid, int destid,
-                    quadlet_t * data, u64 addr, size_t length, u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       DBGMSG("arm_write called by node: %X "
-              "addr: %4.4x %8.8x length: %Zu", nodeid,
-              (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-              length);
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search address-entry */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >= (addr + length))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_write addr_entry FOUND");
-       }
-       if (arm_addr->rec_length < length) {
-               DBGMSG("arm_write blocklength too big -> rcode_data_error");
-               rcode = RCODE_DATA_ERROR;       /* hardware error, data is unavailable */
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_WRITE) {
-                       if (!(arm_addr->client_transactions & ARM_WRITE)) {
-                               memcpy((arm_addr->addr_space_buffer) +
-                                      (addr - (arm_addr->start)), data,
-                                      length);
-                               DBGMSG("arm_write -> (rcode_complete)");
-                               rcode = RCODE_COMPLETE;
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG("arm_write -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_WRITE) {
-               DBGMSG("arm_write -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       DBGMSG("arm_write -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request my be retried */
-               }
-               size =
-                   sizeof(struct arm_request) + sizeof(struct arm_response) +
-                   (length) * sizeof(byte_t) +
-                   sizeof(struct arm_request_response);
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       DBGMSG("arm_write -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc =
-                   (((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               arm_resp->buffer = NULL;
-               memcpy((byte_t *) arm_resp + sizeof(struct arm_response),
-                      data, length);
-               arm_req->buffer = int2ptr((arm_addr->recvb) +
-                                         sizeof(struct arm_request_response) +
-                                         sizeof(struct arm_request) +
-                                         sizeof(struct arm_response));
-               arm_req->buffer_length = length;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = 0;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = destid;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_resp->buffer_length = 0;
-               arm_resp->response_code = rcode;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
-                   u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
-                   u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       quadlet_t old, new;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
-           ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
-               DBGMSG("arm_lock  called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
-                      be32_to_cpu(data));
-       } else {
-               DBGMSG("arm_lock  called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
-                      be32_to_cpu(data), be32_to_cpu(arg));
-       }
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search address-entry */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >=
-                                       (addr + sizeof(*store)))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_lock addr_entry FOUND");
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_LOCK) {
-                       if (!(arm_addr->client_transactions & ARM_LOCK)) {
-                               memcpy(&old,
-                                      (arm_addr->addr_space_buffer) + (addr -
-                                                                       (arm_addr->
-                                                                        start)),
-                                      sizeof(old));
-                               switch (ext_tcode) {
-                               case (EXTCODE_MASK_SWAP):
-                                       new = data | (old & ~arg);
-                                       break;
-                               case (EXTCODE_COMPARE_SWAP):
-                                       if (old == arg) {
-                                               new = data;
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_FETCH_ADD):
-                                       new =
-                                           cpu_to_be32(be32_to_cpu(data) +
-                                                       be32_to_cpu(old));
-                                       break;
-                               case (EXTCODE_LITTLE_ADD):
-                                       new =
-                                           cpu_to_le32(le32_to_cpu(data) +
-                                                       le32_to_cpu(old));
-                                       break;
-                               case (EXTCODE_BOUNDED_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be32(be32_to_cpu
-                                                               (data) +
-                                                               be32_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_WRAP_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be32(be32_to_cpu
-                                                               (data) +
-                                                               be32_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = data;
-                                       }
-                                       break;
-                               default:
-                                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                                       printk(KERN_ERR
-                                              "raw1394: arm_lock FAILED "
-                                              "ext_tcode not allowed -> rcode_type_error\n");
-                                       break;
-                               }       /*switch */
-                               if (rcode == -1) {
-                                       DBGMSG("arm_lock -> (rcode_complete)");
-                                       rcode = RCODE_COMPLETE;
-                                       memcpy(store, &old, sizeof(*store));
-                                       memcpy((arm_addr->addr_space_buffer) +
-                                              (addr - (arm_addr->start)),
-                                              &new, sizeof(*store));
-                               }
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG("arm_lock -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_LOCK) {
-               byte_t *buf1, *buf2;
-               DBGMSG("arm_lock -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       DBGMSG("arm_lock -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);     /* maximum */
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       DBGMSG("arm_lock -> rcode_conflict_error");
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
-               buf2 = buf1 + 2 * sizeof(*store);
-               if ((ext_tcode == EXTCODE_FETCH_ADD) ||
-                   (ext_tcode == EXTCODE_LITTLE_ADD)) {
-                       arm_req->buffer_length = sizeof(*store);
-                       memcpy(buf1, &data, sizeof(*store));
-
-               } else {
-                       arm_req->buffer_length = 2 * sizeof(*store);
-                       memcpy(buf1, &arg, sizeof(*store));
-                       memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
-               }
-               if (rcode == RCODE_COMPLETE) {
-                       arm_resp->buffer_length = sizeof(*store);
-                       memcpy(buf2, &old, sizeof(*store));
-               } else {
-                       arm_resp->buffer_length = 0;
-               }
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
-                                (ARM_LOCK & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = ext_tcode;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = host->node_id;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_resp->response_code = rcode;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               arm_req->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response));
-               arm_resp->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) + 2 * sizeof(*store));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
-                     u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
-                     u16 flags)
-{
-       unsigned long irqflags;
-       struct pending_request *req;
-       struct host_info *hi;
-       struct file_info *fi = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       struct arm_request *arm_req = NULL;
-       struct arm_response *arm_resp = NULL;
-       int found = 0, size = 0, rcode = -1;
-       octlet_t old, new;
-       struct arm_request_response *arm_req_resp = NULL;
-
-       if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
-           ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
-               DBGMSG("arm_lock64 called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF,
-                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
-       } else {
-               DBGMSG("arm_lock64 called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
-                      "%8.8X %8.8X ",
-                      nodeid, (u16) ((addr >> 32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF,
-                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
-                      (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
-       }
-       spin_lock_irqsave(&host_info_lock, irqflags);
-       hi = find_host_info(host);      /* search addressentry in file_info's for host */
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       entry = fi->addr_list.next;
-                       while (entry != &(fi->addr_list)) {
-                               arm_addr =
-                                   list_entry(entry, struct arm_addr,
-                                              addr_list);
-                               if (((arm_addr->start) <= (addr))
-                                   && ((arm_addr->end) >=
-                                       (addr + sizeof(*store)))) {
-                                       found = 1;
-                                       break;
-                               }
-                               entry = entry->next;
-                       }
-                       if (found) {
-                               break;
-                       }
-               }
-       }
-       rcode = -1;
-       if (!found) {
-               printk(KERN_ERR
-                      "raw1394: arm_lock64 FAILED addr_entry not found"
-                      " -> rcode_address_error\n");
-               spin_unlock_irqrestore(&host_info_lock, irqflags);
-               return (RCODE_ADDRESS_ERROR);
-       } else {
-               DBGMSG("arm_lock64 addr_entry FOUND");
-       }
-       if (rcode == -1) {
-               if (arm_addr->access_rights & ARM_LOCK) {
-                       if (!(arm_addr->client_transactions & ARM_LOCK)) {
-                               memcpy(&old,
-                                      (arm_addr->addr_space_buffer) + (addr -
-                                                                       (arm_addr->
-                                                                        start)),
-                                      sizeof(old));
-                               switch (ext_tcode) {
-                               case (EXTCODE_MASK_SWAP):
-                                       new = data | (old & ~arg);
-                                       break;
-                               case (EXTCODE_COMPARE_SWAP):
-                                       if (old == arg) {
-                                               new = data;
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_FETCH_ADD):
-                                       new =
-                                           cpu_to_be64(be64_to_cpu(data) +
-                                                       be64_to_cpu(old));
-                                       break;
-                               case (EXTCODE_LITTLE_ADD):
-                                       new =
-                                           cpu_to_le64(le64_to_cpu(data) +
-                                                       le64_to_cpu(old));
-                                       break;
-                               case (EXTCODE_BOUNDED_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be64(be64_to_cpu
-                                                               (data) +
-                                                               be64_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = old;
-                                       }
-                                       break;
-                               case (EXTCODE_WRAP_ADD):
-                                       if (old != arg) {
-                                               new =
-                                                   cpu_to_be64(be64_to_cpu
-                                                               (data) +
-                                                               be64_to_cpu
-                                                               (old));
-                                       } else {
-                                               new = data;
-                                       }
-                                       break;
-                               default:
-                                       printk(KERN_ERR
-                                              "raw1394: arm_lock64 FAILED "
-                                              "ext_tcode not allowed -> rcode_type_error\n");
-                                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                                       break;
-                               }       /*switch */
-                               if (rcode == -1) {
-                                       DBGMSG
-                                           ("arm_lock64 -> (rcode_complete)");
-                                       rcode = RCODE_COMPLETE;
-                                       memcpy(store, &old, sizeof(*store));
-                                       memcpy((arm_addr->addr_space_buffer) +
-                                              (addr - (arm_addr->start)),
-                                              &new, sizeof(*store));
-                               }
-                       }
-               } else {
-                       rcode = RCODE_TYPE_ERROR;       /* function not allowed */
-                       DBGMSG
-                           ("arm_lock64 -> rcode_type_error (access denied)");
-               }
-       }
-       if (arm_addr->notification_options & ARM_LOCK) {
-               byte_t *buf1, *buf2;
-               DBGMSG("arm_lock64 -> entering notification-section");
-               req = __alloc_pending_request(GFP_ATOMIC);
-               if (!req) {
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       DBGMSG("arm_lock64 -> rcode_conflict_error");
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);     /* maximum */
-               req->data = kmalloc(size, GFP_ATOMIC);
-               if (!(req->data)) {
-                       free_pending_request(req);
-                       spin_unlock_irqrestore(&host_info_lock, irqflags);
-                       DBGMSG("arm_lock64 -> rcode_conflict_error");
-                       return (RCODE_CONFLICT_ERROR);  /* A resource conflict was detected.
-                                                          The request may be retried */
-               }
-               req->free_data = 1;
-               arm_req_resp = (struct arm_request_response *)(req->data);
-               arm_req = (struct arm_request *)((byte_t *) (req->data) +
-                                                (sizeof
-                                                 (struct
-                                                  arm_request_response)));
-               arm_resp =
-                   (struct arm_response *)((byte_t *) (arm_req) +
-                                           (sizeof(struct arm_request)));
-               buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
-               buf2 = buf1 + 2 * sizeof(*store);
-               if ((ext_tcode == EXTCODE_FETCH_ADD) ||
-                   (ext_tcode == EXTCODE_LITTLE_ADD)) {
-                       arm_req->buffer_length = sizeof(*store);
-                       memcpy(buf1, &data, sizeof(*store));
-
-               } else {
-                       arm_req->buffer_length = 2 * sizeof(*store);
-                       memcpy(buf1, &arg, sizeof(*store));
-                       memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
-               }
-               if (rcode == RCODE_COMPLETE) {
-                       arm_resp->buffer_length = sizeof(*store);
-                       memcpy(buf2, &old, sizeof(*store));
-               } else {
-                       arm_resp->buffer_length = 0;
-               }
-               req->file_info = fi;
-               req->req.type = RAW1394_REQ_ARM;
-               req->req.generation = get_hpsb_generation(host);
-               req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
-                                (ARM_LOCK & 0xFF));
-               req->req.tag = arm_addr->arm_tag;
-               req->req.recvb = arm_addr->recvb;
-               req->req.length = size;
-               arm_req->generation = req->req.generation;
-               arm_req->extended_transaction_code = ext_tcode;
-               arm_req->destination_offset = addr;
-               arm_req->source_nodeid = nodeid;
-               arm_req->destination_nodeid = host->node_id;
-               arm_req->tlabel = (flags >> 10) & 0x3f;
-               arm_req->tcode = (flags >> 4) & 0x0f;
-               arm_resp->response_code = rcode;
-               arm_req_resp->request = int2ptr((arm_addr->recvb) +
-                                               sizeof(struct
-                                                      arm_request_response));
-               arm_req_resp->response =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request));
-               arm_req->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response));
-               arm_resp->buffer =
-                   int2ptr((arm_addr->recvb) +
-                           sizeof(struct arm_request_response) +
-                           sizeof(struct arm_request) +
-                           sizeof(struct arm_response) + 2 * sizeof(*store));
-               queue_complete_req(req);
-       }
-       spin_unlock_irqrestore(&host_info_lock, irqflags);
-       return (rcode);
-}
-
-static int arm_register(struct file_info *fi, struct pending_request *req)
-{
-       int retval;
-       struct arm_addr *addr;
-       struct host_info *hi;
-       struct file_info *fi_hlp = NULL;
-       struct list_head *entry;
-       struct arm_addr *arm_addr = NULL;
-       int same_host, another_host;
-       unsigned long flags;
-
-       DBGMSG("arm_register called "
-              "addr(Offset): %8.8x %8.8x length: %u "
-              "rights: %2.2X notify: %2.2X "
-              "max_blk_len: %4.4X",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF),
-              req->req.length, ((req->req.misc >> 8) & 0xFF),
-              (req->req.misc & 0xFF), ((req->req.misc >> 16) & 0xFFFF));
-       /* check addressrange */
-       if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) ||
-           (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) !=
-            0)) {
-               req->req.length = 0;
-               return (-EINVAL);
-       }
-       /* addr-list-entry for fileinfo */
-       addr = kmalloc(sizeof(*addr), GFP_KERNEL);
-       if (!addr) {
-               req->req.length = 0;
-               return (-ENOMEM);
-       }
-       /* allocation of addr_space_buffer */
-       addr->addr_space_buffer = vmalloc(req->req.length);
-       if (!(addr->addr_space_buffer)) {
-               kfree(addr);
-               req->req.length = 0;
-               return (-ENOMEM);
-       }
-       /* initialization of addr_space_buffer */
-       if ((req->req.sendb) == (unsigned long)NULL) {
-               /* init: set 0 */
-               memset(addr->addr_space_buffer, 0, req->req.length);
-       } else {
-               /* init: user -> kernel */
-               if (copy_from_user
-                   (addr->addr_space_buffer, int2ptr(req->req.sendb),
-                    req->req.length)) {
-                       vfree(addr->addr_space_buffer);
-                       kfree(addr);
-                       return (-EFAULT);
-               }
-       }
-       INIT_LIST_HEAD(&addr->addr_list);
-       addr->arm_tag = req->req.tag;
-       addr->start = req->req.address;
-       addr->end = req->req.address + req->req.length;
-       addr->access_rights = (u8) (req->req.misc & 0x0F);
-       addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
-       addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
-       addr->access_rights |= addr->client_transactions;
-       addr->notification_options |= addr->client_transactions;
-       addr->recvb = req->req.recvb;
-       addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(fi->host);
-       same_host = 0;
-       another_host = 0;
-       /* same host with address-entry containing same addressrange ? */
-       list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-               entry = fi_hlp->addr_list.next;
-               while (entry != &(fi_hlp->addr_list)) {
-                       arm_addr =
-                           list_entry(entry, struct arm_addr, addr_list);
-                       if ((arm_addr->start == addr->start)
-                           && (arm_addr->end == addr->end)) {
-                               DBGMSG("same host ownes same "
-                                      "addressrange -> EALREADY");
-                               same_host = 1;
-                               break;
-                       }
-                       entry = entry->next;
-               }
-               if (same_host) {
-                       break;
-               }
-       }
-       if (same_host) {
-               /* addressrange occupied by same host */
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-               return (-EALREADY);
-       }
-       /* another host with valid address-entry containing same addressrange */
-       list_for_each_entry(hi, &host_info_list, list) {
-               if (hi->host != fi->host) {
-                       list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                               entry = fi_hlp->addr_list.next;
-                               while (entry != &(fi_hlp->addr_list)) {
-                                       arm_addr =
-                                           list_entry(entry, struct arm_addr,
-                                                      addr_list);
-                                       if ((arm_addr->start == addr->start)
-                                           && (arm_addr->end == addr->end)) {
-                                               DBGMSG
-                                                   ("another host ownes same "
-                                                    "addressrange");
-                                               another_host = 1;
-                                               break;
-                                       }
-                                       entry = entry->next;
-                               }
-                               if (another_host) {
-                                       break;
-                               }
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       if (another_host) {
-               DBGMSG("another hosts entry is valid -> SUCCESS");
-               if (copy_to_user(int2ptr(req->req.recvb),
-                                &addr->start, sizeof(u64))) {
-                       printk(KERN_ERR "raw1394: arm_register failed "
-                              " address-range-entry is invalid -> EFAULT !!!\n");
-                       vfree(addr->addr_space_buffer);
-                       kfree(addr);
-                       return (-EFAULT);
-               }
-               free_pending_request(req);      /* immediate success or fail */
-               /* INSERT ENTRY */
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_add_tail(&addr->addr_list, &fi->addr_list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               return 0;
-       }
-       retval =
-           hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
-                                   req->req.address,
-                                   req->req.address + req->req.length);
-       if (retval) {
-               /* INSERT ENTRY */
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_add_tail(&addr->addr_list, &fi->addr_list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-       } else {
-               DBGMSG("arm_register failed errno: %d \n", retval);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-               return (-EALREADY);
-       }
-       free_pending_request(req);      /* immediate success or fail */
-       return 0;
-}
-
-static int arm_unregister(struct file_info *fi, struct pending_request *req)
-{
-       int found = 0;
-       int retval = 0;
-       struct list_head *entry;
-       struct arm_addr *addr = NULL;
-       struct host_info *hi;
-       struct file_info *fi_hlp = NULL;
-       struct arm_addr *arm_addr = NULL;
-       int another_host;
-       unsigned long flags;
-
-       DBGMSG("arm_Unregister called addr(Offset): "
-              "%8.8x %8.8x",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF));
-       spin_lock_irqsave(&host_info_lock, flags);
-       /* get addr */
-       entry = fi->addr_list.next;
-       while (entry != &(fi->addr_list)) {
-               addr = list_entry(entry, struct arm_addr, addr_list);
-               if (addr->start == req->req.address) {
-                       found = 1;
-                       break;
-               }
-               entry = entry->next;
-       }
-       if (!found) {
-               DBGMSG("arm_Unregister addr not found");
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               return (-EINVAL);
-       }
-       DBGMSG("arm_Unregister addr found");
-       another_host = 0;
-       /* another host with valid address-entry containing
-          same addressrange */
-       list_for_each_entry(hi, &host_info_list, list) {
-               if (hi->host != fi->host) {
-                       list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                               entry = fi_hlp->addr_list.next;
-                               while (entry != &(fi_hlp->addr_list)) {
-                                       arm_addr = list_entry(entry,
-                                                             struct arm_addr,
-                                                             addr_list);
-                                       if (arm_addr->start == addr->start) {
-                                               DBGMSG("another host ownes "
-                                                      "same addressrange");
-                                               another_host = 1;
-                                               break;
-                                       }
-                                       entry = entry->next;
-                               }
-                               if (another_host) {
-                                       break;
-                               }
-                       }
-               }
-       }
-       if (another_host) {
-               DBGMSG("delete entry from list -> success");
-               list_del(&addr->addr_list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-               free_pending_request(req);      /* immediate success or fail */
-               return 0;
-       }
-       retval =
-           hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
-                                     addr->start);
-       if (!retval) {
-               printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
-               spin_unlock_irqrestore(&host_info_lock, flags);
-               return (-EINVAL);
-       }
-       DBGMSG("delete entry from list -> success");
-       list_del(&addr->addr_list);
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       vfree(addr->addr_space_buffer);
-       kfree(addr);
-       free_pending_request(req);      /* immediate success or fail */
-       return 0;
-}
-
-/* Copy data from ARM buffer(s) to user buffer. */
-static int arm_get_buf(struct file_info *fi, struct pending_request *req)
-{
-       struct arm_addr *arm_addr = NULL;
-       unsigned long flags;
-       unsigned long offset;
-
-       struct list_head *entry;
-
-       DBGMSG("arm_get_buf "
-              "addr(Offset): %04X %08X length: %u",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       entry = fi->addr_list.next;
-       while (entry != &(fi->addr_list)) {
-               arm_addr = list_entry(entry, struct arm_addr, addr_list);
-               if ((arm_addr->start <= req->req.address) &&
-                   (arm_addr->end > req->req.address)) {
-                       if (req->req.address + req->req.length <= arm_addr->end) {
-                               offset = req->req.address - arm_addr->start;
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-
-                               DBGMSG
-                                   ("arm_get_buf copy_to_user( %08X, %p, %u )",
-                                    (u32) req->req.recvb,
-                                    arm_addr->addr_space_buffer + offset,
-                                    (u32) req->req.length);
-                               if (copy_to_user
-                                   (int2ptr(req->req.recvb),
-                                    arm_addr->addr_space_buffer + offset,
-                                    req->req.length))
-                                       return (-EFAULT);
-
-                               /* We have to free the request, because we
-                                * queue no response, and therefore nobody
-                                * will free it. */
-                               free_pending_request(req);
-                               return 0;
-                       } else {
-                               DBGMSG("arm_get_buf request exceeded mapping");
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-                               return (-EINVAL);
-                       }
-               }
-               entry = entry->next;
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       return (-EINVAL);
-}
-
-/* Copy data from user buffer to ARM buffer(s). */
-static int arm_set_buf(struct file_info *fi, struct pending_request *req)
-{
-       struct arm_addr *arm_addr = NULL;
-       unsigned long flags;
-       unsigned long offset;
-
-       struct list_head *entry;
-
-       DBGMSG("arm_set_buf "
-              "addr(Offset): %04X %08X length: %u",
-              (u32) ((req->req.address >> 32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       entry = fi->addr_list.next;
-       while (entry != &(fi->addr_list)) {
-               arm_addr = list_entry(entry, struct arm_addr, addr_list);
-               if ((arm_addr->start <= req->req.address) &&
-                   (arm_addr->end > req->req.address)) {
-                       if (req->req.address + req->req.length <= arm_addr->end) {
-                               offset = req->req.address - arm_addr->start;
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-
-                               DBGMSG
-                                   ("arm_set_buf copy_from_user( %p, %08X, %u )",
-                                    arm_addr->addr_space_buffer + offset,
-                                    (u32) req->req.sendb,
-                                    (u32) req->req.length);
-                               if (copy_from_user
-                                   (arm_addr->addr_space_buffer + offset,
-                                    int2ptr(req->req.sendb),
-                                    req->req.length))
-                                       return (-EFAULT);
-
-                               /* We have to free the request, because we
-                                * queue no response, and therefore nobody
-                                * will free it. */
-                               free_pending_request(req);
-                               return 0;
-                       } else {
-                               DBGMSG("arm_set_buf request exceeded mapping");
-                               spin_unlock_irqrestore(&host_info_lock, flags);
-                               return (-EINVAL);
-                       }
-               }
-               entry = entry->next;
-       }
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       return (-EINVAL);
-}
-
-static int reset_notification(struct file_info *fi, struct pending_request *req)
-{
-       DBGMSG("reset_notification called - switch %s ",
-              (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON");
-       if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
-           (req->req.misc == RAW1394_NOTIFY_ON)) {
-               fi->notification = (u8) req->req.misc;
-               free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-               return 0;
-       }
-       /* error EINVAL (22) invalid argument */
-       return (-EINVAL);
-}
-
-static int write_phypacket(struct file_info *fi, struct pending_request *req)
-{
-       struct hpsb_packet *packet = NULL;
-       int retval = 0;
-       quadlet_t data;
-       unsigned long flags;
-
-       data = be32_to_cpu((u32) req->req.sendb);
-       DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data);
-       packet = hpsb_make_phypacket(fi->host, data);
-       if (!packet)
-               return -ENOMEM;
-       req->req.length = 0;
-       req->packet = packet;
-       hpsb_set_packet_complete_task(packet,
-                                     (void (*)(void *))queue_complete_cb, req);
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       list_add_tail(&req->list, &fi->req_pending);
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-       packet->generation = req->req.generation;
-       retval = hpsb_send_packet(packet);
-       DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
-       if (retval < 0) {
-               req->req.error = RAW1394_ERROR_SEND_ERROR;
-               req->req.length = 0;
-               queue_complete_req(req);
-       }
-       return 0;
-}
-
-static int get_config_rom(struct file_info *fi, struct pending_request *req)
-{
-       int ret = 0;
-       quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
-       int status;
-
-       if (!data)
-               return -ENOMEM;
-
-       status =
-           csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
-                        data, req->req.length);
-       if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length))
-               ret = -EFAULT;
-       if (copy_to_user
-           (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
-            sizeof(fi->host->csr.rom->cache_head->len)))
-               ret = -EFAULT;
-       if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation,
-                        sizeof(fi->host->csr.generation)))
-               ret = -EFAULT;
-       if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status)))
-               ret = -EFAULT;
-       kfree(data);
-       if (ret >= 0) {
-               free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-       }
-       return ret;
-}
-
-static int update_config_rom(struct file_info *fi, struct pending_request *req)
-{
-       int ret = 0;
-       quadlet_t *data = kmalloc(req->req.length, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) {
-               ret = -EFAULT;
-       } else {
-               int status = hpsb_update_config_rom(fi->host,
-                                                   data, req->req.length,
-                                                   (unsigned char)req->req.
-                                                   misc);
-               if (copy_to_user
-                   (int2ptr(req->req.recvb), &status, sizeof(status)))
-                       ret = -ENOMEM;
-       }
-       kfree(data);
-       if (ret >= 0) {
-               free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-               fi->cfgrom_upd = 1;
-       }
-       return ret;
-}
-
-static int modify_config_rom(struct file_info *fi, struct pending_request *req)
-{
-       struct csr1212_keyval *kv;
-       struct csr1212_csr_rom_cache *cache;
-       struct csr1212_dentry *dentry;
-       u32 dr;
-       int ret = 0;
-
-       if (req->req.misc == ~0) {
-               if (req->req.length == 0)
-                       return -EINVAL;
-
-               /* Find an unused slot */
-               for (dr = 0;
-                    dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr];
-                    dr++) ;
-
-               if (dr == RAW1394_MAX_USER_CSR_DIRS)
-                       return -ENOMEM;
-
-               fi->csr1212_dirs[dr] =
-                   csr1212_new_directory(CSR1212_KV_ID_VENDOR);
-               if (!fi->csr1212_dirs[dr])
-                       return -ENOMEM;
-       } else {
-               dr = req->req.misc;
-               if (!fi->csr1212_dirs[dr])
-                       return -EINVAL;
-
-               /* Delete old stuff */
-               for (dentry =
-                    fi->csr1212_dirs[dr]->value.directory.dentries_head;
-                    dentry; dentry = dentry->next) {
-                       csr1212_detach_keyval_from_directory(fi->host->csr.rom->
-                                                            root_kv,
-                                                            dentry->kv);
-               }
-
-               if (req->req.length == 0) {
-                       csr1212_release_keyval(fi->csr1212_dirs[dr]);
-                       fi->csr1212_dirs[dr] = NULL;
-
-                       hpsb_update_config_rom_image(fi->host);
-                       free_pending_request(req);
-                       return 0;
-               }
-       }
-
-       cache = csr1212_rom_cache_malloc(0, req->req.length);
-       if (!cache) {
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               return -ENOMEM;
-       }
-
-       cache->filled_head = kmalloc(sizeof(*cache->filled_head), GFP_KERNEL);
-       if (!cache->filled_head) {
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               CSR1212_FREE(cache);
-               return -ENOMEM;
-       }
-       cache->filled_tail = cache->filled_head;
-
-       if (copy_from_user(cache->data, int2ptr(req->req.sendb),
-                          req->req.length)) {
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               ret = -EFAULT;
-       } else {
-               cache->len = req->req.length;
-               cache->filled_head->offset_start = 0;
-               cache->filled_head->offset_end = cache->size - 1;
-
-               cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr];
-
-               ret = CSR1212_SUCCESS;
-               /* parse all the items */
-               for (kv = cache->layout_head; ret == CSR1212_SUCCESS && kv;
-                    kv = kv->next) {
-                       ret = csr1212_parse_keyval(kv, cache);
-               }
-
-               /* attach top level items to the root directory */
-               for (dentry =
-                    fi->csr1212_dirs[dr]->value.directory.dentries_head;
-                    ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) {
-                       ret =
-                           csr1212_attach_keyval_to_directory(fi->host->csr.
-                                                              rom->root_kv,
-                                                              dentry->kv);
-               }
-
-               if (ret == CSR1212_SUCCESS) {
-                       ret = hpsb_update_config_rom_image(fi->host);
-
-                       if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb),
-                                                    &dr, sizeof(dr))) {
-                               ret = -ENOMEM;
-                       }
-               }
-       }
-       kfree(cache->filled_head);
-       CSR1212_FREE(cache);
-
-       if (ret >= 0) {
-               /* we have to free the request, because we queue no response,
-                * and therefore nobody will free it */
-               free_pending_request(req);
-               return 0;
-       } else {
-               for (dentry =
-                    fi->csr1212_dirs[dr]->value.directory.dentries_head;
-                    dentry; dentry = dentry->next) {
-                       csr1212_detach_keyval_from_directory(fi->host->csr.rom->
-                                                            root_kv,
-                                                            dentry->kv);
-               }
-               csr1212_release_keyval(fi->csr1212_dirs[dr]);
-               fi->csr1212_dirs[dr] = NULL;
-               return ret;
-       }
-}
-
-static int state_connected(struct file_info *fi, struct pending_request *req)
-{
-       int node = req->req.address >> 48;
-
-       req->req.error = RAW1394_ERROR_NONE;
-
-       switch (req->req.type) {
-
-       case RAW1394_REQ_ECHO:
-               queue_complete_req(req);
-               return 0;
-
-       case RAW1394_REQ_ARM_REGISTER:
-               return arm_register(fi, req);
-
-       case RAW1394_REQ_ARM_UNREGISTER:
-               return arm_unregister(fi, req);
-
-       case RAW1394_REQ_ARM_SET_BUF:
-               return arm_set_buf(fi, req);
-
-       case RAW1394_REQ_ARM_GET_BUF:
-               return arm_get_buf(fi, req);
-
-       case RAW1394_REQ_RESET_NOTIFY:
-               return reset_notification(fi, req);
-
-       case RAW1394_REQ_ISO_SEND:
-       case RAW1394_REQ_ISO_LISTEN:
-               printk(KERN_DEBUG "raw1394: old iso ABI has been removed\n");
-               req->req.error = RAW1394_ERROR_COMPAT;
-               req->req.misc = RAW1394_KERNELAPI_VERSION;
-               queue_complete_req(req);
-               return 0;
-
-       case RAW1394_REQ_FCP_LISTEN:
-               handle_fcp_listen(fi, req);
-               return 0;
-
-       case RAW1394_REQ_RESET_BUS:
-               if (req->req.misc == RAW1394_LONG_RESET) {
-                       DBGMSG("busreset called (type: LONG)");
-                       hpsb_reset_bus(fi->host, LONG_RESET);
-                       free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-                       return 0;
-               }
-               if (req->req.misc == RAW1394_SHORT_RESET) {
-                       DBGMSG("busreset called (type: SHORT)");
-                       hpsb_reset_bus(fi->host, SHORT_RESET);
-                       free_pending_request(req);      /* we have to free the request, because we queue no response, and therefore nobody will free it */
-                       return 0;
-               }
-               /* error EINVAL (22) invalid argument */
-               return (-EINVAL);
-       case RAW1394_REQ_GET_ROM:
-               return get_config_rom(fi, req);
-
-       case RAW1394_REQ_UPDATE_ROM:
-               return update_config_rom(fi, req);
-
-       case RAW1394_REQ_MODIFY_ROM:
-               return modify_config_rom(fi, req);
-       }
-
-       if (req->req.generation != get_hpsb_generation(fi->host)) {
-               req->req.error = RAW1394_ERROR_GENERATION;
-               req->req.generation = get_hpsb_generation(fi->host);
-               req->req.length = 0;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       switch (req->req.type) {
-       case RAW1394_REQ_PHYPACKET:
-               return write_phypacket(fi, req);
-       case RAW1394_REQ_ASYNC_SEND:
-               return handle_async_send(fi, req);
-       }
-
-       if (req->req.length == 0) {
-               req->req.error = RAW1394_ERROR_INVALID_ARG;
-               queue_complete_req(req);
-               return 0;
-       }
-
-       return handle_async_request(fi, req, node);
-}
-
-static ssize_t raw1394_write(struct file *file, const char __user * buffer,
-                            size_t count, loff_t * offset_is_ignored)
-{
-       struct file_info *fi = file->private_data;
-       struct pending_request *req;
-       ssize_t retval = -EBADFD;
-
-#ifdef CONFIG_COMPAT
-       if (count == sizeof(struct compat_raw1394_req) &&
-           sizeof(struct compat_raw1394_req) !=
-                       sizeof(struct raw1394_request)) {
-               buffer = raw1394_compat_write(buffer);
-               if (IS_ERR((__force void *)buffer))
-                       return PTR_ERR((__force void *)buffer);
-       } else
-#endif
-       if (count != sizeof(struct raw1394_request)) {
-               return -EINVAL;
-       }
-
-       req = alloc_pending_request();
-       if (req == NULL) {
-               return -ENOMEM;
-       }
-       req->file_info = fi;
-
-       if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
-               free_pending_request(req);
-               return -EFAULT;
-       }
-
-       if (!mutex_trylock(&fi->state_mutex)) {
-               free_pending_request(req);
-               return -EAGAIN;
-       }
-
-       switch (fi->state) {
-       case opened:
-               retval = state_opened(fi, req);
-               break;
-
-       case initialized:
-               retval = state_initialized(fi, req);
-               break;
-
-       case connected:
-               retval = state_connected(fi, req);
-               break;
-       }
-
-       mutex_unlock(&fi->state_mutex);
-
-       if (retval < 0) {
-               free_pending_request(req);
-       } else {
-               BUG_ON(retval);
-               retval = count;
-       }
-
-       return retval;
-}
-
-/* rawiso operations */
-
-/* check if any RAW1394_REQ_RAWISO_ACTIVITY event is already in the
- * completion queue (reqlists_lock must be taken) */
-static inline int __rawiso_event_in_queue(struct file_info *fi)
-{
-       struct pending_request *req;
-
-       list_for_each_entry(req, &fi->req_complete, list)
-           if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
-               return 1;
-
-       return 0;
-}
-
-/* put a RAWISO_ACTIVITY event in the queue, if one isn't there already */
-static void queue_rawiso_event(struct file_info *fi)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-
-       /* only one ISO activity event may be in the queue */
-       if (!__rawiso_event_in_queue(fi)) {
-               struct pending_request *req =
-                   __alloc_pending_request(GFP_ATOMIC);
-
-               if (req) {
-                       req->file_info = fi;
-                       req->req.type = RAW1394_REQ_RAWISO_ACTIVITY;
-                       req->req.generation = get_hpsb_generation(fi->host);
-                       __queue_complete_req(req);
-               } else {
-                       /* on allocation failure, signal an overflow */
-                       if (fi->iso_handle) {
-                               atomic_inc(&fi->iso_handle->overflows);
-                       }
-               }
-       }
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-}
-
-static void rawiso_activity_cb(struct hpsb_iso *iso)
-{
-       unsigned long flags;
-       struct host_info *hi;
-       struct file_info *fi;
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       hi = find_host_info(iso->host);
-
-       if (hi != NULL) {
-               list_for_each_entry(fi, &hi->file_info_list, list) {
-                       if (fi->iso_handle == iso)
-                               queue_rawiso_event(fi);
-               }
-       }
-
-       spin_unlock_irqrestore(&host_info_lock, flags);
-}
-
-/* helper function - gather all the kernel iso status bits for returning to user-space */
-static void raw1394_iso_fill_status(struct hpsb_iso *iso,
-                                   struct raw1394_iso_status *stat)
-{
-       int overflows = atomic_read(&iso->overflows);
-       int skips = atomic_read(&iso->skips);
-
-       stat->config.data_buf_size = iso->buf_size;
-       stat->config.buf_packets = iso->buf_packets;
-       stat->config.channel = iso->channel;
-       stat->config.speed = iso->speed;
-       stat->config.irq_interval = iso->irq_interval;
-       stat->n_packets = hpsb_iso_n_ready(iso);
-       stat->overflows = ((skips & 0xFFFF) << 16) | ((overflows & 0xFFFF));
-       stat->xmit_cycle = iso->xmit_cycle;
-}
-
-static int raw1394_iso_xmit_init(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_status stat;
-
-       if (!fi->host)
-               return -EINVAL;
-
-       if (copy_from_user(&stat, uaddr, sizeof(stat)))
-               return -EFAULT;
-
-       fi->iso_handle = hpsb_iso_xmit_init(fi->host,
-                                           stat.config.data_buf_size,
-                                           stat.config.buf_packets,
-                                           stat.config.channel,
-                                           stat.config.speed,
-                                           stat.config.irq_interval,
-                                           rawiso_activity_cb);
-       if (!fi->iso_handle)
-               return -ENOMEM;
-
-       fi->iso_state = RAW1394_ISO_XMIT;
-
-       raw1394_iso_fill_status(fi->iso_handle, &stat);
-       if (copy_to_user(uaddr, &stat, sizeof(stat)))
-               return -EFAULT;
-
-       /* queue an event to get things started */
-       rawiso_activity_cb(fi->iso_handle);
-
-       return 0;
-}
-
-static int raw1394_iso_recv_init(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_status stat;
-
-       if (!fi->host)
-               return -EINVAL;
-
-       if (copy_from_user(&stat, uaddr, sizeof(stat)))
-               return -EFAULT;
-
-       fi->iso_handle = hpsb_iso_recv_init(fi->host,
-                                           stat.config.data_buf_size,
-                                           stat.config.buf_packets,
-                                           stat.config.channel,
-                                           stat.config.dma_mode,
-                                           stat.config.irq_interval,
-                                           rawiso_activity_cb);
-       if (!fi->iso_handle)
-               return -ENOMEM;
-
-       fi->iso_state = RAW1394_ISO_RECV;
-
-       raw1394_iso_fill_status(fi->iso_handle, &stat);
-       if (copy_to_user(uaddr, &stat, sizeof(stat)))
-               return -EFAULT;
-       return 0;
-}
-
-static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_status stat;
-       struct hpsb_iso *iso = fi->iso_handle;
-
-       raw1394_iso_fill_status(fi->iso_handle, &stat);
-       if (copy_to_user(uaddr, &stat, sizeof(stat)))
-               return -EFAULT;
-
-       /* reset overflow counter */
-       atomic_set(&iso->overflows, 0);
-       /* reset skip counter */
-       atomic_set(&iso->skips, 0);
-
-       return 0;
-}
-
-/* copy N packet_infos out of the ringbuffer into user-supplied array */
-static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_packets upackets;
-       unsigned int packet = fi->iso_handle->first_packet;
-       int i;
-
-       if (copy_from_user(&upackets, uaddr, sizeof(upackets)))
-               return -EFAULT;
-
-       if (upackets.n_packets > hpsb_iso_n_ready(fi->iso_handle))
-               return -EINVAL;
-
-       /* ensure user-supplied buffer is accessible and big enough */
-       if (!access_ok(VERIFY_WRITE, upackets.infos,
-                      upackets.n_packets *
-                      sizeof(struct raw1394_iso_packet_info)))
-               return -EFAULT;
-
-       /* copy the packet_infos out */
-       for (i = 0; i < upackets.n_packets; i++) {
-               if (__copy_to_user(&upackets.infos[i],
-                                  &fi->iso_handle->infos[packet],
-                                  sizeof(struct raw1394_iso_packet_info)))
-                       return -EFAULT;
-
-               packet = (packet + 1) % fi->iso_handle->buf_packets;
-       }
-
-       return 0;
-}
-
-/* copy N packet_infos from user to ringbuffer, and queue them for transmission */
-static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_iso_packets upackets;
-       int i, rv;
-
-       if (copy_from_user(&upackets, uaddr, sizeof(upackets)))
-               return -EFAULT;
-
-       if (upackets.n_packets >= fi->iso_handle->buf_packets)
-               return -EINVAL;
-
-       if (upackets.n_packets >= hpsb_iso_n_ready(fi->iso_handle))
-               return -EAGAIN;
-
-       /* ensure user-supplied buffer is accessible and big enough */
-       if (!access_ok(VERIFY_READ, upackets.infos,
-                      upackets.n_packets *
-                      sizeof(struct raw1394_iso_packet_info)))
-               return -EFAULT;
-
-       /* copy the infos structs in and queue the packets */
-       for (i = 0; i < upackets.n_packets; i++) {
-               struct raw1394_iso_packet_info info;
-
-               if (__copy_from_user(&info, &upackets.infos[i],
-                                    sizeof(struct raw1394_iso_packet_info)))
-                       return -EFAULT;
-
-               rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset,
-                                               info.len, info.tag, info.sy);
-               if (rv)
-                       return rv;
-       }
-
-       return 0;
-}
-
-static void raw1394_iso_shutdown(struct file_info *fi)
-{
-       if (fi->iso_handle)
-               hpsb_iso_shutdown(fi->iso_handle);
-
-       fi->iso_handle = NULL;
-       fi->iso_state = RAW1394_ISO_INACTIVE;
-}
-
-static int raw1394_read_cycle_timer(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_cycle_timer ct;
-       int err;
-
-       err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
-       if (!err)
-               if (copy_to_user(uaddr, &ct, sizeof(ct)))
-                       err = -EFAULT;
-       return err;
-}
-
-/* mmap the rawiso xmit/recv buffer */
-static int raw1394_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct file_info *fi = file->private_data;
-       int ret;
-
-       if (!mutex_trylock(&fi->state_mutex))
-               return -EAGAIN;
-
-       if (fi->iso_state == RAW1394_ISO_INACTIVE)
-               ret = -EINVAL;
-       else
-               ret = dma_region_mmap(&fi->iso_handle->data_buf, file, vma);
-
-       mutex_unlock(&fi->state_mutex);
-
-       return ret;
-}
-
-static long raw1394_ioctl_inactive(struct file_info *fi, unsigned int cmd,
-                                  void __user *argp)
-{
-       switch (cmd) {
-       case RAW1394_IOC_ISO_XMIT_INIT:
-               return raw1394_iso_xmit_init(fi, argp);
-       case RAW1394_IOC_ISO_RECV_INIT:
-               return raw1394_iso_recv_init(fi, argp);
-       default:
-               return -EINVAL;
-       }
-}
-
-static long raw1394_ioctl_recv(struct file_info *fi, unsigned int cmd,
-                              unsigned long arg)
-{
-       void __user *argp = (void __user *)arg;
-
-       switch (cmd) {
-       case RAW1394_IOC_ISO_RECV_START:{
-                       int args[3];
-
-                       if (copy_from_user(&args[0], argp, sizeof(args)))
-                               return -EFAULT;
-                       return hpsb_iso_recv_start(fi->iso_handle,
-                                                  args[0], args[1], args[2]);
-               }
-       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-               hpsb_iso_stop(fi->iso_handle);
-               return 0;
-       case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
-               return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
-       case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
-               return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
-       case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
-                       u64 mask;
-
-                       if (copy_from_user(&mask, argp, sizeof(mask)))
-                               return -EFAULT;
-                       return hpsb_iso_recv_set_channel_mask(fi->iso_handle,
-                                                             mask);
-               }
-       case RAW1394_IOC_ISO_GET_STATUS:
-               return raw1394_iso_get_status(fi, argp);
-       case RAW1394_IOC_ISO_RECV_PACKETS:
-               return raw1394_iso_recv_packets(fi, argp);
-       case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
-               return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
-       case RAW1394_IOC_ISO_RECV_FLUSH:
-               return hpsb_iso_recv_flush(fi->iso_handle);
-       case RAW1394_IOC_ISO_SHUTDOWN:
-               raw1394_iso_shutdown(fi);
-               return 0;
-       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-               queue_rawiso_event(fi);
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-static long raw1394_ioctl_xmit(struct file_info *fi, unsigned int cmd,
-                              void __user *argp)
-{
-       switch (cmd) {
-       case RAW1394_IOC_ISO_XMIT_START:{
-                       int args[2];
-
-                       if (copy_from_user(&args[0], argp, sizeof(args)))
-                               return -EFAULT;
-                       return hpsb_iso_xmit_start(fi->iso_handle,
-                                                  args[0], args[1]);
-               }
-       case RAW1394_IOC_ISO_XMIT_SYNC:
-               return hpsb_iso_xmit_sync(fi->iso_handle);
-       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-               hpsb_iso_stop(fi->iso_handle);
-               return 0;
-       case RAW1394_IOC_ISO_GET_STATUS:
-               return raw1394_iso_get_status(fi, argp);
-       case RAW1394_IOC_ISO_XMIT_PACKETS:
-               return raw1394_iso_send_packets(fi, argp);
-       case RAW1394_IOC_ISO_SHUTDOWN:
-               raw1394_iso_shutdown(fi);
-               return 0;
-       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-               queue_rawiso_event(fi);
-               return 0;
-       default:
-               return -EINVAL;
-       }
-}
-
-/* ioctl is only used for rawiso operations */
-static long raw1394_ioctl(struct file *file, unsigned int cmd,
-                         unsigned long arg)
-{
-       struct file_info *fi = file->private_data;
-       void __user *argp = (void __user *)arg;
-       long ret;
-
-       /* state-independent commands */
-       switch(cmd) {
-       case RAW1394_IOC_GET_CYCLE_TIMER:
-               return raw1394_read_cycle_timer(fi, argp);
-       default:
-               break;
-       }
-
-       if (!mutex_trylock(&fi->state_mutex))
-               return -EAGAIN;
-
-       switch (fi->iso_state) {
-       case RAW1394_ISO_INACTIVE:
-               ret = raw1394_ioctl_inactive(fi, cmd, argp);
-               break;
-       case RAW1394_ISO_RECV:
-               ret = raw1394_ioctl_recv(fi, cmd, arg);
-               break;
-       case RAW1394_ISO_XMIT:
-               ret = raw1394_ioctl_xmit(fi, cmd, argp);
-               break;
-       default:
-               ret = -EINVAL;
-               break;
-       }
-
-       mutex_unlock(&fi->state_mutex);
-
-       return ret;
-}
-
-#ifdef CONFIG_COMPAT
-struct raw1394_iso_packets32 {
-        __u32 n_packets;
-        compat_uptr_t infos;
-} __attribute__((packed));
-
-struct raw1394_cycle_timer32 {
-        __u32 cycle_timer;
-        __u64 local_time;
-}
-#if defined(CONFIG_X86_64) || defined(CONFIG_IA64)
-__attribute__((packed))
-#endif
-;
-
-#define RAW1394_IOC_ISO_RECV_PACKETS32          \
-        _IOW ('#', 0x25, struct raw1394_iso_packets32)
-#define RAW1394_IOC_ISO_XMIT_PACKETS32          \
-        _IOW ('#', 0x27, struct raw1394_iso_packets32)
-#define RAW1394_IOC_GET_CYCLE_TIMER32           \
-        _IOR ('#', 0x30, struct raw1394_cycle_timer32)
-
-static long raw1394_iso_xmit_recv_packets32(struct file *file, unsigned int cmd,
-                                          struct raw1394_iso_packets32 __user *arg)
-{
-       compat_uptr_t infos32;
-       void __user *infos;
-       long err = -EFAULT;
-       struct raw1394_iso_packets __user *dst = compat_alloc_user_space(sizeof(struct raw1394_iso_packets));
-
-       if (!copy_in_user(&dst->n_packets, &arg->n_packets, sizeof arg->n_packets) &&
-           !copy_from_user(&infos32, &arg->infos, sizeof infos32)) {
-               infos = compat_ptr(infos32);
-               if (!copy_to_user(&dst->infos, &infos, sizeof infos))
-                       err = raw1394_ioctl(file, cmd, (unsigned long)dst);
-       }
-       return err;
-}
-
-static long raw1394_read_cycle_timer32(struct file_info *fi, void __user * uaddr)
-{
-       struct raw1394_cycle_timer32 ct;
-       int err;
-
-       err = hpsb_read_cycle_timer(fi->host, &ct.cycle_timer, &ct.local_time);
-       if (!err)
-               if (copy_to_user(uaddr, &ct, sizeof(ct)))
-                       err = -EFAULT;
-       return err;
-}
-
-static long raw1394_compat_ioctl(struct file *file,
-                                unsigned int cmd, unsigned long arg)
-{
-       struct file_info *fi = file->private_data;
-       void __user *argp = (void __user *)arg;
-       long err;
-
-       switch (cmd) {
-       /* These requests have same format as long as 'int' has same size. */
-       case RAW1394_IOC_ISO_RECV_INIT:
-       case RAW1394_IOC_ISO_RECV_START:
-       case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
-       case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
-       case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:
-       case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
-       case RAW1394_IOC_ISO_RECV_FLUSH:
-       case RAW1394_IOC_ISO_XMIT_RECV_STOP:
-       case RAW1394_IOC_ISO_XMIT_INIT:
-       case RAW1394_IOC_ISO_XMIT_START:
-       case RAW1394_IOC_ISO_XMIT_SYNC:
-       case RAW1394_IOC_ISO_GET_STATUS:
-       case RAW1394_IOC_ISO_SHUTDOWN:
-       case RAW1394_IOC_ISO_QUEUE_ACTIVITY:
-               err = raw1394_ioctl(file, cmd, arg);
-               break;
-       /* These request have different format. */
-       case RAW1394_IOC_ISO_RECV_PACKETS32:
-               err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_RECV_PACKETS, argp);
-               break;
-       case RAW1394_IOC_ISO_XMIT_PACKETS32:
-               err = raw1394_iso_xmit_recv_packets32(file, RAW1394_IOC_ISO_XMIT_PACKETS, argp);
-               break;
-       case RAW1394_IOC_GET_CYCLE_TIMER32:
-               err = raw1394_read_cycle_timer32(fi, argp);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-
-       return err;
-}
-#endif
-
-static unsigned int raw1394_poll(struct file *file, poll_table * pt)
-{
-       struct file_info *fi = file->private_data;
-       unsigned int mask = POLLOUT | POLLWRNORM;
-       unsigned long flags;
-
-       poll_wait(file, &fi->wait_complete, pt);
-
-       spin_lock_irqsave(&fi->reqlists_lock, flags);
-       if (!list_empty(&fi->req_complete)) {
-               mask |= POLLIN | POLLRDNORM;
-       }
-       spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-       return mask;
-}
-
-static int raw1394_open(struct inode *inode, struct file *file)
-{
-       struct file_info *fi;
-
-       fi = kzalloc(sizeof(*fi), GFP_KERNEL);
-       if (!fi)
-               return -ENOMEM;
-
-       fi->notification = (u8) RAW1394_NOTIFY_ON;      /* busreset notification */
-
-       INIT_LIST_HEAD(&fi->list);
-       mutex_init(&fi->state_mutex);
-       fi->state = opened;
-       INIT_LIST_HEAD(&fi->req_pending);
-       INIT_LIST_HEAD(&fi->req_complete);
-       spin_lock_init(&fi->reqlists_lock);
-       init_waitqueue_head(&fi->wait_complete);
-       INIT_LIST_HEAD(&fi->addr_list);
-
-       file->private_data = fi;
-
-       return nonseekable_open(inode, file);
-}
-
-static int raw1394_release(struct inode *inode, struct file *file)
-{
-       struct file_info *fi = file->private_data;
-       struct list_head *lh;
-       struct pending_request *req;
-       int i, fail;
-       int retval = 0;
-       struct list_head *entry;
-       struct arm_addr *addr = NULL;
-       struct host_info *hi;
-       struct file_info *fi_hlp = NULL;
-       struct arm_addr *arm_addr = NULL;
-       int another_host;
-       int csr_mod = 0;
-       unsigned long flags;
-
-       if (fi->iso_state != RAW1394_ISO_INACTIVE)
-               raw1394_iso_shutdown(fi);
-
-       spin_lock_irqsave(&host_info_lock, flags);
-
-       fail = 0;
-       /* set address-entries invalid */
-
-       while (!list_empty(&fi->addr_list)) {
-               another_host = 0;
-               lh = fi->addr_list.next;
-               addr = list_entry(lh, struct arm_addr, addr_list);
-               /* another host with valid address-entry containing
-                  same addressrange? */
-               list_for_each_entry(hi, &host_info_list, list) {
-                       if (hi->host != fi->host) {
-                               list_for_each_entry(fi_hlp, &hi->file_info_list,
-                                                   list) {
-                                       entry = fi_hlp->addr_list.next;
-                                       while (entry != &(fi_hlp->addr_list)) {
-                                               arm_addr = list_entry(entry, struct
-                                                                     arm_addr,
-                                                                     addr_list);
-                                               if (arm_addr->start ==
-                                                   addr->start) {
-                                                       DBGMSG
-                                                           ("raw1394_release: "
-                                                            "another host ownes "
-                                                            "same addressrange");
-                                                       another_host = 1;
-                                                       break;
-                                               }
-                                               entry = entry->next;
-                                       }
-                                       if (another_host) {
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               if (!another_host) {
-                       DBGMSG("raw1394_release: call hpsb_arm_unregister");
-                       retval =
-                           hpsb_unregister_addrspace(&raw1394_highlevel,
-                                                     fi->host, addr->start);
-                       if (!retval) {
-                               ++fail;
-                               printk(KERN_ERR
-                                      "raw1394_release arm_Unregister failed\n");
-                       }
-               }
-               DBGMSG("raw1394_release: delete addr_entry from list");
-               list_del(&addr->addr_list);
-               vfree(addr->addr_space_buffer);
-               kfree(addr);
-       }                       /* while */
-       spin_unlock_irqrestore(&host_info_lock, flags);
-       if (fail > 0) {
-               printk(KERN_ERR "raw1394: during addr_list-release "
-                      "error(s) occurred \n");
-       }
-
-       for (;;) {
-               /* This locked section guarantees that neither
-                * complete nor pending requests exist once i!=0 */
-               spin_lock_irqsave(&fi->reqlists_lock, flags);
-               while ((req = __next_complete_req(fi)))
-                       free_pending_request(req);
-
-               i = list_empty(&fi->req_pending);
-               spin_unlock_irqrestore(&fi->reqlists_lock, flags);
-
-               if (i)
-                       break;
-               /*
-                * Sleep until more requests can be freed.
-                *
-                * NB: We call the macro wait_event() with a condition argument
-                * with side effect.  This is only possible because the side
-                * effect does not occur until the condition became true, and
-                * wait_event() won't evaluate the condition again after that.
-                */
-               wait_event(fi->wait_complete, (req = next_complete_req(fi)));
-               free_pending_request(req);
-       }
-
-       /* Remove any sub-trees left by user space programs */
-       for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) {
-               struct csr1212_dentry *dentry;
-               if (!fi->csr1212_dirs[i])
-                       continue;
-               for (dentry =
-                    fi->csr1212_dirs[i]->value.directory.dentries_head; dentry;
-                    dentry = dentry->next) {
-                       csr1212_detach_keyval_from_directory(fi->host->csr.rom->
-                                                            root_kv,
-                                                            dentry->kv);
-               }
-               csr1212_release_keyval(fi->csr1212_dirs[i]);
-               fi->csr1212_dirs[i] = NULL;
-               csr_mod = 1;
-       }
-
-       if ((csr_mod || fi->cfgrom_upd)
-           && hpsb_update_config_rom_image(fi->host) < 0)
-               HPSB_ERR
-                   ("Failed to generate Configuration ROM image for host %d",
-                    fi->host->id);
-
-       if (fi->state == connected) {
-               spin_lock_irqsave(&host_info_lock, flags);
-               list_del(&fi->list);
-               spin_unlock_irqrestore(&host_info_lock, flags);
-
-               put_device(&fi->host->device);
-       }
-
-       spin_lock_irqsave(&host_info_lock, flags);
-       if (fi->host)
-               module_put(fi->host->driver->owner);
-       spin_unlock_irqrestore(&host_info_lock, flags);
-
-       kfree(fi);
-
-       return 0;
-}
-
-/*** HOTPLUG STUFF **********************************************************/
-/*
- * Export information about protocols/devices supported by this driver.
- */
-#ifdef MODULE
-static const struct ieee1394_device_id raw1394_id_table[] = {
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = AVC_SW_VERSION_ENTRY & 0xffffff},
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = CAMERA_SW_VERSION_ENTRY & 0xffffff},
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff},
-       {
-        .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff},
-       {}
-};
-
-MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
-#endif /* MODULE */
-
-static struct hpsb_protocol_driver raw1394_driver = {
-       .name = "raw1394",
-};
-
-/******************************************************************************/
-
-static struct hpsb_highlevel raw1394_highlevel = {
-       .name = RAW1394_DEVICE_NAME,
-       .add_host = add_host,
-       .remove_host = remove_host,
-       .host_reset = host_reset,
-       .fcp_request = fcp_request,
-};
-
-static struct cdev raw1394_cdev;
-static const struct file_operations raw1394_fops = {
-       .owner = THIS_MODULE,
-       .read = raw1394_read,
-       .write = raw1394_write,
-       .mmap = raw1394_mmap,
-       .unlocked_ioctl = raw1394_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = raw1394_compat_ioctl,
-#endif
-       .poll = raw1394_poll,
-       .open = raw1394_open,
-       .release = raw1394_release,
-       .llseek = no_llseek,
-};
-
-static int __init init_raw1394(void)
-{
-       int ret = 0;
-
-       hpsb_register_highlevel(&raw1394_highlevel);
-
-       if (IS_ERR
-           (device_create(hpsb_protocol_class, NULL,
-                          MKDEV(IEEE1394_MAJOR,
-                                IEEE1394_MINOR_BLOCK_RAW1394 * 16),
-                          NULL, RAW1394_DEVICE_NAME))) {
-               ret = -EFAULT;
-               goto out_unreg;
-       }
-
-       cdev_init(&raw1394_cdev, &raw1394_fops);
-       raw1394_cdev.owner = THIS_MODULE;
-       ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
-       if (ret) {
-               HPSB_ERR("raw1394 failed to register minor device block");
-               goto out_dev;
-       }
-
-       HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME);
-
-       ret = hpsb_register_protocol(&raw1394_driver);
-       if (ret) {
-               HPSB_ERR("raw1394: failed to register protocol");
-               cdev_del(&raw1394_cdev);
-               goto out_dev;
-       }
-
-       goto out;
-
-      out_dev:
-       device_destroy(hpsb_protocol_class,
-                      MKDEV(IEEE1394_MAJOR,
-                            IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-      out_unreg:
-       hpsb_unregister_highlevel(&raw1394_highlevel);
-      out:
-       return ret;
-}
-
-static void __exit cleanup_raw1394(void)
-{
-       device_destroy(hpsb_protocol_class,
-                      MKDEV(IEEE1394_MAJOR,
-                            IEEE1394_MINOR_BLOCK_RAW1394 * 16));
-       cdev_del(&raw1394_cdev);
-       hpsb_unregister_highlevel(&raw1394_highlevel);
-       hpsb_unregister_protocol(&raw1394_driver);
-}
-
-module_init(init_raw1394);
-module_exit(cleanup_raw1394);
-MODULE_LICENSE("GPL");
diff --git a/drivers/ieee1394/raw1394.h b/drivers/ieee1394/raw1394.h
deleted file mode 100644 (file)
index 963ac20..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-#ifndef IEEE1394_RAW1394_H
-#define IEEE1394_RAW1394_H
-
-/* header for the raw1394 API that is exported to user-space */
-
-#define RAW1394_KERNELAPI_VERSION 4
-
-/* state: opened */
-#define RAW1394_REQ_INITIALIZE    1
-
-/* state: initialized */
-#define RAW1394_REQ_LIST_CARDS    2
-#define RAW1394_REQ_SET_CARD      3
-
-/* state: connected */
-#define RAW1394_REQ_ASYNC_READ      100
-#define RAW1394_REQ_ASYNC_WRITE     101
-#define RAW1394_REQ_LOCK            102
-#define RAW1394_REQ_LOCK64          103
-#define RAW1394_REQ_ISO_SEND        104 /* removed ABI, now a no-op */
-#define RAW1394_REQ_ASYNC_SEND      105
-#define RAW1394_REQ_ASYNC_STREAM    106
-
-#define RAW1394_REQ_ISO_LISTEN      200 /* removed ABI, now a no-op */
-#define RAW1394_REQ_FCP_LISTEN      201
-#define RAW1394_REQ_RESET_BUS       202
-#define RAW1394_REQ_GET_ROM         203
-#define RAW1394_REQ_UPDATE_ROM      204
-#define RAW1394_REQ_ECHO            205
-#define RAW1394_REQ_MODIFY_ROM      206
-
-#define RAW1394_REQ_ARM_REGISTER    300
-#define RAW1394_REQ_ARM_UNREGISTER  301
-#define RAW1394_REQ_ARM_SET_BUF     302
-#define RAW1394_REQ_ARM_GET_BUF     303
-
-#define RAW1394_REQ_RESET_NOTIFY    400
-
-#define RAW1394_REQ_PHYPACKET       500
-
-/* kernel to user */
-#define RAW1394_REQ_BUS_RESET        10000
-#define RAW1394_REQ_ISO_RECEIVE      10001
-#define RAW1394_REQ_FCP_REQUEST      10002
-#define RAW1394_REQ_ARM              10003
-#define RAW1394_REQ_RAWISO_ACTIVITY  10004
-
-/* error codes */
-#define RAW1394_ERROR_NONE        0
-#define RAW1394_ERROR_COMPAT      (-1001)
-#define RAW1394_ERROR_STATE_ORDER (-1002)
-#define RAW1394_ERROR_GENERATION  (-1003)
-#define RAW1394_ERROR_INVALID_ARG (-1004)
-#define RAW1394_ERROR_MEMFAULT    (-1005)
-#define RAW1394_ERROR_ALREADY     (-1006)
-
-#define RAW1394_ERROR_EXCESSIVE   (-1020)
-#define RAW1394_ERROR_UNTIDY_LEN  (-1021)
-
-#define RAW1394_ERROR_SEND_ERROR  (-1100)
-#define RAW1394_ERROR_ABORTED     (-1101)
-#define RAW1394_ERROR_TIMEOUT     (-1102)
-
-/* arm_codes */
-#define ARM_READ   1
-#define ARM_WRITE  2
-#define ARM_LOCK   4
-
-#define RAW1394_LONG_RESET  0
-#define RAW1394_SHORT_RESET 1
-
-/* busresetnotify ... */
-#define RAW1394_NOTIFY_OFF 0
-#define RAW1394_NOTIFY_ON  1
-
-#include <asm/types.h>
-
-struct raw1394_request {
-        __u32 type;
-        __s32 error;
-        __u32 misc;
-
-        __u32 generation;
-        __u32 length;
-
-        __u64 address;
-
-        __u64 tag;
-
-        __u64 sendb;
-        __u64 recvb;
-};
-
-struct raw1394_khost_list {
-        __u32 nodes;
-        __u8 name[32];
-};
-
-typedef struct arm_request {
-        __u16           destination_nodeid;
-        __u16           source_nodeid;
-        __u64           destination_offset;
-        __u8            tlabel;
-        __u8            tcode;
-        __u8            extended_transaction_code;
-        __u32           generation;
-        __u16           buffer_length;
-        __u8            __user *buffer;
-} *arm_request_t;
-
-typedef struct arm_response {
-        __s32           response_code;
-        __u16           buffer_length;
-        __u8            __user *buffer;
-} *arm_response_t;
-
-typedef struct arm_request_response {
-        struct arm_request  __user *request;
-        struct arm_response __user *response;
-} *arm_request_response_t;
-
-/* rawiso API */
-#include "ieee1394-ioctl.h"
-
-/* per-packet metadata embedded in the ringbuffer */
-/* must be identical to hpsb_iso_packet_info in iso.h! */
-struct raw1394_iso_packet_info {
-       __u32 offset;
-       __u16 len;
-       __u16 cycle;   /* recv only */
-       __u8  channel; /* recv only */
-       __u8  tag;
-       __u8  sy;
-};
-
-/* argument for RAW1394_ISO_RECV/XMIT_PACKETS ioctls */
-struct raw1394_iso_packets {
-       __u32 n_packets;
-       struct raw1394_iso_packet_info __user *infos;
-};
-
-struct raw1394_iso_config {
-       /* size of packet data buffer, in bytes (will be rounded up to PAGE_SIZE) */
-       __u32 data_buf_size;
-
-       /* # of packets to buffer */
-       __u32 buf_packets;
-
-       /* iso channel (set to -1 for multi-channel recv) */
-       __s32 channel;
-
-       /* xmit only - iso transmission speed */
-       __u8 speed;
-
-       /* The mode of the dma when receiving iso data. Must be supported by chip */
-       __u8 dma_mode;
-
-       /* max. latency of buffer, in packets (-1 if you don't care) */
-       __s32 irq_interval;
-};
-
-/* argument to RAW1394_ISO_XMIT/RECV_INIT and RAW1394_ISO_GET_STATUS */
-struct raw1394_iso_status {
-       /* current settings */
-       struct raw1394_iso_config config;
-
-       /* number of packets waiting to be filled with data (ISO transmission)
-          or containing data received (ISO reception) */
-       __u32 n_packets;
-
-       /* approximate number of packets dropped due to overflow or
-          underflow of the packet buffer (a value of zero guarantees
-          that no packets have been dropped) */
-       __u32 overflows;
-
-       /* cycle number at which next packet will be transmitted;
-          -1 if not known */
-       __s16 xmit_cycle;
-};
-
-/* argument to RAW1394_IOC_GET_CYCLE_TIMER ioctl */
-struct raw1394_cycle_timer {
-       /* contents of Isochronous Cycle Timer register,
-          as in OHCI 1.1 clause 5.13 (also with non-OHCI hosts) */
-       __u32 cycle_timer;
-
-       /* local time in microseconds since Epoch,
-          simultaneously read with cycle timer */
-       __u64 local_time;
-};
-#endif /* IEEE1394_RAW1394_H */
diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
deleted file mode 100644 (file)
index d6e251a..0000000
+++ /dev/null
@@ -1,2138 +0,0 @@
-/*
- * sbp2.c - SBP-2 protocol driver for IEEE-1394
- *
- * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com)
- * jamesg@filanet.com (JSG)
- *
- * Copyright (C) 2003 Ben Collins <bcollins@debian.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.
- *
- * 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.
- */
-
-/*
- * Brief Description:
- *
- * This driver implements the Serial Bus Protocol 2 (SBP-2) over IEEE-1394
- * under Linux. The SBP-2 driver is implemented as an IEEE-1394 high-level
- * driver. It also registers as a SCSI lower-level driver in order to accept
- * SCSI commands for transport using SBP-2.
- *
- * You may access any attached SBP-2 (usually storage devices) as regular
- * SCSI devices. E.g. mount /dev/sda1, fdisk, mkfs, etc..
- *
- * See http://www.t10.org/drafts.htm#sbp2 for the final draft of the SBP-2
- * specification and for where to purchase the official standard.
- *
- * TODO:
- *   - look into possible improvements of the SCSI error handlers
- *   - handle Unit_Characteristics.mgt_ORB_timeout and .ORB_size
- *   - handle Logical_Unit_Number.ordered
- *   - handle src == 1 in status blocks
- *   - reimplement the DMA mapping in absence of physical DMA so that
- *     bus_to_virt is no longer required
- *   - debug the handling of absent physical DMA
- *   - replace CONFIG_IEEE1394_SBP2_PHYS_DMA by automatic detection
- *     (this is easy but depends on the previous two TODO items)
- *   - make the parameter serialize_io configurable per device
- *   - move all requests to fetch agent registers into non-atomic context,
- *     replace all usages of sbp2util_node_write_no_wait by true transactions
- * Grep for inline FIXME comments below.
- */
-
-#include <linux/blkdev.h>
-#include <linux/compiler.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/stat.h>
-#include <linux/string.h>
-#include <linux/stringify.h>
-#include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
-#include <linux/scatterlist.h>
-
-#include <asm/byteorder.h>
-#include <asm/errno.h>
-#include <asm/param.h>
-#include <asm/system.h>
-#include <asm/types.h>
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-#include <asm/io.h> /* for bus_to_virt */
-#endif
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_dbg.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-
-#include "csr1212.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_transactions.h"
-#include "ieee1394_types.h"
-#include "nodemgr.h"
-#include "sbp2.h"
-
-/*
- * Module load parameter definitions
- */
-
-/*
- * Change max_speed on module load if you have a bad IEEE-1394
- * controller that has trouble running 2KB packets at 400mb.
- *
- * NOTE: On certain OHCI parts I have seen short packets on async transmit
- * (probably due to PCI latency/throughput issues with the part). You can
- * bump down the speed if you are running into problems.
- */
-static int sbp2_max_speed = IEEE1394_SPEED_MAX;
-module_param_named(max_speed, sbp2_max_speed, int, 0644);
-MODULE_PARM_DESC(max_speed, "Limit data transfer speed (5 <= 3200, "
-                "4 <= 1600, 3 <= 800, 2 <= 400, 1 <= 200, 0 = 100 Mb/s)");
-
-/*
- * Set serialize_io to 0 or N to use dynamically appended lists of command ORBs.
- * This is and always has been buggy in multiple subtle ways. See above TODOs.
- */
-static int sbp2_serialize_io = 1;
-module_param_named(serialize_io, sbp2_serialize_io, bool, 0444);
-MODULE_PARM_DESC(serialize_io, "Serialize requests coming from SCSI drivers "
-                "(default = Y, faster but buggy = N)");
-
-/*
- * Adjust max_sectors if you'd like to influence how many sectors each SCSI
- * command can transfer at most. Please note that some older SBP-2 bridge
- * chips are broken for transfers greater or equal to 128KB, therefore
- * max_sectors used to be a safe 255 sectors for many years. We now have a
- * default of 0 here which means that we let the SCSI stack choose a limit.
- *
- * The SBP2_WORKAROUND_128K_MAX_TRANS flag, if set either in the workarounds
- * module parameter or in the sbp2_workarounds_table[], will override the
- * value of max_sectors. We should use sbp2_workarounds_table[] to cover any
- * bridge chip which becomes known to need the 255 sectors limit.
- */
-static int sbp2_max_sectors;
-module_param_named(max_sectors, sbp2_max_sectors, int, 0444);
-MODULE_PARM_DESC(max_sectors, "Change max sectors per I/O supported "
-                "(default = 0 = use SCSI stack's default)");
-
-/*
- * Exclusive login to sbp2 device? In most cases, the sbp2 driver should
- * do an exclusive login, as it's generally unsafe to have two hosts
- * talking to a single sbp2 device at the same time (filesystem coherency,
- * etc.). If you're running an sbp2 device that supports multiple logins,
- * and you're either running read-only filesystems or some sort of special
- * filesystem supporting multiple hosts, e.g. OpenGFS, Oracle Cluster
- * File System, or Lustre, then set exclusive_login to zero.
- *
- * So far only bridges from Oxford Semiconductor are known to support
- * concurrent logins. Depending on firmware, four or two concurrent logins
- * are possible on OXFW911 and newer Oxsemi bridges.
- */
-static int sbp2_exclusive_login = 1;
-module_param_named(exclusive_login, sbp2_exclusive_login, bool, 0644);
-MODULE_PARM_DESC(exclusive_login, "Exclusive login to sbp2 device "
-                "(default = Y, use N for concurrent initiators)");
-
-/*
- * If any of the following workarounds is required for your device to work,
- * please submit the kernel messages logged by sbp2 to the linux1394-devel
- * mailing list.
- *
- * - 128kB max transfer
- *   Limit transfer size. Necessary for some old bridges.
- *
- * - 36 byte inquiry
- *   When scsi_mod probes the device, let the inquiry command look like that
- *   from MS Windows.
- *
- * - skip mode page 8
- *   Suppress sending of mode_sense for mode page 8 if the device pretends to
- *   support the SCSI Primary Block commands instead of Reduced Block Commands.
- *
- * - fix capacity
- *   Tell sd_mod to correct the last sector number reported by read_capacity.
- *   Avoids access beyond actual disk limits on devices with an off-by-one bug.
- *   Don't use this with devices which don't have this bug.
- *
- * - delay inquiry
- *   Wait extra SBP2_INQUIRY_DELAY seconds after login before SCSI inquiry.
- *
- * - power condition
- *   Set the power condition field in the START STOP UNIT commands sent by
- *   sd_mod on suspend, resume, and shutdown (if manage_start_stop is on).
- *   Some disks need this to spin down or to resume properly.
- *
- * - override internal blacklist
- *   Instead of adding to the built-in blacklist, use only the workarounds
- *   specified in the module load parameter.
- *   Useful if a blacklist entry interfered with a non-broken device.
- */
-static int sbp2_default_workarounds;
-module_param_named(workarounds, sbp2_default_workarounds, int, 0644);
-MODULE_PARM_DESC(workarounds, "Work around device bugs (default = 0"
-       ", 128kB max transfer = " __stringify(SBP2_WORKAROUND_128K_MAX_TRANS)
-       ", 36 byte inquiry = "    __stringify(SBP2_WORKAROUND_INQUIRY_36)
-       ", skip mode page 8 = "   __stringify(SBP2_WORKAROUND_MODE_SENSE_8)
-       ", fix capacity = "       __stringify(SBP2_WORKAROUND_FIX_CAPACITY)
-       ", delay inquiry = "      __stringify(SBP2_WORKAROUND_DELAY_INQUIRY)
-       ", set power condition in start stop unit = "
-                                 __stringify(SBP2_WORKAROUND_POWER_CONDITION)
-       ", override internal blacklist = " __stringify(SBP2_WORKAROUND_OVERRIDE)
-       ", or a combination)");
-
-/*
- * This influences the format of the sysfs attribute
- * /sys/bus/scsi/devices/.../ieee1394_id.
- *
- * The default format is like in older kernels:  %016Lx:%d:%d
- * It contains the target's EUI-64, a number given to the logical unit by
- * the ieee1394 driver's nodemgr (starting at 0), and the LUN.
- *
- * The long format is:  %016Lx:%06x:%04x
- * It contains the target's EUI-64, the unit directory's directory_ID as per
- * IEEE 1212 clause 7.7.19, and the LUN.  This format comes closest to the
- * format of SBP(-3) target port and logical unit identifier as per SAM (SCSI
- * Architecture Model) rev.2 to 4 annex A.  Therefore and because it is
- * independent of the implementation of the ieee1394 nodemgr, the longer format
- * is recommended for future use.
- */
-static int sbp2_long_sysfs_ieee1394_id;
-module_param_named(long_ieee1394_id, sbp2_long_sysfs_ieee1394_id, bool, 0644);
-MODULE_PARM_DESC(long_ieee1394_id, "8+3+2 bytes format of ieee1394_id in sysfs "
-                "(default = backwards-compatible = N, SAM-conforming = Y)");
-
-
-#define SBP2_INFO(fmt, args...)        HPSB_INFO("sbp2: "fmt, ## args)
-#define SBP2_ERR(fmt, args...) HPSB_ERR("sbp2: "fmt, ## args)
-
-/*
- * Globals
- */
-static void sbp2scsi_complete_all_commands(struct sbp2_lu *, u32);
-static void sbp2scsi_complete_command(struct sbp2_lu *, u32, struct scsi_cmnd *,
-                                     void (*)(struct scsi_cmnd *));
-static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *);
-static int sbp2_start_device(struct sbp2_lu *);
-static void sbp2_remove_device(struct sbp2_lu *);
-static int sbp2_login_device(struct sbp2_lu *);
-static int sbp2_reconnect_device(struct sbp2_lu *);
-static int sbp2_logout_device(struct sbp2_lu *);
-static void sbp2_host_reset(struct hpsb_host *);
-static int sbp2_handle_status_write(struct hpsb_host *, int, int, quadlet_t *,
-                                   u64, size_t, u16);
-static int sbp2_agent_reset(struct sbp2_lu *, int);
-static void sbp2_parse_unit_directory(struct sbp2_lu *,
-                                     struct unit_directory *);
-static int sbp2_set_busy_timeout(struct sbp2_lu *);
-static int sbp2_max_speed_and_size(struct sbp2_lu *);
-
-
-static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xa, 0xa, 0xa };
-
-static DEFINE_RWLOCK(sbp2_hi_logical_units_lock);
-
-static struct hpsb_highlevel sbp2_highlevel = {
-       .name           = SBP2_DEVICE_NAME,
-       .host_reset     = sbp2_host_reset,
-};
-
-static const struct hpsb_address_ops sbp2_ops = {
-       .write          = sbp2_handle_status_write
-};
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-static int sbp2_handle_physdma_write(struct hpsb_host *, int, int, quadlet_t *,
-                                    u64, size_t, u16);
-static int sbp2_handle_physdma_read(struct hpsb_host *, int, quadlet_t *, u64,
-                                   size_t, u16);
-
-static const struct hpsb_address_ops sbp2_physdma_ops = {
-       .read           = sbp2_handle_physdma_read,
-       .write          = sbp2_handle_physdma_write,
-};
-#endif
-
-
-/*
- * Interface to driver core and IEEE 1394 core
- */
-static const struct ieee1394_device_id sbp2_id_table[] = {
-       {
-        .match_flags   = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-        .specifier_id  = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff,
-        .version       = SBP2_SW_VERSION_ENTRY & 0xffffff},
-       {}
-};
-MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table);
-
-static int sbp2_probe(struct device *);
-static int sbp2_remove(struct device *);
-static int sbp2_update(struct unit_directory *);
-
-static struct hpsb_protocol_driver sbp2_driver = {
-       .name           = SBP2_DEVICE_NAME,
-       .id_table       = sbp2_id_table,
-       .update         = sbp2_update,
-       .driver         = {
-               .probe          = sbp2_probe,
-               .remove         = sbp2_remove,
-       },
-};
-
-
-/*
- * Interface to SCSI core
- */
-static int sbp2scsi_queuecommand(struct scsi_cmnd *,
-                                void (*)(struct scsi_cmnd *));
-static int sbp2scsi_abort(struct scsi_cmnd *);
-static int sbp2scsi_reset(struct scsi_cmnd *);
-static int sbp2scsi_slave_alloc(struct scsi_device *);
-static int sbp2scsi_slave_configure(struct scsi_device *);
-static void sbp2scsi_slave_destroy(struct scsi_device *);
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *,
-                                          struct device_attribute *, char *);
-
-static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
-
-static struct device_attribute *sbp2_sysfs_sdev_attrs[] = {
-       &dev_attr_ieee1394_id,
-       NULL
-};
-
-static struct scsi_host_template sbp2_shost_template = {
-       .module                  = THIS_MODULE,
-       .name                    = "SBP-2 IEEE-1394",
-       .proc_name               = SBP2_DEVICE_NAME,
-       .queuecommand            = sbp2scsi_queuecommand,
-       .eh_abort_handler        = sbp2scsi_abort,
-       .eh_device_reset_handler = sbp2scsi_reset,
-       .slave_alloc             = sbp2scsi_slave_alloc,
-       .slave_configure         = sbp2scsi_slave_configure,
-       .slave_destroy           = sbp2scsi_slave_destroy,
-       .this_id                 = -1,
-       .sg_tablesize            = SG_ALL,
-       .use_clustering          = ENABLE_CLUSTERING,
-       .cmd_per_lun             = SBP2_MAX_CMDS,
-       .can_queue               = SBP2_MAX_CMDS,
-       .sdev_attrs              = sbp2_sysfs_sdev_attrs,
-};
-
-#define SBP2_ROM_VALUE_WILDCARD ~0         /* match all */
-#define SBP2_ROM_VALUE_MISSING  0xff000000 /* not present in the unit dir. */
-
-/*
- * List of devices with known bugs.
- *
- * The firmware_revision field, masked with 0xffff00, is the best indicator
- * for the type of bridge chip of a device.  It yields a few false positives
- * but this did not break correctly behaving devices so far.
- */
-static const struct {
-       u32 firmware_revision;
-       u32 model;
-       unsigned workarounds;
-} sbp2_workarounds_table[] = {
-       /* DViCO Momobay CX-1 with TSB42AA9 bridge */ {
-               .firmware_revision      = 0x002800,
-               .model                  = 0x001010,
-               .workarounds            = SBP2_WORKAROUND_INQUIRY_36 |
-                                         SBP2_WORKAROUND_MODE_SENSE_8 |
-                                         SBP2_WORKAROUND_POWER_CONDITION,
-       },
-       /* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
-               .firmware_revision      = 0x002800,
-               .model                  = 0x000000,
-               .workarounds            = SBP2_WORKAROUND_POWER_CONDITION,
-       },
-       /* Initio bridges, actually only needed for some older ones */ {
-               .firmware_revision      = 0x000200,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_INQUIRY_36,
-       },
-       /* PL-3507 bridge with Prolific firmware */ {
-               .firmware_revision      = 0x012800,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_POWER_CONDITION,
-       },
-       /* Symbios bridge */ {
-               .firmware_revision      = 0xa0b800,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS,
-       },
-       /* Datafab MD2-FW2 with Symbios/LSILogic SYM13FW500 bridge */ {
-               .firmware_revision      = 0x002600,
-               .model                  = SBP2_ROM_VALUE_WILDCARD,
-               .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS,
-       },
-       /*
-        * iPod 2nd generation: needs 128k max transfer size workaround
-        * iPod 3rd generation: needs fix capacity workaround
-        */
-       {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000000,
-               .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS |
-                                         SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod 4th generation */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000021,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod mini */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000022,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod mini */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x000023,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       },
-       /* iPod Photo */ {
-               .firmware_revision      = 0x0a2700,
-               .model                  = 0x00007e,
-               .workarounds            = SBP2_WORKAROUND_FIX_CAPACITY,
-       }
-};
-
-/**************************************
- * General utility functions
- **************************************/
-
-#ifndef __BIG_ENDIAN
-/*
- * Converts a buffer from be32 to cpu byte ordering. Length is in bytes.
- */
-static inline void sbp2util_be32_to_cpu_buffer(void *buffer, int length)
-{
-       u32 *temp = buffer;
-
-       for (length = (length >> 2); length--; )
-               temp[length] = be32_to_cpu(temp[length]);
-}
-
-/*
- * Converts a buffer from cpu to be32 byte ordering. Length is in bytes.
- */
-static inline void sbp2util_cpu_to_be32_buffer(void *buffer, int length)
-{
-       u32 *temp = buffer;
-
-       for (length = (length >> 2); length--; )
-               temp[length] = cpu_to_be32(temp[length]);
-}
-#else /* BIG_ENDIAN */
-/* Why waste the cpu cycles? */
-#define sbp2util_be32_to_cpu_buffer(x,y) do {} while (0)
-#define sbp2util_cpu_to_be32_buffer(x,y) do {} while (0)
-#endif
-
-static DECLARE_WAIT_QUEUE_HEAD(sbp2_access_wq);
-
-/*
- * Waits for completion of an SBP-2 access request.
- * Returns nonzero if timed out or prematurely interrupted.
- */
-static int sbp2util_access_timeout(struct sbp2_lu *lu, int timeout)
-{
-       long leftover;
-
-       leftover = wait_event_interruptible_timeout(
-                       sbp2_access_wq, lu->access_complete, timeout);
-       lu->access_complete = 0;
-       return leftover <= 0;
-}
-
-static void sbp2_free_packet(void *packet)
-{
-       hpsb_free_tlabel(packet);
-       hpsb_free_packet(packet);
-}
-
-/*
- * This is much like hpsb_node_write(), except it ignores the response
- * subaction and returns immediately. Can be used from atomic context.
- */
-static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
-                                      quadlet_t *buf, size_t len)
-{
-       struct hpsb_packet *packet;
-
-       packet = hpsb_make_writepacket(ne->host, ne->nodeid, addr, buf, len);
-       if (!packet)
-               return -ENOMEM;
-
-       hpsb_set_packet_complete_task(packet, sbp2_free_packet, packet);
-       hpsb_node_fill_packet(ne, packet);
-       if (hpsb_send_packet(packet) < 0) {
-               sbp2_free_packet(packet);
-               return -EIO;
-       }
-       return 0;
-}
-
-static void sbp2util_notify_fetch_agent(struct sbp2_lu *lu, u64 offset,
-                                       quadlet_t *data, size_t len)
-{
-       /* There is a small window after a bus reset within which the node
-        * entry's generation is current but the reconnect wasn't completed. */
-       if (unlikely(atomic_read(&lu->state) == SBP2LU_STATE_IN_RESET))
-               return;
-
-       if (hpsb_node_write(lu->ne, lu->command_block_agent_addr + offset,
-                           data, len))
-               SBP2_ERR("sbp2util_notify_fetch_agent failed.");
-
-       /* Now accept new SCSI commands, unless a bus reset happended during
-        * hpsb_node_write. */
-       if (likely(atomic_read(&lu->state) != SBP2LU_STATE_IN_RESET))
-               scsi_unblock_requests(lu->shost);
-}
-
-static void sbp2util_write_orb_pointer(struct work_struct *work)
-{
-       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
-       quadlet_t data[2];
-
-       data[0] = ORB_SET_NODE_ID(lu->hi->host->node_id);
-       data[1] = lu->last_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-       sbp2util_notify_fetch_agent(lu, SBP2_ORB_POINTER_OFFSET, data, 8);
-}
-
-static void sbp2util_write_doorbell(struct work_struct *work)
-{
-       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
-
-       sbp2util_notify_fetch_agent(lu, SBP2_DOORBELL_OFFSET, NULL, 4);
-}
-
-static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
-{
-       struct sbp2_command_info *cmd;
-       struct device *dmadev = lu->hi->host->device.parent;
-       int i, orbs = sbp2_serialize_io ? 2 : SBP2_MAX_CMDS;
-
-       for (i = 0; i < orbs; i++) {
-               cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-               if (!cmd)
-                       goto failed_alloc;
-
-               cmd->command_orb_dma =
-                   dma_map_single(dmadev, &cmd->command_orb,
-                                  sizeof(struct sbp2_command_orb),
-                                  DMA_TO_DEVICE);
-               if (dma_mapping_error(dmadev, cmd->command_orb_dma))
-                       goto failed_orb;
-
-               cmd->sge_dma =
-                   dma_map_single(dmadev, &cmd->scatter_gather_element,
-                                  sizeof(cmd->scatter_gather_element),
-                                  DMA_TO_DEVICE);
-               if (dma_mapping_error(dmadev, cmd->sge_dma))
-                       goto failed_sge;
-
-               INIT_LIST_HEAD(&cmd->list);
-               list_add_tail(&cmd->list, &lu->cmd_orb_completed);
-       }
-       return 0;
-
-failed_sge:
-       dma_unmap_single(dmadev, cmd->command_orb_dma,
-                        sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
-failed_orb:
-       kfree(cmd);
-failed_alloc:
-       return -ENOMEM;
-}
-
-static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu,
-                                            struct hpsb_host *host)
-{
-       struct list_head *lh, *next;
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       if (!list_empty(&lu->cmd_orb_completed))
-               list_for_each_safe(lh, next, &lu->cmd_orb_completed) {
-                       cmd = list_entry(lh, struct sbp2_command_info, list);
-                       dma_unmap_single(host->device.parent,
-                                        cmd->command_orb_dma,
-                                        sizeof(struct sbp2_command_orb),
-                                        DMA_TO_DEVICE);
-                       dma_unmap_single(host->device.parent, cmd->sge_dma,
-                                        sizeof(cmd->scatter_gather_element),
-                                        DMA_TO_DEVICE);
-                       kfree(cmd);
-               }
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-       return;
-}
-
-/*
- * Finds the sbp2_command for a given outstanding command ORB.
- * Only looks at the in-use list.
- */
-static struct sbp2_command_info *sbp2util_find_command_for_orb(
-                               struct sbp2_lu *lu, dma_addr_t orb)
-{
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       if (!list_empty(&lu->cmd_orb_inuse))
-               list_for_each_entry(cmd, &lu->cmd_orb_inuse, list)
-                       if (cmd->command_orb_dma == orb) {
-                               spin_unlock_irqrestore(
-                                               &lu->cmd_orb_lock, flags);
-                               return cmd;
-                       }
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-       return NULL;
-}
-
-/*
- * Finds the sbp2_command for a given outstanding SCpnt.
- * Only looks at the in-use list.
- * Must be called with lu->cmd_orb_lock held.
- */
-static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(
-                               struct sbp2_lu *lu, void *SCpnt)
-{
-       struct sbp2_command_info *cmd;
-
-       if (!list_empty(&lu->cmd_orb_inuse))
-               list_for_each_entry(cmd, &lu->cmd_orb_inuse, list)
-                       if (cmd->Current_SCpnt == SCpnt)
-                               return cmd;
-       return NULL;
-}
-
-static struct sbp2_command_info *sbp2util_allocate_command_orb(
-                               struct sbp2_lu *lu,
-                               struct scsi_cmnd *Current_SCpnt,
-                               void (*Current_done)(struct scsi_cmnd *))
-{
-       struct list_head *lh;
-       struct sbp2_command_info *cmd = NULL;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       if (!list_empty(&lu->cmd_orb_completed)) {
-               lh = lu->cmd_orb_completed.next;
-               list_del(lh);
-               cmd = list_entry(lh, struct sbp2_command_info, list);
-               cmd->Current_done = Current_done;
-               cmd->Current_SCpnt = Current_SCpnt;
-               list_add_tail(&cmd->list, &lu->cmd_orb_inuse);
-       } else
-               SBP2_ERR("%s: no orbs available", __func__);
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-       return cmd;
-}
-
-/*
- * Unmaps the DMAs of a command and moves the command to the completed ORB list.
- * Must be called with lu->cmd_orb_lock held.
- */
-static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
-                                           struct sbp2_command_info *cmd)
-{
-       if (scsi_sg_count(cmd->Current_SCpnt))
-               dma_unmap_sg(lu->ud->ne->host->device.parent,
-                            scsi_sglist(cmd->Current_SCpnt),
-                            scsi_sg_count(cmd->Current_SCpnt),
-                            cmd->Current_SCpnt->sc_data_direction);
-       list_move_tail(&cmd->list, &lu->cmd_orb_completed);
-}
-
-/*
- * Is lu valid? Is the 1394 node still present?
- */
-static inline int sbp2util_node_is_available(struct sbp2_lu *lu)
-{
-       return lu && lu->ne && !lu->ne->in_limbo;
-}
-
-/*********************************************
- * IEEE-1394 core driver stack related section
- *********************************************/
-
-static int sbp2_probe(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct sbp2_lu *lu;
-
-       ud = container_of(dev, struct unit_directory, device);
-
-       /* Don't probe UD's that have the LUN flag. We'll probe the LUN(s)
-        * instead. */
-       if (ud->flags & UNIT_DIRECTORY_HAS_LUN_DIRECTORY)
-               return -ENODEV;
-
-       lu = sbp2_alloc_device(ud);
-       if (!lu)
-               return -ENOMEM;
-
-       sbp2_parse_unit_directory(lu, ud);
-       return sbp2_start_device(lu);
-}
-
-static int sbp2_remove(struct device *dev)
-{
-       struct unit_directory *ud;
-       struct sbp2_lu *lu;
-       struct scsi_device *sdev;
-
-       ud = container_of(dev, struct unit_directory, device);
-       lu = dev_get_drvdata(&ud->device);
-       if (!lu)
-               return 0;
-
-       if (lu->shost) {
-               /* Get rid of enqueued commands if there is no chance to
-                * send them. */
-               if (!sbp2util_node_is_available(lu))
-                       sbp2scsi_complete_all_commands(lu, DID_NO_CONNECT);
-               /* scsi_remove_device() may trigger shutdown functions of SCSI
-                * highlevel drivers which would deadlock if blocked. */
-               atomic_set(&lu->state, SBP2LU_STATE_IN_SHUTDOWN);
-               scsi_unblock_requests(lu->shost);
-       }
-       sdev = lu->sdev;
-       if (sdev) {
-               lu->sdev = NULL;
-               scsi_remove_device(sdev);
-       }
-
-       sbp2_logout_device(lu);
-       sbp2_remove_device(lu);
-
-       return 0;
-}
-
-static int sbp2_update(struct unit_directory *ud)
-{
-       struct sbp2_lu *lu = dev_get_drvdata(&ud->device);
-
-       if (sbp2_reconnect_device(lu) != 0) {
-               /*
-                * Reconnect failed.  If another bus reset happened,
-                * let nodemgr proceed and call sbp2_update again later
-                * (or sbp2_remove if this node went away).
-                */
-               if (!hpsb_node_entry_valid(lu->ne))
-                       return 0;
-               /*
-                * Or the target rejected the reconnect because we weren't
-                * fast enough.  Try a regular login, but first log out
-                * just in case of any weirdness.
-                */
-               sbp2_logout_device(lu);
-
-               if (sbp2_login_device(lu) != 0) {
-                       if (!hpsb_node_entry_valid(lu->ne))
-                               return 0;
-
-                       /* Maybe another initiator won the login. */
-                       SBP2_ERR("Failed to reconnect to sbp2 device!");
-                       return -EBUSY;
-               }
-       }
-
-       sbp2_set_busy_timeout(lu);
-       sbp2_agent_reset(lu, 1);
-       sbp2_max_speed_and_size(lu);
-
-       /* Complete any pending commands with busy (so they get retried)
-        * and remove them from our queue. */
-       sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY);
-
-       /* Accept new commands unless there was another bus reset in the
-        * meantime. */
-       if (hpsb_node_entry_valid(lu->ne)) {
-               atomic_set(&lu->state, SBP2LU_STATE_RUNNING);
-               scsi_unblock_requests(lu->shost);
-       }
-       return 0;
-}
-
-static struct sbp2_lu *sbp2_alloc_device(struct unit_directory *ud)
-{
-       struct sbp2_fwhost_info *hi;
-       struct Scsi_Host *shost = NULL;
-       struct sbp2_lu *lu = NULL;
-       unsigned long flags;
-
-       lu = kzalloc(sizeof(*lu), GFP_KERNEL);
-       if (!lu) {
-               SBP2_ERR("failed to create lu");
-               goto failed_alloc;
-       }
-
-       lu->ne = ud->ne;
-       lu->ud = ud;
-       lu->speed_code = IEEE1394_SPEED_100;
-       lu->max_payload_size = sbp2_speedto_max_payload[IEEE1394_SPEED_100];
-       lu->status_fifo_addr = CSR1212_INVALID_ADDR_SPACE;
-       INIT_LIST_HEAD(&lu->cmd_orb_inuse);
-       INIT_LIST_HEAD(&lu->cmd_orb_completed);
-       INIT_LIST_HEAD(&lu->lu_list);
-       spin_lock_init(&lu->cmd_orb_lock);
-       atomic_set(&lu->state, SBP2LU_STATE_RUNNING);
-       INIT_WORK(&lu->protocol_work, NULL);
-
-       dev_set_drvdata(&ud->device, lu);
-
-       hi = hpsb_get_hostinfo(&sbp2_highlevel, ud->ne->host);
-       if (!hi) {
-               hi = hpsb_create_hostinfo(&sbp2_highlevel, ud->ne->host,
-                                         sizeof(*hi));
-               if (!hi) {
-                       SBP2_ERR("failed to allocate hostinfo");
-                       goto failed_alloc;
-               }
-               hi->host = ud->ne->host;
-               INIT_LIST_HEAD(&hi->logical_units);
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-               /* Handle data movement if physical dma is not
-                * enabled or not supported on host controller */
-               if (!hpsb_register_addrspace(&sbp2_highlevel, ud->ne->host,
-                                            &sbp2_physdma_ops,
-                                            0x0ULL, 0xfffffffcULL)) {
-                       SBP2_ERR("failed to register lower 4GB address range");
-                       goto failed_alloc;
-               }
-#endif
-       }
-
-       if (dma_get_max_seg_size(hi->host->device.parent) > SBP2_MAX_SEG_SIZE)
-               BUG_ON(dma_set_max_seg_size(hi->host->device.parent,
-                                           SBP2_MAX_SEG_SIZE));
-
-       /* Prevent unloading of the 1394 host */
-       if (!try_module_get(hi->host->driver->owner)) {
-               SBP2_ERR("failed to get a reference on 1394 host driver");
-               goto failed_alloc;
-       }
-
-       lu->hi = hi;
-
-       write_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-       list_add_tail(&lu->lu_list, &hi->logical_units);
-       write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-
-       /* Register the status FIFO address range. We could use the same FIFO
-        * for targets at different nodes. However we need different FIFOs per
-        * target in order to support multi-unit devices.
-        * The FIFO is located out of the local host controller's physical range
-        * but, if possible, within the posted write area. Status writes will
-        * then be performed as unified transactions. This slightly reduces
-        * bandwidth usage, and some Prolific based devices seem to require it.
-        */
-       lu->status_fifo_addr = hpsb_allocate_and_register_addrspace(
-                       &sbp2_highlevel, ud->ne->host, &sbp2_ops,
-                       sizeof(struct sbp2_status_block), sizeof(quadlet_t),
-                       ud->ne->host->low_addr_space, CSR1212_ALL_SPACE_END);
-       if (lu->status_fifo_addr == CSR1212_INVALID_ADDR_SPACE) {
-               SBP2_ERR("failed to allocate status FIFO address range");
-               goto failed_alloc;
-       }
-
-       shost = scsi_host_alloc(&sbp2_shost_template, sizeof(unsigned long));
-       if (!shost) {
-               SBP2_ERR("failed to register scsi host");
-               goto failed_alloc;
-       }
-
-       shost->hostdata[0] = (unsigned long)lu;
-       shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
-
-       if (!scsi_add_host(shost, &ud->device)) {
-               lu->shost = shost;
-               return lu;
-       }
-
-       SBP2_ERR("failed to add scsi host");
-       scsi_host_put(shost);
-
-failed_alloc:
-       sbp2_remove_device(lu);
-       return NULL;
-}
-
-static void sbp2_host_reset(struct hpsb_host *host)
-{
-       struct sbp2_fwhost_info *hi;
-       struct sbp2_lu *lu;
-       unsigned long flags;
-
-       hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-       if (!hi)
-               return;
-
-       read_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-
-       list_for_each_entry(lu, &hi->logical_units, lu_list)
-               if (atomic_cmpxchg(&lu->state,
-                                  SBP2LU_STATE_RUNNING, SBP2LU_STATE_IN_RESET)
-                   == SBP2LU_STATE_RUNNING)
-                       scsi_block_requests(lu->shost);
-
-       read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-}
-
-static int sbp2_start_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       int error;
-
-       lu->login_response = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_login_response),
-                                    &lu->login_response_dma, GFP_KERNEL);
-       if (!lu->login_response)
-               goto alloc_fail;
-
-       lu->query_logins_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_query_logins_orb),
-                                    &lu->query_logins_orb_dma, GFP_KERNEL);
-       if (!lu->query_logins_orb)
-               goto alloc_fail;
-
-       lu->query_logins_response = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_query_logins_response),
-                                    &lu->query_logins_response_dma, GFP_KERNEL);
-       if (!lu->query_logins_response)
-               goto alloc_fail;
-
-       lu->reconnect_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_reconnect_orb),
-                                    &lu->reconnect_orb_dma, GFP_KERNEL);
-       if (!lu->reconnect_orb)
-               goto alloc_fail;
-
-       lu->logout_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_logout_orb),
-                                    &lu->logout_orb_dma, GFP_KERNEL);
-       if (!lu->logout_orb)
-               goto alloc_fail;
-
-       lu->login_orb = dma_alloc_coherent(hi->host->device.parent,
-                                    sizeof(struct sbp2_login_orb),
-                                    &lu->login_orb_dma, GFP_KERNEL);
-       if (!lu->login_orb)
-               goto alloc_fail;
-
-       if (sbp2util_create_command_orb_pool(lu))
-               goto alloc_fail;
-
-       /* Wait a second before trying to log in. Previously logged in
-        * initiators need a chance to reconnect. */
-       if (msleep_interruptible(1000)) {
-               sbp2_remove_device(lu);
-               return -EINTR;
-       }
-
-       if (sbp2_login_device(lu)) {
-               sbp2_remove_device(lu);
-               return -EBUSY;
-       }
-
-       sbp2_set_busy_timeout(lu);
-       sbp2_agent_reset(lu, 1);
-       sbp2_max_speed_and_size(lu);
-
-       if (lu->workarounds & SBP2_WORKAROUND_DELAY_INQUIRY)
-               ssleep(SBP2_INQUIRY_DELAY);
-
-       error = scsi_add_device(lu->shost, 0, lu->ud->id, 0);
-       if (error) {
-               SBP2_ERR("scsi_add_device failed");
-               sbp2_logout_device(lu);
-               sbp2_remove_device(lu);
-               return error;
-       }
-
-       return 0;
-
-alloc_fail:
-       SBP2_ERR("Could not allocate memory for lu");
-       sbp2_remove_device(lu);
-       return -ENOMEM;
-}
-
-static void sbp2_remove_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi;
-       unsigned long flags;
-
-       if (!lu)
-               return;
-       hi = lu->hi;
-       if (!hi)
-               goto no_hi;
-
-       if (lu->shost) {
-               scsi_remove_host(lu->shost);
-               scsi_host_put(lu->shost);
-       }
-       flush_scheduled_work();
-       sbp2util_remove_command_orb_pool(lu, hi->host);
-
-       write_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-       list_del(&lu->lu_list);
-       write_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-
-       if (lu->login_response)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_login_response),
-                                   lu->login_response,
-                                   lu->login_response_dma);
-       if (lu->login_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_login_orb),
-                                   lu->login_orb,
-                                   lu->login_orb_dma);
-       if (lu->reconnect_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_reconnect_orb),
-                                   lu->reconnect_orb,
-                                   lu->reconnect_orb_dma);
-       if (lu->logout_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_logout_orb),
-                                   lu->logout_orb,
-                                   lu->logout_orb_dma);
-       if (lu->query_logins_orb)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_query_logins_orb),
-                                   lu->query_logins_orb,
-                                   lu->query_logins_orb_dma);
-       if (lu->query_logins_response)
-               dma_free_coherent(hi->host->device.parent,
-                                   sizeof(struct sbp2_query_logins_response),
-                                   lu->query_logins_response,
-                                   lu->query_logins_response_dma);
-
-       if (lu->status_fifo_addr != CSR1212_INVALID_ADDR_SPACE)
-               hpsb_unregister_addrspace(&sbp2_highlevel, hi->host,
-                                         lu->status_fifo_addr);
-
-       dev_set_drvdata(&lu->ud->device, NULL);
-
-       module_put(hi->host->driver->owner);
-no_hi:
-       kfree(lu);
-}
-
-#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
-/*
- * Deal with write requests on adapters which do not support physical DMA or
- * have it switched off.
- */
-static int sbp2_handle_physdma_write(struct hpsb_host *host, int nodeid,
-                                    int destid, quadlet_t *data, u64 addr,
-                                    size_t length, u16 flags)
-{
-       memcpy(bus_to_virt((u32) addr), data, length);
-       return RCODE_COMPLETE;
-}
-
-/*
- * Deal with read requests on adapters which do not support physical DMA or
- * have it switched off.
- */
-static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid,
-                                   quadlet_t *data, u64 addr, size_t length,
-                                   u16 flags)
-{
-       memcpy(data, bus_to_virt((u32) addr), length);
-       return RCODE_COMPLETE;
-}
-#endif
-
-/**************************************
- * SBP-2 protocol related section
- **************************************/
-
-static int sbp2_query_logins(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-       int max_logins;
-       int active_logins;
-
-       lu->query_logins_orb->reserved1 = 0x0;
-       lu->query_logins_orb->reserved2 = 0x0;
-
-       lu->query_logins_orb->query_response_lo = lu->query_logins_response_dma;
-       lu->query_logins_orb->query_response_hi =
-                       ORB_SET_NODE_ID(hi->host->node_id);
-       lu->query_logins_orb->lun_misc =
-                       ORB_SET_FUNCTION(SBP2_QUERY_LOGINS_REQUEST);
-       lu->query_logins_orb->lun_misc |= ORB_SET_NOTIFY(1);
-       lu->query_logins_orb->lun_misc |= ORB_SET_LUN(lu->lun);
-
-       lu->query_logins_orb->reserved_resp_length =
-               ORB_SET_QUERY_LOGINS_RESP_LENGTH(
-                       sizeof(struct sbp2_query_logins_response));
-
-       lu->query_logins_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->query_logins_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->query_logins_orb,
-                                   sizeof(struct sbp2_query_logins_orb));
-
-       memset(lu->query_logins_response, 0,
-              sizeof(struct sbp2_query_logins_response));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->query_logins_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-
-       if (sbp2util_access_timeout(lu, 2*HZ)) {
-               SBP2_INFO("Error querying logins to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (lu->status_block.ORB_offset_lo != lu->query_logins_orb_dma) {
-               SBP2_INFO("Error querying logins to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
-               SBP2_INFO("Error querying logins to SBP-2 device - failed");
-               return -EIO;
-       }
-
-       sbp2util_cpu_to_be32_buffer(lu->query_logins_response,
-                                   sizeof(struct sbp2_query_logins_response));
-
-       max_logins = RESPONSE_GET_MAX_LOGINS(
-                       lu->query_logins_response->length_max_logins);
-       SBP2_INFO("Maximum concurrent logins supported: %d", max_logins);
-
-       active_logins = RESPONSE_GET_ACTIVE_LOGINS(
-                       lu->query_logins_response->length_max_logins);
-       SBP2_INFO("Number of active logins: %d", active_logins);
-
-       if (active_logins >= max_logins) {
-               return -EIO;
-       }
-
-       return 0;
-}
-
-static int sbp2_login_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-
-       if (!lu->login_orb)
-               return -EIO;
-
-       if (!sbp2_exclusive_login && sbp2_query_logins(lu)) {
-               SBP2_INFO("Device does not support any more concurrent logins");
-               return -EIO;
-       }
-
-       /* assume no password */
-       lu->login_orb->password_hi = 0;
-       lu->login_orb->password_lo = 0;
-
-       lu->login_orb->login_response_lo = lu->login_response_dma;
-       lu->login_orb->login_response_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       lu->login_orb->lun_misc = ORB_SET_FUNCTION(SBP2_LOGIN_REQUEST);
-
-       /* one second reconnect time */
-       lu->login_orb->lun_misc |= ORB_SET_RECONNECT(0);
-       lu->login_orb->lun_misc |= ORB_SET_EXCLUSIVE(sbp2_exclusive_login);
-       lu->login_orb->lun_misc |= ORB_SET_NOTIFY(1);
-       lu->login_orb->lun_misc |= ORB_SET_LUN(lu->lun);
-
-       lu->login_orb->passwd_resp_lengths =
-               ORB_SET_LOGIN_RESP_LENGTH(sizeof(struct sbp2_login_response));
-
-       lu->login_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->login_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->login_orb,
-                                   sizeof(struct sbp2_login_orb));
-
-       memset(lu->login_response, 0, sizeof(struct sbp2_login_response));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->login_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-
-       /* wait up to 20 seconds for login status */
-       if (sbp2util_access_timeout(lu, 20*HZ)) {
-               SBP2_ERR("Error logging into SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       /* make sure that the returned status matches the login ORB */
-       if (lu->status_block.ORB_offset_lo != lu->login_orb_dma) {
-               SBP2_ERR("Error logging into SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
-               SBP2_ERR("Error logging into SBP-2 device - failed");
-               return -EIO;
-       }
-
-       sbp2util_cpu_to_be32_buffer(lu->login_response,
-                                   sizeof(struct sbp2_login_response));
-       lu->command_block_agent_addr =
-                       ((u64)lu->login_response->command_block_agent_hi) << 32;
-       lu->command_block_agent_addr |=
-                       ((u64)lu->login_response->command_block_agent_lo);
-       lu->command_block_agent_addr &= 0x0000ffffffffffffULL;
-
-       SBP2_INFO("Logged into SBP-2 device");
-       return 0;
-}
-
-static int sbp2_logout_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-       int error;
-
-       lu->logout_orb->reserved1 = 0x0;
-       lu->logout_orb->reserved2 = 0x0;
-       lu->logout_orb->reserved3 = 0x0;
-       lu->logout_orb->reserved4 = 0x0;
-
-       lu->logout_orb->login_ID_misc = ORB_SET_FUNCTION(SBP2_LOGOUT_REQUEST);
-       lu->logout_orb->login_ID_misc |=
-                       ORB_SET_LOGIN_ID(lu->login_response->length_login_ID);
-       lu->logout_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
-
-       lu->logout_orb->reserved5 = 0x0;
-       lu->logout_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->logout_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->logout_orb,
-                                   sizeof(struct sbp2_logout_orb));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->logout_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-       if (error)
-               return error;
-
-       /* wait up to 1 second for the device to complete logout */
-       if (sbp2util_access_timeout(lu, HZ))
-               return -EIO;
-
-       SBP2_INFO("Logged out of SBP-2 device");
-       return 0;
-}
-
-static int sbp2_reconnect_device(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       quadlet_t data[2];
-       int error;
-
-       lu->reconnect_orb->reserved1 = 0x0;
-       lu->reconnect_orb->reserved2 = 0x0;
-       lu->reconnect_orb->reserved3 = 0x0;
-       lu->reconnect_orb->reserved4 = 0x0;
-
-       lu->reconnect_orb->login_ID_misc =
-                       ORB_SET_FUNCTION(SBP2_RECONNECT_REQUEST);
-       lu->reconnect_orb->login_ID_misc |=
-                       ORB_SET_LOGIN_ID(lu->login_response->length_login_ID);
-       lu->reconnect_orb->login_ID_misc |= ORB_SET_NOTIFY(1);
-
-       lu->reconnect_orb->reserved5 = 0x0;
-       lu->reconnect_orb->status_fifo_hi =
-               ORB_SET_STATUS_FIFO_HI(lu->status_fifo_addr, hi->host->node_id);
-       lu->reconnect_orb->status_fifo_lo =
-               ORB_SET_STATUS_FIFO_LO(lu->status_fifo_addr);
-
-       sbp2util_cpu_to_be32_buffer(lu->reconnect_orb,
-                                   sizeof(struct sbp2_reconnect_orb));
-
-       data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-       data[1] = lu->reconnect_orb_dma;
-       sbp2util_cpu_to_be32_buffer(data, 8);
-
-       error = hpsb_node_write(lu->ne, lu->management_agent_addr, data, 8);
-       if (error)
-               return error;
-
-       /* wait up to 1 second for reconnect status */
-       if (sbp2util_access_timeout(lu, HZ)) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       /* make sure that the returned status matches the reconnect ORB */
-       if (lu->status_block.ORB_offset_lo != lu->reconnect_orb_dma) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - timed out");
-               return -EIO;
-       }
-
-       if (STATUS_TEST_RDS(lu->status_block.ORB_offset_hi_misc)) {
-               SBP2_ERR("Error reconnecting to SBP-2 device - failed");
-               return -EIO;
-       }
-
-       SBP2_INFO("Reconnected to SBP-2 device");
-       return 0;
-}
-
-/*
- * Set the target node's Single Phase Retry limit. Affects the target's retry
- * behaviour if our node is too busy to accept requests.
- */
-static int sbp2_set_busy_timeout(struct sbp2_lu *lu)
-{
-       quadlet_t data;
-
-       data = cpu_to_be32(SBP2_BUSY_TIMEOUT_VALUE);
-       if (hpsb_node_write(lu->ne, SBP2_BUSY_TIMEOUT_ADDRESS, &data, 4))
-               SBP2_ERR("%s error", __func__);
-       return 0;
-}
-
-static void sbp2_parse_unit_directory(struct sbp2_lu *lu,
-                                     struct unit_directory *ud)
-{
-       struct csr1212_keyval *kv;
-       struct csr1212_dentry *dentry;
-       u64 management_agent_addr;
-       u32 firmware_revision, model;
-       unsigned workarounds;
-       int i;
-
-       management_agent_addr = 0;
-       firmware_revision = SBP2_ROM_VALUE_MISSING;
-       model = ud->flags & UNIT_DIRECTORY_MODEL_ID ?
-                               ud->model_id : SBP2_ROM_VALUE_MISSING;
-
-       csr1212_for_each_dir_entry(ud->ne->csr, kv, ud->ud_kv, dentry) {
-               switch (kv->key.id) {
-               case CSR1212_KV_ID_DEPENDENT_INFO:
-                       if (kv->key.type == CSR1212_KV_TYPE_CSR_OFFSET)
-                               management_agent_addr =
-                                   CSR1212_REGISTER_SPACE_BASE +
-                                   (kv->value.csr_offset << 2);
-
-                       else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE)
-                               lu->lun = ORB_SET_LUN(kv->value.immediate);
-                       break;
-
-
-               case SBP2_FIRMWARE_REVISION_KEY:
-                       firmware_revision = kv->value.immediate;
-                       break;
-
-               default:
-                       /* FIXME: Check for SBP2_UNIT_CHARACTERISTICS_KEY
-                        * mgt_ORB_timeout and ORB_size, SBP-2 clause 7.4.8. */
-
-                       /* FIXME: Check for SBP2_DEVICE_TYPE_AND_LUN_KEY.
-                        * Its "ordered" bit has consequences for command ORB
-                        * list handling. See SBP-2 clauses 4.6, 7.4.11, 10.2 */
-                       break;
-               }
-       }
-
-       workarounds = sbp2_default_workarounds;
-
-       if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
-               for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
-                       if (sbp2_workarounds_table[i].firmware_revision !=
-                           SBP2_ROM_VALUE_WILDCARD &&
-                           sbp2_workarounds_table[i].firmware_revision !=
-                           (firmware_revision & 0xffff00))
-                               continue;
-                       if (sbp2_workarounds_table[i].model !=
-                           SBP2_ROM_VALUE_WILDCARD &&
-                           sbp2_workarounds_table[i].model != model)
-                               continue;
-                       workarounds |= sbp2_workarounds_table[i].workarounds;
-                       break;
-               }
-
-       if (workarounds)
-               SBP2_INFO("Workarounds for node " NODE_BUS_FMT ": 0x%x "
-                         "(firmware_revision 0x%06x, vendor_id 0x%06x,"
-                         " model_id 0x%06x)",
-                         NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
-                         workarounds, firmware_revision, ud->vendor_id,
-                         model);
-
-       /* We would need one SCSI host template for each target to adjust
-        * max_sectors on the fly, therefore warn only. */
-       if (workarounds & SBP2_WORKAROUND_128K_MAX_TRANS &&
-           (sbp2_max_sectors * 512) > (128 * 1024))
-               SBP2_INFO("Node " NODE_BUS_FMT ": Bridge only supports 128KB "
-                         "max transfer size. WARNING: Current max_sectors "
-                         "setting is larger than 128KB (%d sectors)",
-                         NODE_BUS_ARGS(ud->ne->host, ud->ne->nodeid),
-                         sbp2_max_sectors);
-
-       /* If this is a logical unit directory entry, process the parent
-        * to get the values. */
-       if (ud->flags & UNIT_DIRECTORY_LUN_DIRECTORY) {
-               struct unit_directory *parent_ud = container_of(
-                       ud->device.parent, struct unit_directory, device);
-               sbp2_parse_unit_directory(lu, parent_ud);
-       } else {
-               lu->management_agent_addr = management_agent_addr;
-               lu->workarounds = workarounds;
-               if (ud->flags & UNIT_DIRECTORY_HAS_LUN)
-                       lu->lun = ORB_SET_LUN(ud->lun);
-       }
-}
-
-#define SBP2_PAYLOAD_TO_BYTES(p) (1 << ((p) + 2))
-
-/*
- * This function is called in order to determine the max speed and packet
- * size we can use in our ORBs. Note, that we (the driver and host) only
- * initiate the transaction. The SBP-2 device actually transfers the data
- * (by reading from the DMA area we tell it). This means that the SBP-2
- * device decides the actual maximum data it can transfer. We just tell it
- * the speed that it needs to use, and the max_rec the host supports, and
- * it takes care of the rest.
- */
-static int sbp2_max_speed_and_size(struct sbp2_lu *lu)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       u8 payload;
-
-       lu->speed_code = hi->host->speed[NODEID_TO_NODE(lu->ne->nodeid)];
-
-       if (lu->speed_code > sbp2_max_speed) {
-               lu->speed_code = sbp2_max_speed;
-               SBP2_INFO("Reducing speed to %s",
-                         hpsb_speedto_str[sbp2_max_speed]);
-       }
-
-       /* Payload size is the lesser of what our speed supports and what
-        * our host supports.  */
-       payload = min(sbp2_speedto_max_payload[lu->speed_code],
-                     (u8) (hi->host->csr.max_rec - 1));
-
-       /* If physical DMA is off, work around limitation in ohci1394:
-        * packet size must not exceed PAGE_SIZE */
-       if (lu->ne->host->low_addr_space < (1ULL << 32))
-               while (SBP2_PAYLOAD_TO_BYTES(payload) + 24 > PAGE_SIZE &&
-                      payload)
-                       payload--;
-
-       SBP2_INFO("Node " NODE_BUS_FMT ": Max speed [%s] - Max payload [%u]",
-                 NODE_BUS_ARGS(hi->host, lu->ne->nodeid),
-                 hpsb_speedto_str[lu->speed_code],
-                 SBP2_PAYLOAD_TO_BYTES(payload));
-
-       lu->max_payload_size = payload;
-       return 0;
-}
-
-static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
-{
-       quadlet_t data;
-       u64 addr;
-       int retval;
-       unsigned long flags;
-
-       /* flush lu->protocol_work */
-       if (wait)
-               flush_scheduled_work();
-
-       data = ntohl(SBP2_AGENT_RESET_DATA);
-       addr = lu->command_block_agent_addr + SBP2_AGENT_RESET_OFFSET;
-
-       if (wait)
-               retval = hpsb_node_write(lu->ne, addr, &data, 4);
-       else
-               retval = sbp2util_node_write_no_wait(lu->ne, addr, &data, 4);
-
-       if (retval < 0) {
-               SBP2_ERR("hpsb_node_write failed.\n");
-               return -EIO;
-       }
-
-       /* make sure that the ORB_POINTER is written on next command */
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       lu->last_orb = NULL;
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       return 0;
-}
-
-static int sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
-                                   struct sbp2_fwhost_info *hi,
-                                   struct sbp2_command_info *cmd,
-                                   unsigned int sg_count,
-                                   struct scatterlist *sg,
-                                   u32 orb_direction,
-                                   enum dma_data_direction dma_dir)
-{
-       struct device *dmadev = hi->host->device.parent;
-       struct sbp2_unrestricted_page_table *pt;
-       int i, n;
-
-       n = dma_map_sg(dmadev, sg, sg_count, dma_dir);
-       if (n == 0)
-               return -ENOMEM;
-
-       orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
-       orb->misc |= ORB_SET_DIRECTION(orb_direction);
-
-       /* special case if only one element (and less than 64KB in size) */
-       if (n == 1) {
-               orb->misc |= ORB_SET_DATA_SIZE(sg_dma_len(sg));
-               orb->data_descriptor_lo = sg_dma_address(sg);
-       } else {
-               pt = &cmd->scatter_gather_element[0];
-
-               dma_sync_single_for_cpu(dmadev, cmd->sge_dma,
-                                       sizeof(cmd->scatter_gather_element),
-                                       DMA_TO_DEVICE);
-
-               for_each_sg(sg, sg, n, i) {
-                       pt[i].high = cpu_to_be32(sg_dma_len(sg) << 16);
-                       pt[i].low = cpu_to_be32(sg_dma_address(sg));
-               }
-
-               orb->misc |= ORB_SET_PAGE_TABLE_PRESENT(0x1) |
-                            ORB_SET_DATA_SIZE(n);
-               orb->data_descriptor_lo = cmd->sge_dma;
-
-               dma_sync_single_for_device(dmadev, cmd->sge_dma,
-                                          sizeof(cmd->scatter_gather_element),
-                                          DMA_TO_DEVICE);
-       }
-       return 0;
-}
-
-static int sbp2_create_command_orb(struct sbp2_lu *lu,
-                                  struct sbp2_command_info *cmd,
-                                  struct scsi_cmnd *SCpnt)
-{
-       struct device *dmadev = lu->hi->host->device.parent;
-       struct sbp2_command_orb *orb = &cmd->command_orb;
-       unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
-       enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
-       u32 orb_direction;
-       int ret;
-
-       dma_sync_single_for_cpu(dmadev, cmd->command_orb_dma,
-                               sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
-       /*
-        * Set-up our command ORB.
-        *
-        * NOTE: We're doing unrestricted page tables (s/g), as this is
-        * best performance (at least with the devices I have). This means
-        * that data_size becomes the number of s/g elements, and
-        * page_size should be zero (for unrestricted).
-        */
-       orb->next_ORB_hi = ORB_SET_NULL_PTR(1);
-       orb->next_ORB_lo = 0x0;
-       orb->misc = ORB_SET_MAX_PAYLOAD(lu->max_payload_size);
-       orb->misc |= ORB_SET_SPEED(lu->speed_code);
-       orb->misc |= ORB_SET_NOTIFY(1);
-
-       if (dma_dir == DMA_NONE)
-               orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
-       else if (dma_dir == DMA_TO_DEVICE && scsi_request_bufflen)
-               orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
-       else if (dma_dir == DMA_FROM_DEVICE && scsi_request_bufflen)
-               orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
-       else {
-               SBP2_INFO("Falling back to DMA_NONE");
-               orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
-       }
-
-       /* set up our page table stuff */
-       if (orb_direction == ORB_DIRECTION_NO_DATA_TRANSFER) {
-               orb->data_descriptor_hi = 0x0;
-               orb->data_descriptor_lo = 0x0;
-               orb->misc |= ORB_SET_DIRECTION(1);
-               ret = 0;
-       } else {
-               ret = sbp2_prep_command_orb_sg(orb, lu->hi, cmd,
-                                              scsi_sg_count(SCpnt),
-                                              scsi_sglist(SCpnt),
-                                              orb_direction, dma_dir);
-       }
-       sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
-
-       memset(orb->cdb, 0, sizeof(orb->cdb));
-       memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len);
-
-       dma_sync_single_for_device(dmadev, cmd->command_orb_dma,
-                       sizeof(struct sbp2_command_orb), DMA_TO_DEVICE);
-       return ret;
-}
-
-static void sbp2_link_orb_command(struct sbp2_lu *lu,
-                                 struct sbp2_command_info *cmd)
-{
-       struct sbp2_fwhost_info *hi = lu->hi;
-       struct sbp2_command_orb *last_orb;
-       dma_addr_t last_orb_dma;
-       u64 addr = lu->command_block_agent_addr;
-       quadlet_t data[2];
-       size_t length;
-       unsigned long flags;
-
-       /* check to see if there are any previous orbs to use */
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       last_orb = lu->last_orb;
-       last_orb_dma = lu->last_orb_dma;
-       if (!last_orb) {
-               /*
-                * last_orb == NULL means: We know that the target's fetch agent
-                * is not active right now.
-                */
-               addr += SBP2_ORB_POINTER_OFFSET;
-               data[0] = ORB_SET_NODE_ID(hi->host->node_id);
-               data[1] = cmd->command_orb_dma;
-               sbp2util_cpu_to_be32_buffer(data, 8);
-               length = 8;
-       } else {
-               /*
-                * last_orb != NULL means: We know that the target's fetch agent
-                * is (very probably) not dead or in reset state right now.
-                * We have an ORB already sent that we can append a new one to.
-                * The target's fetch agent may or may not have read this
-                * previous ORB yet.
-                */
-               dma_sync_single_for_cpu(hi->host->device.parent, last_orb_dma,
-                                       sizeof(struct sbp2_command_orb),
-                                       DMA_TO_DEVICE);
-               last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma);
-               wmb();
-               /* Tells hardware that this pointer is valid */
-               last_orb->next_ORB_hi = 0;
-               dma_sync_single_for_device(hi->host->device.parent,
-                                          last_orb_dma,
-                                          sizeof(struct sbp2_command_orb),
-                                          DMA_TO_DEVICE);
-               addr += SBP2_DOORBELL_OFFSET;
-               data[0] = 0;
-               length = 4;
-       }
-       lu->last_orb = &cmd->command_orb;
-       lu->last_orb_dma = cmd->command_orb_dma;
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       if (sbp2util_node_write_no_wait(lu->ne, addr, data, length)) {
-               /*
-                * sbp2util_node_write_no_wait failed. We certainly ran out
-                * of transaction labels, perhaps just because there were no
-                * context switches which gave khpsbpkt a chance to collect
-                * free tlabels. Try again in non-atomic context. If necessary,
-                * the workqueue job will sleep to guaranteedly get a tlabel.
-                * We do not accept new commands until the job is over.
-                */
-               scsi_block_requests(lu->shost);
-               PREPARE_WORK(&lu->protocol_work,
-                            last_orb ? sbp2util_write_doorbell:
-                                       sbp2util_write_orb_pointer);
-               schedule_work(&lu->protocol_work);
-       }
-}
-
-static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
-                            void (*done)(struct scsi_cmnd *))
-{
-       struct sbp2_command_info *cmd;
-
-       cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
-       if (!cmd)
-               return -EIO;
-
-       if (sbp2_create_command_orb(lu, cmd, SCpnt))
-               return -ENOMEM;
-
-       sbp2_link_orb_command(lu, cmd);
-       return 0;
-}
-
-/*
- * Translates SBP-2 status into SCSI sense data for check conditions
- */
-static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status,
-                                             unchar *sense_data)
-{
-       /* OK, it's pretty ugly... ;-) */
-       sense_data[0] = 0x70;
-       sense_data[1] = 0x0;
-       sense_data[2] = sbp2_status[9];
-       sense_data[3] = sbp2_status[12];
-       sense_data[4] = sbp2_status[13];
-       sense_data[5] = sbp2_status[14];
-       sense_data[6] = sbp2_status[15];
-       sense_data[7] = 10;
-       sense_data[8] = sbp2_status[16];
-       sense_data[9] = sbp2_status[17];
-       sense_data[10] = sbp2_status[18];
-       sense_data[11] = sbp2_status[19];
-       sense_data[12] = sbp2_status[10];
-       sense_data[13] = sbp2_status[11];
-       sense_data[14] = sbp2_status[20];
-       sense_data[15] = sbp2_status[21];
-
-       return sbp2_status[8] & 0x3f;
-}
-
-static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
-                                   int destid, quadlet_t *data, u64 addr,
-                                   size_t length, u16 fl)
-{
-       struct sbp2_fwhost_info *hi;
-       struct sbp2_lu *lu = NULL, *lu_tmp;
-       struct scsi_cmnd *SCpnt = NULL;
-       struct sbp2_status_block *sb;
-       u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       if (unlikely(length < 8 || length > sizeof(struct sbp2_status_block))) {
-               SBP2_ERR("Wrong size of status block");
-               return RCODE_ADDRESS_ERROR;
-       }
-       if (unlikely(!host)) {
-               SBP2_ERR("host is NULL - this is bad!");
-               return RCODE_ADDRESS_ERROR;
-       }
-       hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-       if (unlikely(!hi)) {
-               SBP2_ERR("host info is NULL - this is bad!");
-               return RCODE_ADDRESS_ERROR;
-       }
-
-       /* Find the unit which wrote the status. */
-       read_lock_irqsave(&sbp2_hi_logical_units_lock, flags);
-       list_for_each_entry(lu_tmp, &hi->logical_units, lu_list) {
-               if (lu_tmp->ne->nodeid == nodeid &&
-                   lu_tmp->status_fifo_addr == addr) {
-                       lu = lu_tmp;
-                       break;
-               }
-       }
-       read_unlock_irqrestore(&sbp2_hi_logical_units_lock, flags);
-
-       if (unlikely(!lu)) {
-               SBP2_ERR("lu is NULL - device is gone?");
-               return RCODE_ADDRESS_ERROR;
-       }
-
-       /* Put response into lu status fifo buffer. The first two bytes
-        * come in big endian bit order. Often the target writes only a
-        * truncated status block, minimally the first two quadlets. The rest
-        * is implied to be zeros. */
-       sb = &lu->status_block;
-       memset(sb->command_set_dependent, 0, sizeof(sb->command_set_dependent));
-       memcpy(sb, data, length);
-       sbp2util_be32_to_cpu_buffer(sb, 8);
-
-       /* Ignore unsolicited status. Handle command ORB status. */
-       if (unlikely(STATUS_GET_SRC(sb->ORB_offset_hi_misc) == 2))
-               cmd = NULL;
-       else
-               cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
-       if (cmd) {
-               /* Grab SCSI command pointers and check status. */
-               /*
-                * FIXME: If the src field in the status is 1, the ORB DMA must
-                * not be reused until status for a subsequent ORB is received.
-                */
-               SCpnt = cmd->Current_SCpnt;
-               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-               sbp2util_mark_command_completed(lu, cmd);
-               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-               if (SCpnt) {
-                       u32 h = sb->ORB_offset_hi_misc;
-                       u32 r = STATUS_GET_RESP(h);
-
-                       if (r != RESP_STATUS_REQUEST_COMPLETE) {
-                               SBP2_INFO("resp 0x%x, sbp_status 0x%x",
-                                         r, STATUS_GET_SBP_STATUS(h));
-                               scsi_status =
-                                       r == RESP_STATUS_TRANSPORT_FAILURE ?
-                                       SBP2_SCSI_STATUS_BUSY :
-                                       SBP2_SCSI_STATUS_COMMAND_TERMINATED;
-                       }
-
-                       if (STATUS_GET_LEN(h) > 1)
-                               scsi_status = sbp2_status_to_sense_data(
-                                       (unchar *)sb, SCpnt->sense_buffer);
-
-                       if (STATUS_TEST_DEAD(h))
-                                sbp2_agent_reset(lu, 0);
-               }
-
-               /* Check here to see if there are no commands in-use. If there
-                * are none, we know that the fetch agent left the active state
-                * _and_ that we did not reactivate it yet. Therefore clear
-                * last_orb so that next time we write directly to the
-                * ORB_POINTER register. That way the fetch agent does not need
-                * to refetch the next_ORB. */
-               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-               if (list_empty(&lu->cmd_orb_inuse))
-                       lu->last_orb = NULL;
-               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       } else {
-               /* It's probably status after a management request. */
-               if ((sb->ORB_offset_lo == lu->reconnect_orb_dma) ||
-                   (sb->ORB_offset_lo == lu->login_orb_dma) ||
-                   (sb->ORB_offset_lo == lu->query_logins_orb_dma) ||
-                   (sb->ORB_offset_lo == lu->logout_orb_dma)) {
-                       lu->access_complete = 1;
-                       wake_up_interruptible(&sbp2_access_wq);
-               }
-       }
-
-       if (SCpnt)
-               sbp2scsi_complete_command(lu, scsi_status, SCpnt,
-                                         cmd->Current_done);
-       return RCODE_COMPLETE;
-}
-
-/**************************************
- * SCSI interface related section
- **************************************/
-
-static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
-                                void (*done)(struct scsi_cmnd *))
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
-       struct sbp2_fwhost_info *hi;
-       int result = DID_NO_CONNECT << 16;
-
-       if (unlikely(!sbp2util_node_is_available(lu)))
-               goto done;
-
-       hi = lu->hi;
-
-       if (unlikely(!hi)) {
-               SBP2_ERR("sbp2_fwhost_info is NULL - this is bad!");
-               goto done;
-       }
-
-       /* Multiple units are currently represented to the SCSI core as separate
-        * targets, not as one target with multiple LUs. Therefore return
-        * selection time-out to any IO directed at non-zero LUNs. */
-       if (unlikely(SCpnt->device->lun))
-               goto done;
-
-       if (unlikely(!hpsb_node_entry_valid(lu->ne))) {
-               SBP2_ERR("Bus reset in progress - rejecting command");
-               result = DID_BUS_BUSY << 16;
-               goto done;
-       }
-
-       /* Bidirectional commands are not yet implemented,
-        * and unknown transfer direction not handled. */
-       if (unlikely(SCpnt->sc_data_direction == DMA_BIDIRECTIONAL)) {
-               SBP2_ERR("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
-               result = DID_ERROR << 16;
-               goto done;
-       }
-
-       if (sbp2_send_command(lu, SCpnt, done)) {
-               SBP2_ERR("Error sending SCSI command");
-               sbp2scsi_complete_command(lu,
-                                         SBP2_SCSI_STATUS_SELECTION_TIMEOUT,
-                                         SCpnt, done);
-       }
-       return 0;
-
-done:
-       SCpnt->result = result;
-       done(SCpnt);
-       return 0;
-}
-
-static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
-{
-       struct list_head *lh;
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-       while (!list_empty(&lu->cmd_orb_inuse)) {
-               lh = lu->cmd_orb_inuse.next;
-               cmd = list_entry(lh, struct sbp2_command_info, list);
-               sbp2util_mark_command_completed(lu, cmd);
-               if (cmd->Current_SCpnt) {
-                       cmd->Current_SCpnt->result = status << 16;
-                       cmd->Current_done(cmd->Current_SCpnt);
-               }
-       }
-       spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-       return;
-}
-
-/*
- * Complete a regular SCSI command. Can be called in atomic context.
- */
-static void sbp2scsi_complete_command(struct sbp2_lu *lu, u32 scsi_status,
-                                     struct scsi_cmnd *SCpnt,
-                                     void (*done)(struct scsi_cmnd *))
-{
-       if (!SCpnt) {
-               SBP2_ERR("SCpnt is NULL");
-               return;
-       }
-
-       switch (scsi_status) {
-       case SBP2_SCSI_STATUS_GOOD:
-               SCpnt->result = DID_OK << 16;
-               break;
-
-       case SBP2_SCSI_STATUS_BUSY:
-               SBP2_ERR("SBP2_SCSI_STATUS_BUSY");
-               SCpnt->result = DID_BUS_BUSY << 16;
-               break;
-
-       case SBP2_SCSI_STATUS_CHECK_CONDITION:
-               SCpnt->result = CHECK_CONDITION << 1 | DID_OK << 16;
-               break;
-
-       case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
-               SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
-               SCpnt->result = DID_NO_CONNECT << 16;
-               scsi_print_command(SCpnt);
-               break;
-
-       case SBP2_SCSI_STATUS_CONDITION_MET:
-       case SBP2_SCSI_STATUS_RESERVATION_CONFLICT:
-       case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
-               SBP2_ERR("Bad SCSI status = %x", scsi_status);
-               SCpnt->result = DID_ERROR << 16;
-               scsi_print_command(SCpnt);
-               break;
-
-       default:
-               SBP2_ERR("Unsupported SCSI status = %x", scsi_status);
-               SCpnt->result = DID_ERROR << 16;
-       }
-
-       /* If a bus reset is in progress and there was an error, complete
-        * the command as busy so that it will get retried. */
-       if (!hpsb_node_entry_valid(lu->ne)
-           && (scsi_status != SBP2_SCSI_STATUS_GOOD)) {
-               SBP2_ERR("Completing command with busy (bus reset)");
-               SCpnt->result = DID_BUS_BUSY << 16;
-       }
-
-       /* Tell the SCSI stack that we're done with this command. */
-       done(SCpnt);
-}
-
-static int sbp2scsi_slave_alloc(struct scsi_device *sdev)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
-
-       if (sdev->lun != 0 || sdev->id != lu->ud->id || sdev->channel != 0)
-               return -ENODEV;
-
-       lu->sdev = sdev;
-       sdev->allow_restart = 1;
-
-       /* SBP-2 requires quadlet alignment of the data buffers. */
-       blk_queue_update_dma_alignment(sdev->request_queue, 4 - 1);
-
-       if (lu->workarounds & SBP2_WORKAROUND_INQUIRY_36)
-               sdev->inquiry_len = 36;
-       return 0;
-}
-
-static int sbp2scsi_slave_configure(struct scsi_device *sdev)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
-
-       sdev->use_10_for_rw = 1;
-
-       if (sbp2_exclusive_login)
-               sdev->manage_start_stop = 1;
-       if (sdev->type == TYPE_ROM)
-               sdev->use_10_for_ms = 1;
-       if (sdev->type == TYPE_DISK &&
-           lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
-               sdev->skip_ms_page_8 = 1;
-       if (lu->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
-               sdev->fix_capacity = 1;
-       if (lu->workarounds & SBP2_WORKAROUND_POWER_CONDITION)
-               sdev->start_stop_pwr_cond = 1;
-       if (lu->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
-               blk_queue_max_hw_sectors(sdev->request_queue, 128 * 1024 / 512);
-
-       blk_queue_max_segment_size(sdev->request_queue, SBP2_MAX_SEG_SIZE);
-       return 0;
-}
-
-static void sbp2scsi_slave_destroy(struct scsi_device *sdev)
-{
-       ((struct sbp2_lu *)sdev->host->hostdata[0])->sdev = NULL;
-       return;
-}
-
-/*
- * Called by scsi stack when something has really gone wrong.
- * Usually called when a command has timed-out for some reason.
- */
-static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
-       struct sbp2_command_info *cmd;
-       unsigned long flags;
-
-       SBP2_INFO("aborting sbp2 command");
-       scsi_print_command(SCpnt);
-
-       if (sbp2util_node_is_available(lu)) {
-               sbp2_agent_reset(lu, 1);
-
-               /* Return a matching command structure to the free pool. */
-               spin_lock_irqsave(&lu->cmd_orb_lock, flags);
-               cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
-               if (cmd) {
-                       sbp2util_mark_command_completed(lu, cmd);
-                       if (cmd->Current_SCpnt) {
-                               cmd->Current_SCpnt->result = DID_ABORT << 16;
-                               cmd->Current_done(cmd->Current_SCpnt);
-                       }
-               }
-               spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
-
-               sbp2scsi_complete_all_commands(lu, DID_BUS_BUSY);
-       }
-
-       return SUCCESS;
-}
-
-/*
- * Called by scsi stack when something has really gone wrong.
- */
-static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
-{
-       struct sbp2_lu *lu = (struct sbp2_lu *)SCpnt->device->host->hostdata[0];
-
-       SBP2_INFO("reset requested");
-
-       if (sbp2util_node_is_available(lu)) {
-               SBP2_INFO("generating sbp2 fetch agent reset");
-               sbp2_agent_reset(lu, 1);
-       }
-
-       return SUCCESS;
-}
-
-static ssize_t sbp2_sysfs_ieee1394_id_show(struct device *dev,
-                                          struct device_attribute *attr,
-                                          char *buf)
-{
-       struct scsi_device *sdev;
-       struct sbp2_lu *lu;
-
-       if (!(sdev = to_scsi_device(dev)))
-               return 0;
-
-       if (!(lu = (struct sbp2_lu *)sdev->host->hostdata[0]))
-               return 0;
-
-       if (sbp2_long_sysfs_ieee1394_id)
-               return sprintf(buf, "%016Lx:%06x:%04x\n",
-                               (unsigned long long)lu->ne->guid,
-                               lu->ud->directory_id, ORB_SET_LUN(lu->lun));
-       else
-               return sprintf(buf, "%016Lx:%d:%d\n",
-                               (unsigned long long)lu->ne->guid,
-                               lu->ud->id, ORB_SET_LUN(lu->lun));
-}
-
-MODULE_AUTHOR("Ben Collins <bcollins@debian.org>");
-MODULE_DESCRIPTION("IEEE-1394 SBP-2 protocol driver");
-MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME);
-MODULE_LICENSE("GPL");
-
-static int sbp2_module_init(void)
-{
-       int ret;
-
-       if (sbp2_serialize_io) {
-               sbp2_shost_template.can_queue = 1;
-               sbp2_shost_template.cmd_per_lun = 1;
-       }
-
-       sbp2_shost_template.max_sectors = sbp2_max_sectors;
-
-       hpsb_register_highlevel(&sbp2_highlevel);
-       ret = hpsb_register_protocol(&sbp2_driver);
-       if (ret) {
-               SBP2_ERR("Failed to register protocol");
-               hpsb_unregister_highlevel(&sbp2_highlevel);
-               return ret;
-       }
-       return 0;
-}
-
-static void __exit sbp2_module_exit(void)
-{
-       hpsb_unregister_protocol(&sbp2_driver);
-       hpsb_unregister_highlevel(&sbp2_highlevel);
-}
-
-module_init(sbp2_module_init);
-module_exit(sbp2_module_exit);
diff --git a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
deleted file mode 100644 (file)
index 64a3a66..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * sbp2.h - Defines and prototypes for sbp2.c
- *
- * Copyright (C) 2000 James Goodwin, Filanet Corporation (www.filanet.com)
- * jamesg@filanet.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef SBP2_H
-#define SBP2_H
-
-#define SBP2_DEVICE_NAME               "sbp2"
-
-/*
- * There is no transport protocol limit to the CDB length,  but we implement
- * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
- */
-#define SBP2_MAX_CDB_SIZE              16
-
-/*
- * SBP-2 specific definitions
- */
-
-#define ORB_DIRECTION_WRITE_TO_MEDIA   0x0
-#define ORB_DIRECTION_READ_FROM_MEDIA  0x1
-#define ORB_DIRECTION_NO_DATA_TRANSFER 0x2
-
-#define ORB_SET_NULL_PTR(v)            (((v) & 0x1) << 31)
-#define ORB_SET_NOTIFY(v)              (((v) & 0x1) << 31)
-#define ORB_SET_RQ_FMT(v)              (((v) & 0x3) << 29)
-#define ORB_SET_NODE_ID(v)             (((v) & 0xffff) << 16)
-#define ORB_SET_STATUS_FIFO_HI(v, id)  ((v) >> 32 | ORB_SET_NODE_ID(id))
-#define ORB_SET_STATUS_FIFO_LO(v)      ((v) & 0xffffffff)
-#define ORB_SET_DATA_SIZE(v)           ((v) & 0xffff)
-#define ORB_SET_PAGE_SIZE(v)           (((v) & 0x7) << 16)
-#define ORB_SET_PAGE_TABLE_PRESENT(v)  (((v) & 0x1) << 19)
-#define ORB_SET_MAX_PAYLOAD(v)         (((v) & 0xf) << 20)
-#define ORB_SET_SPEED(v)               (((v) & 0x7) << 24)
-#define ORB_SET_DIRECTION(v)           (((v) & 0x1) << 27)
-
-struct sbp2_command_orb {
-       u32 next_ORB_hi;
-       u32 next_ORB_lo;
-       u32 data_descriptor_hi;
-       u32 data_descriptor_lo;
-       u32 misc;
-       u8 cdb[SBP2_MAX_CDB_SIZE];
-} __attribute__((packed));
-
-#define SBP2_LOGIN_REQUEST             0x0
-#define SBP2_QUERY_LOGINS_REQUEST      0x1
-#define SBP2_RECONNECT_REQUEST         0x3
-#define SBP2_SET_PASSWORD_REQUEST      0x4
-#define SBP2_LOGOUT_REQUEST            0x7
-#define SBP2_ABORT_TASK_REQUEST                0xb
-#define SBP2_ABORT_TASK_SET            0xc
-#define SBP2_LOGICAL_UNIT_RESET                0xe
-#define SBP2_TARGET_RESET_REQUEST      0xf
-
-#define ORB_SET_LUN(v)                 ((v) & 0xffff)
-#define ORB_SET_FUNCTION(v)            (((v) & 0xf) << 16)
-#define ORB_SET_RECONNECT(v)           (((v) & 0xf) << 20)
-#define ORB_SET_EXCLUSIVE(v)           ((v) ? 1 << 28 : 0)
-#define ORB_SET_LOGIN_RESP_LENGTH(v)   ((v) & 0xffff)
-#define ORB_SET_PASSWD_LENGTH(v)       (((v) & 0xffff) << 16)
-
-struct sbp2_login_orb {
-       u32 password_hi;
-       u32 password_lo;
-       u32 login_response_hi;
-       u32 login_response_lo;
-       u32 lun_misc;
-       u32 passwd_resp_lengths;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-#define RESPONSE_GET_LOGIN_ID(v)       ((v) & 0xffff)
-#define RESPONSE_GET_LENGTH(v)         (((v) >> 16) & 0xffff)
-#define RESPONSE_GET_RECONNECT_HOLD(v) ((v) & 0xffff)
-
-struct sbp2_login_response {
-       u32 length_login_ID;
-       u32 command_block_agent_hi;
-       u32 command_block_agent_lo;
-       u32 reconnect_hold;
-} __attribute__((packed));
-
-#define ORB_SET_LOGIN_ID(v)                 ((v) & 0xffff)
-#define ORB_SET_QUERY_LOGINS_RESP_LENGTH(v) ((v) & 0xffff)
-
-struct sbp2_query_logins_orb {
-       u32 reserved1;
-       u32 reserved2;
-       u32 query_response_hi;
-       u32 query_response_lo;
-       u32 lun_misc;
-       u32 reserved_resp_length;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-#define RESPONSE_GET_MAX_LOGINS(v)     ((v) & 0xffff)
-#define RESPONSE_GET_ACTIVE_LOGINS(v)  ((RESPONSE_GET_LENGTH((v)) - 4) / 12)
-
-struct sbp2_query_logins_response {
-       u32 length_max_logins;
-       u32 misc_IDs;
-       u32 initiator_misc_hi;
-       u32 initiator_misc_lo;
-} __attribute__((packed));
-
-struct sbp2_reconnect_orb {
-       u32 reserved1;
-       u32 reserved2;
-       u32 reserved3;
-       u32 reserved4;
-       u32 login_ID_misc;
-       u32 reserved5;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-struct sbp2_logout_orb {
-       u32 reserved1;
-       u32 reserved2;
-       u32 reserved3;
-       u32 reserved4;
-       u32 login_ID_misc;
-       u32 reserved5;
-       u32 status_fifo_hi;
-       u32 status_fifo_lo;
-} __attribute__((packed));
-
-struct sbp2_unrestricted_page_table {
-       __be32 high;
-       __be32 low;
-};
-
-#define RESP_STATUS_REQUEST_COMPLETE           0x0
-#define RESP_STATUS_TRANSPORT_FAILURE          0x1
-#define RESP_STATUS_ILLEGAL_REQUEST            0x2
-#define RESP_STATUS_VENDOR_DEPENDENT           0x3
-
-#define SBP2_STATUS_NO_ADDITIONAL_INFO         0x0
-#define SBP2_STATUS_REQ_TYPE_NOT_SUPPORTED     0x1
-#define SBP2_STATUS_SPEED_NOT_SUPPORTED                0x2
-#define SBP2_STATUS_PAGE_SIZE_NOT_SUPPORTED    0x3
-#define SBP2_STATUS_ACCESS_DENIED              0x4
-#define SBP2_STATUS_LU_NOT_SUPPORTED           0x5
-#define SBP2_STATUS_MAX_PAYLOAD_TOO_SMALL      0x6
-#define SBP2_STATUS_RESOURCES_UNAVAILABLE      0x8
-#define SBP2_STATUS_FUNCTION_REJECTED          0x9
-#define SBP2_STATUS_LOGIN_ID_NOT_RECOGNIZED    0xa
-#define SBP2_STATUS_DUMMY_ORB_COMPLETED                0xb
-#define SBP2_STATUS_REQUEST_ABORTED            0xc
-#define SBP2_STATUS_UNSPECIFIED_ERROR          0xff
-
-#define SFMT_CURRENT_ERROR                     0x0
-#define SFMT_DEFERRED_ERROR                    0x1
-#define SFMT_VENDOR_DEPENDENT_STATUS           0x3
-
-#define STATUS_GET_SRC(v)                      (((v) >> 30) & 0x3)
-#define STATUS_GET_RESP(v)                     (((v) >> 28) & 0x3)
-#define STATUS_GET_LEN(v)                      (((v) >> 24) & 0x7)
-#define STATUS_GET_SBP_STATUS(v)               (((v) >> 16) & 0xff)
-#define STATUS_GET_ORB_OFFSET_HI(v)            ((v) & 0x0000ffff)
-#define STATUS_TEST_DEAD(v)                    ((v) & 0x08000000)
-/* test 'resp' | 'dead' | 'sbp2_status' */
-#define STATUS_TEST_RDS(v)                     ((v) & 0x38ff0000)
-
-struct sbp2_status_block {
-       u32 ORB_offset_hi_misc;
-       u32 ORB_offset_lo;
-       u8 command_set_dependent[24];
-} __attribute__((packed));
-
-
-/*
- * SBP2 related configuration ROM definitions
- */
-
-#define SBP2_UNIT_DIRECTORY_OFFSET_KEY         0xd1
-#define SBP2_CSR_OFFSET_KEY                    0x54
-#define SBP2_UNIT_SPEC_ID_KEY                  0x12
-#define SBP2_UNIT_SW_VERSION_KEY               0x13
-#define SBP2_COMMAND_SET_SPEC_ID_KEY           0x38
-#define SBP2_COMMAND_SET_KEY                   0x39
-#define SBP2_UNIT_CHARACTERISTICS_KEY          0x3a
-#define SBP2_DEVICE_TYPE_AND_LUN_KEY           0x14
-#define SBP2_FIRMWARE_REVISION_KEY             0x3c
-
-#define SBP2_AGENT_STATE_OFFSET                        0x00ULL
-#define SBP2_AGENT_RESET_OFFSET                        0x04ULL
-#define SBP2_ORB_POINTER_OFFSET                        0x08ULL
-#define SBP2_DOORBELL_OFFSET                   0x10ULL
-#define SBP2_UNSOLICITED_STATUS_ENABLE_OFFSET  0x14ULL
-#define SBP2_UNSOLICITED_STATUS_VALUE          0xf
-
-#define SBP2_BUSY_TIMEOUT_ADDRESS              0xfffff0000210ULL
-/* biggest possible value for Single Phase Retry count is 0xf */
-#define SBP2_BUSY_TIMEOUT_VALUE                        0xf
-
-#define SBP2_AGENT_RESET_DATA                  0xf
-
-#define SBP2_UNIT_SPEC_ID_ENTRY                        0x0000609e
-#define SBP2_SW_VERSION_ENTRY                  0x00010483
-
-/*
- * The default maximum s/g segment size of a FireWire controller is
- * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
- * be quadlet-aligned, we set the length limit to 0xffff & ~3.
- */
-#define SBP2_MAX_SEG_SIZE                      0xfffc
-
-/*
- * There is no real limitation of the queue depth (i.e. length of the linked
- * list of command ORBs) at the target. The chosen depth is merely an
- * implementation detail of the sbp2 driver.
- */
-#define SBP2_MAX_CMDS                          8
-
-#define SBP2_SCSI_STATUS_GOOD                  0x0
-#define SBP2_SCSI_STATUS_CHECK_CONDITION       0x2
-#define SBP2_SCSI_STATUS_CONDITION_MET         0x4
-#define SBP2_SCSI_STATUS_BUSY                  0x8
-#define SBP2_SCSI_STATUS_RESERVATION_CONFLICT  0x18
-#define SBP2_SCSI_STATUS_COMMAND_TERMINATED    0x22
-#define SBP2_SCSI_STATUS_SELECTION_TIMEOUT     0xff
-
-
-/*
- * Representations of commands and devices
- */
-
-/* Per SCSI command */
-struct sbp2_command_info {
-       struct list_head list;
-       struct sbp2_command_orb command_orb;
-       dma_addr_t command_orb_dma;
-       struct scsi_cmnd *Current_SCpnt;
-       void (*Current_done)(struct scsi_cmnd *);
-
-       /* Also need s/g structure for each sbp2 command */
-       struct sbp2_unrestricted_page_table
-               scatter_gather_element[SG_ALL] __attribute__((aligned(8)));
-       dma_addr_t sge_dma;
-};
-
-/* Per FireWire host */
-struct sbp2_fwhost_info {
-       struct hpsb_host *host;
-       struct list_head logical_units;
-};
-
-/* Per logical unit */
-struct sbp2_lu {
-       /* Operation request blocks */
-       struct sbp2_command_orb *last_orb;
-       dma_addr_t last_orb_dma;
-       struct sbp2_login_orb *login_orb;
-       dma_addr_t login_orb_dma;
-       struct sbp2_login_response *login_response;
-       dma_addr_t login_response_dma;
-       struct sbp2_query_logins_orb *query_logins_orb;
-       dma_addr_t query_logins_orb_dma;
-       struct sbp2_query_logins_response *query_logins_response;
-       dma_addr_t query_logins_response_dma;
-       struct sbp2_reconnect_orb *reconnect_orb;
-       dma_addr_t reconnect_orb_dma;
-       struct sbp2_logout_orb *logout_orb;
-       dma_addr_t logout_orb_dma;
-       struct sbp2_status_block status_block;
-
-       /* How to talk to the unit */
-       u64 management_agent_addr;
-       u64 command_block_agent_addr;
-       u32 speed_code;
-       u32 max_payload_size;
-       u16 lun;
-
-       /* Address for the unit to write status blocks to */
-       u64 status_fifo_addr;
-
-       /* Waitqueue flag for logins, reconnects, logouts, query logins */
-       unsigned int access_complete:1;
-
-       /* Pool of command ORBs for this logical unit */
-       spinlock_t cmd_orb_lock;
-       struct list_head cmd_orb_inuse;
-       struct list_head cmd_orb_completed;
-
-       /* Backlink to FireWire host; list of units attached to the host */
-       struct sbp2_fwhost_info *hi;
-       struct list_head lu_list;
-
-       /* IEEE 1394 core's device representations */
-       struct node_entry *ne;
-       struct unit_directory *ud;
-
-       /* SCSI core's device representations */
-       struct scsi_device *sdev;
-       struct Scsi_Host *shost;
-
-       /* Device specific workarounds/brokeness */
-       unsigned workarounds;
-
-       /* Connection state */
-       atomic_t state;
-
-       /* For deferred requests to the fetch agent */
-       struct work_struct protocol_work;
-};
-
-/* For use in sbp2_lu.state */
-enum sbp2lu_state_types {
-       SBP2LU_STATE_RUNNING,           /* all normal */
-       SBP2LU_STATE_IN_RESET,          /* between bus reset and reconnect */
-       SBP2LU_STATE_IN_SHUTDOWN        /* when sbp2_remove was called */
-};
-
-/* For use in sbp2_lu.workarounds and in the corresponding
- * module load parameter */
-#define SBP2_WORKAROUND_128K_MAX_TRANS 0x1
-#define SBP2_WORKAROUND_INQUIRY_36     0x2
-#define SBP2_WORKAROUND_MODE_SENSE_8   0x4
-#define SBP2_WORKAROUND_FIX_CAPACITY   0x8
-#define SBP2_WORKAROUND_DELAY_INQUIRY  0x10
-#define SBP2_INQUIRY_DELAY             12
-#define SBP2_WORKAROUND_POWER_CONDITION        0x20
-#define SBP2_WORKAROUND_OVERRIDE       0x100
-
-#endif /* SBP2_H */
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
deleted file mode 100644 (file)
index 5c74f79..0000000
+++ /dev/null
@@ -1,1528 +0,0 @@
-/*
- * video1394.c - video driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Peter Schlaile <udbz@rz.uni-karlsruhe.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * NOTES:
- *
- * ioctl return codes:
- * EFAULT is only for invalid address for the argp
- * EINVAL for out of range values
- * EBUSY when trying to use an already used resource
- * ESRCH when trying to free/stop a not used resource
- * EAGAIN for resource allocation failure that could perhaps succeed later
- * ENOTTY for unsupported ioctl request
- *
- */
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-#include <linux/timex.h>
-#include <linux/mm.h>
-#include <linux/compat.h>
-#include <linux/cdev.h>
-
-#include "dma.h"
-#include "highlevel.h"
-#include "hosts.h"
-#include "ieee1394.h"
-#include "ieee1394_core.h"
-#include "ieee1394_hotplug.h"
-#include "ieee1394_types.h"
-#include "nodemgr.h"
-#include "ohci1394.h"
-#include "video1394.h"
-
-#define ISO_CHANNELS 64
-
-struct it_dma_prg {
-       struct dma_cmd begin;
-       quadlet_t data[4];
-       struct dma_cmd end;
-       quadlet_t pad[4]; /* FIXME: quick hack for memory alignment */
-};
-
-struct dma_iso_ctx {
-       struct ti_ohci *ohci;
-       int type; /* OHCI_ISO_TRANSMIT or OHCI_ISO_RECEIVE */
-       struct ohci1394_iso_tasklet iso_tasklet;
-       int channel;
-       int ctx;
-       int last_buffer;
-       int * next_buffer;  /* For ISO Transmit of video packets
-                              to write the correct SYT field
-                              into the next block */
-       unsigned int num_desc;
-       unsigned int buf_size;
-       unsigned int frame_size;
-       unsigned int packet_size;
-       unsigned int left_size;
-       unsigned int nb_cmd;
-
-       struct dma_region dma;
-
-       struct dma_prog_region *prg_reg;
-
-        struct dma_cmd **ir_prg;
-       struct it_dma_prg **it_prg;
-
-       unsigned int *buffer_status;
-       unsigned int *buffer_prg_assignment;
-        struct timeval *buffer_time; /* time when the buffer was received */
-       unsigned int *last_used_cmd; /* For ISO Transmit with
-                                       variable sized packets only ! */
-       int ctrlClear;
-       int ctrlSet;
-       int cmdPtr;
-       int ctxMatch;
-       wait_queue_head_t waitq;
-       spinlock_t lock;
-       unsigned int syt_offset;
-       int flags;
-
-       struct list_head link;
-};
-
-
-struct file_ctx {
-       struct ti_ohci *ohci;
-       struct list_head context_list;
-       struct dma_iso_ctx *current_ctx;
-};
-
-#ifdef CONFIG_IEEE1394_VERBOSEDEBUG
-#define VIDEO1394_DEBUG
-#endif
-
-#ifdef DBGMSG
-#undef DBGMSG
-#endif
-
-#ifdef VIDEO1394_DEBUG
-#define DBGMSG(card, fmt, args...) \
-printk(KERN_INFO "video1394_%d: " fmt "\n" , card , ## args)
-#else
-#define DBGMSG(card, fmt, args...) do {} while (0)
-#endif
-
-/* print general (card independent) information */
-#define PRINT_G(level, fmt, args...) \
-printk(level "video1394: " fmt "\n" , ## args)
-
-/* print card specific information */
-#define PRINT(level, card, fmt, args...) \
-printk(level "video1394_%d: " fmt "\n" , card , ## args)
-
-static void wakeup_dma_ir_ctx(unsigned long l);
-static void wakeup_dma_it_ctx(unsigned long l);
-
-static struct hpsb_highlevel video1394_highlevel;
-
-static int free_dma_iso_ctx(struct dma_iso_ctx *d)
-{
-       int i;
-
-       DBGMSG(d->ohci->host->id, "Freeing dma_iso_ctx %d", d->ctx);
-
-       ohci1394_stop_context(d->ohci, d->ctrlClear, NULL);
-       if (d->iso_tasklet.link.next != NULL)
-               ohci1394_unregister_iso_tasklet(d->ohci, &d->iso_tasklet);
-
-       dma_region_free(&d->dma);
-
-       if (d->prg_reg) {
-               for (i = 0; i < d->num_desc; i++)
-                       dma_prog_region_free(&d->prg_reg[i]);
-               kfree(d->prg_reg);
-       }
-
-       kfree(d->ir_prg);
-       kfree(d->it_prg);
-       kfree(d->buffer_status);
-       kfree(d->buffer_prg_assignment);
-       kfree(d->buffer_time);
-       kfree(d->last_used_cmd);
-       kfree(d->next_buffer);
-       list_del(&d->link);
-       kfree(d);
-
-       return 0;
-}
-
-static struct dma_iso_ctx *
-alloc_dma_iso_ctx(struct ti_ohci *ohci, int type, int num_desc,
-                 int buf_size, int channel, unsigned int packet_size)
-{
-       struct dma_iso_ctx *d;
-       int i;
-
-       d = kzalloc(sizeof(*d), GFP_KERNEL);
-       if (!d) {
-               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma_iso_ctx");
-               return NULL;
-       }
-
-       d->ohci = ohci;
-       d->type = type;
-       d->channel = channel;
-       d->num_desc = num_desc;
-       d->frame_size = buf_size;
-       d->buf_size = PAGE_ALIGN(buf_size);
-       d->last_buffer = -1;
-       INIT_LIST_HEAD(&d->link);
-       init_waitqueue_head(&d->waitq);
-
-       /* Init the regions for easy cleanup */
-       dma_region_init(&d->dma);
-
-       if (dma_region_alloc(&d->dma, (d->num_desc - 1) * d->buf_size, ohci->dev,
-                            PCI_DMA_BIDIRECTIONAL)) {
-               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma buffer");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-
-       if (type == OHCI_ISO_RECEIVE)
-               ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
-                                         wakeup_dma_ir_ctx,
-                                         (unsigned long) d);
-       else
-               ohci1394_init_iso_tasklet(&d->iso_tasklet, type,
-                                         wakeup_dma_it_ctx,
-                                         (unsigned long) d);
-
-       if (ohci1394_register_iso_tasklet(ohci, &d->iso_tasklet) < 0) {
-               PRINT(KERN_ERR, ohci->host->id, "no free iso %s contexts",
-                     type == OHCI_ISO_RECEIVE ? "receive" : "transmit");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-       d->ctx = d->iso_tasklet.context;
-
-       d->prg_reg = kmalloc(d->num_desc * sizeof(*d->prg_reg), GFP_KERNEL);
-       if (!d->prg_reg) {
-               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate ir prg regs");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-       /* Makes for easier cleanup */
-       for (i = 0; i < d->num_desc; i++)
-               dma_prog_region_init(&d->prg_reg[i]);
-
-       if (type == OHCI_ISO_RECEIVE) {
-               d->ctrlSet = OHCI1394_IsoRcvContextControlSet+32*d->ctx;
-               d->ctrlClear = OHCI1394_IsoRcvContextControlClear+32*d->ctx;
-               d->cmdPtr = OHCI1394_IsoRcvCommandPtr+32*d->ctx;
-               d->ctxMatch = OHCI1394_IsoRcvContextMatch+32*d->ctx;
-
-               d->ir_prg = kzalloc(d->num_desc * sizeof(*d->ir_prg),
-                                   GFP_KERNEL);
-
-               if (!d->ir_prg) {
-                       PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
-                       free_dma_iso_ctx(d);
-                       return NULL;
-               }
-
-               d->nb_cmd = d->buf_size / PAGE_SIZE + 1;
-               d->left_size = (d->frame_size % PAGE_SIZE) ?
-                       d->frame_size % PAGE_SIZE : PAGE_SIZE;
-
-               for (i = 0;i < d->num_desc; i++) {
-                       if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
-                                                 sizeof(struct dma_cmd), ohci->dev)) {
-                               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma ir prg");
-                               free_dma_iso_ctx(d);
-                               return NULL;
-                       }
-                       d->ir_prg[i] = (struct dma_cmd *)d->prg_reg[i].kvirt;
-               }
-
-       } else {  /* OHCI_ISO_TRANSMIT */
-               d->ctrlSet = OHCI1394_IsoXmitContextControlSet+16*d->ctx;
-               d->ctrlClear = OHCI1394_IsoXmitContextControlClear+16*d->ctx;
-               d->cmdPtr = OHCI1394_IsoXmitCommandPtr+16*d->ctx;
-
-               d->it_prg = kzalloc(d->num_desc * sizeof(*d->it_prg),
-                                   GFP_KERNEL);
-
-               if (!d->it_prg) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Failed to allocate dma it prg");
-                       free_dma_iso_ctx(d);
-                       return NULL;
-               }
-
-               d->packet_size = packet_size;
-
-               if (PAGE_SIZE % packet_size || packet_size>4096) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Packet size %d (page_size: %ld) "
-                             "not yet supported\n",
-                             packet_size, PAGE_SIZE);
-                       free_dma_iso_ctx(d);
-                       return NULL;
-               }
-
-               d->nb_cmd = d->frame_size / d->packet_size;
-               if (d->frame_size % d->packet_size) {
-                       d->nb_cmd++;
-                       d->left_size = d->frame_size % d->packet_size;
-               } else
-                       d->left_size = d->packet_size;
-
-               for (i = 0; i < d->num_desc; i++) {
-                       if (dma_prog_region_alloc(&d->prg_reg[i], d->nb_cmd *
-                                               sizeof(struct it_dma_prg), ohci->dev)) {
-                               PRINT(KERN_ERR, ohci->host->id, "Failed to allocate dma it prg");
-                               free_dma_iso_ctx(d);
-                               return NULL;
-                       }
-                       d->it_prg[i] = (struct it_dma_prg *)d->prg_reg[i].kvirt;
-               }
-       }
-
-       d->buffer_status =
-           kzalloc(d->num_desc * sizeof(*d->buffer_status), GFP_KERNEL);
-       d->buffer_prg_assignment =
-           kzalloc(d->num_desc * sizeof(*d->buffer_prg_assignment), GFP_KERNEL);
-       d->buffer_time =
-           kzalloc(d->num_desc * sizeof(*d->buffer_time), GFP_KERNEL);
-       d->last_used_cmd =
-           kzalloc(d->num_desc * sizeof(*d->last_used_cmd), GFP_KERNEL);
-       d->next_buffer =
-           kzalloc(d->num_desc * sizeof(*d->next_buffer), GFP_KERNEL);
-
-       if (!d->buffer_status || !d->buffer_prg_assignment || !d->buffer_time ||
-           !d->last_used_cmd || !d->next_buffer) {
-               PRINT(KERN_ERR, ohci->host->id,
-                     "Failed to allocate dma_iso_ctx member");
-               free_dma_iso_ctx(d);
-               return NULL;
-       }
-
-        spin_lock_init(&d->lock);
-
-       DBGMSG(ohci->host->id, "Iso %s DMA: %d buffers "
-             "of size %d allocated for a frame size %d, each with %d prgs",
-             (type == OHCI_ISO_RECEIVE) ? "receive" : "transmit",
-             d->num_desc - 1, d->buf_size, d->frame_size, d->nb_cmd);
-
-       return d;
-}
-
-static void reset_ir_status(struct dma_iso_ctx *d, int n)
-{
-       int i;
-       d->ir_prg[n][0].status = cpu_to_le32(4);
-       d->ir_prg[n][1].status = cpu_to_le32(PAGE_SIZE-4);
-       for (i = 2; i < d->nb_cmd - 1; i++)
-               d->ir_prg[n][i].status = cpu_to_le32(PAGE_SIZE);
-       d->ir_prg[n][i].status = cpu_to_le32(d->left_size);
-}
-
-static void reprogram_dma_ir_prg(struct dma_iso_ctx *d, int n, int buffer, int flags)
-{
-       struct dma_cmd *ir_prg = d->ir_prg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
-       int i;
-
-       d->buffer_prg_assignment[n] = buffer;
-
-       ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
-                               (unsigned long)d->dma.kvirt));
-       ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                               (buf + 4) - (unsigned long)d->dma.kvirt));
-
-       for (i=2;i<d->nb_cmd-1;i++) {
-               ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                               (buf+(i-1)*PAGE_SIZE) -
-                                               (unsigned long)d->dma.kvirt));
-       }
-
-       ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                 DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-       ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                 (buf+(i-1)*PAGE_SIZE) - (unsigned long)d->dma.kvirt));
-}
-
-static void initialize_dma_ir_prg(struct dma_iso_ctx *d, int n, int flags)
-{
-       struct dma_cmd *ir_prg = d->ir_prg[n];
-       struct dma_prog_region *ir_reg = &d->prg_reg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt;
-       int i;
-
-       /* the first descriptor will read only 4 bytes */
-       ir_prg[0].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-               DMA_CTL_BRANCH | 4);
-
-       /* set the sync flag */
-       if (flags & VIDEO1394_SYNC_FRAMES)
-               ir_prg[0].control |= cpu_to_le32(DMA_CTL_WAIT);
-
-       ir_prg[0].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, buf -
-                               (unsigned long)d->dma.kvirt));
-       ir_prg[0].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-                                       1 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-
-       /* If there is *not* only one DMA page per frame (hence, d->nb_cmd==2) */
-       if (d->nb_cmd > 2) {
-               /* The second descriptor will read PAGE_SIZE-4 bytes */
-               ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                               DMA_CTL_BRANCH | (PAGE_SIZE-4));
-               ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf + 4) -
-                                               (unsigned long)d->dma.kvirt));
-               ir_prg[1].branchAddress = cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-                                                     2 * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-
-               for (i = 2; i < d->nb_cmd - 1; i++) {
-                       ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                                       DMA_CTL_BRANCH | PAGE_SIZE);
-                       ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                                       (buf+(i-1)*PAGE_SIZE) -
-                                                       (unsigned long)d->dma.kvirt));
-
-                       ir_prg[i].branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(ir_reg,
-                                           (i + 1) * sizeof(struct dma_cmd)) & 0xfffffff0) | 0x1);
-               }
-
-               /* The last descriptor will generate an interrupt */
-               ir_prg[i].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                               DMA_CTL_IRQ | DMA_CTL_BRANCH | d->left_size);
-               ir_prg[i].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                               (buf+(i-1)*PAGE_SIZE) -
-                                               (unsigned long)d->dma.kvirt));
-       } else {
-               /* Only one DMA page is used. Read d->left_size immediately and */
-               /* generate an interrupt as this is also the last page. */
-               ir_prg[1].control = cpu_to_le32(DMA_CTL_INPUT_MORE | DMA_CTL_UPDATE |
-                                               DMA_CTL_IRQ | DMA_CTL_BRANCH | (d->left_size-4));
-               ir_prg[1].address = cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                                               (buf + 4) - (unsigned long)d->dma.kvirt));
-       }
-}
-
-static void initialize_dma_ir_ctx(struct dma_iso_ctx *d, int tag, int flags)
-{
-       struct ti_ohci *ohci = (struct ti_ohci *)d->ohci;
-       int i;
-
-       d->flags = flags;
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       for (i=0;i<d->num_desc;i++) {
-               initialize_dma_ir_prg(d, i, flags);
-               reset_ir_status(d, i);
-       }
-
-       /* reset the ctrl register */
-       reg_write(ohci, d->ctrlClear, 0xf0000000);
-
-       /* Set bufferFill */
-       reg_write(ohci, d->ctrlSet, 0x80000000);
-
-       /* Set isoch header */
-       if (flags & VIDEO1394_INCLUDE_ISO_HEADERS)
-               reg_write(ohci, d->ctrlSet, 0x40000000);
-
-       /* Set the context match register to match on all tags,
-          sync for sync tag, and listen to d->channel */
-       reg_write(ohci, d->ctxMatch, 0xf0000000|((tag&0xf)<<8)|d->channel);
-
-       /* Set up isoRecvIntMask to generate interrupts */
-       reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, 1<<d->ctx);
-}
-
-/* find which context is listening to this channel */
-static struct dma_iso_ctx *
-find_ctx(struct list_head *list, int type, int channel)
-{
-       struct dma_iso_ctx *ctx;
-
-       list_for_each_entry(ctx, list, link) {
-               if (ctx->type == type && ctx->channel == channel)
-                       return ctx;
-       }
-
-       return NULL;
-}
-
-static void wakeup_dma_ir_ctx(unsigned long l)
-{
-       struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
-       int i;
-
-       spin_lock(&d->lock);
-
-       for (i = 0; i < d->num_desc; i++) {
-               if (d->ir_prg[i][d->nb_cmd-1].status & cpu_to_le32(0xFFFF0000)) {
-                       reset_ir_status(d, i);
-                       d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
-                       do_gettimeofday(&d->buffer_time[d->buffer_prg_assignment[i]]);
-                       dma_region_sync_for_cpu(&d->dma,
-                               d->buffer_prg_assignment[i] * d->buf_size,
-                               d->buf_size);
-               }
-       }
-
-       spin_unlock(&d->lock);
-
-       if (waitqueue_active(&d->waitq))
-               wake_up_interruptible(&d->waitq);
-}
-
-static inline void put_timestamp(struct ti_ohci *ohci, struct dma_iso_ctx * d,
-                                int n)
-{
-       unsigned char* buf = d->dma.kvirt + n * d->buf_size;
-       u32 cycleTimer;
-       u32 timeStamp;
-
-       if (n == -1) {
-         return;
-       }
-
-       cycleTimer = reg_read(ohci, OHCI1394_IsochronousCycleTimer);
-
-       timeStamp = ((cycleTimer & 0x0fff) + d->syt_offset); /* 11059 = 450 us */
-       timeStamp = (timeStamp % 3072 + ((timeStamp / 3072) << 12)
-               + (cycleTimer & 0xf000)) & 0xffff;
-
-       buf[6] = timeStamp >> 8;
-       buf[7] = timeStamp & 0xff;
-
-    /* if first packet is empty packet, then put timestamp into the next full one too */
-    if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) {
-           buf += d->packet_size;
-       buf[6] = timeStamp >> 8;
-           buf[7] = timeStamp & 0xff;
-       }
-
-    /* do the next buffer frame too in case of irq latency */
-       n = d->next_buffer[n];
-       if (n == -1) {
-         return;
-       }
-       buf = d->dma.kvirt + n * d->buf_size;
-
-       timeStamp += (d->last_used_cmd[n] << 12) & 0xffff;
-
-       buf[6] = timeStamp >> 8;
-       buf[7] = timeStamp & 0xff;
-
-    /* if first packet is empty packet, then put timestamp into the next full one too */
-    if ( (le32_to_cpu(d->it_prg[n][0].data[1]) >>16) == 0x008) {
-           buf += d->packet_size;
-       buf[6] = timeStamp >> 8;
-           buf[7] = timeStamp & 0xff;
-       }
-
-#if 0
-       printk("curr: %d, next: %d, cycleTimer: %08x timeStamp: %08x\n",
-              curr, n, cycleTimer, timeStamp);
-#endif
-}
-
-static void wakeup_dma_it_ctx(unsigned long l)
-{
-       struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
-       struct ti_ohci *ohci = d->ohci;
-       int i;
-
-       spin_lock(&d->lock);
-
-       for (i = 0; i < d->num_desc; i++) {
-               if (d->it_prg[i][d->last_used_cmd[i]].end.status &
-                   cpu_to_le32(0xFFFF0000)) {
-                       int next = d->next_buffer[i];
-                       put_timestamp(ohci, d, next);
-                       d->it_prg[i][d->last_used_cmd[i]].end.status = 0;
-                       d->buffer_status[d->buffer_prg_assignment[i]] = VIDEO1394_BUFFER_READY;
-               }
-       }
-
-       spin_unlock(&d->lock);
-
-       if (waitqueue_active(&d->waitq))
-               wake_up_interruptible(&d->waitq);
-}
-
-static void reprogram_dma_it_prg(struct dma_iso_ctx  *d, int n, int buffer)
-{
-       struct it_dma_prg *it_prg = d->it_prg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt + buffer * d->buf_size;
-       int i;
-
-       d->buffer_prg_assignment[n] = buffer;
-       for (i=0;i<d->nb_cmd;i++) {
-         it_prg[i].end.address =
-               cpu_to_le32(dma_region_offset_to_bus(&d->dma,
-                       (buf+i*d->packet_size) - (unsigned long)d->dma.kvirt));
-       }
-}
-
-static void initialize_dma_it_prg(struct dma_iso_ctx *d, int n, int sync_tag)
-{
-       struct it_dma_prg *it_prg = d->it_prg[n];
-       struct dma_prog_region *it_reg = &d->prg_reg[n];
-       unsigned long buf = (unsigned long)d->dma.kvirt;
-       int i;
-       d->last_used_cmd[n] = d->nb_cmd - 1;
-       for (i=0;i<d->nb_cmd;i++) {
-
-               it_prg[i].begin.control = cpu_to_le32(DMA_CTL_OUTPUT_MORE |
-                       DMA_CTL_IMMEDIATE | 8) ;
-               it_prg[i].begin.address = 0;
-
-               it_prg[i].begin.status = 0;
-
-               it_prg[i].data[0] = cpu_to_le32(
-                       (IEEE1394_SPEED_100 << 16)
-                       | (/* tag */ 1 << 14)
-                       | (d->channel << 8)
-                       | (TCODE_ISO_DATA << 4));
-               if (i==0) it_prg[i].data[0] |= cpu_to_le32(sync_tag);
-               it_prg[i].data[1] = cpu_to_le32(d->packet_size << 16);
-               it_prg[i].data[2] = 0;
-               it_prg[i].data[3] = 0;
-
-               it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST |
-                                            DMA_CTL_BRANCH);
-               it_prg[i].end.address =
-                       cpu_to_le32(dma_region_offset_to_bus(&d->dma, (buf+i*d->packet_size) -
-                                               (unsigned long)d->dma.kvirt));
-
-               if (i<d->nb_cmd-1) {
-                       it_prg[i].end.control |= cpu_to_le32(d->packet_size);
-                       it_prg[i].begin.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-                       it_prg[i].end.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-               } else {
-                       /* the last prg generates an interrupt */
-                       it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE |
-                               DMA_CTL_IRQ | d->left_size);
-                       /* the last prg doesn't branch */
-                       it_prg[i].begin.branchAddress = 0;
-                       it_prg[i].end.branchAddress = 0;
-               }
-               it_prg[i].end.status = 0;
-       }
-}
-
-static void initialize_dma_it_prg_var_packet_queue(
-       struct dma_iso_ctx *d, int n, unsigned int * packet_sizes,
-       struct ti_ohci *ohci)
-{
-       struct it_dma_prg *it_prg = d->it_prg[n];
-       struct dma_prog_region *it_reg = &d->prg_reg[n];
-       int i;
-
-#if 0
-       if (n != -1) {
-               put_timestamp(ohci, d, n);
-       }
-#endif
-       d->last_used_cmd[n] = d->nb_cmd - 1;
-
-       for (i = 0; i < d->nb_cmd; i++) {
-               unsigned int size;
-               if (packet_sizes[i] > d->packet_size) {
-                       size = d->packet_size;
-               } else {
-                       size = packet_sizes[i];
-               }
-               it_prg[i].data[1] = cpu_to_le32(size << 16);
-               it_prg[i].end.control = cpu_to_le32(DMA_CTL_OUTPUT_LAST | DMA_CTL_BRANCH);
-
-               if (i < d->nb_cmd-1 && packet_sizes[i+1] != 0) {
-                       it_prg[i].end.control |= cpu_to_le32(size);
-                       it_prg[i].begin.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-                       it_prg[i].end.branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(it_reg, (i + 1) *
-                                       sizeof(struct it_dma_prg)) & 0xfffffff0) | 0x3);
-               } else {
-                       /* the last prg generates an interrupt */
-                       it_prg[i].end.control |= cpu_to_le32(DMA_CTL_UPDATE |
-                               DMA_CTL_IRQ | size);
-                       /* the last prg doesn't branch */
-                       it_prg[i].begin.branchAddress = 0;
-                       it_prg[i].end.branchAddress = 0;
-                       d->last_used_cmd[n] = i;
-                       break;
-               }
-       }
-}
-
-static void initialize_dma_it_ctx(struct dma_iso_ctx *d, int sync_tag,
-                                 unsigned int syt_offset, int flags)
-{
-       struct ti_ohci *ohci = (struct ti_ohci *)d->ohci;
-       int i;
-
-       d->flags = flags;
-       d->syt_offset = (syt_offset == 0 ? 11000 : syt_offset);
-
-       ohci1394_stop_context(ohci, d->ctrlClear, NULL);
-
-       for (i=0;i<d->num_desc;i++)
-               initialize_dma_it_prg(d, i, sync_tag);
-
-       /* Set up isoRecvIntMask to generate interrupts */
-       reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1<<d->ctx);
-}
-
-static inline unsigned video1394_buffer_state(struct dma_iso_ctx *d,
-                                             unsigned int buffer)
-{
-       unsigned long flags;
-       unsigned int ret;
-       spin_lock_irqsave(&d->lock, flags);
-       ret = d->buffer_status[buffer];
-       spin_unlock_irqrestore(&d->lock, flags);
-       return ret;
-}
-
-static long video1394_ioctl(struct file *file,
-                           unsigned int cmd, unsigned long arg)
-{
-       struct file_ctx *ctx = file->private_data;
-       struct ti_ohci *ohci = ctx->ohci;
-       unsigned long flags;
-       void __user *argp = (void __user *)arg;
-
-       switch(cmd)
-       {
-       case VIDEO1394_IOC_LISTEN_CHANNEL:
-       case VIDEO1394_IOC_TALK_CHANNEL:
-       {
-               struct video1394_mmap v;
-               u64 mask;
-               struct dma_iso_ctx *d;
-               int i;
-
-               if (copy_from_user(&v, argp, sizeof(v)))
-                       return -EFAULT;
-
-               /* if channel < 0, find lowest available one */
-               if (v.channel < 0) {
-                   mask = (u64)0x1;
-                   for (i=0; ; i++) {
-                       if (i == ISO_CHANNELS) {
-                           PRINT(KERN_ERR, ohci->host->id, 
-                                 "No free channel found");
-                           return -EAGAIN;
-                       }
-                       if (!(ohci->ISO_channel_usage & mask)) {
-                           v.channel = i;
-                           PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i);
-                           break;
-                       }
-                       mask = mask << 1;
-                   }
-               } else if (v.channel >= ISO_CHANNELS) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Iso channel %d out of bounds", v.channel);
-                       return -EINVAL;
-               } else {
-                       mask = (u64)0x1<<v.channel;
-               }
-               DBGMSG(ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",
-                       (u32)(mask>>32),(u32)(mask&0xffffffff),
-                       (u32)(ohci->ISO_channel_usage>>32),
-                       (u32)(ohci->ISO_channel_usage&0xffffffff));
-               if (ohci->ISO_channel_usage & mask) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Channel %d is already taken", v.channel);
-                       return -EBUSY;
-               }
-
-               if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Invalid %d length buffer requested",v.buf_size);
-                       return -EINVAL;
-               }
-
-               if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Invalid %d buffers requested",v.nb_buffers);
-                       return -EINVAL;
-               }
-
-               if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "%d buffers of size %d bytes is too big",
-                             v.nb_buffers, v.buf_size);
-                       return -EINVAL;
-               }
-
-               if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
-                       d = alloc_dma_iso_ctx(ohci, OHCI_ISO_RECEIVE,
-                                             v.nb_buffers + 1, v.buf_size,
-                                             v.channel, 0);
-
-                       if (d == NULL) {
-                               PRINT(KERN_ERR, ohci->host->id,
-                                     "Couldn't allocate ir context");
-                               return -EAGAIN;
-                       }
-                       initialize_dma_ir_ctx(d, v.sync_tag, v.flags);
-
-                       ctx->current_ctx = d;
-
-                       v.buf_size = d->buf_size;
-                       list_add_tail(&d->link, &ctx->context_list);
-
-                       DBGMSG(ohci->host->id,
-                             "iso context %d listen on channel %d",
-                             d->ctx, v.channel);
-               }
-               else {
-                       d = alloc_dma_iso_ctx(ohci, OHCI_ISO_TRANSMIT,
-                                             v.nb_buffers + 1, v.buf_size,
-                                             v.channel, v.packet_size);
-
-                       if (d == NULL) {
-                               PRINT(KERN_ERR, ohci->host->id,
-                                     "Couldn't allocate it context");
-                               return -EAGAIN;
-                       }
-                       initialize_dma_it_ctx(d, v.sync_tag,
-                                             v.syt_offset, v.flags);
-
-                       ctx->current_ctx = d;
-
-                       v.buf_size = d->buf_size;
-
-                       list_add_tail(&d->link, &ctx->context_list);
-
-                       DBGMSG(ohci->host->id,
-                             "Iso context %d talk on channel %d", d->ctx,
-                             v.channel);
-               }
-
-               if (copy_to_user(argp, &v, sizeof(v))) {
-                       /* FIXME : free allocated dma resources */
-                       return -EFAULT;
-               }
-               
-               ohci->ISO_channel_usage |= mask;
-
-               return 0;
-       }
-       case VIDEO1394_IOC_UNLISTEN_CHANNEL:
-       case VIDEO1394_IOC_UNTALK_CHANNEL:
-       {
-               int channel;
-               u64 mask;
-               struct dma_iso_ctx *d;
-
-               if (copy_from_user(&channel, argp, sizeof(int)))
-                       return -EFAULT;
-
-               if (channel < 0 || channel >= ISO_CHANNELS) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Iso channel %d out of bound", channel);
-                       return -EINVAL;
-               }
-               mask = (u64)0x1<<channel;
-               if (!(ohci->ISO_channel_usage & mask)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Channel %d is not being used", channel);
-                       return -ESRCH;
-               }
-
-               /* Mark this channel as unused */
-               ohci->ISO_channel_usage &= ~mask;
-
-               if (cmd == VIDEO1394_IOC_UNLISTEN_CHANNEL)
-                       d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, channel);
-               else
-                       d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
-
-               if (d == NULL) return -ESRCH;
-               DBGMSG(ohci->host->id, "Iso context %d "
-                     "stop talking on channel %d", d->ctx, channel);
-               free_dma_iso_ctx(d);
-
-               return 0;
-       }
-       case VIDEO1394_IOC_LISTEN_QUEUE_BUFFER:
-       {
-               struct video1394_wait v;
-               struct dma_iso_ctx *d;
-               int next_prg;
-
-               if (unlikely(copy_from_user(&v, argp, sizeof(v))))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
-               if (unlikely(d == NULL))
-                       return -EFAULT;
-
-               if (unlikely(v.buffer >= d->num_desc - 1)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               spin_lock_irqsave(&d->lock,flags);
-
-               if (unlikely(d->buffer_status[v.buffer]==VIDEO1394_BUFFER_QUEUED)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is already used",v.buffer);
-                       spin_unlock_irqrestore(&d->lock,flags);
-                       return -EBUSY;
-               }
-
-               d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
-
-               next_prg = (d->last_buffer + 1) % d->num_desc;
-               if (d->last_buffer>=0)
-                       d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress =
-                               cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0)
-                                       & 0xfffffff0) | 0x1);
-
-               d->last_buffer = next_prg;
-               reprogram_dma_ir_prg(d, d->last_buffer, v.buffer, d->flags);
-
-               d->ir_prg[d->last_buffer][d->nb_cmd-1].branchAddress = 0;
-
-               spin_unlock_irqrestore(&d->lock,flags);
-
-               if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
-               {
-                       DBGMSG(ohci->host->id, "Starting iso DMA ctx=%d",d->ctx);
-
-                       /* Tell the controller where the first program is */
-                       reg_write(ohci, d->cmdPtr,
-                                 dma_prog_region_offset_to_bus(&d->prg_reg[d->last_buffer], 0) | 0x1);
-
-                       /* Run IR context */
-                       reg_write(ohci, d->ctrlSet, 0x8000);
-               }
-               else {
-                       /* Wake up dma context if necessary */
-                       if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-                               DBGMSG(ohci->host->id,
-                                     "Waking up iso dma ctx=%d", d->ctx);
-                               reg_write(ohci, d->ctrlSet, 0x1000);
-                       }
-               }
-               return 0;
-
-       }
-       case VIDEO1394_IOC_LISTEN_WAIT_BUFFER:
-       case VIDEO1394_IOC_LISTEN_POLL_BUFFER:
-       {
-               struct video1394_wait v;
-               struct dma_iso_ctx *d;
-               int i = 0;
-
-               if (unlikely(copy_from_user(&v, argp, sizeof(v))))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_RECEIVE, v.channel);
-               if (unlikely(d == NULL))
-                       return -EFAULT;
-
-               if (unlikely(v.buffer > d->num_desc - 1)) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               /*
-                * I change the way it works so that it returns
-                * the last received frame.
-                */
-               spin_lock_irqsave(&d->lock, flags);
-               switch(d->buffer_status[v.buffer]) {
-               case VIDEO1394_BUFFER_READY:
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       break;
-               case VIDEO1394_BUFFER_QUEUED:
-                       if (cmd == VIDEO1394_IOC_LISTEN_POLL_BUFFER) {
-                           /* for polling, return error code EINTR */
-                           spin_unlock_irqrestore(&d->lock, flags);
-                           return -EINTR;
-                       }
-
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       wait_event_interruptible(d->waitq,
-                                       video1394_buffer_state(d, v.buffer) ==
-                                        VIDEO1394_BUFFER_READY);
-                       if (signal_pending(current))
-                                return -EINTR;
-                       spin_lock_irqsave(&d->lock, flags);
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       break;
-               default:
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is not queued",v.buffer);
-                       spin_unlock_irqrestore(&d->lock, flags);
-                       return -ESRCH;
-               }
-
-               /* set time of buffer */
-               v.filltime = d->buffer_time[v.buffer];
-
-               /*
-                * Look ahead to see how many more buffers have been received
-                */
-               i=0;
-               while (d->buffer_status[(v.buffer+1)%(d->num_desc - 1)]==
-                      VIDEO1394_BUFFER_READY) {
-                       v.buffer=(v.buffer+1)%(d->num_desc - 1);
-                       i++;
-               }
-               spin_unlock_irqrestore(&d->lock, flags);
-
-               v.buffer=i;
-               if (unlikely(copy_to_user(argp, &v, sizeof(v))))
-                       return -EFAULT;
-
-               return 0;
-       }
-       case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
-       {
-               struct video1394_wait v;
-               unsigned int *psizes = NULL;
-               struct dma_iso_ctx *d;
-               int next_prg;
-
-               if (copy_from_user(&v, argp, sizeof(v)))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
-               if (d == NULL) return -EFAULT;
-
-               if (v.buffer >= d->num_desc - 1) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
-                       int buf_size = d->nb_cmd * sizeof(*psizes);
-                       struct video1394_queue_variable __user *p = argp;
-                       unsigned int __user *qv;
-
-                       if (get_user(qv, &p->packet_sizes))
-                               return -EFAULT;
-
-                       psizes = memdup_user(qv, buf_size);
-                       if (IS_ERR(psizes))
-                               return PTR_ERR(psizes);
-               }
-
-               spin_lock_irqsave(&d->lock,flags);
-
-               /* last_buffer is last_prg */
-               next_prg = (d->last_buffer + 1) % d->num_desc;
-               if (d->buffer_status[v.buffer]!=VIDEO1394_BUFFER_FREE) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is already used",v.buffer);
-                       spin_unlock_irqrestore(&d->lock,flags);
-                       kfree(psizes);
-                       return -EBUSY;
-               }
-
-               if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
-                       initialize_dma_it_prg_var_packet_queue(
-                               d, next_prg, psizes, ohci);
-               }
-
-               d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
-
-               if (d->last_buffer >= 0) {
-                       d->it_prg[d->last_buffer]
-                               [ d->last_used_cmd[d->last_buffer] ].end.branchAddress =
-                                       cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
-                                               0) & 0xfffffff0) | 0x3);
-
-                       d->it_prg[d->last_buffer]
-                               [ d->last_used_cmd[d->last_buffer] ].begin.branchAddress =
-                                       cpu_to_le32((dma_prog_region_offset_to_bus(&d->prg_reg[next_prg],
-                                               0) & 0xfffffff0) | 0x3);
-                       d->next_buffer[d->last_buffer] = (v.buffer + 1) % (d->num_desc - 1);
-               }
-               d->last_buffer = next_prg;
-               reprogram_dma_it_prg(d, d->last_buffer, v.buffer);
-               d->next_buffer[d->last_buffer] = -1;
-
-               d->it_prg[d->last_buffer][d->last_used_cmd[d->last_buffer]].end.branchAddress = 0;
-
-               spin_unlock_irqrestore(&d->lock,flags);
-
-               if (!(reg_read(ohci, d->ctrlSet) & 0x8000))
-               {
-                       DBGMSG(ohci->host->id, "Starting iso transmit DMA ctx=%d",
-                              d->ctx);
-                       put_timestamp(ohci, d, d->last_buffer);
-                       dma_region_sync_for_device(&d->dma,
-                               v.buffer * d->buf_size, d->buf_size);
-
-                       /* Tell the controller where the first program is */
-                       reg_write(ohci, d->cmdPtr,
-                               dma_prog_region_offset_to_bus(&d->prg_reg[next_prg], 0) | 0x3);
-
-                       /* Run IT context */
-                       reg_write(ohci, d->ctrlSet, 0x8000);
-               }
-               else {
-                       /* Wake up dma context if necessary */
-                       if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
-                               DBGMSG(ohci->host->id,
-                                     "Waking up iso transmit dma ctx=%d",
-                                     d->ctx);
-                               put_timestamp(ohci, d, d->last_buffer);
-                               dma_region_sync_for_device(&d->dma,
-                                       v.buffer * d->buf_size, d->buf_size);
-
-                               reg_write(ohci, d->ctrlSet, 0x1000);
-                       }
-               }
-
-               kfree(psizes);
-               return 0;
-
-       }
-       case VIDEO1394_IOC_TALK_WAIT_BUFFER:
-       {
-               struct video1394_wait v;
-               struct dma_iso_ctx *d;
-
-               if (copy_from_user(&v, argp, sizeof(v)))
-                       return -EFAULT;
-
-               d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, v.channel);
-               if (d == NULL) return -EFAULT;
-
-               if (v.buffer >= d->num_desc - 1) {
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d out of range",v.buffer);
-                       return -EINVAL;
-               }
-
-               switch(d->buffer_status[v.buffer]) {
-               case VIDEO1394_BUFFER_READY:
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       return 0;
-               case VIDEO1394_BUFFER_QUEUED:
-                       wait_event_interruptible(d->waitq,
-                                       (d->buffer_status[v.buffer] == VIDEO1394_BUFFER_READY));
-                       if (signal_pending(current))
-                               return -EINTR;
-                       d->buffer_status[v.buffer]=VIDEO1394_BUFFER_FREE;
-                       return 0;
-               default:
-                       PRINT(KERN_ERR, ohci->host->id,
-                             "Buffer %d is not queued",v.buffer);
-                       return -ESRCH;
-               }
-       }
-       default:
-               return -ENOTTY;
-       }
-}
-
-/*
- *     This maps the vmalloced and reserved buffer to user space.
- *
- *  FIXME:
- *  - PAGE_READONLY should suffice!?
- *  - remap_pfn_range is kind of inefficient for page by page remapping.
- *    But e.g. pte_alloc() does not work in modules ... :-(
- */
-
-static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
-{
-       struct file_ctx *ctx = file->private_data;
-
-       if (ctx->current_ctx == NULL) {
-               PRINT(KERN_ERR, ctx->ohci->host->id,
-                               "Current iso context not set");
-               return -EINVAL;
-       }
-
-       return dma_region_mmap(&ctx->current_ctx->dma, file, vma);
-}
-
-static unsigned int video1394_poll(struct file *file, poll_table *pt)
-{
-       struct file_ctx *ctx;
-       unsigned int mask = 0;
-       unsigned long flags;
-       struct dma_iso_ctx *d;
-       int i;
-
-       ctx = file->private_data;
-       d = ctx->current_ctx;
-       if (d == NULL) {
-               PRINT(KERN_ERR, ctx->ohci->host->id,
-                               "Current iso context not set");
-               return POLLERR;
-       }
-
-       poll_wait(file, &d->waitq, pt);
-
-       spin_lock_irqsave(&d->lock, flags);
-       for (i = 0; i < d->num_desc; i++) {
-               if (d->buffer_status[i] == VIDEO1394_BUFFER_READY) {
-                       mask |= POLLIN | POLLRDNORM;
-                       break;
-               }
-       }
-       spin_unlock_irqrestore(&d->lock, flags);
-
-       return mask;
-}
-
-static int video1394_open(struct inode *inode, struct file *file)
-{
-       int i = ieee1394_file_to_instance(file);
-       struct ti_ohci *ohci;
-       struct file_ctx *ctx;
-
-       ohci = hpsb_get_hostinfo_bykey(&video1394_highlevel, i);
-        if (ohci == NULL)
-                return -EIO;
-
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
-       if (!ctx)  {
-               PRINT(KERN_ERR, ohci->host->id, "Cannot malloc file_ctx");
-               return -ENOMEM;
-       }
-
-       ctx->ohci = ohci;
-       INIT_LIST_HEAD(&ctx->context_list);
-       ctx->current_ctx = NULL;
-       file->private_data = ctx;
-
-       return nonseekable_open(inode, file);
-}
-
-static int video1394_release(struct inode *inode, struct file *file)
-{
-       struct file_ctx *ctx = file->private_data;
-       struct ti_ohci *ohci = ctx->ohci;
-       struct list_head *lh, *next;
-       u64 mask;
-
-       list_for_each_safe(lh, next, &ctx->context_list) {
-               struct dma_iso_ctx *d;
-               d = list_entry(lh, struct dma_iso_ctx, link);
-               mask = (u64) 1 << d->channel;
-
-               if (!(ohci->ISO_channel_usage & mask))
-                       PRINT(KERN_ERR, ohci->host->id, "On release: Channel %d "
-                             "is not being used", d->channel);
-               else
-                       ohci->ISO_channel_usage &= ~mask;
-               DBGMSG(ohci->host->id, "On release: Iso %s context "
-                     "%d stop listening on channel %d",
-                     d->type == OHCI_ISO_RECEIVE ? "receive" : "transmit",
-                     d->ctx, d->channel);
-               free_dma_iso_ctx(d);
-       }
-
-       kfree(ctx);
-       file->private_data = NULL;
-
-       return 0;
-}
-
-#ifdef CONFIG_COMPAT
-static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg);
-#endif
-
-static struct cdev video1394_cdev;
-static const struct file_operations video1394_fops=
-{
-       .owner =        THIS_MODULE,
-       .unlocked_ioctl = video1394_ioctl,
-#ifdef CONFIG_COMPAT
-       .compat_ioctl = video1394_compat_ioctl,
-#endif
-       .poll =         video1394_poll,
-       .mmap =         video1394_mmap,
-       .open =         video1394_open,
-       .release =      video1394_release,
-       .llseek =       no_llseek,
-};
-
-/*** HOTPLUG STUFF **********************************************************/
-/*
- * Export information about protocols/devices supported by this driver.
- */
-#ifdef MODULE
-static const struct ieee1394_device_id video1394_id_table[] = {
-       {
-               .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-               .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-               .version        = CAMERA_SW_VERSION_ENTRY & 0xffffff
-       },
-        {
-                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-                .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-                .version        = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff
-        },
-        {
-                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-                .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-                .version        = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff
-        },
-       { }
-};
-
-MODULE_DEVICE_TABLE(ieee1394, video1394_id_table);
-#endif /* MODULE */
-
-static struct hpsb_protocol_driver video1394_driver = {
-       .name = VIDEO1394_DRIVER_NAME,
-};
-
-
-static void video1394_add_host (struct hpsb_host *host)
-{
-       struct ti_ohci *ohci;
-       int minor;
-
-       /* We only work with the OHCI-1394 driver */
-       if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
-               return;
-
-       ohci = (struct ti_ohci *)host->hostdata;
-
-       if (!hpsb_create_hostinfo(&video1394_highlevel, host, 0)) {
-               PRINT(KERN_ERR, ohci->host->id, "Cannot allocate hostinfo");
-               return;
-       }
-
-       hpsb_set_hostinfo(&video1394_highlevel, host, ohci);
-       hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
-
-       minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
-       device_create(hpsb_protocol_class, NULL, MKDEV(IEEE1394_MAJOR, minor),
-                     NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
-}
-
-
-static void video1394_remove_host (struct hpsb_host *host)
-{
-       struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
-
-       if (ohci)
-               device_destroy(hpsb_protocol_class, MKDEV(IEEE1394_MAJOR,
-                              IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
-       return;
-}
-
-
-static struct hpsb_highlevel video1394_highlevel = {
-       .name =         VIDEO1394_DRIVER_NAME,
-       .add_host =     video1394_add_host,
-       .remove_host =  video1394_remove_host,
-};
-
-MODULE_AUTHOR("Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>");
-MODULE_DESCRIPTION("driver for digital video on OHCI board");
-MODULE_SUPPORTED_DEVICE(VIDEO1394_DRIVER_NAME);
-MODULE_LICENSE("GPL");
-
-#ifdef CONFIG_COMPAT
-
-#define VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER     \
-       _IOW ('#', 0x12, struct video1394_wait32)
-#define VIDEO1394_IOC32_LISTEN_WAIT_BUFFER      \
-       _IOWR('#', 0x13, struct video1394_wait32)
-#define VIDEO1394_IOC32_TALK_WAIT_BUFFER        \
-       _IOW ('#', 0x17, struct video1394_wait32)
-#define VIDEO1394_IOC32_LISTEN_POLL_BUFFER      \
-       _IOWR('#', 0x18, struct video1394_wait32)
-
-struct video1394_wait32 {
-       u32 channel;
-       u32 buffer;
-       struct compat_timeval filltime;
-};
-
-static int video1394_wr_wait32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-        struct video1394_wait32 __user *argp = (void __user *)arg;
-        struct video1394_wait32 wait32;
-        struct video1394_wait wait;
-        mm_segment_t old_fs;
-        int ret;
-
-        if (copy_from_user(&wait32, argp, sizeof(wait32)))
-                return -EFAULT;
-
-        wait.channel = wait32.channel;
-        wait.buffer = wait32.buffer;
-        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
-        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
-
-        old_fs = get_fs();
-        set_fs(KERNEL_DS);
-        if (cmd == VIDEO1394_IOC32_LISTEN_WAIT_BUFFER)
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_LISTEN_WAIT_BUFFER,
-                                     (unsigned long) &wait);
-        else
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_LISTEN_POLL_BUFFER,
-                                     (unsigned long) &wait);
-        set_fs(old_fs);
-
-        if (!ret) {
-                wait32.channel = wait.channel;
-                wait32.buffer = wait.buffer;
-                wait32.filltime.tv_sec = (int)wait.filltime.tv_sec;
-                wait32.filltime.tv_usec = (int)wait.filltime.tv_usec;
-
-                if (copy_to_user(argp, &wait32, sizeof(wait32)))
-                        ret = -EFAULT;
-        }
-
-        return ret;
-}
-
-static int video1394_w_wait32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-        struct video1394_wait32 wait32;
-        struct video1394_wait wait;
-        mm_segment_t old_fs;
-        int ret;
-
-        if (copy_from_user(&wait32, (void __user *)arg, sizeof(wait32)))
-                return -EFAULT;
-
-        wait.channel = wait32.channel;
-        wait.buffer = wait32.buffer;
-        wait.filltime.tv_sec = (time_t)wait32.filltime.tv_sec;
-        wait.filltime.tv_usec = (suseconds_t)wait32.filltime.tv_usec;
-
-        old_fs = get_fs();
-        set_fs(KERNEL_DS);
-        if (cmd == VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER)
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_LISTEN_QUEUE_BUFFER,
-                                     (unsigned long) &wait);
-        else
-               ret = video1394_ioctl(file,
-                                     VIDEO1394_IOC_TALK_WAIT_BUFFER,
-                                     (unsigned long) &wait);
-        set_fs(old_fs);
-
-        return ret;
-}
-
-static int video1394_queue_buf32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-        return -EFAULT;   /* ??? was there before. */
-
-       return video1394_ioctl(file,
-                               VIDEO1394_IOC_TALK_QUEUE_BUFFER, arg);
-}
-
-static long video1394_compat_ioctl(struct file *f, unsigned cmd, unsigned long arg)
-{
-       switch (cmd) {
-       case VIDEO1394_IOC_LISTEN_CHANNEL:
-       case VIDEO1394_IOC_UNLISTEN_CHANNEL:
-       case VIDEO1394_IOC_TALK_CHANNEL:
-       case VIDEO1394_IOC_UNTALK_CHANNEL:
-               return video1394_ioctl(f, cmd, arg);
-
-       case VIDEO1394_IOC32_LISTEN_QUEUE_BUFFER:
-               return video1394_w_wait32(f, cmd, arg);
-       case VIDEO1394_IOC32_LISTEN_WAIT_BUFFER:
-               return video1394_wr_wait32(f, cmd, arg);
-       case VIDEO1394_IOC_TALK_QUEUE_BUFFER:
-               return video1394_queue_buf32(f, cmd, arg);
-       case VIDEO1394_IOC32_TALK_WAIT_BUFFER:
-               return video1394_w_wait32(f, cmd, arg);
-       case VIDEO1394_IOC32_LISTEN_POLL_BUFFER:
-               return video1394_wr_wait32(f, cmd, arg);
-       default:
-               return -ENOIOCTLCMD;
-       }
-}
-
-#endif /* CONFIG_COMPAT */
-
-static void __exit video1394_exit_module (void)
-{
-       hpsb_unregister_protocol(&video1394_driver);
-       hpsb_unregister_highlevel(&video1394_highlevel);
-       cdev_del(&video1394_cdev);
-       PRINT_G(KERN_INFO, "Removed " VIDEO1394_DRIVER_NAME " module");
-}
-
-static int __init video1394_init_module (void)
-{
-       int ret;
-
-       hpsb_init_highlevel(&video1394_highlevel);
-
-       cdev_init(&video1394_cdev, &video1394_fops);
-       video1394_cdev.owner = THIS_MODULE;
-       ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
-       if (ret) {
-               PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
-               return ret;
-        }
-
-       hpsb_register_highlevel(&video1394_highlevel);
-
-       ret = hpsb_register_protocol(&video1394_driver);
-       if (ret) {
-               PRINT_G(KERN_ERR, "video1394: failed to register protocol");
-               hpsb_unregister_highlevel(&video1394_highlevel);
-               cdev_del(&video1394_cdev);
-               return ret;
-       }
-
-       PRINT_G(KERN_INFO, "Installed " VIDEO1394_DRIVER_NAME " module");
-       return 0;
-}
-
-
-module_init(video1394_init_module);
-module_exit(video1394_exit_module);
diff --git a/drivers/ieee1394/video1394.h b/drivers/ieee1394/video1394.h
deleted file mode 100644 (file)
index 9a89d9c..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * video1394.h - driver for OHCI 1394 boards
- * Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
- *                        Peter Schlaile <udbz@rz.uni-karlsruhe.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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _VIDEO_1394_H
-#define _VIDEO_1394_H
-
-#include "ieee1394-ioctl.h"
-
-#define VIDEO1394_DRIVER_NAME "video1394"
-
-#define VIDEO1394_MAX_SIZE 0x4000000
-
-enum {
-       VIDEO1394_BUFFER_FREE = 0,
-       VIDEO1394_BUFFER_QUEUED,
-       VIDEO1394_BUFFER_READY
-};
-
-#define VIDEO1394_SYNC_FRAMES          0x00000001
-#define VIDEO1394_INCLUDE_ISO_HEADERS  0x00000002
-#define VIDEO1394_VARIABLE_PACKET_SIZE 0x00000004
-
-struct video1394_mmap {
-       int channel;                    /* -1 to find an open channel in LISTEN/TALK */
-       unsigned int sync_tag;
-       unsigned int nb_buffers;
-       unsigned int buf_size;
-       unsigned int packet_size; /* For VARIABLE_PACKET_SIZE:
-                                    Maximum packet size */
-       unsigned int fps;
-       unsigned int syt_offset;
-       unsigned int flags;
-};
-
-/* For TALK_QUEUE_BUFFER with VIDEO1394_VARIABLE_PACKET_SIZE use */
-struct video1394_queue_variable {
-       unsigned int channel;
-       unsigned int buffer;
-       unsigned int __user * packet_sizes; /* Buffer of size:
-                                      buf_size / packet_size  */
-};
-
-struct video1394_wait {
-       unsigned int channel;
-       unsigned int buffer;
-       struct timeval filltime;        /* time of buffer full */
-};
-
-
-#endif
index 535fea4..e3f7fc6 100644 (file)
@@ -534,6 +534,80 @@ static int handle_eviocgbit(struct input_dev *dev,
 }
 #undef OLD_KEY_MAX
 
+static int evdev_handle_get_keycode(struct input_dev *dev,
+                                   void __user *p, size_t size)
+{
+       struct input_keymap_entry ke;
+       int error;
+
+       memset(&ke, 0, sizeof(ke));
+
+       if (size == sizeof(unsigned int[2])) {
+               /* legacy case */
+               int __user *ip = (int __user *)p;
+
+               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+                       return -EFAULT;
+
+               ke.len = sizeof(unsigned int);
+               ke.flags = 0;
+
+               error = input_get_keycode(dev, &ke);
+               if (error)
+                       return error;
+
+               if (put_user(ke.keycode, ip + 1))
+                       return -EFAULT;
+
+       } else {
+               size = min(size, sizeof(ke));
+
+               if (copy_from_user(&ke, p, size))
+                       return -EFAULT;
+
+               error = input_get_keycode(dev, &ke);
+               if (error)
+                       return error;
+
+               if (copy_to_user(p, &ke, size))
+                       return -EFAULT;
+       }
+       return 0;
+}
+
+static int evdev_handle_set_keycode(struct input_dev *dev,
+                                   void __user *p, size_t size)
+{
+       struct input_keymap_entry ke;
+
+       memset(&ke, 0, sizeof(ke));
+
+       if (size == sizeof(unsigned int[2])) {
+               /* legacy case */
+               int __user *ip = (int __user *)p;
+
+               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+                       return -EFAULT;
+
+               if (get_user(ke.keycode, ip + 1))
+                       return -EFAULT;
+
+               ke.len = sizeof(unsigned int);
+               ke.flags = 0;
+
+       } else {
+               size = min(size, sizeof(ke));
+
+               if (copy_from_user(&ke, p, size))
+                       return -EFAULT;
+
+               if (ke.len > sizeof(ke.scancode))
+                       return -EINVAL;
+       }
+
+       return input_set_keycode(dev, &ke);
+}
+
 static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                           void __user *p, int compat_mode)
 {
@@ -580,25 +654,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
                return 0;
 
-       case EVIOCGKEYCODE:
-               if (get_user(t, ip))
-                       return -EFAULT;
-
-               error = input_get_keycode(dev, t, &v);
-               if (error)
-                       return error;
-
-               if (put_user(v, ip + 1))
-                       return -EFAULT;
-
-               return 0;
-
-       case EVIOCSKEYCODE:
-               if (get_user(t, ip) || get_user(v, ip + 1))
-                       return -EFAULT;
-
-               return input_set_keycode(dev, t, v);
-
        case EVIOCRMFF:
                return input_ff_erase(dev, (int)(unsigned long) p, file);
 
@@ -620,7 +675,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 
        /* Now check variable-length commands */
 #define EVIOC_MASK_SIZE(nr)    ((nr) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
-
        switch (EVIOC_MASK_SIZE(cmd)) {
 
        case EVIOCGKEY(0):
@@ -654,6 +708,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                return error;
+
+       case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
+               return evdev_handle_get_keycode(dev, p, size);
+
+       case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
+               return evdev_handle_set_keycode(dev, p, size);
        }
 
        /* Multi-number variable-length handlers */
index 7392992..422aa0a 100644 (file)
@@ -59,44 +59,52 @@ MODULE_DEVICE_TABLE(pci, emu_tbl);
 
 static int __devinit emu_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-       int ioport, iolen;
        struct emu *emu;
        struct gameport *port;
-
-       if (pci_enable_device(pdev))
-               return -EBUSY;
-
-       ioport = pci_resource_start(pdev, 0);
-       iolen = pci_resource_len(pdev, 0);
-
-       if (!request_region(ioport, iolen, "emu10k1-gp"))
-               return -EBUSY;
+       int error;
 
        emu = kzalloc(sizeof(struct emu), GFP_KERNEL);
        port = gameport_allocate_port();
        if (!emu || !port) {
                printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
-               release_region(ioport, iolen);
-               kfree(emu);
-               gameport_free_port(port);
-               return -ENOMEM;
+               error = -ENOMEM;
+               goto err_out_free;
        }
 
-       emu->io = ioport;
-       emu->size = iolen;
+       error = pci_enable_device(pdev);
+       if (error)
+               goto err_out_free;
+
+       emu->io = pci_resource_start(pdev, 0);
+       emu->size = pci_resource_len(pdev, 0);
+
        emu->dev = pdev;
        emu->gameport = port;
 
        gameport_set_name(port, "EMU10K1");
        gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
        port->dev.parent = &pdev->dev;
-       port->io = ioport;
+       port->io = emu->io;
+
+       if (!request_region(emu->io, emu->size, "emu10k1-gp")) {
+               printk(KERN_ERR "emu10k1-gp: unable to grab region 0x%x-0x%x\n",
+                       emu->io, emu->io + emu->size - 1);
+               error = -EBUSY;
+               goto err_out_disable_dev;
+       }
 
        pci_set_drvdata(pdev, emu);
 
        gameport_register_port(port);
 
        return 0;
+
+ err_out_disable_dev:
+       pci_disable_device(pdev);
+ err_out_free:
+       gameport_free_port(port);
+       kfree(emu);
+       return error;
 }
 
 static void __devexit emu_remove(struct pci_dev *pdev)
@@ -106,6 +114,8 @@ static void __devexit emu_remove(struct pci_dev *pdev)
        gameport_unregister_port(emu->gameport);
        release_region(emu->io, emu->size);
        kfree(emu);
+
+       pci_disable_device(pdev);
 }
 
 static struct pci_driver emu_driver = {
index 14d3f3e..a3b70ff 100644 (file)
@@ -133,11 +133,11 @@ static void __devexit fm801_gp_remove(struct pci_dev *pci)
 {
        struct fm801_gp *gp = pci_get_drvdata(pci);
 
-       if (gp) {
-               gameport_unregister_port(gp->gameport);
-               release_resource(gp->res_port);
-               kfree(gp);
-       }
+       gameport_unregister_port(gp->gameport);
+       release_resource(gp->res_port);
+       kfree(gp);
+
+       pci_disable_device(pci);
 }
 
 static const struct pci_device_id fm801_gp_id_table[] = {
index 7919c25..d092ef9 100644 (file)
@@ -171,7 +171,7 @@ static int input_handle_abs_event(struct input_dev *dev,
        if (code == ABS_MT_SLOT) {
                /*
                 * "Stage" the event; we'll flush it later, when we
-                * get actiual touch data.
+                * get actual touch data.
                 */
                if (*pval >= 0 && *pval < dev->mtsize)
                        dev->slot = *pval;
@@ -188,7 +188,7 @@ static int input_handle_abs_event(struct input_dev *dev,
                pold = &mtslot->abs[code - ABS_MT_FIRST];
        } else {
                /*
-                * Bypass filtering for multitouch events when
+                * Bypass filtering for multi-touch events when
                 * not employing slots.
                 */
                pold = NULL;
@@ -634,78 +634,141 @@ static void input_disconnect_device(struct input_dev *dev)
        spin_unlock_irq(&dev->event_lock);
 }
 
-static int input_fetch_keycode(struct input_dev *dev, int scancode)
+/**
+ * input_scancode_to_scalar() - converts scancode in &struct input_keymap_entry
+ * @ke: keymap entry containing scancode to be converted.
+ * @scancode: pointer to the location where converted scancode should
+ *     be stored.
+ *
+ * This function is used to convert scancode stored in &struct keymap_entry
+ * into scalar form understood by legacy keymap handling methods. These
+ * methods expect scancodes to be represented as 'unsigned int'.
+ */
+int input_scancode_to_scalar(const struct input_keymap_entry *ke,
+                            unsigned int *scancode)
+{
+       switch (ke->len) {
+       case 1:
+               *scancode = *((u8 *)ke->scancode);
+               break;
+
+       case 2:
+               *scancode = *((u16 *)ke->scancode);
+               break;
+
+       case 4:
+               *scancode = *((u32 *)ke->scancode);
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(input_scancode_to_scalar);
+
+/*
+ * Those routines handle the default case where no [gs]etkeycode() is
+ * defined. In this case, an array indexed by the scancode is used.
+ */
+
+static unsigned int input_fetch_keycode(struct input_dev *dev,
+                                       unsigned int index)
 {
        switch (dev->keycodesize) {
-               case 1:
-                       return ((u8 *)dev->keycode)[scancode];
+       case 1:
+               return ((u8 *)dev->keycode)[index];
 
-               case 2:
-                       return ((u16 *)dev->keycode)[scancode];
+       case 2:
+               return ((u16 *)dev->keycode)[index];
 
-               default:
-                       return ((u32 *)dev->keycode)[scancode];
+       default:
+               return ((u32 *)dev->keycode)[index];
        }
 }
 
 static int input_default_getkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int *keycode)
+                                   struct input_keymap_entry *ke)
 {
+       unsigned int index;
+       int error;
+
        if (!dev->keycodesize)
                return -EINVAL;
 
-       if (scancode >= dev->keycodemax)
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX)
+               index = ke->index;
+       else {
+               error = input_scancode_to_scalar(ke, &index);
+               if (error)
+                       return error;
+       }
+
+       if (index >= dev->keycodemax)
                return -EINVAL;
 
-       *keycode = input_fetch_keycode(dev, scancode);
+       ke->keycode = input_fetch_keycode(dev, index);
+       ke->index = index;
+       ke->len = sizeof(index);
+       memcpy(ke->scancode, &index, sizeof(index));
 
        return 0;
 }
 
 static int input_default_setkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int keycode)
+                                   const struct input_keymap_entry *ke,
+                                   unsigned int *old_keycode)
 {
-       int old_keycode;
+       unsigned int index;
+       int error;
        int i;
 
-       if (scancode >= dev->keycodemax)
+       if (!dev->keycodesize)
                return -EINVAL;
 
-       if (!dev->keycodesize)
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+       } else {
+               error = input_scancode_to_scalar(ke, &index);
+               if (error)
+                       return error;
+       }
+
+       if (index >= dev->keycodemax)
                return -EINVAL;
 
-       if (dev->keycodesize < sizeof(keycode) && (keycode >> (dev->keycodesize * 8)))
+       if (dev->keycodesize < sizeof(dev->keycode) &&
+                       (ke->keycode >> (dev->keycodesize * 8)))
                return -EINVAL;
 
        switch (dev->keycodesize) {
                case 1: {
                        u8 *k = (u8 *)dev->keycode;
-                       old_keycode = k[scancode];
-                       k[scancode] = keycode;
+                       *old_keycode = k[index];
+                       k[index] = ke->keycode;
                        break;
                }
                case 2: {
                        u16 *k = (u16 *)dev->keycode;
-                       old_keycode = k[scancode];
-                       k[scancode] = keycode;
+                       *old_keycode = k[index];
+                       k[index] = ke->keycode;
                        break;
                }
                default: {
                        u32 *k = (u32 *)dev->keycode;
-                       old_keycode = k[scancode];
-                       k[scancode] = keycode;
+                       *old_keycode = k[index];
+                       k[index] = ke->keycode;
                        break;
                }
        }
 
-       __clear_bit(old_keycode, dev->keybit);
-       __set_bit(keycode, dev->keybit);
+       __clear_bit(*old_keycode, dev->keybit);
+       __set_bit(ke->keycode, dev->keybit);
 
        for (i = 0; i < dev->keycodemax; i++) {
-               if (input_fetch_keycode(dev, i) == old_keycode) {
-                       __set_bit(old_keycode, dev->keybit);
+               if (input_fetch_keycode(dev, i) == *old_keycode) {
+                       __set_bit(*old_keycode, dev->keybit);
                        break; /* Setting the bit twice is useless, so break */
                }
        }
@@ -716,53 +779,86 @@ static int input_default_setkeycode(struct input_dev *dev,
 /**
  * input_get_keycode - retrieve keycode currently mapped to a given scancode
  * @dev: input device which keymap is being queried
- * @scancode: scancode (or its equivalent for device in question) for which
- *     keycode is needed
- * @keycode: result
+ * @ke: keymap entry
  *
  * This function should be called by anyone interested in retrieving current
- * keymap. Presently keyboard and evdev handlers use it.
+ * keymap. Presently evdev handlers use it.
  */
-int input_get_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int *keycode)
+int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke)
 {
        unsigned long flags;
        int retval;
 
        spin_lock_irqsave(&dev->event_lock, flags);
-       retval = dev->getkeycode(dev, scancode, keycode);
-       spin_unlock_irqrestore(&dev->event_lock, flags);
 
+       if (dev->getkeycode) {
+               /*
+                * Support for legacy drivers, that don't implement the new
+                * ioctls
+                */
+               u32 scancode = ke->index;
+
+               memcpy(ke->scancode, &scancode, sizeof(scancode));
+               ke->len = sizeof(scancode);
+               retval = dev->getkeycode(dev, scancode, &ke->keycode);
+       } else {
+               retval = dev->getkeycode_new(dev, ke);
+       }
+
+       spin_unlock_irqrestore(&dev->event_lock, flags);
        return retval;
 }
 EXPORT_SYMBOL(input_get_keycode);
 
 /**
- * input_get_keycode - assign new keycode to a given scancode
+ * input_set_keycode - attribute a keycode to a given scancode
  * @dev: input device which keymap is being updated
- * @scancode: scancode (or its equivalent for device in question)
- * @keycode: new keycode to be assigned to the scancode
+ * @ke: new keymap entry
  *
  * This function should be called by anyone needing to update current
  * keymap. Presently keyboard and evdev handlers use it.
  */
 int input_set_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int keycode)
+                     const struct input_keymap_entry *ke)
 {
        unsigned long flags;
        unsigned int old_keycode;
        int retval;
 
-       if (keycode > KEY_MAX)
+       if (ke->keycode > KEY_MAX)
                return -EINVAL;
 
        spin_lock_irqsave(&dev->event_lock, flags);
 
-       retval = dev->getkeycode(dev, scancode, &old_keycode);
-       if (retval)
-               goto out;
+       if (dev->setkeycode) {
+               /*
+                * Support for legacy drivers, that don't implement the new
+                * ioctls
+                */
+               unsigned int scancode;
+
+               retval = input_scancode_to_scalar(ke, &scancode);
+               if (retval)
+                       goto out;
+
+               /*
+                * We need to know the old scancode, in order to generate a
+                * keyup effect, if the set operation happens successfully
+                */
+               if (!dev->getkeycode) {
+                       retval = -EINVAL;
+                       goto out;
+               }
+
+               retval = dev->getkeycode(dev, scancode, &old_keycode);
+               if (retval)
+                       goto out;
+
+               retval = dev->setkeycode(dev, scancode, ke->keycode);
+       } else {
+               retval = dev->setkeycode_new(dev, ke, &old_keycode);
+       }
 
-       retval = dev->setkeycode(dev, scancode, keycode);
        if (retval)
                goto out;
 
@@ -1601,7 +1697,7 @@ EXPORT_SYMBOL(input_free_device);
  *
  * This function allocates all necessary memory for MT slot handling in the
  * input device, and adds ABS_MT_SLOT to the device capabilities. All slots
- * are initially marked as unused iby setting ABS_MT_TRACKING_ID to -1.
+ * are initially marked as unused by setting ABS_MT_TRACKING_ID to -1.
  */
 int input_mt_create_slots(struct input_dev *dev, unsigned int num_slots)
 {
@@ -1759,11 +1855,11 @@ int input_register_device(struct input_dev *dev)
                dev->rep[REP_PERIOD] = 33;
        }
 
-       if (!dev->getkeycode)
-               dev->getkeycode = input_default_getkeycode;
+       if (!dev->getkeycode && !dev->getkeycode_new)
+               dev->getkeycode_new = input_default_getkeycode;
 
-       if (!dev->setkeycode)
-               dev->setkeycode = input_default_setkeycode;
+       if (!dev->setkeycode && !dev->setkeycode_new)
+               dev->setkeycode_new = input_default_setkeycode;
 
        dev_set_name(&dev->dev, "input%ld",
                     (unsigned long) atomic_inc_return(&input_no) - 1);
index aa037fe..0426630 100644 (file)
@@ -327,6 +327,16 @@ config KEYBOARD_NEWTON
          To compile this driver as a module, choose M here: the
          module will be called newtonkbd.
 
+config KEYBOARD_NOMADIK
+       tristate "ST-Ericsson Nomadik SKE keyboard"
+       depends on PLAT_NOMADIK
+       help
+         Say Y here if you want to use a keypad provided on the SKE controller
+         used on the Ux500 and Nomadik platforms
+
+         To compile this driver as a module, choose M here: the
+         module will be called nmk-ske-keypad.
+
 config KEYBOARD_OPENCORES
        tristate "OpenCores Keyboard Controller"
        help
@@ -424,6 +434,15 @@ config KEYBOARD_OMAP
          To compile this driver as a module, choose M here: the
          module will be called omap-keypad.
 
+config KEYBOARD_OMAP4
+       tristate "TI OMAP4 keypad support"
+       depends on ARCH_OMAP4
+       help
+         Say Y here if you want to use the OMAP4 keypad.
+
+         To compile this driver as a module, choose M here: the
+         module will be called omap4-keypad.
+
 config KEYBOARD_TWL4030
        tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
        depends on TWL4030_CORE
index 504b591..c13809c 100644 (file)
@@ -28,7 +28,9 @@ obj-$(CONFIG_KEYBOARD_MATRIX)         += matrix_keypad.o
 obj-$(CONFIG_KEYBOARD_MAX7359)         += max7359_keypad.o
 obj-$(CONFIG_KEYBOARD_MCS)             += mcs_touchkey.o
 obj-$(CONFIG_KEYBOARD_NEWTON)          += newtonkbd.o
+obj-$(CONFIG_KEYBOARD_NOMADIK)         += nomadik-ske-keypad.o
 obj-$(CONFIG_KEYBOARD_OMAP)            += omap-keypad.o
+obj-$(CONFIG_KEYBOARD_OMAP4)           += omap4-keypad.o
 obj-$(CONFIG_KEYBOARD_OPENCORES)       += opencores-kbd.o
 obj-$(CONFIG_KEYBOARD_PXA27x)          += pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)   += pxa930_rotary.o
index d6918cb..b92d1cd 100644 (file)
@@ -660,7 +660,7 @@ static const struct dev_pm_ops adp5588_dev_pm_ops = {
 #endif
 
 static const struct i2c_device_id adp5588_id[] = {
-       { KBUILD_MODNAME, 0 },
+       { "adp5588-keys", 0 },
        { "adp5587-keys", 0 },
        { }
 };
index 19fa94a..fed31e0 100644 (file)
@@ -570,6 +570,8 @@ static struct serio_device_id hil_dev_ids[] = {
        { 0 }
 };
 
+MODULE_DEVICE_TABLE(serio, hil_dev_ids);
+
 static struct serio_driver hil_serio_drv = {
        .driver         = {
                .name   = "hil_dev",
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
new file mode 100644 (file)
index 0000000..6e0f230
--- /dev/null
@@ -0,0 +1,408 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *
+ * License terms:GNU General Public License (GPL) version 2
+ *
+ * Keypad controller driver for the SKE (Scroll Key Encoder) module used in
+ * the Nomadik 8815 and Ux500 platforms.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <plat/ske.h>
+
+/* SKE_CR bits */
+#define SKE_KPMLT      (0x1 << 6)
+#define SKE_KPCN       (0x7 << 3)
+#define SKE_KPASEN     (0x1 << 2)
+#define SKE_KPASON     (0x1 << 7)
+
+/* SKE_IMSC bits */
+#define SKE_KPIMA      (0x1 << 2)
+
+/* SKE_ICR bits */
+#define SKE_KPICS      (0x1 << 3)
+#define SKE_KPICA      (0x1 << 2)
+
+/* SKE_RIS bits */
+#define SKE_KPRISA     (0x1 << 2)
+
+#define SKE_KEYPAD_ROW_SHIFT   3
+#define SKE_KPD_KEYMAP_SIZE    (8 * 8)
+
+/* keypad auto scan registers */
+#define SKE_ASR0       0x20
+#define SKE_ASR1       0x24
+#define SKE_ASR2       0x28
+#define SKE_ASR3       0x2C
+
+#define SKE_NUM_ASRX_REGISTERS (4)
+
+/**
+ * struct ske_keypad  - data structure used by keypad driver
+ * @irq:       irq no
+ * @reg_base:  ske regsiters base address
+ * @input:     pointer to input device object
+ * @board:     keypad platform device
+ * @keymap:    matrix scan code table for keycodes
+ * @clk:       clock structure pointer
+ */
+struct ske_keypad {
+       int irq;
+       void __iomem *reg_base;
+       struct input_dev *input;
+       const struct ske_keypad_platform_data *board;
+       unsigned short keymap[SKE_KPD_KEYMAP_SIZE];
+       struct clk *clk;
+       spinlock_t ske_keypad_lock;
+};
+
+static void ske_keypad_set_bits(struct ske_keypad *keypad, u16 addr,
+               u8 mask, u8 data)
+{
+       u32 ret;
+
+       spin_lock(&keypad->ske_keypad_lock);
+
+       ret = readl(keypad->reg_base + addr);
+       ret &= ~mask;
+       ret |= data;
+       writel(ret, keypad->reg_base + addr);
+
+       spin_unlock(&keypad->ske_keypad_lock);
+}
+
+/*
+ * ske_keypad_chip_init: init keypad controller configuration
+ *
+ * Enable Multi key press detection, auto scan mode
+ */
+static int __devinit ske_keypad_chip_init(struct ske_keypad *keypad)
+{
+       u32 value;
+       int timeout = 50;
+
+       /* check SKE_RIS to be 0 */
+       while ((readl(keypad->reg_base + SKE_RIS) != 0x00000000) && timeout--)
+               cpu_relax();
+
+       if (!timeout)
+               return -EINVAL;
+
+       /*
+        * set debounce value
+        * keypad dbounce is configured in DBCR[15:8]
+        * dbounce value in steps of 32/32.768 ms
+        */
+       spin_lock(&keypad->ske_keypad_lock);
+       value = readl(keypad->reg_base + SKE_DBCR);
+       value = value & 0xff;
+       value |= ((keypad->board->debounce_ms * 32000)/32768) << 8;
+       writel(value, keypad->reg_base + SKE_DBCR);
+       spin_unlock(&keypad->ske_keypad_lock);
+
+       /* enable multi key detection */
+       ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPMLT);
+
+       /*
+        * set up the number of columns
+        * KPCN[5:3] defines no. of keypad columns to be auto scanned
+        */
+       value = (keypad->board->kcol - 1) << 3;
+       ske_keypad_set_bits(keypad, SKE_CR, SKE_KPCN, value);
+
+       /* clear keypad interrupt for auto(and pending SW) scans */
+       ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA | SKE_KPICS);
+
+       /* un-mask keypad interrupts */
+       ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+       /* enable automatic scan */
+       ske_keypad_set_bits(keypad, SKE_CR, 0x0, SKE_KPASEN);
+
+       return 0;
+}
+
+static void ske_keypad_read_data(struct ske_keypad *keypad)
+{
+       struct input_dev *input = keypad->input;
+       u16 status;
+       int col = 0, row = 0, code;
+       int ske_asr, ske_ris, key_pressed, i;
+
+       /*
+        * Read the auto scan registers
+        *
+        * Each SKE_ASRx (x=0 to x=3) contains two row values.
+        * lower byte contains row value for column 2*x,
+        * upper byte contains row value for column 2*x + 1
+        */
+       for (i = 0; i < SKE_NUM_ASRX_REGISTERS; i++) {
+               ske_asr = readl(keypad->reg_base + SKE_ASR0 + (4 * i));
+               if (!ske_asr)
+                       continue;
+
+               /* now that ASRx is zero, find out the column x and row y*/
+               if (ske_asr & 0xff) {
+                       col = i * 2;
+                       status = ske_asr & 0xff;
+               } else {
+                       col = (i * 2) + 1;
+                       status = (ske_asr & 0xff00) >> 8;
+               }
+
+               /* find out the row */
+               row = __ffs(status);
+
+               code = MATRIX_SCAN_CODE(row, col, SKE_KEYPAD_ROW_SHIFT);
+               ske_ris = readl(keypad->reg_base + SKE_RIS);
+               key_pressed = ske_ris & SKE_KPRISA;
+
+               input_event(input, EV_MSC, MSC_SCAN, code);
+               input_report_key(input, keypad->keymap[code], key_pressed);
+               input_sync(input);
+       }
+}
+
+static irqreturn_t ske_keypad_irq(int irq, void *dev_id)
+{
+       struct ske_keypad *keypad = dev_id;
+       int retries = 20;
+
+       /* disable auto scan interrupt; mask the interrupt generated */
+       ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
+       ske_keypad_set_bits(keypad, SKE_ICR, 0x0, SKE_KPICA);
+
+       while ((readl(keypad->reg_base + SKE_CR) & SKE_KPASON) && --retries)
+               msleep(5);
+
+       if (retries) {
+               /* SKEx registers are stable and can be read */
+               ske_keypad_read_data(keypad);
+       }
+
+       /* enable auto scan interrupts */
+       ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit ske_keypad_probe(struct platform_device *pdev)
+{
+       const struct ske_keypad_platform_data *plat = pdev->dev.platform_data;
+       struct ske_keypad *keypad;
+       struct input_dev *input;
+       struct resource *res;
+       int irq;
+       int error;
+
+       if (!plat) {
+               dev_err(&pdev->dev, "invalid keypad platform data\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get keypad irq\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "missing platform resources\n");
+               return -EINVAL;
+       }
+
+       keypad = kzalloc(sizeof(struct ske_keypad), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!keypad || !input) {
+               dev_err(&pdev->dev, "failed to allocate keypad memory\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       keypad->irq = irq;
+       keypad->board = plat;
+       keypad->input = input;
+       spin_lock_init(&keypad->ske_keypad_lock);
+
+       if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+               dev_err(&pdev->dev, "failed to request I/O memory\n");
+               error = -EBUSY;
+               goto err_free_mem;
+       }
+
+       keypad->reg_base = ioremap(res->start, resource_size(res));
+       if (!keypad->reg_base) {
+               dev_err(&pdev->dev, "failed to remap I/O memory\n");
+               error = -ENXIO;
+               goto err_free_mem_region;
+       }
+
+       keypad->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(keypad->clk)) {
+               dev_err(&pdev->dev, "failed to get clk\n");
+               error = PTR_ERR(keypad->clk);
+               goto err_iounmap;
+       }
+
+       input->id.bustype = BUS_HOST;
+       input->name = "ux500-ske-keypad";
+       input->dev.parent = &pdev->dev;
+
+       input->keycode = keypad->keymap;
+       input->keycodesize = sizeof(keypad->keymap[0]);
+       input->keycodemax = ARRAY_SIZE(keypad->keymap);
+
+       input_set_capability(input, EV_MSC, MSC_SCAN);
+
+       __set_bit(EV_KEY, input->evbit);
+       if (!plat->no_autorepeat)
+               __set_bit(EV_REP, input->evbit);
+
+       matrix_keypad_build_keymap(plat->keymap_data, SKE_KEYPAD_ROW_SHIFT,
+                       input->keycode, input->keybit);
+
+       clk_enable(keypad->clk);
+
+       /* go through board initialization helpers */
+       if (keypad->board->init)
+               keypad->board->init();
+
+       error = ske_keypad_chip_init(keypad);
+       if (error) {
+               dev_err(&pdev->dev, "unable to init keypad hardware\n");
+               goto err_clk_disable;
+       }
+
+       error = request_threaded_irq(keypad->irq, NULL, ske_keypad_irq,
+                                    IRQF_ONESHOT, "ske-keypad", keypad);
+       if (error) {
+               dev_err(&pdev->dev, "allocate irq %d failed\n", keypad->irq);
+               goto err_clk_disable;
+       }
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(&pdev->dev,
+                               "unable to register input device: %d\n", error);
+               goto err_free_irq;
+       }
+
+       if (plat->wakeup_enable)
+               device_init_wakeup(&pdev->dev, true);
+
+       platform_set_drvdata(pdev, keypad);
+
+       return 0;
+
+err_free_irq:
+       free_irq(keypad->irq, keypad);
+err_clk_disable:
+       clk_disable(keypad->clk);
+       clk_put(keypad->clk);
+err_iounmap:
+       iounmap(keypad->reg_base);
+err_free_mem_region:
+       release_mem_region(res->start, resource_size(res));
+err_free_mem:
+       input_free_device(input);
+       kfree(keypad);
+       return error;
+}
+
+static int __devexit ske_keypad_remove(struct platform_device *pdev)
+{
+       struct ske_keypad *keypad = platform_get_drvdata(pdev);
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       free_irq(keypad->irq, keypad);
+
+       input_unregister_device(keypad->input);
+
+       clk_disable(keypad->clk);
+       clk_put(keypad->clk);
+
+       if (keypad->board->exit)
+               keypad->board->exit();
+
+       iounmap(keypad->reg_base);
+       release_mem_region(res->start, resource_size(res));
+       kfree(keypad);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int ske_keypad_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ske_keypad *keypad = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (device_may_wakeup(dev))
+               enable_irq_wake(irq);
+       else
+               ske_keypad_set_bits(keypad, SKE_IMSC, ~SKE_KPIMA, 0x0);
+
+       return 0;
+}
+
+static int ske_keypad_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct ske_keypad *keypad = platform_get_drvdata(pdev);
+       int irq = platform_get_irq(pdev, 0);
+
+       if (device_may_wakeup(dev))
+               disable_irq_wake(irq);
+       else
+               ske_keypad_set_bits(keypad, SKE_IMSC, 0x0, SKE_KPIMA);
+
+       return 0;
+}
+
+static const struct dev_pm_ops ske_keypad_dev_pm_ops = {
+       .suspend = ske_keypad_suspend,
+       .resume = ske_keypad_resume,
+};
+#endif
+
+struct platform_driver ske_keypad_driver = {
+       .driver = {
+               .name = "nmk-ske-keypad",
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm = &ske_keypad_dev_pm_ops,
+#endif
+       },
+       .probe = ske_keypad_probe,
+       .remove = __devexit_p(ske_keypad_remove),
+};
+
+static int __init ske_keypad_init(void)
+{
+       return platform_driver_probe(&ske_keypad_driver, ske_keypad_probe);
+}
+module_init(ske_keypad_init);
+
+static void __exit ske_keypad_exit(void)
+{
+       platform_driver_unregister(&ske_keypad_driver);
+}
+module_exit(ske_keypad_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Naveen Kumar <naveen.gaddipati@stericsson.com> / Sundar Iyer <sundar.iyer@stericsson.com>");
+MODULE_DESCRIPTION("Nomadik Scroll-Key-Encoder Keypad Driver");
+MODULE_ALIAS("platform:nomadik-ske-keypad");
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
new file mode 100644 (file)
index 0000000..45bd097
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * OMAP4 Keypad Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Author: Abraham Arce <x0066660@ti.com>
+ * Initial Code: Syed Rafiuddin <rafiuddin.syed@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <plat/omap4-keypad.h>
+
+/* OMAP4 registers */
+#define OMAP4_KBD_REVISION             0x00
+#define OMAP4_KBD_SYSCONFIG            0x10
+#define OMAP4_KBD_SYSSTATUS            0x14
+#define OMAP4_KBD_IRQSTATUS            0x18
+#define OMAP4_KBD_IRQENABLE            0x1C
+#define OMAP4_KBD_WAKEUPENABLE         0x20
+#define OMAP4_KBD_PENDING              0x24
+#define OMAP4_KBD_CTRL                 0x28
+#define OMAP4_KBD_DEBOUNCINGTIME       0x2C
+#define OMAP4_KBD_LONGKEYTIME          0x30
+#define OMAP4_KBD_TIMEOUT              0x34
+#define OMAP4_KBD_STATEMACHINE         0x38
+#define OMAP4_KBD_ROWINPUTS            0x3C
+#define OMAP4_KBD_COLUMNOUTPUTS                0x40
+#define OMAP4_KBD_FULLCODE31_0         0x44
+#define OMAP4_KBD_FULLCODE63_32                0x48
+
+/* OMAP4 bit definitions */
+#define OMAP4_DEF_IRQENABLE_EVENTEN    (1 << 0)
+#define OMAP4_DEF_IRQENABLE_LONGKEY    (1 << 1)
+#define OMAP4_DEF_IRQENABLE_TIMEOUTEN  (1 << 2)
+#define OMAP4_DEF_WUP_EVENT_ENA                (1 << 0)
+#define OMAP4_DEF_WUP_LONG_KEY_ENA     (1 << 1)
+#define OMAP4_DEF_CTRL_NOSOFTMODE      (1 << 1)
+#define OMAP4_DEF_CTRLPTVVALUE         (1 << 2)
+#define OMAP4_DEF_CTRLPTV              (1 << 1)
+
+/* OMAP4 values */
+#define OMAP4_VAL_IRQDISABLE           0x00
+#define OMAP4_VAL_DEBOUNCINGTIME       0x07
+#define OMAP4_VAL_FUNCTIONALCFG                0x1E
+
+#define OMAP4_MASK_IRQSTATUSDISABLE    0xFFFF
+
+struct omap4_keypad {
+       struct input_dev *input;
+
+       void __iomem *base;
+       int irq;
+
+       unsigned int rows;
+       unsigned int cols;
+       unsigned int row_shift;
+       unsigned char key_state[8];
+       unsigned short keymap[];
+};
+
+static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data)
+{
+       __raw_writel(OMAP4_VAL_FUNCTIONALCFG,
+                       keypad_data->base + OMAP4_KBD_CTRL);
+       __raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
+                       keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
+       __raw_writel(OMAP4_VAL_IRQDISABLE,
+                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
+       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
+                       keypad_data->base + OMAP4_KBD_IRQENABLE);
+       __raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
+                       keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+}
+
+/* Interrupt handler */
+static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
+{
+       struct omap4_keypad *keypad_data = dev_id;
+       struct input_dev *input_dev = keypad_data->input;
+       unsigned char key_state[ARRAY_SIZE(keypad_data->key_state)];
+       unsigned int col, row, code, changed;
+       u32 *new_state = (u32 *) key_state;
+
+       /* Disable interrupts */
+       __raw_writel(OMAP4_VAL_IRQDISABLE,
+                    keypad_data->base + OMAP4_KBD_IRQENABLE);
+
+       *new_state = __raw_readl(keypad_data->base + OMAP4_KBD_FULLCODE31_0);
+       *(new_state + 1) = __raw_readl(keypad_data->base
+                                               + OMAP4_KBD_FULLCODE63_32);
+
+       for (row = 0; row < keypad_data->rows; row++) {
+               changed = key_state[row] ^ keypad_data->key_state[row];
+               if (!changed)
+                       continue;
+
+               for (col = 0; col < keypad_data->cols; col++) {
+                       if (changed & (1 << col)) {
+                               code = MATRIX_SCAN_CODE(row, col,
+                                               keypad_data->row_shift);
+                               input_event(input_dev, EV_MSC, MSC_SCAN, code);
+                               input_report_key(input_dev,
+                                                keypad_data->keymap[code],
+                                                key_state[row] & (1 << col));
+                       }
+               }
+       }
+
+       input_sync(input_dev);
+
+       memcpy(keypad_data->key_state, key_state,
+               sizeof(keypad_data->key_state));
+
+       /* clear pending interrupts */
+       __raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
+                       keypad_data->base + OMAP4_KBD_IRQSTATUS);
+
+       /* enable interrupts */
+       __raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
+                       keypad_data->base + OMAP4_KBD_IRQENABLE);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit omap4_keypad_probe(struct platform_device *pdev)
+{
+       const struct omap4_keypad_platform_data *pdata;
+       struct omap4_keypad *keypad_data;
+       struct input_dev *input_dev;
+       struct resource *res;
+       resource_size_t size;
+       unsigned int row_shift, max_keys;
+       int irq;
+       int error;
+
+       /* platform data */
+       pdata = pdev->dev.platform_data;
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data defined\n");
+               return -EINVAL;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "no base address specified\n");
+               return -EINVAL;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (!irq) {
+               dev_err(&pdev->dev, "no keyboard irq assigned\n");
+               return -EINVAL;
+       }
+
+       if (!pdata->keymap_data) {
+               dev_err(&pdev->dev, "no keymap data defined\n");
+               return -EINVAL;
+       }
+
+       row_shift = get_count_order(pdata->cols);
+       max_keys = pdata->rows << row_shift;
+
+       keypad_data = kzalloc(sizeof(struct omap4_keypad) +
+                               max_keys * sizeof(keypad_data->keymap[0]),
+                             GFP_KERNEL);
+       if (!keypad_data) {
+               dev_err(&pdev->dev, "keypad_data memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       size = resource_size(res);
+
+       res = request_mem_region(res->start, size, pdev->name);
+       if (!res) {
+               dev_err(&pdev->dev, "can't request mem region\n");
+               error = -EBUSY;
+               goto err_free_keypad;
+       }
+
+       keypad_data->base = ioremap(res->start, resource_size(res));
+       if (!keypad_data->base) {
+               dev_err(&pdev->dev, "can't ioremap mem resource\n");
+               error = -ENOMEM;
+               goto err_release_mem;
+       }
+
+       keypad_data->irq = irq;
+       keypad_data->row_shift = row_shift;
+       keypad_data->rows = pdata->rows;
+       keypad_data->cols = pdata->cols;
+
+       /* input device allocation */
+       keypad_data->input = input_dev = input_allocate_device();
+       if (!input_dev) {
+               error = -ENOMEM;
+               goto err_unmap;
+       }
+
+       input_dev->name = pdev->name;
+       input_dev->dev.parent = &pdev->dev;
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->id.vendor = 0x0001;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0001;
+
+       input_dev->keycode      = keypad_data->keymap;
+       input_dev->keycodesize  = sizeof(keypad_data->keymap[0]);
+       input_dev->keycodemax   = max_keys;
+
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(EV_REP, input_dev->evbit);
+
+       input_set_capability(input_dev, EV_MSC, MSC_SCAN);
+
+       input_set_drvdata(input_dev, keypad_data);
+
+       matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
+                       input_dev->keycode, input_dev->keybit);
+
+       omap4_keypad_config(keypad_data);
+
+       error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
+                            IRQF_TRIGGER_RISING,
+                            "omap4-keypad", keypad_data);
+       if (error) {
+               dev_err(&pdev->dev, "failed to register interrupt\n");
+               goto err_free_input;
+       }
+
+       error = input_register_device(keypad_data->input);
+       if (error < 0) {
+               dev_err(&pdev->dev, "failed to register input device\n");
+               goto err_free_irq;
+       }
+
+
+       platform_set_drvdata(pdev, keypad_data);
+       return 0;
+
+err_free_irq:
+       free_irq(keypad_data->irq, keypad_data);
+err_free_input:
+       input_free_device(input_dev);
+err_unmap:
+       iounmap(keypad_data->base);
+err_release_mem:
+       release_mem_region(res->start, size);
+err_free_keypad:
+       kfree(keypad_data);
+       return error;
+}
+
+static int __devexit omap4_keypad_remove(struct platform_device *pdev)
+{
+       struct omap4_keypad *keypad_data = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       free_irq(keypad_data->irq, keypad_data);
+       input_unregister_device(keypad_data->input);
+
+       iounmap(keypad_data->base);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(keypad_data);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver omap4_keypad_driver = {
+       .probe          = omap4_keypad_probe,
+       .remove         = __devexit_p(omap4_keypad_remove),
+       .driver         = {
+               .name   = "omap4-keypad",
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init omap4_keypad_init(void)
+{
+       return platform_driver_register(&omap4_keypad_driver);
+}
+module_init(omap4_keypad_init);
+
+static void __exit omap4_keypad_exit(void)
+{
+       platform_driver_unregister(&omap4_keypad_driver);
+}
+module_exit(omap4_keypad_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("OMAP4 Keypad Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap4-keypad");
index fb16b5e..09bef79 100644 (file)
@@ -406,23 +406,22 @@ static int __devinit twl4030_kp_probe(struct platform_device *pdev)
        if (error) {
                dev_info(kp->dbg_dev, "request_irq failed for irq no=%d\n",
                        kp->irq);
-               goto err3;
+               goto err2;
        }
 
        /* Enable KP and TO interrupts now. */
        reg = (u8) ~(KEYP_IMR1_KP | KEYP_IMR1_TO);
        if (twl4030_kpwrite_u8(kp, reg, KEYP_IMR1)) {
                error = -EIO;
-               goto err4;
+               goto err3;
        }
 
        platform_set_drvdata(pdev, kp);
        return 0;
 
-err4:
+err3:
        /* mask all events - we don't care about the result */
        (void) twl4030_kpwrite_u8(kp, 0xff, KEYP_IMR1);
-err3:
        free_irq(kp->irq, NULL);
 err2:
        input_unregister_device(input);
index b49e233..b99b8cb 100644 (file)
@@ -22,6 +22,16 @@ config INPUT_88PM860X_ONKEY
          To compile this driver as a module, choose M here: the module
          will be called 88pm860x_onkey.
 
+config INPUT_AB8500_PONKEY
+       tristate "AB8500 Pon (PowerOn) Key"
+       depends on AB8500_CORE
+       help
+         Say Y here to use the PowerOn Key for ST-Ericsson's AB8500
+         Mix-Sig PMIC.
+
+         To compile this driver as a module, choose M here: the module
+         will be called ab8500-ponkey.
+
 config INPUT_AD714X
        tristate "Analog Devices AD714x Capacitance Touch Sensor"
        help
index 19ccca7..1fe1f6c 100644 (file)
@@ -5,6 +5,7 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_INPUT_88PM860X_ONKEY)     += 88pm860x_onkey.o
+obj-$(CONFIG_INPUT_AB8500_PONKEY)      += ab8500-ponkey.o
 obj-$(CONFIG_INPUT_AD714X)             += ad714x.o
 obj-$(CONFIG_INPUT_AD714X_I2C)         += ad714x-i2c.o
 obj-$(CONFIG_INPUT_AD714X_SPI)         += ad714x-spi.o
diff --git a/drivers/input/misc/ab8500-ponkey.c b/drivers/input/misc/ab8500-ponkey.c
new file mode 100644 (file)
index 0000000..3d3288a
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *
+ * AB8500 Power-On Key handler
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/slab.h>
+
+/**
+ * struct ab8500_ponkey - ab8500 ponkey information
+ * @input_dev: pointer to input device
+ * @ab8500: ab8500 parent
+ * @irq_dbf: irq number for falling transition
+ * @irq_dbr: irq number for rising transition
+ */
+struct ab8500_ponkey {
+       struct input_dev        *idev;
+       struct ab8500           *ab8500;
+       int                     irq_dbf;
+       int                     irq_dbr;
+};
+
+/* AB8500 gives us an interrupt when ONKEY is held */
+static irqreturn_t ab8500_ponkey_handler(int irq, void *data)
+{
+       struct ab8500_ponkey *ponkey = data;
+
+       if (irq == ponkey->irq_dbf)
+               input_report_key(ponkey->idev, KEY_POWER, true);
+       else if (irq == ponkey->irq_dbr)
+               input_report_key(ponkey->idev, KEY_POWER, false);
+
+       input_sync(ponkey->idev);
+
+       return IRQ_HANDLED;
+}
+
+static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
+{
+       struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
+       struct ab8500_ponkey *ponkey;
+       struct input_dev *input;
+       int irq_dbf, irq_dbr;
+       int error;
+
+       irq_dbf = platform_get_irq_byname(pdev, "ONKEY_DBF");
+       if (irq_dbf < 0) {
+               dev_err(&pdev->dev, "No IRQ for ONKEY_DBF, error=%d\n", irq_dbf);
+               return irq_dbf;
+       }
+
+       irq_dbr = platform_get_irq_byname(pdev, "ONKEY_DBR");
+       if (irq_dbr < 0) {
+               dev_err(&pdev->dev, "No IRQ for ONKEY_DBR, error=%d\n", irq_dbr);
+               return irq_dbr;
+       }
+
+       ponkey = kzalloc(sizeof(struct ab8500_ponkey), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!ponkey || !input) {
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       ponkey->idev = input;
+       ponkey->ab8500 = ab8500;
+       ponkey->irq_dbf = irq_dbf;
+       ponkey->irq_dbr = irq_dbr;
+
+       input->name = "AB8500 POn(PowerOn) Key";
+       input->dev.parent = &pdev->dev;
+
+       input_set_capability(input, EV_KEY, KEY_POWER);
+
+       error = request_any_context_irq(ponkey->irq_dbf, ab8500_ponkey_handler,
+                                       0, "ab8500-ponkey-dbf", ponkey);
+       if (error < 0) {
+               dev_err(ab8500->dev, "Failed to request dbf IRQ#%d: %d\n",
+                       ponkey->irq_dbf, error);
+               goto err_free_mem;
+       }
+
+       error = request_any_context_irq(ponkey->irq_dbr, ab8500_ponkey_handler,
+                                       0, "ab8500-ponkey-dbr", ponkey);
+       if (error < 0) {
+               dev_err(ab8500->dev, "Failed to request dbr IRQ#%d: %d\n",
+                       ponkey->irq_dbr, error);
+               goto err_free_dbf_irq;
+       }
+
+       error = input_register_device(ponkey->idev);
+       if (error) {
+               dev_err(ab8500->dev, "Can't register input device: %d\n", error);
+               goto err_free_dbr_irq;
+       }
+
+       platform_set_drvdata(pdev, ponkey);
+       return 0;
+
+err_free_dbr_irq:
+       free_irq(ponkey->irq_dbr, ponkey);
+err_free_dbf_irq:
+       free_irq(ponkey->irq_dbf, ponkey);
+err_free_mem:
+       input_free_device(input);
+       kfree(ponkey);
+
+       return error;
+}
+
+static int __devexit ab8500_ponkey_remove(struct platform_device *pdev)
+{
+       struct ab8500_ponkey *ponkey = platform_get_drvdata(pdev);
+
+       free_irq(ponkey->irq_dbf, ponkey);
+       free_irq(ponkey->irq_dbr, ponkey);
+       input_unregister_device(ponkey->idev);
+       kfree(ponkey);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver ab8500_ponkey_driver = {
+       .driver         = {
+               .name   = "ab8500-poweron-key",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = ab8500_ponkey_probe,
+       .remove         = __devexit_p(ab8500_ponkey_remove),
+};
+
+static int __init ab8500_ponkey_init(void)
+{
+       return platform_driver_register(&ab8500_ponkey_driver);
+}
+module_init(ab8500_ponkey_init);
+
+static void __exit ab8500_ponkey_exit(void)
+{
+       platform_driver_unregister(&ab8500_ponkey_driver);
+}
+module_exit(ab8500_ponkey_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sundar Iyer <sundar.iyer@stericsson.com>");
+MODULE_DESCRIPTION("ST-Ericsson AB8500 Power-ON(Pon) Key driver");
index 2325765..0b0e9be 100644 (file)
@@ -483,51 +483,88 @@ static void ati_remote2_complete_key(struct urb *urb)
 }
 
 static int ati_remote2_getkeycode(struct input_dev *idev,
-                                 unsigned int scancode, unsigned int *keycode)
+                                 struct input_keymap_entry *ke)
 {
        struct ati_remote2 *ar2 = input_get_drvdata(idev);
        unsigned int mode;
-       int index;
+       int offset;
+       unsigned int index;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+               if (index >= ATI_REMOTE2_MODES *
+                               ARRAY_SIZE(ati_remote2_key_table))
+                       return -EINVAL;
+
+               mode = ke->index / ARRAY_SIZE(ati_remote2_key_table);
+               offset = ke->index % ARRAY_SIZE(ati_remote2_key_table);
+               scancode = (mode << 8) + ati_remote2_key_table[offset].hw_code;
+       } else {
+               if (input_scancode_to_scalar(ke, &scancode))
+                       return -EINVAL;
+
+               mode = scancode >> 8;
+               if (mode > ATI_REMOTE2_PC)
+                       return -EINVAL;
+
+               offset = ati_remote2_lookup(scancode & 0xff);
+               if (offset < 0)
+                       return -EINVAL;
+
+               index = mode * ARRAY_SIZE(ati_remote2_key_table) + offset;
+       }
 
-       mode = scancode >> 8;
-       if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
-               return -EINVAL;
+       ke->keycode = ar2->keycode[mode][offset];
+       ke->len = sizeof(scancode);
+       memcpy(&ke->scancode, &scancode, sizeof(scancode));
+       ke->index = index;
 
-       index = ati_remote2_lookup(scancode & 0xFF);
-       if (index < 0)
-               return -EINVAL;
-
-       *keycode = ar2->keycode[mode][index];
        return 0;
 }
 
 static int ati_remote2_setkeycode(struct input_dev *idev,
-                                 unsigned int scancode, unsigned int keycode)
+                                 const struct input_keymap_entry *ke,
+                                 unsigned int *old_keycode)
 {
        struct ati_remote2 *ar2 = input_get_drvdata(idev);
-       unsigned int mode, old_keycode;
-       int index;
-
-       mode = scancode >> 8;
-       if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask))
-               return -EINVAL;
-
-       index = ati_remote2_lookup(scancode & 0xFF);
-       if (index < 0)
-               return -EINVAL;
+       unsigned int mode;
+       int offset;
+       unsigned int index;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               if (ke->index >= ATI_REMOTE2_MODES *
+                               ARRAY_SIZE(ati_remote2_key_table))
+                       return -EINVAL;
+
+               mode = ke->index / ARRAY_SIZE(ati_remote2_key_table);
+               offset = ke->index % ARRAY_SIZE(ati_remote2_key_table);
+       } else {
+               if (input_scancode_to_scalar(ke, &scancode))
+                       return -EINVAL;
+
+               mode = scancode >> 8;
+               if (mode > ATI_REMOTE2_PC)
+                       return -EINVAL;
+
+               offset = ati_remote2_lookup(scancode & 0xff);
+               if (offset < 0)
+                       return -EINVAL;
+       }
 
-       old_keycode = ar2->keycode[mode][index];
-       ar2->keycode[mode][index] = keycode;
-       __set_bit(keycode, idev->keybit);
+       *old_keycode = ar2->keycode[mode][offset];
+       ar2->keycode[mode][offset] = ke->keycode;
+       __set_bit(ke->keycode, idev->keybit);
 
        for (mode = 0; mode < ATI_REMOTE2_MODES; mode++) {
                for (index = 0; index < ARRAY_SIZE(ati_remote2_key_table); index++) {
-                       if (ar2->keycode[mode][index] == old_keycode)
+                       if (ar2->keycode[mode][index] == *old_keycode)
                                return 0;
                }
        }
 
-       __clear_bit(old_keycode, idev->keybit);
+       __clear_bit(*old_keycode, idev->keybit);
 
        return 0;
 }
@@ -575,8 +612,8 @@ static int ati_remote2_input_init(struct ati_remote2 *ar2)
        idev->open = ati_remote2_open;
        idev->close = ati_remote2_close;
 
-       idev->getkeycode = ati_remote2_getkeycode;
-       idev->setkeycode = ati_remote2_setkeycode;
+       idev->getkeycode_new = ati_remote2_getkeycode;
+       idev->setkeycode_new = ati_remote2_setkeycode;
 
        idev->name = ar2->name;
        idev->phys = ar2->phys;
index bf170f6..f459471 100644 (file)
@@ -280,7 +280,7 @@ static int powermate_alloc_buffers(struct usb_device *udev, struct powermate_dev
 
        pm->configcr = kmalloc(sizeof(*(pm->configcr)), GFP_KERNEL);
        if (!pm->configcr)
-               return -1;
+               return -ENOMEM;
 
        return 0;
 }
index 4831120..04d9bf3 100644 (file)
@@ -699,7 +699,7 @@ int elantech_init(struct psmouse *psmouse)
 
        psmouse->private = etd = kzalloc(sizeof(struct elantech_data), GFP_KERNEL);
        if (!etd)
-               return -1;
+               return -ENOMEM;
 
        etd->parity[0] = 1;
        for (i = 1; i < 256; i++)
index 73a7af2..cd9d0c9 100644 (file)
@@ -1584,10 +1584,10 @@ static ssize_t psmouse_attr_set_protocol(struct psmouse *psmouse, void *data, co
        if (!new_dev)
                return -ENOMEM;
 
-       while (serio->child) {
+       while (!list_empty(&serio->children)) {
                if (++retry > 3) {
                        printk(KERN_WARNING
-                               "psmouse: failed to destroy child port, "
+                               "psmouse: failed to destroy children ports, "
                                "protocol change aborted.\n");
                        input_free_device(new_dev);
                        return -EIO;
index 96b70a4..2e300a4 100644 (file)
@@ -294,7 +294,29 @@ static int synaptics_pt_write(struct serio *serio, unsigned char c)
        return 0;
 }
 
-static inline int synaptics_is_pt_packet(unsigned char *buf)
+static int synaptics_pt_start(struct serio *serio)
+{
+       struct psmouse *parent = serio_get_drvdata(serio->parent);
+       struct synaptics_data *priv = parent->private;
+
+       serio_pause_rx(parent->ps2dev.serio);
+       priv->pt_port = serio;
+       serio_continue_rx(parent->ps2dev.serio);
+
+       return 0;
+}
+
+static void synaptics_pt_stop(struct serio *serio)
+{
+       struct psmouse *parent = serio_get_drvdata(serio->parent);
+       struct synaptics_data *priv = parent->private;
+
+       serio_pause_rx(parent->ps2dev.serio);
+       priv->pt_port = NULL;
+       serio_continue_rx(parent->ps2dev.serio);
+}
+
+static int synaptics_is_pt_packet(unsigned char *buf)
 {
        return (buf[0] & 0xFC) == 0x84 && (buf[3] & 0xCC) == 0xC4;
 }
@@ -315,9 +337,8 @@ static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
 {
-       struct serio *ptport = psmouse->ps2dev.serio->child;
-       struct psmouse *child = serio_get_drvdata(ptport);
        struct synaptics_data *priv = psmouse->private;
+       struct psmouse *child = serio_get_drvdata(priv->pt_port);
 
        /* adjust the touchpad to child's choice of protocol */
        if (child) {
@@ -345,6 +366,8 @@ static void synaptics_pt_create(struct psmouse *psmouse)
        strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
        strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
        serio->write = synaptics_pt_write;
+       serio->start = synaptics_pt_start;
+       serio->stop = synaptics_pt_stop;
        serio->parent = psmouse->ps2dev.serio;
 
        psmouse->pt_activate = synaptics_pt_activate;
@@ -578,9 +601,10 @@ static psmouse_ret_t synaptics_process_byte(struct psmouse *psmouse)
                if (unlikely(priv->pkt_type == SYN_NEWABS))
                        priv->pkt_type = synaptics_detect_pkt_type(psmouse);
 
-               if (SYN_CAP_PASS_THROUGH(priv->capabilities) && synaptics_is_pt_packet(psmouse->packet)) {
-                       if (psmouse->ps2dev.serio->child)
-                               synaptics_pass_pt_packet(psmouse->ps2dev.serio->child, psmouse->packet);
+               if (SYN_CAP_PASS_THROUGH(priv->capabilities) &&
+                   synaptics_is_pt_packet(psmouse->packet)) {
+                       if (priv->pt_port)
+                               synaptics_pass_pt_packet(priv->pt_port, psmouse->packet);
                } else
                        synaptics_process_packet(psmouse);
 
@@ -731,7 +755,7 @@ int synaptics_init(struct psmouse *psmouse)
 
        psmouse->private = priv = kzalloc(sizeof(struct synaptics_data), GFP_KERNEL);
        if (!priv)
-               return -1;
+               return -ENOMEM;
 
        psmouse_reset(psmouse);
 
index b6aa7d2..613a365 100644 (file)
@@ -110,6 +110,8 @@ struct synaptics_data {
        unsigned char pkt_type;                 /* packet type - old, new, etc */
        unsigned char mode;                     /* current mode byte */
        int scroll;
+
+       struct serio *pt_port;                  /* Pass-through serio port */
 };
 
 void synaptics_module_init(void);
index 0643e49..54b2fa8 100644 (file)
@@ -303,7 +303,7 @@ int trackpoint_detect(struct psmouse *psmouse, bool set_properties)
 
        psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
        if (!psmouse->private)
-               return -1;
+               return -ENOMEM;
 
        psmouse->vendor = "IBM";
        psmouse->name = "TrackPoint";
index 31ec726..2a00ddf 100644 (file)
@@ -867,7 +867,7 @@ static struct mousedev *mousedev_create(struct input_dev *dev,
        spin_lock_init(&mousedev->client_lock);
        mutex_init(&mousedev->mutex);
        lockdep_set_subclass(&mousedev->mutex,
-                            minor == MOUSEDEV_MIX ? MOUSEDEV_MIX : 0);
+                            minor == MOUSEDEV_MIX ? SINGLE_DEPTH_NESTING : 0);
        init_waitqueue_head(&mousedev->wait);
 
        if (minor == MOUSEDEV_MIX)
index 3bfe8fa..6256233 100644 (file)
@@ -226,4 +226,13 @@ config SERIO_AMS_DELTA
          To compile this driver as a module, choose M here;
          the module will be called ams_delta_serio.
 
+config SERIO_PS2MULT
+       tristate "TQC PS/2 multiplexer"
+       help
+         Say Y here if you have the PS/2 line multiplexer like the one
+         present on TQC boads.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ps2mult.
+
 endif
index 84c80bf..dbbe376 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_SERIO_GSCPS2)    += gscps2.o
 obj-$(CONFIG_HP_SDC)           += hp_sdc.o
 obj-$(CONFIG_HIL_MLC)          += hp_sdc_mlc.o hil_mlc.o
 obj-$(CONFIG_SERIO_PCIPS2)     += pcips2.o
+obj-$(CONFIG_SERIO_PS2MULT)    += ps2mult.o
 obj-$(CONFIG_SERIO_MACEPS2)    += maceps2.o
 obj-$(CONFIG_SERIO_LIBPS2)     += libps2.o
 obj-$(CONFIG_SERIO_RAW)                += serio_raw.o
index f585131..18db5a8 100644 (file)
@@ -1063,7 +1063,7 @@ static long i8042_panic_blink(int state)
 #ifdef CONFIG_X86
 static void i8042_dritek_enable(void)
 {
-       char param = 0x90;
+       unsigned char param = 0x90;
        int error;
 
        error = i8042_command(&param, 0x1059);
diff --git a/drivers/input/serio/ps2mult.c b/drivers/input/serio/ps2mult.c
new file mode 100644 (file)
index 0000000..6bce22e
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+ * TQC PS/2 Multiplexer driver
+ *
+ * Copyright (C) 2010 Dmitry Eremin-Solenikov
+ *
+ * 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/slab.h>
+#include <linux/module.h>
+#include <linux/serio.h>
+
+MODULE_AUTHOR("Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>");
+MODULE_DESCRIPTION("TQC PS/2 Multiplexer driver");
+MODULE_LICENSE("GPL");
+
+#define PS2MULT_KB_SELECTOR            0xA0
+#define PS2MULT_MS_SELECTOR            0xA1
+#define PS2MULT_ESCAPE                 0x7D
+#define PS2MULT_BSYNC                  0x7E
+#define PS2MULT_SESSION_START          0x55
+#define PS2MULT_SESSION_END            0x56
+
+struct ps2mult_port {
+       struct serio *serio;
+       unsigned char sel;
+       bool registered;
+};
+
+#define PS2MULT_NUM_PORTS      2
+#define PS2MULT_KBD_PORT       0
+#define PS2MULT_MOUSE_PORT     1
+
+struct ps2mult {
+       struct serio *mx_serio;
+       struct ps2mult_port ports[PS2MULT_NUM_PORTS];
+
+       spinlock_t lock;
+       struct ps2mult_port *in_port;
+       struct ps2mult_port *out_port;
+       bool escape;
+};
+
+/* First MUST come PS2MULT_NUM_PORTS selectors */
+static const unsigned char ps2mult_controls[] = {
+       PS2MULT_KB_SELECTOR, PS2MULT_MS_SELECTOR,
+       PS2MULT_ESCAPE, PS2MULT_BSYNC,
+       PS2MULT_SESSION_START, PS2MULT_SESSION_END,
+};
+
+static const struct serio_device_id ps2mult_serio_ids[] = {
+       {
+               .type   = SERIO_RS232,
+               .proto  = SERIO_PS2MULT,
+               .id     = SERIO_ANY,
+               .extra  = SERIO_ANY,
+       },
+       { 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, ps2mult_serio_ids);
+
+static void ps2mult_select_port(struct ps2mult *psm, struct ps2mult_port *port)
+{
+       struct serio *mx_serio = psm->mx_serio;
+
+       serio_write(mx_serio, port->sel);
+       psm->out_port = port;
+       dev_dbg(&mx_serio->dev, "switched to sel %02x\n", port->sel);
+}
+
+static int ps2mult_serio_write(struct serio *serio, unsigned char data)
+{
+       struct serio *mx_port = serio->parent;
+       struct ps2mult *psm = serio_get_drvdata(mx_port);
+       struct ps2mult_port *port = serio->port_data;
+       bool need_escape;
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+
+       if (psm->out_port != port)
+               ps2mult_select_port(psm, port);
+
+       need_escape = memchr(ps2mult_controls, data, sizeof(ps2mult_controls));
+
+       dev_dbg(&serio->dev,
+               "write: %s%02x\n", need_escape ? "ESC " : "", data);
+
+       if (need_escape)
+               serio_write(mx_port, PS2MULT_ESCAPE);
+
+       serio_write(mx_port, data);
+
+       spin_unlock_irqrestore(&psm->lock, flags);
+
+       return 0;
+}
+
+static int ps2mult_serio_start(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio->parent);
+       struct ps2mult_port *port = serio->port_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+       port->registered = true;
+       spin_unlock_irqrestore(&psm->lock, flags);
+
+       return 0;
+}
+
+static void ps2mult_serio_stop(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio->parent);
+       struct ps2mult_port *port = serio->port_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+       port->registered = false;
+       spin_unlock_irqrestore(&psm->lock, flags);
+}
+
+static int ps2mult_create_port(struct ps2mult *psm, int i)
+{
+       struct serio *mx_serio = psm->mx_serio;
+       struct serio *serio;
+
+       serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
+       if (!serio)
+               return -ENOMEM;
+
+       strlcpy(serio->name, "TQC PS/2 Multiplexer", sizeof(serio->name));
+       snprintf(serio->phys, sizeof(serio->phys),
+                "%s/port%d", mx_serio->phys, i);
+       serio->id.type = SERIO_8042;
+       serio->write = ps2mult_serio_write;
+       serio->start = ps2mult_serio_start;
+       serio->stop = ps2mult_serio_stop;
+       serio->parent = psm->mx_serio;
+       serio->port_data = &psm->ports[i];
+
+       psm->ports[i].serio = serio;
+
+       return 0;
+}
+
+static void ps2mult_reset(struct ps2mult *psm)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&psm->lock, flags);
+
+       serio_write(psm->mx_serio, PS2MULT_SESSION_END);
+       serio_write(psm->mx_serio, PS2MULT_SESSION_START);
+
+       ps2mult_select_port(psm, &psm->ports[PS2MULT_KBD_PORT]);
+
+       spin_unlock_irqrestore(&psm->lock, flags);
+}
+
+static int ps2mult_connect(struct serio *serio, struct serio_driver *drv)
+{
+       struct ps2mult *psm;
+       int i;
+       int error;
+
+       if (!serio->write)
+               return -EINVAL;
+
+       psm = kzalloc(sizeof(*psm), GFP_KERNEL);
+       if (!psm)
+               return -ENOMEM;
+
+       spin_lock_init(&psm->lock);
+       psm->mx_serio = serio;
+
+       for (i = 0; i < PS2MULT_NUM_PORTS; i++) {
+               psm->ports[i].sel = ps2mult_controls[i];
+               error = ps2mult_create_port(psm, i);
+               if (error)
+                       goto err_out;
+       }
+
+       psm->in_port = psm->out_port = &psm->ports[PS2MULT_KBD_PORT];
+
+       serio_set_drvdata(serio, psm);
+       error = serio_open(serio, drv);
+       if (error)
+               goto err_out;
+
+       ps2mult_reset(psm);
+
+       for (i = 0; i <  PS2MULT_NUM_PORTS; i++) {
+               struct serio *s = psm->ports[i].serio;
+
+               dev_info(&serio->dev, "%s port at %s\n", s->name, serio->phys);
+               serio_register_port(s);
+       }
+
+       return 0;
+
+err_out:
+       while (--i >= 0)
+               kfree(psm->ports[i].serio);
+       kfree(serio);
+       return error;
+}
+
+static void ps2mult_disconnect(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio);
+
+       /* Note that serio core already take care of children ports */
+       serio_write(serio, PS2MULT_SESSION_END);
+       serio_close(serio);
+       kfree(psm);
+
+       serio_set_drvdata(serio, NULL);
+}
+
+static int ps2mult_reconnect(struct serio *serio)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio);
+
+       ps2mult_reset(psm);
+
+       return 0;
+}
+
+static irqreturn_t ps2mult_interrupt(struct serio *serio,
+                                    unsigned char data, unsigned int dfl)
+{
+       struct ps2mult *psm = serio_get_drvdata(serio);
+       struct ps2mult_port *in_port;
+       unsigned long flags;
+
+       dev_dbg(&serio->dev, "Received %02x flags %02x\n", data, dfl);
+
+       spin_lock_irqsave(&psm->lock, flags);
+
+       if (psm->escape) {
+               psm->escape = false;
+               in_port = psm->in_port;
+               if (in_port->registered)
+                       serio_interrupt(in_port->serio, data, dfl);
+               goto out;
+       }
+
+       switch (data) {
+       case PS2MULT_ESCAPE:
+               dev_dbg(&serio->dev, "ESCAPE\n");
+               psm->escape = true;
+               break;
+
+       case PS2MULT_BSYNC:
+               dev_dbg(&serio->dev, "BSYNC\n");
+               psm->in_port = psm->out_port;
+               break;
+
+       case PS2MULT_SESSION_START:
+               dev_dbg(&serio->dev, "SS\n");
+               break;
+
+       case PS2MULT_SESSION_END:
+               dev_dbg(&serio->dev, "SE\n");
+               break;
+
+       case PS2MULT_KB_SELECTOR:
+               dev_dbg(&serio->dev, "KB\n");
+               psm->in_port = &psm->ports[PS2MULT_KBD_PORT];
+               break;
+
+       case PS2MULT_MS_SELECTOR:
+               dev_dbg(&serio->dev, "MS\n");
+               psm->in_port = &psm->ports[PS2MULT_MOUSE_PORT];
+               break;
+
+       default:
+               in_port = psm->in_port;
+               if (in_port->registered)
+                       serio_interrupt(in_port->serio, data, dfl);
+               break;
+       }
+
+ out:
+       spin_unlock_irqrestore(&psm->lock, flags);
+       return IRQ_HANDLED;
+}
+
+static struct serio_driver ps2mult_drv = {
+       .driver         = {
+               .name   = "ps2mult",
+       },
+       .description    = "TQC PS/2 Multiplexer driver",
+       .id_table       = ps2mult_serio_ids,
+       .interrupt      = ps2mult_interrupt,
+       .connect        = ps2mult_connect,
+       .disconnect     = ps2mult_disconnect,
+       .reconnect      = ps2mult_reconnect,
+};
+
+static int __init ps2mult_init(void)
+{
+       return serio_register_driver(&ps2mult_drv);
+}
+
+static void __exit ps2mult_exit(void)
+{
+       serio_unregister_driver(&ps2mult_drv);
+}
+
+module_init(ps2mult_init);
+module_exit(ps2mult_exit);
index c3b626e..405bf21 100644 (file)
@@ -37,7 +37,6 @@
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/mutex.h>
-#include <linux/freezer.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Serio abstraction core");
@@ -56,7 +55,7 @@ static struct bus_type serio_bus;
 static void serio_add_port(struct serio *serio);
 static int serio_reconnect_port(struct serio *serio);
 static void serio_disconnect_port(struct serio *serio);
-static void serio_reconnect_chain(struct serio *serio);
+static void serio_reconnect_subtree(struct serio *serio);
 static void serio_attach_driver(struct serio_driver *drv);
 
 static int serio_connect_driver(struct serio *serio, struct serio_driver *drv)
@@ -152,7 +151,7 @@ static void serio_find_driver(struct serio *serio)
 enum serio_event_type {
        SERIO_RESCAN_PORT,
        SERIO_RECONNECT_PORT,
-       SERIO_RECONNECT_CHAIN,
+       SERIO_RECONNECT_SUBTREE,
        SERIO_REGISTER_PORT,
        SERIO_ATTACH_DRIVER,
 };
@@ -292,8 +291,8 @@ static void serio_handle_event(void)
                        serio_find_driver(event->object);
                        break;
 
-               case SERIO_RECONNECT_CHAIN:
-                       serio_reconnect_chain(event->object);
+               case SERIO_RECONNECT_SUBTREE:
+                       serio_reconnect_subtree(event->object);
                        break;
 
                case SERIO_ATTACH_DRIVER:
@@ -330,12 +329,10 @@ static void serio_remove_pending_events(void *object)
 }
 
 /*
- * Destroy child serio port (if any) that has not been fully registered yet.
+ * Locate child serio port (if any) that has not been fully registered yet.
  *
- * Note that we rely on the fact that port can have only one child and therefore
- * only one child registration request can be pending. Additionally, children
- * are registered by driver's connect() handler so there can't be a grandchild
- * pending registration together with a child.
+ * Children are registered by driver's connect() handler so there can't be a
+ * grandchild pending registration together with a child.
  */
 static struct serio *serio_get_pending_child(struct serio *parent)
 {
@@ -449,7 +446,7 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
        if (!strncmp(buf, "none", count)) {
                serio_disconnect_port(serio);
        } else if (!strncmp(buf, "reconnect", count)) {
-               serio_reconnect_chain(serio);
+               serio_reconnect_subtree(serio);
        } else if (!strncmp(buf, "rescan", count)) {
                serio_disconnect_port(serio);
                serio_find_driver(serio);
@@ -516,6 +513,8 @@ static void serio_init_port(struct serio *serio)
        __module_get(THIS_MODULE);
 
        INIT_LIST_HEAD(&serio->node);
+       INIT_LIST_HEAD(&serio->child_node);
+       INIT_LIST_HEAD(&serio->children);
        spin_lock_init(&serio->lock);
        mutex_init(&serio->drv_mutex);
        device_initialize(&serio->dev);
@@ -538,12 +537,13 @@ static void serio_init_port(struct serio *serio)
  */
 static void serio_add_port(struct serio *serio)
 {
+       struct serio *parent = serio->parent;
        int error;
 
-       if (serio->parent) {
-               serio_pause_rx(serio->parent);
-               serio->parent->child = serio;
-               serio_continue_rx(serio->parent);
+       if (parent) {
+               serio_pause_rx(parent);
+               list_add_tail(&serio->child_node, &parent->children);
+               serio_continue_rx(parent);
        }
 
        list_add_tail(&serio->node, &serio_list);
@@ -559,15 +559,14 @@ static void serio_add_port(struct serio *serio)
 }
 
 /*
- * serio_destroy_port() completes deregistration process and removes
+ * serio_destroy_port() completes unregistration process and removes
  * port from the system
  */
 static void serio_destroy_port(struct serio *serio)
 {
        struct serio *child;
 
-       child = serio_get_pending_child(serio);
-       if (child) {
+       while ((child = serio_get_pending_child(serio)) != NULL) {
                serio_remove_pending_events(child);
                put_device(&child->dev);
        }
@@ -577,7 +576,7 @@ static void serio_destroy_port(struct serio *serio)
 
        if (serio->parent) {
                serio_pause_rx(serio->parent);
-               serio->parent->child = NULL;
+               list_del_init(&serio->child_node);
                serio_continue_rx(serio->parent);
                serio->parent = NULL;
        }
@@ -609,46 +608,82 @@ static int serio_reconnect_port(struct serio *serio)
 }
 
 /*
- * Reconnect serio port and all its children (re-initialize attached devices)
+ * Reconnect serio port and all its children (re-initialize attached
+ * devices).
  */
-static void serio_reconnect_chain(struct serio *serio)
+static void serio_reconnect_subtree(struct serio *root)
 {
+       struct serio *s = root;
+       int error;
+
        do {
-               if (serio_reconnect_port(serio)) {
-                       /* Ok, old children are now gone, we are done */
-                       break;
+               error = serio_reconnect_port(s);
+               if (!error) {
+                       /*
+                        * Reconnect was successful, move on to do the
+                        * first child.
+                        */
+                       if (!list_empty(&s->children)) {
+                               s = list_first_entry(&s->children,
+                                                    struct serio, child_node);
+                               continue;
+                       }
                }
-               serio = serio->child;
-       } while (serio);
+
+               /*
+                * Either it was a leaf node or reconnect failed and it
+                * became a leaf node. Continue reconnecting starting with
+                * the next sibling of the parent node.
+                */
+               while (s != root) {
+                       struct serio *parent = s->parent;
+
+                       if (!list_is_last(&s->child_node, &parent->children)) {
+                               s = list_entry(s->child_node.next,
+                                              struct serio, child_node);
+                               break;
+                       }
+
+                       s = parent;
+               }
+       } while (s != root);
 }
 
 /*
  * serio_disconnect_port() unbinds a port from its driver. As a side effect
- * all child ports are unbound and destroyed.
+ * all children ports are unbound and destroyed.
  */
 static void serio_disconnect_port(struct serio *serio)
 {
-       struct serio *s, *parent;
+       struct serio *s = serio;
+
+       /*
+        * Children ports should be disconnected and destroyed
+        * first; we travel the tree in depth-first order.
+        */
+       while (!list_empty(&serio->children)) {
+
+               /* Locate a leaf */
+               while (!list_empty(&s->children))
+                       s = list_first_entry(&s->children,
+                                            struct serio, child_node);
 
-       if (serio->child) {
                /*
-                * Children ports should be disconnected and destroyed
-                * first, staring with the leaf one, since we don't want
-                * to do recursion
+                * Prune this leaf node unless it is the one we
+                * started with.
                 */
-               for (s = serio; s->child; s = s->child)
-                       /* empty */;
-
-               do {
-                       parent = s->parent;
+               if (s != serio) {
+                       struct serio *parent = s->parent;
 
                        device_release_driver(&s->dev);
                        serio_destroy_port(s);
-               } while ((s = parent) != serio);
+
+                       s = parent;
+               }
        }
 
        /*
-        * Ok, no children left, now disconnect this port
+        * OK, no children left, now disconnect this port.
         */
        device_release_driver(&serio->dev);
 }
@@ -661,7 +696,7 @@ EXPORT_SYMBOL(serio_rescan);
 
 void serio_reconnect(struct serio *serio)
 {
-       serio_queue_event(serio, NULL, SERIO_RECONNECT_CHAIN);
+       serio_queue_event(serio, NULL, SERIO_RECONNECT_SUBTREE);
 }
 EXPORT_SYMBOL(serio_reconnect);
 
@@ -689,14 +724,16 @@ void serio_unregister_port(struct serio *serio)
 EXPORT_SYMBOL(serio_unregister_port);
 
 /*
- * Safely unregisters child port if one is present.
+ * Safely unregisters children ports if they are present.
  */
 void serio_unregister_child_port(struct serio *serio)
 {
+       struct serio *s, *next;
+
        mutex_lock(&serio_mutex);
-       if (serio->child) {
-               serio_disconnect_port(serio->child);
-               serio_destroy_port(serio->child);
+       list_for_each_entry_safe(s, next, &serio->children, child_node) {
+               serio_disconnect_port(s);
+               serio_destroy_port(s);
        }
        mutex_unlock(&serio_mutex);
 }
index 0142483..a29a781 100644 (file)
@@ -22,6 +22,37 @@ MODULE_DESCRIPTION("Generic support for sparse keymaps");
 MODULE_LICENSE("GPL v2");
 MODULE_VERSION("0.1");
 
+static unsigned int sparse_keymap_get_key_index(struct input_dev *dev,
+                                               const struct key_entry *k)
+{
+       struct key_entry *key;
+       unsigned int idx = 0;
+
+       for (key = dev->keycode; key->type != KE_END; key++) {
+               if (key->type == KE_KEY) {
+                       if (key == k)
+                               break;
+                       idx++;
+               }
+       }
+
+       return idx;
+}
+
+static struct key_entry *sparse_keymap_entry_by_index(struct input_dev *dev,
+                                                     unsigned int index)
+{
+       struct key_entry *key;
+       unsigned int key_cnt = 0;
+
+       for (key = dev->keycode; key->type != KE_END; key++)
+               if (key->type == KE_KEY)
+                       if (key_cnt++ == index)
+                               return key;
+
+       return NULL;
+}
+
 /**
  * sparse_keymap_entry_from_scancode - perform sparse keymap lookup
  * @dev: Input device using sparse keymap
@@ -64,16 +95,36 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev,
 }
 EXPORT_SYMBOL(sparse_keymap_entry_from_keycode);
 
+static struct key_entry *sparse_keymap_locate(struct input_dev *dev,
+                                       const struct input_keymap_entry *ke)
+{
+       struct key_entry *key;
+       unsigned int scancode;
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX)
+               key = sparse_keymap_entry_by_index(dev, ke->index);
+       else if (input_scancode_to_scalar(ke, &scancode) == 0)
+               key = sparse_keymap_entry_from_scancode(dev, scancode);
+       else
+               key = NULL;
+
+       return key;
+}
+
 static int sparse_keymap_getkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int *keycode)
+                                   struct input_keymap_entry *ke)
 {
        const struct key_entry *key;
 
        if (dev->keycode) {
-               key = sparse_keymap_entry_from_scancode(dev, scancode);
+               key = sparse_keymap_locate(dev, ke);
                if (key && key->type == KE_KEY) {
-                       *keycode = key->keycode;
+                       ke->keycode = key->keycode;
+                       if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
+                               ke->index =
+                                       sparse_keymap_get_key_index(dev, key);
+                       ke->len = sizeof(key->code);
+                       memcpy(ke->scancode, &key->code, sizeof(key->code));
                        return 0;
                }
        }
@@ -82,20 +133,19 @@ static int sparse_keymap_getkeycode(struct input_dev *dev,
 }
 
 static int sparse_keymap_setkeycode(struct input_dev *dev,
-                                   unsigned int scancode,
-                                   unsigned int keycode)
+                                   const struct input_keymap_entry *ke,
+                                   unsigned int *old_keycode)
 {
        struct key_entry *key;
-       int old_keycode;
 
        if (dev->keycode) {
-               key = sparse_keymap_entry_from_scancode(dev, scancode);
+               key = sparse_keymap_locate(dev, ke);
                if (key && key->type == KE_KEY) {
-                       old_keycode = key->keycode;
-                       key->keycode = keycode;
-                       set_bit(keycode, dev->keybit);
-                       if (!sparse_keymap_entry_from_keycode(dev, old_keycode))
-                               clear_bit(old_keycode, dev->keybit);
+                       *old_keycode = key->keycode;
+                       key->keycode = ke->keycode;
+                       set_bit(ke->keycode, dev->keybit);
+                       if (!sparse_keymap_entry_from_keycode(dev, *old_keycode))
+                               clear_bit(*old_keycode, dev->keybit);
                        return 0;
                }
        }
@@ -159,15 +209,14 @@ int sparse_keymap_setup(struct input_dev *dev,
 
        dev->keycode = map;
        dev->keycodemax = map_size;
-       dev->getkeycode = sparse_keymap_getkeycode;
-       dev->setkeycode = sparse_keymap_setkeycode;
+       dev->getkeycode_new = sparse_keymap_getkeycode;
+       dev->setkeycode_new = sparse_keymap_setkeycode;
 
        return 0;
 
  err_out:
        kfree(map);
        return error;
-
 }
 EXPORT_SYMBOL(sparse_keymap_setup);
 
index effb49e..58a8775 100644 (file)
@@ -49,6 +49,17 @@ config TABLET_USB_GTCO
           To compile this driver as a module, choose M here: the
           module will be called gtco.
 
+config TABLET_USB_HANWANG
+       tristate "Hanwang Art Master III tablet support (USB)"
+       depends on USB_ARCH_HAS_HCD
+       select USB
+       help
+         Say Y here if you want to use the USB version of the Hanwang Art
+         Master III tablet.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hanwang.
+
 config TABLET_USB_KBTAB
        tristate "KB Gear JamStudio tablet support (USB)"
        depends on USB_ARCH_HAS_HCD
index ce8b9a9..3f6c252 100644 (file)
@@ -8,5 +8,6 @@ wacom-objs      := wacom_wac.o wacom_sys.o
 obj-$(CONFIG_TABLET_USB_ACECAD)        += acecad.o
 obj-$(CONFIG_TABLET_USB_AIPTEK)        += aiptek.o
 obj-$(CONFIG_TABLET_USB_GTCO)  += gtco.o
+obj-$(CONFIG_TABLET_USB_HANWANG) += hanwang.o
 obj-$(CONFIG_TABLET_USB_KBTAB) += kbtab.o
 obj-$(CONFIG_TABLET_USB_WACOM) += wacom.o
diff --git a/drivers/input/tablet/hanwang.c b/drivers/input/tablet/hanwang.c
new file mode 100644 (file)
index 0000000..6504b62
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ *  USB Hanwang tablet support
+ *
+ *  Copyright (c) 2010 Xing Wei <weixing@hanwang.com.cn>
+ *
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/usb/input.h>
+
+#define DRIVER_AUTHOR   "Xing Wei <weixing@hanwang.com.cn>"
+#define DRIVER_DESC     "USB Hanwang tablet driver"
+#define DRIVER_LICENSE  "GPL"
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE(DRIVER_LICENSE);
+
+#define USB_VENDOR_ID_HANWANG          0x0b57
+#define HANWANG_TABLET_INT_CLASS       0x0003
+#define HANWANG_TABLET_INT_SUB_CLASS   0x0001
+#define HANWANG_TABLET_INT_PROTOCOL    0x0002
+
+#define ART_MASTER_PKGLEN_MAX  10
+
+/* device IDs */
+#define STYLUS_DEVICE_ID       0x02
+#define TOUCH_DEVICE_ID                0x03
+#define CURSOR_DEVICE_ID       0x06
+#define ERASER_DEVICE_ID       0x0A
+#define PAD_DEVICE_ID          0x0F
+
+/* match vendor and interface info  */
+#define HANWANG_TABLET_DEVICE(vend, cl, sc, pr) \
+       .match_flags = USB_DEVICE_ID_MATCH_VENDOR \
+               | USB_DEVICE_ID_MATCH_INT_INFO, \
+       .idVendor = (vend), \
+       .bInterfaceClass = (cl), \
+       .bInterfaceSubClass = (sc), \
+       .bInterfaceProtocol = (pr)
+
+enum hanwang_tablet_type {
+       HANWANG_ART_MASTER_III,
+       HANWANG_ART_MASTER_HD,
+};
+
+struct hanwang {
+       unsigned char *data;
+       dma_addr_t data_dma;
+       struct input_dev *dev;
+       struct usb_device *usbdev;
+       struct urb *irq;
+       const struct hanwang_features *features;
+       unsigned int current_tool;
+       unsigned int current_id;
+       char name[64];
+       char phys[32];
+};
+
+struct hanwang_features {
+       unsigned short pid;
+       char *name;
+       enum hanwang_tablet_type type;
+       int pkg_len;
+       int max_x;
+       int max_y;
+       int max_tilt_x;
+       int max_tilt_y;
+       int max_pressure;
+};
+
+static const struct hanwang_features features_array[] = {
+       { 0x8528, "Hanwang Art Master III 0906", HANWANG_ART_MASTER_III,
+         ART_MASTER_PKGLEN_MAX, 0x5757, 0x3692, 0x3f, 0x7f, 2048 },
+       { 0x8529, "Hanwang Art Master III 0604", HANWANG_ART_MASTER_III,
+         ART_MASTER_PKGLEN_MAX, 0x3d84, 0x2672, 0x3f, 0x7f, 2048 },
+       { 0x852a, "Hanwang Art Master III 1308", HANWANG_ART_MASTER_III,
+         ART_MASTER_PKGLEN_MAX, 0x7f00, 0x4f60, 0x3f, 0x7f, 2048 },
+       { 0x8401, "Hanwang Art Master HD 5012", HANWANG_ART_MASTER_HD,
+         ART_MASTER_PKGLEN_MAX, 0x678e, 0x4150, 0x3f, 0x7f, 1024 },
+};
+
+static const int hw_eventtypes[] = {
+       EV_KEY, EV_ABS, EV_MSC,
+};
+
+static const int hw_absevents[] = {
+       ABS_X, ABS_Y, ABS_TILT_X, ABS_TILT_Y, ABS_WHEEL,
+       ABS_RX, ABS_RY, ABS_PRESSURE, ABS_MISC,
+};
+
+static const int hw_btnevents[] = {
+       BTN_STYLUS, BTN_STYLUS2, BTN_TOOL_PEN, BTN_TOOL_RUBBER,
+       BTN_TOOL_MOUSE, BTN_TOOL_FINGER,
+       BTN_0, BTN_1, BTN_2, BTN_3, BTN_4, BTN_5, BTN_6, BTN_7, BTN_8,
+};
+
+static const int hw_mscevents[] = {
+       MSC_SERIAL,
+};
+
+static void hanwang_parse_packet(struct hanwang *hanwang)
+{
+       unsigned char *data = hanwang->data;
+       struct input_dev *input_dev = hanwang->dev;
+       struct usb_device *dev = hanwang->usbdev;
+       enum hanwang_tablet_type type = hanwang->features->type;
+       int i;
+       u16 x, y, p;
+
+       switch (data[0]) {
+       case 0x02:      /* data packet */
+               switch (data[1]) {
+               case 0x80:      /* tool prox out */
+                       hanwang->current_id = 0;
+                       input_report_key(input_dev, hanwang->current_tool, 0);
+                       break;
+
+               case 0xc2:      /* first time tool prox in */
+                       switch (data[3] & 0xf0) {
+                       case 0x20:      /* art_master III */
+                       case 0x30:      /* art_master_HD */
+                               hanwang->current_id = STYLUS_DEVICE_ID;
+                               hanwang->current_tool = BTN_TOOL_PEN;
+                               input_report_key(input_dev, BTN_TOOL_PEN, 1);
+                               break;
+                       case 0xa0:      /* art_master III */
+                       case 0xb0:      /* art_master_HD */
+                               hanwang->current_id = ERASER_DEVICE_ID;
+                               hanwang->current_tool = BTN_TOOL_RUBBER;
+                               input_report_key(input_dev, BTN_TOOL_RUBBER, 1);
+                               break;
+                       default:
+                               hanwang->current_id = 0;
+                               dev_dbg(&dev->dev,
+                                       "unknown tablet tool %02x ", data[0]);
+                               break;
+                       }
+                       break;
+
+               default:        /* tool data packet */
+                       x = (data[2] << 8) | data[3];
+                       y = (data[4] << 8) | data[5];
+
+                       switch (type) {
+                       case HANWANG_ART_MASTER_III:
+                               p = (data[6] << 3) |
+                                   ((data[7] & 0xc0) >> 5) |
+                                   (data[1] & 0x01);
+                               break;
+
+                       case HANWANG_ART_MASTER_HD:
+                               p = (data[7] >> 6) | (data[6] << 2);
+                               break;
+
+                       default:
+                               p = 0;
+                               break;
+                       }
+
+                       input_report_abs(input_dev, ABS_X,
+                                               le16_to_cpup((__le16 *)&x));
+                       input_report_abs(input_dev, ABS_Y,
+                                               le16_to_cpup((__le16 *)&y));
+                       input_report_abs(input_dev, ABS_PRESSURE,
+                                               le16_to_cpup((__le16 *)&p));
+                       input_report_abs(input_dev, ABS_TILT_X, data[7] & 0x3f);
+                       input_report_abs(input_dev, ABS_TILT_Y, data[8] & 0x7f);
+                       input_report_key(input_dev, BTN_STYLUS, data[1] & 0x02);
+                       input_report_key(input_dev, BTN_STYLUS2, data[1] & 0x04);
+                       break;
+               }
+               input_report_abs(input_dev, ABS_MISC, hanwang->current_id);
+               input_event(input_dev, EV_MSC, MSC_SERIAL,
+                               hanwang->features->pid);
+               break;
+
+       case 0x0c:
+               /* roll wheel */
+               hanwang->current_id = PAD_DEVICE_ID;
+
+               switch (type) {
+               case HANWANG_ART_MASTER_III:
+                       input_report_key(input_dev, BTN_TOOL_FINGER, data[1] ||
+                                                       data[2] || data[3]);
+                       input_report_abs(input_dev, ABS_WHEEL, data[1]);
+                       input_report_key(input_dev, BTN_0, data[2]);
+                       for (i = 0; i < 8; i++)
+                               input_report_key(input_dev,
+                                        BTN_1 + i, data[3] & (1 << i));
+                       break;
+
+               case HANWANG_ART_MASTER_HD:
+                       input_report_key(input_dev, BTN_TOOL_FINGER, data[1] ||
+                                       data[2] || data[3] || data[4] ||
+                                       data[5] || data[6]);
+                       input_report_abs(input_dev, ABS_RX,
+                                       ((data[1] & 0x1f) << 8) | data[2]);
+                       input_report_abs(input_dev, ABS_RY,
+                                       ((data[3] & 0x1f) << 8) | data[4]);
+                       input_report_key(input_dev, BTN_0, data[5] & 0x01);
+                       for (i = 0; i < 4; i++) {
+                               input_report_key(input_dev,
+                                        BTN_1 + i, data[5] & (1 << i));
+                               input_report_key(input_dev,
+                                        BTN_5 + i, data[6] & (1 << i));
+                       }
+                       break;
+               }
+
+               input_report_abs(input_dev, ABS_MISC, hanwang->current_id);
+               input_event(input_dev, EV_MSC, MSC_SERIAL, 0xffffffff);
+               break;
+
+       default:
+               dev_dbg(&dev->dev, "error packet  %02x ", data[0]);
+               break;
+       }
+
+       input_sync(input_dev);
+}
+
+static void hanwang_irq(struct urb *urb)
+{
+       struct hanwang *hanwang = urb->context;
+       struct usb_device *dev = hanwang->usbdev;
+       int retval;
+
+       switch (urb->status) {
+       case 0:
+               /* success */;
+               hanwang_parse_packet(hanwang);
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* this urb is terminated, clean up */
+               dev_err(&dev->dev, "%s - urb shutting down with status: %d",
+                       __func__, urb->status);
+               return;
+       default:
+               dev_err(&dev->dev, "%s - nonzero urb status received: %d",
+                       __func__, urb->status);
+               break;
+       }
+
+       retval = usb_submit_urb(urb, GFP_ATOMIC);
+       if (retval)
+               dev_err(&dev->dev, "%s - usb_submit_urb failed with result %d",
+                       __func__, retval);
+}
+
+static int hanwang_open(struct input_dev *dev)
+{
+       struct hanwang *hanwang = input_get_drvdata(dev);
+
+       hanwang->irq->dev = hanwang->usbdev;
+       if (usb_submit_urb(hanwang->irq, GFP_KERNEL))
+               return -EIO;
+
+       return 0;
+}
+
+static void hanwang_close(struct input_dev *dev)
+{
+       struct hanwang *hanwang = input_get_drvdata(dev);
+
+       usb_kill_urb(hanwang->irq);
+}
+
+static bool get_features(struct usb_device *dev, struct hanwang *hanwang)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(features_array); i++) {
+               if (le16_to_cpu(dev->descriptor.idProduct) ==
+                               features_array[i].pid) {
+                       hanwang->features = &features_array[i];
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+
+static int hanwang_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+       struct usb_device *dev = interface_to_usbdev(intf);
+       struct usb_endpoint_descriptor *endpoint;
+       struct hanwang *hanwang;
+       struct input_dev *input_dev;
+       int error;
+       int i;
+
+       hanwang = kzalloc(sizeof(struct hanwang), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!hanwang || !input_dev) {
+               error = -ENOMEM;
+               goto fail1;
+       }
+
+       if (!get_features(dev, hanwang)) {
+               error = -ENXIO;
+               goto fail1;
+       }
+
+       hanwang->data = usb_alloc_coherent(dev, hanwang->features->pkg_len,
+                                       GFP_KERNEL, &hanwang->data_dma);
+       if (!hanwang->data) {
+               error = -ENOMEM;
+               goto fail1;
+       }
+
+       hanwang->irq = usb_alloc_urb(0, GFP_KERNEL);
+       if (!hanwang->irq) {
+               error = -ENOMEM;
+               goto fail2;
+       }
+
+       hanwang->usbdev = dev;
+       hanwang->dev = input_dev;
+
+       usb_make_path(dev, hanwang->phys, sizeof(hanwang->phys));
+       strlcat(hanwang->phys, "/input0", sizeof(hanwang->phys));
+
+       strlcpy(hanwang->name, hanwang->features->name, sizeof(hanwang->name));
+       input_dev->name = hanwang->name;
+       input_dev->phys = hanwang->phys;
+       usb_to_input_id(dev, &input_dev->id);
+       input_dev->dev.parent = &intf->dev;
+
+       input_set_drvdata(input_dev, hanwang);
+
+       input_dev->open = hanwang_open;
+       input_dev->close = hanwang_close;
+
+       for (i = 0; i < ARRAY_SIZE(hw_eventtypes); ++i)
+               __set_bit(hw_eventtypes[i], input_dev->evbit);
+
+       for (i = 0; i < ARRAY_SIZE(hw_absevents); ++i)
+               __set_bit(hw_absevents[i], input_dev->absbit);
+
+       for (i = 0; i < ARRAY_SIZE(hw_btnevents); ++i)
+               __set_bit(hw_btnevents[i], input_dev->keybit);
+
+       for (i = 0; i < ARRAY_SIZE(hw_mscevents); ++i)
+               __set_bit(hw_mscevents[i], input_dev->mscbit);
+
+       input_set_abs_params(input_dev, ABS_X,
+                            0, hanwang->features->max_x, 4, 0);
+       input_set_abs_params(input_dev, ABS_Y,
+                            0, hanwang->features->max_y, 4, 0);
+       input_set_abs_params(input_dev, ABS_TILT_X,
+                            0, hanwang->features->max_tilt_x, 0, 0);
+       input_set_abs_params(input_dev, ABS_TILT_Y,
+                            0, hanwang->features->max_tilt_y, 0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE,
+                            0, hanwang->features->max_pressure, 0, 0);
+
+       endpoint = &intf->cur_altsetting->endpoint[0].desc;
+       usb_fill_int_urb(hanwang->irq, dev,
+                       usb_rcvintpipe(dev, endpoint->bEndpointAddress),
+                       hanwang->data, hanwang->features->pkg_len,
+                       hanwang_irq, hanwang, endpoint->bInterval);
+       hanwang->irq->transfer_dma = hanwang->data_dma;
+       hanwang->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       error = input_register_device(hanwang->dev);
+       if (error)
+               goto fail3;
+
+       usb_set_intfdata(intf, hanwang);
+
+       return 0;
+
+ fail3:        usb_free_urb(hanwang->irq);
+ fail2:        usb_free_coherent(dev, hanwang->features->pkg_len,
+                       hanwang->data, hanwang->data_dma);
+ fail1:        input_free_device(input_dev);
+       kfree(hanwang);
+       return error;
+
+}
+
+static void hanwang_disconnect(struct usb_interface *intf)
+{
+       struct hanwang *hanwang = usb_get_intfdata(intf);
+
+       input_unregister_device(hanwang->dev);
+       usb_free_urb(hanwang->irq);
+       usb_free_coherent(interface_to_usbdev(intf),
+                       hanwang->features->pkg_len, hanwang->data,
+                       hanwang->data_dma);
+       kfree(hanwang);
+       usb_set_intfdata(intf, NULL);
+}
+
+static const struct usb_device_id hanwang_ids[] = {
+       { HANWANG_TABLET_DEVICE(USB_VENDOR_ID_HANWANG, HANWANG_TABLET_INT_CLASS,
+               HANWANG_TABLET_INT_SUB_CLASS, HANWANG_TABLET_INT_PROTOCOL) },
+       {}
+};
+
+MODULE_DEVICE_TABLE(usb, hanwang_ids);
+
+static struct usb_driver hanwang_driver = {
+       .name           = "hanwang",
+       .probe          = hanwang_probe,
+       .disconnect     = hanwang_disconnect,
+       .id_table       = hanwang_ids,
+};
+
+static int __init hanwang_init(void)
+{
+       return usb_register(&hanwang_driver);
+}
+
+static void __exit hanwang_exit(void)
+{
+       usb_deregister(&hanwang_driver);
+}
+
+module_init(hanwang_init);
+module_exit(hanwang_exit);
index 284dfaa..de5adb1 100644 (file)
@@ -118,6 +118,7 @@ struct wacom {
 extern const struct usb_device_id wacom_ids[];
 
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
+void wacom_setup_device_quirks(struct wacom_features *features);
 void wacom_setup_input_capabilities(struct input_dev *input_dev,
                                    struct wacom_wac *wacom_wac);
 #endif
index b35876e..fc38149 100644 (file)
@@ -120,14 +120,16 @@ static int wacom_open(struct input_dev *dev)
 
 out:
        mutex_unlock(&wacom->lock);
-       if (retval)
-               usb_autopm_put_interface(wacom->intf);
+       usb_autopm_put_interface(wacom->intf);
        return retval;
 }
 
 static void wacom_close(struct input_dev *dev)
 {
        struct wacom *wacom = input_get_drvdata(dev);
+       int autopm_error;
+
+       autopm_error = usb_autopm_get_interface(wacom->intf);
 
        mutex_lock(&wacom->lock);
        usb_kill_urb(wacom->irq);
@@ -135,7 +137,8 @@ static void wacom_close(struct input_dev *dev)
        wacom->intf->needs_remote_wakeup = 0;
        mutex_unlock(&wacom->lock);
 
-       usb_autopm_put_interface(wacom->intf);
+       if (!autopm_error)
+               usb_autopm_put_interface(wacom->intf);
 }
 
 static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hid_desc,
@@ -196,17 +199,30 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                                                        features->pktlen = WACOM_PKGLEN_TPC2FG;
                                                        features->device_type = BTN_TOOL_TRIPLETAP;
                                                }
-                                               features->x_max =
-                                                       get_unaligned_le16(&report[i + 3]);
-                                               features->x_phy =
-                                                       get_unaligned_le16(&report[i + 6]);
-                                               features->unit = report[i + 9];
-                                               features->unitExpo = report[i + 11];
-                                               i += 12;
+                                               if (features->type == BAMBOO_PT) {
+                                                       /* need to reset back */
+                                                       features->pktlen = WACOM_PKGLEN_BBTOUCH;
+                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 5]);
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 8]);
+                                                       i += 15;
+                                               } else {
+                                                       features->x_max =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->x_phy =
+                                                               get_unaligned_le16(&report[i + 6]);
+                                                       features->unit = report[i + 9];
+                                                       features->unitExpo = report[i + 11];
+                                                       i += 12;
+                                               }
                                        } else if (pen) {
                                                /* penabled only accepts exact bytes of data */
                                                if (features->type == TABLETPC2FG)
                                                        features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                               if (features->type == BAMBOO_PT)
+                                                       features->pktlen = WACOM_PKGLEN_BBFUN;
                                                features->device_type = BTN_TOOL_PEN;
                                                features->x_max =
                                                        get_unaligned_le16(&report[i + 3]);
@@ -235,6 +251,15 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                                                        features->y_phy =
                                                                get_unaligned_le16(&report[i + 6]);
                                                        i += 7;
+                                               } else if (features->type == BAMBOO_PT) {
+                                                       /* need to reset back */
+                                                       features->pktlen = WACOM_PKGLEN_BBTOUCH;
+                                                       features->device_type = BTN_TOOL_TRIPLETAP;
+                                                       features->y_phy =
+                                                               get_unaligned_le16(&report[i + 3]);
+                                                       features->y_max =
+                                                               get_unaligned_le16(&report[i + 6]);
+                                                       i += 12;
                                                } else {
                                                        features->y_max =
                                                                features->x_max;
@@ -246,6 +271,8 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi
                                                /* penabled only accepts exact bytes of data */
                                                if (features->type == TABLETPC2FG)
                                                        features->pktlen = WACOM_PKGLEN_GRAPHIRE;
+                                               if (features->type == BAMBOO_PT)
+                                                       features->pktlen = WACOM_PKGLEN_BBFUN;
                                                features->device_type = BTN_TOOL_PEN;
                                                features->y_max =
                                                        get_unaligned_le16(&report[i + 3]);
@@ -296,8 +323,9 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
        if (!rep_data)
                return error;
 
-       /* ask to report tablet data if it is 2FGT or not a Tablet PC */
-       if (features->device_type == BTN_TOOL_TRIPLETAP) {
+       /* ask to report tablet data if it is 2FGT Tablet PC or
+        * not a Tablet PC */
+       if (features->type == TABLETPC2FG) {
                do {
                        rep_data[0] = 3;
                        rep_data[1] = 4;
@@ -309,7 +337,7 @@ static int wacom_query_tablet_data(struct usb_interface *intf, struct wacom_feat
                                        WAC_HID_FEATURE_REPORT, report_id,
                                        rep_data, 3);
                } while ((error < 0 || rep_data[1] != 4) && limit++ < 5);
-       } else if (features->type != TABLETPC && features->type != TABLETPC2FG) {
+       } else if (features->type != TABLETPC) {
                do {
                        rep_data[0] = 2;
                        rep_data[1] = 2;
@@ -334,11 +362,16 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
        struct usb_host_interface *interface = intf->cur_altsetting;
        struct hid_descriptor *hid_desc;
 
-       /* default device to penabled */
+       /* default features */
        features->device_type = BTN_TOOL_PEN;
-
-       /* only Tablet PCs need to retrieve the info */
-       if ((features->type != TABLETPC) && (features->type != TABLETPC2FG))
+       features->x_fuzz = 4;
+       features->y_fuzz = 4;
+       features->pressure_fuzz = 0;
+       features->distance_fuzz = 0;
+
+       /* only Tablet PCs and Bamboo P&T need to retrieve the info */
+       if ((features->type != TABLETPC) && (features->type != TABLETPC2FG) &&
+           (features->type != BAMBOO_PT))
                goto out;
 
        if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
@@ -353,12 +386,6 @@ static int wacom_retrieve_hid_descriptor(struct usb_interface *intf,
        if (error)
                goto out;
 
-       /* touch device found but size is not defined. use default */
-       if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
-               features->x_max = 1023;
-               features->y_max = 1023;
-       }
-
  out:
        return error;
 }
@@ -494,9 +521,11 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i
        if (error)
                goto fail2;
 
+       wacom_setup_device_quirks(features);
+
        strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name));
 
-       if (features->type == TABLETPC || features->type == TABLETPC2FG) {
+       if (features->quirks & WACOM_QUIRK_MULTI_INPUT) {
                /* Append the device type to the name */
                strlcat(wacom_wac->name,
                        features->device_type == BTN_TOOL_PEN ?
index 47fd7a0..b3252ef 100644 (file)
@@ -857,6 +857,134 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
        return retval;
 }
 
+static int wacom_bpt_touch(struct wacom_wac *wacom)
+{
+       struct wacom_features *features = &wacom->features;
+       struct input_dev *input = wacom->input;
+       unsigned char *data = wacom->data;
+       int sp = 0, sx = 0, sy = 0, count = 0;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               int p = data[9 * i + 2];
+               input_mt_slot(input, i);
+               /*
+                * Touch events need to be disabled while stylus is
+                * in proximity because user's hand is resting on touchpad
+                * and sending unwanted events.  User expects tablet buttons
+                * to continue working though.
+                */
+               if (p && !wacom->shared->stylus_in_proximity) {
+                       int x = get_unaligned_be16(&data[9 * i + 3]) & 0x7ff;
+                       int y = get_unaligned_be16(&data[9 * i + 5]) & 0x7ff;
+                       if (features->quirks & WACOM_QUIRK_BBTOUCH_LOWRES) {
+                               x <<= 5;
+                               y <<= 5;
+                       }
+                       input_report_abs(input, ABS_MT_PRESSURE, p);
+                       input_report_abs(input, ABS_MT_POSITION_X, x);
+                       input_report_abs(input, ABS_MT_POSITION_Y, y);
+                       if (wacom->id[i] < 0)
+                               wacom->id[i] = wacom->trk_id++ & MAX_TRACKING_ID;
+                       if (!count++)
+                               sp = p, sx = x, sy = y;
+               } else {
+                       wacom->id[i] = -1;
+               }
+               input_report_abs(input, ABS_MT_TRACKING_ID, wacom->id[i]);
+       }
+
+       input_report_key(input, BTN_TOUCH, count > 0);
+       input_report_key(input, BTN_TOOL_FINGER, count == 1);
+       input_report_key(input, BTN_TOOL_DOUBLETAP, count == 2);
+
+       input_report_abs(input, ABS_PRESSURE, sp);
+       input_report_abs(input, ABS_X, sx);
+       input_report_abs(input, ABS_Y, sy);
+
+       input_report_key(input, BTN_LEFT, (data[1] & 0x08) != 0);
+       input_report_key(input, BTN_FORWARD, (data[1] & 0x04) != 0);
+       input_report_key(input, BTN_BACK, (data[1] & 0x02) != 0);
+       input_report_key(input, BTN_RIGHT, (data[1] & 0x01) != 0);
+
+       input_sync(input);
+
+       return 0;
+}
+
+static int wacom_bpt_pen(struct wacom_wac *wacom)
+{
+       struct input_dev *input = wacom->input;
+       unsigned char *data = wacom->data;
+       int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0;
+
+       /*
+        * Similar to Graphire protocol, data[1] & 0x20 is proximity and
+        * data[1] & 0x18 is tool ID.  0x30 is safety check to ignore
+        * 2 unused tool ID's.
+        */
+       prox = (data[1] & 0x30) == 0x30;
+
+       /*
+        * All reports shared between PEN and RUBBER tool must be
+        * forced to a known starting value (zero) when transitioning to
+        * out-of-prox.
+        *
+        * If not reset then, to userspace, it will look like lost events
+        * if new tool comes in-prox with same values as previous tool sent.
+        *
+        * Hardware does report zero in most out-of-prox cases but not all.
+        */
+       if (prox) {
+               if (!wacom->shared->stylus_in_proximity) {
+                       if (data[1] & 0x08) {
+                               wacom->tool[0] = BTN_TOOL_RUBBER;
+                               wacom->id[0] = ERASER_DEVICE_ID;
+                       } else {
+                               wacom->tool[0] = BTN_TOOL_PEN;
+                               wacom->id[0] = STYLUS_DEVICE_ID;
+                       }
+                       wacom->shared->stylus_in_proximity = true;
+               }
+               x = le16_to_cpup((__le16 *)&data[2]);
+               y = le16_to_cpup((__le16 *)&data[4]);
+               p = le16_to_cpup((__le16 *)&data[6]);
+               d = data[8];
+               pen = data[1] & 0x01;
+               btn1 = data[1] & 0x02;
+               btn2 = data[1] & 0x04;
+       }
+
+       input_report_key(input, BTN_TOUCH, pen);
+       input_report_key(input, BTN_STYLUS, btn1);
+       input_report_key(input, BTN_STYLUS2, btn2);
+
+       input_report_abs(input, ABS_X, x);
+       input_report_abs(input, ABS_Y, y);
+       input_report_abs(input, ABS_PRESSURE, p);
+       input_report_abs(input, ABS_DISTANCE, d);
+
+       if (!prox) {
+               wacom->id[0] = 0;
+               wacom->shared->stylus_in_proximity = false;
+       }
+
+       input_report_key(input, wacom->tool[0], prox); /* PEN or RUBBER */
+       input_report_abs(input, ABS_MISC, wacom->id[0]); /* TOOL ID */
+
+       return 1;
+}
+
+static int wacom_bpt_irq(struct wacom_wac *wacom, size_t len)
+{
+       if (len == WACOM_PKGLEN_BBTOUCH)
+               return wacom_bpt_touch(wacom);
+       else if (len == WACOM_PKGLEN_BBFUN)
+               return wacom_bpt_pen(wacom);
+
+       return 0;
+}
+
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
 {
        bool sync;
@@ -902,6 +1030,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                sync = wacom_tpc_irq(wacom_wac, len);
                break;
 
+       case BAMBOO_PT:
+               sync = wacom_bpt_irq(wacom_wac, len);
+               break;
+
        default:
                sync = false;
                break;
@@ -911,26 +1043,17 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len)
                input_sync(wacom_wac->input);
 }
 
-static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
+static void wacom_setup_cintiq(struct wacom_wac *wacom_wac)
 {
        struct input_dev *input_dev = wacom_wac->input;
 
        input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
-       input_set_capability(input_dev, EV_REL, REL_WHEEL);
-
-       __set_bit(BTN_LEFT, input_dev->keybit);
-       __set_bit(BTN_RIGHT, input_dev->keybit);
-       __set_bit(BTN_MIDDLE, input_dev->keybit);
-       __set_bit(BTN_SIDE, input_dev->keybit);
-       __set_bit(BTN_EXTRA, input_dev->keybit);
 
        __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
        __set_bit(BTN_TOOL_PEN, input_dev->keybit);
-       __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
        __set_bit(BTN_TOOL_BRUSH, input_dev->keybit);
        __set_bit(BTN_TOOL_PENCIL, input_dev->keybit);
        __set_bit(BTN_TOOL_AIRBRUSH, input_dev->keybit);
-       __set_bit(BTN_TOOL_LENS, input_dev->keybit);
        __set_bit(BTN_STYLUS, input_dev->keybit);
        __set_bit(BTN_STYLUS2, input_dev->keybit);
 
@@ -939,10 +1062,55 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
        input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0);
        input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0);
        input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0);
+}
+
+static void wacom_setup_intuos(struct wacom_wac *wacom_wac)
+{
+       struct input_dev *input_dev = wacom_wac->input;
+
+       input_set_capability(input_dev, EV_REL, REL_WHEEL);
+
+       wacom_setup_cintiq(wacom_wac);
+
+       __set_bit(BTN_LEFT, input_dev->keybit);
+       __set_bit(BTN_RIGHT, input_dev->keybit);
+       __set_bit(BTN_MIDDLE, input_dev->keybit);
+       __set_bit(BTN_SIDE, input_dev->keybit);
+       __set_bit(BTN_EXTRA, input_dev->keybit);
+       __set_bit(BTN_TOOL_MOUSE, input_dev->keybit);
+       __set_bit(BTN_TOOL_LENS, input_dev->keybit);
+
        input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0);
        input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0);
 }
 
+void wacom_setup_device_quirks(struct wacom_features *features)
+{
+
+       /* touch device found but size is not defined. use default */
+       if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
+               features->x_max = 1023;
+               features->y_max = 1023;
+       }
+
+       /* these device have multiple inputs */
+       if (features->type == TABLETPC || features->type == TABLETPC2FG ||
+           features->type == BAMBOO_PT)
+               features->quirks |= WACOM_QUIRK_MULTI_INPUT;
+
+       /* quirks for bamboo touch */
+       if (features->type == BAMBOO_PT &&
+           features->device_type == BTN_TOOL_TRIPLETAP) {
+               features->x_max <<= 5;
+               features->y_max <<= 5;
+               features->x_fuzz <<= 5;
+               features->y_fuzz <<= 5;
+               features->pressure_max = 256;
+               features->pressure_fuzz = 16;
+               features->quirks |= WACOM_QUIRK_BBTOUCH_LOWRES;
+       }
+}
+
 void wacom_setup_input_capabilities(struct input_dev *input_dev,
                                    struct wacom_wac *wacom_wac)
 {
@@ -953,9 +1121,12 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
 
        __set_bit(BTN_TOUCH, input_dev->keybit);
 
-       input_set_abs_params(input_dev, ABS_X, 0, features->x_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_Y, 0, features->y_max, 4, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, 0, 0);
+       input_set_abs_params(input_dev, ABS_X, 0, features->x_max,
+                            features->x_fuzz, 0);
+       input_set_abs_params(input_dev, ABS_Y, 0, features->y_max,
+                            features->y_fuzz, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max,
+                            features->pressure_fuzz, 0);
 
        __set_bit(ABS_MISC, input_dev->absbit);
 
@@ -1005,9 +1176,19 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
                __set_bit(BTN_9, input_dev->keybit);
                /* fall through */
 
+       case CINTIQ:
+               for (i = 0; i < 8; i++)
+                       __set_bit(BTN_0 + i, input_dev->keybit);
+               __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+
+               input_set_abs_params(input_dev, ABS_RX, 0, 4096, 0, 0);
+               input_set_abs_params(input_dev, ABS_RY, 0, 4096, 0, 0);
+               input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);
+               wacom_setup_cintiq(wacom_wac);
+               break;
+
        case INTUOS3:
        case INTUOS3L:
-       case CINTIQ:
                __set_bit(BTN_4, input_dev->keybit);
                __set_bit(BTN_5, input_dev->keybit);
                __set_bit(BTN_6, input_dev->keybit);
@@ -1078,6 +1259,38 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev,
        case PENPARTNER:
                __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
                break;
+
+       case BAMBOO_PT:
+               __clear_bit(ABS_MISC, input_dev->absbit);
+
+               if (features->device_type == BTN_TOOL_TRIPLETAP) {
+                       __set_bit(BTN_LEFT, input_dev->keybit);
+                       __set_bit(BTN_FORWARD, input_dev->keybit);
+                       __set_bit(BTN_BACK, input_dev->keybit);
+                       __set_bit(BTN_RIGHT, input_dev->keybit);
+
+                       __set_bit(BTN_TOOL_FINGER, input_dev->keybit);
+                       __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
+
+                       input_mt_create_slots(input_dev, 2);
+                       input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+                                            0, features->x_max,
+                                            features->x_fuzz, 0);
+                       input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+                                            0, features->y_max,
+                                            features->y_fuzz, 0);
+                       input_set_abs_params(input_dev, ABS_MT_PRESSURE,
+                                            0, features->pressure_max,
+                                            features->pressure_fuzz, 0);
+                       input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0,
+                                            MAX_TRACKING_ID, 0, 0);
+               } else if (features->device_type == BTN_TOOL_PEN) {
+                       __set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
+                       __set_bit(BTN_TOOL_PEN, input_dev->keybit);
+                       __set_bit(BTN_STYLUS, input_dev->keybit);
+                       __set_bit(BTN_STYLUS2, input_dev->keybit);
+               }
+               break;
        }
 }
 
@@ -1215,6 +1428,14 @@ static const struct wacom_features wacom_features_0xE3 =
        { "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG };
 static const struct wacom_features wacom_features_0x47 =
        { "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS };
+static struct wacom_features wacom_features_0xD0 =
+       { "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD1 =
+       { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD2 =
+       { "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
+static struct wacom_features wacom_features_0xD3 =
+       { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
 
 #define USB_DEVICE_WACOM(prod)                                 \
        USB_DEVICE(USB_VENDOR_ID_WACOM, prod),                  \
@@ -1279,6 +1500,10 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xC6) },
        { USB_DEVICE_WACOM(0xC7) },
        { USB_DEVICE_WACOM(0xCE) },
+       { USB_DEVICE_WACOM(0xD0) },
+       { USB_DEVICE_WACOM(0xD1) },
+       { USB_DEVICE_WACOM(0xD2) },
+       { USB_DEVICE_WACOM(0xD3) },
        { USB_DEVICE_WACOM(0xF0) },
        { USB_DEVICE_WACOM(0xCC) },
        { USB_DEVICE_WACOM(0x90) },
index 99e1a54..00ca015 100644 (file)
@@ -21,6 +21,7 @@
 #define WACOM_PKGLEN_INTUOS    10
 #define WACOM_PKGLEN_TPC1FG     5
 #define WACOM_PKGLEN_TPC2FG    14
+#define WACOM_PKGLEN_BBTOUCH   20
 
 /* device IDs */
 #define STYLUS_DEVICE_ID       0x02
 #define WACOM_REPORT_TPC1FG            6
 #define WACOM_REPORT_TPC2FG            13
 
+/* device quirks */
+#define WACOM_QUIRK_MULTI_INPUT                0x0001
+#define WACOM_QUIRK_BBTOUCH_LOWRES     0x0002
+
+/* largest reported tracking id */
+#define MAX_TRACKING_ID                        0xfff
+
 enum {
        PENPARTNER = 0,
        GRAPHIRE,
@@ -44,6 +52,7 @@ enum {
        PTU,
        PL,
        DTU,
+       BAMBOO_PT,
        INTUOS,
        INTUOS3S,
        INTUOS3,
@@ -73,6 +82,11 @@ struct wacom_features {
        int y_phy;
        unsigned char unit;
        unsigned char unitExpo;
+       int x_fuzz;
+       int y_fuzz;
+       int pressure_fuzz;
+       int distance_fuzz;
+       unsigned quirks;
 };
 
 struct wacom_shared {
@@ -86,6 +100,7 @@ struct wacom_wac {
        int id[3];
        __u32 serial[2];
        int last_finger;
+       int trk_id;
        struct wacom_features features;
        struct wacom_shared *shared;
        struct input_dev *input;
index 0069d97..0ea361f 100644 (file)
@@ -98,6 +98,18 @@ config TOUCHSCREEN_BITSY
          To compile this driver as a module, choose M here: the
          module will be called h3600_ts_input.
 
+config TOUCHSCREEN_BU21013
+       tristate "BU21013 based touch panel controllers"
+       depends on I2C
+       help
+         Say Y here if you have a bu21013 touchscreen connected to
+         your system.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bu21013_ts.
+
 config TOUCHSCREEN_CY8CTMG110
        tristate "cy8ctmg110 touchscreen"
        depends on I2C
@@ -214,6 +226,16 @@ config TOUCHSCREEN_WACOM_W8001
          To compile this driver as a module, choose M here: the
          module will be called wacom_w8001.
 
+config TOUCHSCREEN_LPC32XX
+       tristate "LPC32XX touchscreen controller"
+       depends on ARCH_LPC32XX
+       help
+         Say Y here if you have a LPC32XX device and want
+         to support the built-in touchscreen.
+
+         To compile this driver as a module, choose M here: the
+         module will be called lpc32xx_ts.
+
 config TOUCHSCREEN_MCS5000
        tristate "MELFAS MCS-5000 touchscreen"
        depends on I2C
@@ -250,6 +272,18 @@ config TOUCHSCREEN_INEXIO
          To compile this driver as a module, choose M here: the
          module will be called inexio.
 
+config TOUCHSCREEN_INTEL_MID
+       tristate "Intel MID platform resistive touchscreen"
+       depends on INTEL_SCU_IPC
+       help
+         Say Y here if you have a Intel MID based touchscreen in
+         your system.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called intel_mid_touch.
+
 config TOUCHSCREEN_MK712
        tristate "ICS MicroClock MK712 touchscreen"
        help
index 28217e1..99b353c 100644 (file)
@@ -14,6 +14,7 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)  += ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)      += ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)                += h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)   += cy8ctmg110_ts.o
 obj-$(CONFIG_TOUCHSCREEN_DA9034)       += da9034-ts.o
 obj-$(CONFIG_TOUCHSCREEN_DYNAPRO)      += dynapro.o
@@ -23,6 +24,8 @@ obj-$(CONFIG_TOUCHSCREEN_EETI)                += eeti_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ELO)          += elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)      += fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)       += inexio.o
+obj-$(CONFIG_TOUCHSCREEN_INTEL_MID)    += intel-mid-touch.o
+obj-$(CONFIG_TOUCHSCREEN_LPC32XX)      += lpc32xx_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MC13783)      += mc13783_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MCS5000)      += mcs5000_ts.o
 obj-$(CONFIG_TOUCHSCREEN_MIGOR)                += migor_ts.o
index 5f0221c..a1952fc 100644 (file)
@@ -191,13 +191,12 @@ struct ad7877 {
        struct spi_message      msg;
 
        struct mutex            mutex;
-       unsigned                disabled:1;     /* P: mutex */
-       unsigned                gpio3:1;        /* P: mutex */
-       unsigned                gpio4:1;        /* P: mutex */
+       bool                    disabled;       /* P: mutex */
+       bool                    gpio3;          /* P: mutex */
+       bool                    gpio4;          /* P: mutex */
 
        spinlock_t              lock;
        struct timer_list       timer;          /* P: lock */
-       unsigned                pending:1;      /* P: lock */
 
        /*
         * DMA (thus cache coherency maintenance) requires the
@@ -206,8 +205,8 @@ struct ad7877 {
        u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned;
 };
 
-static int gpio3;
-module_param(gpio3, int, 0);
+static bool gpio3;
+module_param(gpio3, bool, 0);
 MODULE_PARM_DESC(gpio3, "If gpio3 is set to 1 AUX3 acts as GPIO3");
 
 /*
@@ -230,6 +229,7 @@ static int ad7877_read(struct spi_device *spi, u16 reg)
                        AD7877_READADD(reg));
        req->xfer[0].tx_buf = &req->command;
        req->xfer[0].len = 2;
+       req->xfer[0].cs_change = 1;
 
        req->xfer[1].rx_buf = &req->sample;
        req->xfer[1].len = 2;
@@ -295,20 +295,25 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
 
        req->xfer[0].tx_buf = &req->reset;
        req->xfer[0].len = 2;
+       req->xfer[0].cs_change = 1;
 
        req->xfer[1].tx_buf = &req->ref_on;
        req->xfer[1].len = 2;
        req->xfer[1].delay_usecs = ts->vref_delay_usecs;
+       req->xfer[1].cs_change = 1;
 
        req->xfer[2].tx_buf = &req->command;
        req->xfer[2].len = 2;
        req->xfer[2].delay_usecs = ts->vref_delay_usecs;
+       req->xfer[2].cs_change = 1;
 
        req->xfer[3].rx_buf = &req->sample;
        req->xfer[3].len = 2;
+       req->xfer[3].cs_change = 1;
 
        req->xfer[4].tx_buf = &ts->cmd_crtl2;   /*REF OFF*/
        req->xfer[4].len = 2;
+       req->xfer[4].cs_change = 1;
 
        req->xfer[5].tx_buf = &ts->cmd_crtl1;   /*DEFAULT*/
        req->xfer[5].len = 2;
@@ -327,7 +332,7 @@ static int ad7877_read_adc(struct spi_device *spi, unsigned command)
        return status ? : sample;
 }
 
-static void ad7877_rx(struct ad7877 *ts)
+static int ad7877_process_data(struct ad7877 *ts)
 {
        struct input_dev *input_dev = ts->input;
        unsigned Rt;
@@ -354,11 +359,25 @@ static void ad7877_rx(struct ad7877 *ts)
                Rt /= z1;
                Rt = (Rt + 2047) >> 12;
 
+               /*
+                * Sample found inconsistent, pressure is beyond
+                * the maximum. Don't report it to user space.
+                */
+               if (Rt > ts->pressure_max)
+                       return -EINVAL;
+
+               if (!timer_pending(&ts->timer))
+                       input_report_key(input_dev, BTN_TOUCH, 1);
+
                input_report_abs(input_dev, ABS_X, x);
                input_report_abs(input_dev, ABS_Y, y);
                input_report_abs(input_dev, ABS_PRESSURE, Rt);
                input_sync(input_dev);
+
+               return 0;
        }
+
+       return -EINVAL;
 }
 
 static inline void ad7877_ts_event_release(struct ad7877 *ts)
@@ -366,72 +385,56 @@ static inline void ad7877_ts_event_release(struct ad7877 *ts)
        struct input_dev *input_dev = ts->input;
 
        input_report_abs(input_dev, ABS_PRESSURE, 0);
+       input_report_key(input_dev, BTN_TOUCH, 0);
        input_sync(input_dev);
 }
 
 static void ad7877_timer(unsigned long handle)
 {
        struct ad7877 *ts = (void *)handle;
+       unsigned long flags;
 
+       spin_lock_irqsave(&ts->lock, flags);
        ad7877_ts_event_release(ts);
+       spin_unlock_irqrestore(&ts->lock, flags);
 }
 
 static irqreturn_t ad7877_irq(int irq, void *handle)
 {
        struct ad7877 *ts = handle;
        unsigned long flags;
-       int status;
+       int error;
 
-       /*
-        * The repeated conversion sequencer controlled by TMR kicked off
-        * too fast. We ignore the last and process the sample sequence
-        * currently in the queue. It can't be older than 9.4ms, and we
-        * need to avoid that ts->msg doesn't get issued twice while in work.
-        */
+       error = spi_sync(ts->spi, &ts->msg);
+       if (error) {
+               dev_err(&ts->spi->dev, "spi_sync --> %d\n", error);
+               goto out;
+       }
 
        spin_lock_irqsave(&ts->lock, flags);
-       if (!ts->pending) {
-               ts->pending = 1;
-
-               status = spi_async(ts->spi, &ts->msg);
-               if (status)
-                       dev_err(&ts->spi->dev, "spi_sync --> %d\n", status);
-       }
+       error = ad7877_process_data(ts);
+       if (!error)
+               mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
        spin_unlock_irqrestore(&ts->lock, flags);
 
+out:
        return IRQ_HANDLED;
 }
 
-static void ad7877_callback(void *_ts)
-{
-       struct ad7877 *ts = _ts;
-
-       spin_lock_irq(&ts->lock);
-
-       ad7877_rx(ts);
-       ts->pending = 0;
-       mod_timer(&ts->timer, jiffies + TS_PEN_UP_TIMEOUT);
-
-       spin_unlock_irq(&ts->lock);
-}
-
 static void ad7877_disable(struct ad7877 *ts)
 {
        mutex_lock(&ts->mutex);
 
        if (!ts->disabled) {
-               ts->disabled = 1;
+               ts->disabled = true;
                disable_irq(ts->spi->irq);
 
-               /* Wait for spi_async callback */
-               while (ts->pending)
-                       msleep(1);
-
                if (del_timer_sync(&ts->timer))
                        ad7877_ts_event_release(ts);
        }
 
-       /* we know the chip's in lowpower mode since we always
+       /*
+        * We know the chip's in lowpower mode since we always
         * leave it that way after every request
         */
 
@@ -443,7 +446,7 @@ static void ad7877_enable(struct ad7877 *ts)
        mutex_lock(&ts->mutex);
 
        if (ts->disabled) {
-               ts->disabled = 0;
+               ts->disabled = false;
                enable_irq(ts->spi->irq);
        }
 
@@ -453,7 +456,7 @@ static void ad7877_enable(struct ad7877 *ts)
 #define SHOW(name) static ssize_t \
 name ## _show(struct device *dev, struct device_attribute *attr, char *buf) \
 { \
-       struct ad7877   *ts = dev_get_drvdata(dev); \
+       struct ad7877 *ts = dev_get_drvdata(dev); \
        ssize_t v = ad7877_read_adc(ts->spi, \
                        AD7877_READ_CHAN(name)); \
        if (v < 0) \
@@ -473,7 +476,7 @@ SHOW(temp2)
 static ssize_t ad7877_disable_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->disabled);
 }
@@ -503,7 +506,7 @@ static DEVICE_ATTR(disable, 0664, ad7877_disable_show, ad7877_disable_store);
 static ssize_t ad7877_dac_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->dac);
 }
@@ -533,7 +536,7 @@ static DEVICE_ATTR(dac, 0664, ad7877_dac_show, ad7877_dac_store);
 static ssize_t ad7877_gpio3_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->gpio3);
 }
@@ -564,7 +567,7 @@ static DEVICE_ATTR(gpio3, 0664, ad7877_gpio3_show, ad7877_gpio3_store);
 static ssize_t ad7877_gpio4_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ad7877   *ts = dev_get_drvdata(dev);
+       struct ad7877 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->gpio4);
 }
@@ -597,16 +600,35 @@ static struct attribute *ad7877_attributes[] = {
        &dev_attr_temp2.attr,
        &dev_attr_aux1.attr,
        &dev_attr_aux2.attr,
+       &dev_attr_aux3.attr,
        &dev_attr_bat1.attr,
        &dev_attr_bat2.attr,
        &dev_attr_disable.attr,
        &dev_attr_dac.attr,
+       &dev_attr_gpio3.attr,
        &dev_attr_gpio4.attr,
        NULL
 };
 
+static mode_t ad7877_attr_is_visible(struct kobject *kobj,
+                                    struct attribute *attr, int n)
+{
+       mode_t mode = attr->mode;
+
+       if (attr == &dev_attr_aux3.attr) {
+               if (gpio3)
+                       mode = 0;
+       } else if (attr == &dev_attr_gpio3.attr) {
+               if (!gpio3)
+                       mode = 0;
+       }
+
+       return mode;
+}
+
 static const struct attribute_group ad7877_attr_group = {
-       .attrs = ad7877_attributes,
+       .is_visible     = ad7877_attr_is_visible,
+       .attrs          = ad7877_attributes,
 };
 
 static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
@@ -635,22 +657,25 @@ static void ad7877_setup_ts_def_msg(struct spi_device *spi, struct ad7877 *ts)
 
        spi_message_init(m);
 
-       m->complete = ad7877_callback;
        m->context = ts;
 
        ts->xfer[0].tx_buf = &ts->cmd_crtl1;
        ts->xfer[0].len = 2;
+       ts->xfer[0].cs_change = 1;
 
        spi_message_add_tail(&ts->xfer[0], m);
 
        ts->xfer[1].tx_buf = &ts->cmd_dummy; /* Send ZERO */
        ts->xfer[1].len = 2;
+       ts->xfer[1].cs_change = 1;
 
        spi_message_add_tail(&ts->xfer[1], m);
 
-       for (i = 0; i < 11; i++) {
+       for (i = 0; i < AD7877_NR_SENSE; i++) {
                ts->xfer[i + 2].rx_buf = &ts->conversion_data[AD7877_SEQ_YPOS + i];
                ts->xfer[i + 2].len = 2;
+               if (i < (AD7877_NR_SENSE - 1))
+                       ts->xfer[i + 2].cs_change = 1;
                spi_message_add_tail(&ts->xfer[i + 2], m);
        }
 }
@@ -718,6 +743,8 @@ static int __devinit ad7877_probe(struct spi_device *spi)
        input_dev->phys = ts->phys;
        input_dev->dev.parent = &spi->dev;
 
+       __set_bit(EV_KEY, input_dev->evbit);
+       __set_bit(BTN_TOUCH, input_dev->keybit);
        __set_bit(EV_ABS, input_dev->evbit);
        __set_bit(ABS_X, input_dev->absbit);
        __set_bit(ABS_Y, input_dev->absbit);
@@ -752,8 +779,9 @@ static int __devinit ad7877_probe(struct spi_device *spi)
 
        /* Request AD7877 /DAV GPIO interrupt */
 
-       err = request_irq(spi->irq, ad7877_irq, IRQF_TRIGGER_FALLING,
-                       spi->dev.driver->name, ts);
+       err = request_threaded_irq(spi->irq, NULL, ad7877_irq,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  spi->dev.driver->name, ts);
        if (err) {
                dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq);
                goto err_free_mem;
@@ -763,20 +791,12 @@ static int __devinit ad7877_probe(struct spi_device *spi)
        if (err)
                goto err_free_irq;
 
-       err = device_create_file(&spi->dev,
-                                gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
-       if (err)
-               goto err_remove_attr_group;
-
        err = input_register_device(input_dev);
        if (err)
-               goto err_remove_attr;
+               goto err_remove_attr_group;
 
        return 0;
 
-err_remove_attr:
-       device_remove_file(&spi->dev,
-                          gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
 err_remove_attr_group:
        sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
 err_free_irq:
@@ -790,11 +810,9 @@ err_free_mem:
 
 static int __devexit ad7877_remove(struct spi_device *spi)
 {
-       struct ad7877           *ts = dev_get_drvdata(&spi->dev);
+       struct ad7877 *ts = dev_get_drvdata(&spi->dev);
 
        sysfs_remove_group(&spi->dev.kobj, &ad7877_attr_group);
-       device_remove_file(&spi->dev,
-                          gpio3 ? &dev_attr_gpio3 : &dev_attr_aux3);
 
        ad7877_disable(ts);
        free_irq(ts->spi->irq, ts);
index 1603193..14ea54b 100644 (file)
  *  it under the terms of the GNU General Public License version 2 as
  *  published by the Free Software Foundation.
  */
+#include <linux/types.h>
 #include <linux/hwmon.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
  * files.
  */
 
-#define TS_POLL_DELAY  (1 * 1000000)   /* ns delay before the first sample */
-#define TS_POLL_PERIOD (5 * 1000000)   /* ns delay between samples */
+#define TS_POLL_DELAY  1       /* ms delay before the first sample */
+#define TS_POLL_PERIOD 5       /* ms delay between samples */
 
 /* this driver doesn't aim at the peak continuous sample rate */
 #define        SAMPLE_BITS     (8 /*cmd*/ + 16 /*sample*/ + 2 /* before, after */)
 
 struct ts_event {
-       /* For portability, we can't read 12 bit values using SPI (which
-        * would make the controller deliver them as native byteorder u16
+       /*
+        * For portability, we can't read 12 bit values using SPI (which
+        * would make the controller deliver them as native byte order u16
         * with msbs zeroed).  Instead, we read them as two 8-bit values,
         * *** WHICH NEED BYTESWAPPING *** and range adjustment.
         */
        u16     x;
        u16     y;
        u16     z1, z2;
-       int     ignore;
+       bool    ignore;
        u8      x_buf[3];
        u8      y_buf[3];
 };
@@ -110,8 +113,11 @@ struct ads7846 {
 
        struct spi_transfer     xfer[18];
        struct spi_message      msg[5];
-       struct spi_message      *last_msg;
-       int                     msg_idx;
+       int                     msg_count;
+       wait_queue_head_t       wait;
+
+       bool                    pendown;
+
        int                     read_cnt;
        int                     read_rep;
        int                     last_read;
@@ -122,14 +128,10 @@ struct ads7846 {
 
        u16                     penirq_recheck_delay_usecs;
 
-       spinlock_t              lock;
-       struct hrtimer          timer;
-       unsigned                pendown:1;      /* P: lock */
-       unsigned                pending:1;      /* P: lock */
-// FIXME remove "irq_disabled"
-       unsigned                irq_disabled:1; /* P: lock */
-       unsigned                disabled:1;
-       unsigned                is_suspended:1;
+       struct mutex            lock;
+       bool                    stopped;        /* P: lock */
+       bool                    disabled;       /* P: lock */
+       bool                    suspended;      /* P: lock */
 
        int                     (*filter)(void *data, int data_idx, int *val);
        void                    *filter_data;
@@ -165,7 +167,7 @@ struct ads7846 {
 #define        ADS_12_BIT              (0 << 3)
 #define        ADS_SER                 (1 << 2)        /* non-differential */
 #define        ADS_DFR                 (0 << 2)        /* differential */
-#define        ADS_PD10_PDOWN          (0 << 0)        /* lowpower mode + penirq */
+#define        ADS_PD10_PDOWN          (0 << 0)        /* low power mode + penirq */
 #define        ADS_PD10_ADC_ON         (1 << 0)        /* ADC on */
 #define        ADS_PD10_REF_ON         (2 << 0)        /* vREF on + penirq */
 #define        ADS_PD10_ALL_ON         (3 << 0)        /* ADC + vREF on */
@@ -193,6 +195,78 @@ struct ads7846 {
 #define        REF_ON  (READ_12BIT_DFR(x, 1, 1))
 #define        REF_OFF (READ_12BIT_DFR(y, 0, 0))
 
+/* Must be called with ts->lock held */
+static void ads7846_stop(struct ads7846 *ts)
+{
+       if (!ts->disabled && !ts->suspended) {
+               /* Signal IRQ thread to stop polling and disable the handler. */
+               ts->stopped = true;
+               mb();
+               wake_up(&ts->wait);
+               disable_irq(ts->spi->irq);
+       }
+}
+
+/* Must be called with ts->lock held */
+static void ads7846_restart(struct ads7846 *ts)
+{
+       if (!ts->disabled && !ts->suspended) {
+               /* Tell IRQ thread that it may poll the device. */
+               ts->stopped = false;
+               mb();
+               enable_irq(ts->spi->irq);
+       }
+}
+
+/* Must be called with ts->lock held */
+static void __ads7846_disable(struct ads7846 *ts)
+{
+       ads7846_stop(ts);
+       regulator_disable(ts->reg);
+
+       /*
+        * We know the chip's in low power mode since we always
+        * leave it that way after every request
+        */
+}
+
+/* Must be called with ts->lock held */
+static void __ads7846_enable(struct ads7846 *ts)
+{
+       regulator_enable(ts->reg);
+       ads7846_restart(ts);
+}
+
+static void ads7846_disable(struct ads7846 *ts)
+{
+       mutex_lock(&ts->lock);
+
+       if (!ts->disabled) {
+
+               if  (!ts->suspended)
+                       __ads7846_disable(ts);
+
+               ts->disabled = true;
+       }
+
+       mutex_unlock(&ts->lock);
+}
+
+static void ads7846_enable(struct ads7846 *ts)
+{
+       mutex_lock(&ts->lock);
+
+       if (ts->disabled) {
+
+               ts->disabled = false;
+
+               if (!ts->suspended)
+                       __ads7846_enable(ts);
+       }
+
+       mutex_unlock(&ts->lock);
+}
+
 /*--------------------------------------------------------------------------*/
 
 /*
@@ -219,23 +293,15 @@ struct ads7845_ser_req {
        struct spi_transfer     xfer[2];
 };
 
-static void ads7846_enable(struct ads7846 *ts);
-static void ads7846_disable(struct ads7846 *ts);
-
-static int device_suspended(struct device *dev)
-{
-       struct ads7846 *ts = dev_get_drvdata(dev);
-       return ts->is_suspended || ts->disabled;
-}
-
 static int ads7846_read12_ser(struct device *dev, unsigned command)
 {
-       struct spi_device       *spi = to_spi_device(dev);
-       struct ads7846          *ts = dev_get_drvdata(dev);
-       struct ser_req          *req = kzalloc(sizeof *req, GFP_KERNEL);
-       int                     status;
-       int                     use_internal;
+       struct spi_device *spi = to_spi_device(dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
+       struct ser_req *req;
+       int status;
+       int use_internal;
 
+       req = kzalloc(sizeof *req, GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
@@ -282,11 +348,11 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
        CS_CHANGE(req->xfer[5]);
        spi_message_add_tail(&req->xfer[5], &req->msg);
 
-       ts->irq_disabled = 1;
-       disable_irq(spi->irq);
+       mutex_lock(&ts->lock);
+       ads7846_stop(ts);
        status = spi_sync(spi, &req->msg);
-       ts->irq_disabled = 0;
-       enable_irq(spi->irq);
+       ads7846_restart(ts);
+       mutex_unlock(&ts->lock);
 
        if (status == 0) {
                /* on-wire is a must-ignore bit, a BE12 value, then padding */
@@ -301,11 +367,12 @@ static int ads7846_read12_ser(struct device *dev, unsigned command)
 
 static int ads7845_read12_ser(struct device *dev, unsigned command)
 {
-       struct spi_device       *spi = to_spi_device(dev);
-       struct ads7846          *ts = dev_get_drvdata(dev);
-       struct ads7845_ser_req  *req = kzalloc(sizeof *req, GFP_KERNEL);
-       int                     status;
+       struct spi_device *spi = to_spi_device(dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
+       struct ads7845_ser_req *req;
+       int status;
 
+       req = kzalloc(sizeof *req, GFP_KERNEL);
        if (!req)
                return -ENOMEM;
 
@@ -317,11 +384,11 @@ static int ads7845_read12_ser(struct device *dev, unsigned command)
        req->xfer[0].len = 3;
        spi_message_add_tail(&req->xfer[0], &req->msg);
 
-       ts->irq_disabled = 1;
-       disable_irq(spi->irq);
+       mutex_lock(&ts->lock);
+       ads7846_stop(ts);
        status = spi_sync(spi, &req->msg);
-       ts->irq_disabled = 0;
-       enable_irq(spi->irq);
+       ads7846_restart(ts);
+       mutex_unlock(&ts->lock);
 
        if (status == 0) {
                /* BE12 value, then padding */
@@ -374,6 +441,7 @@ static inline unsigned vaux_adjust(struct ads7846 *ts, ssize_t v)
        /* external resistors may scale vAUX into 0..vREF */
        retval *= ts->vref_mv;
        retval = retval >> 12;
+
        return retval;
 }
 
@@ -384,13 +452,13 @@ static inline unsigned vbatt_adjust(struct ads7846 *ts, ssize_t v)
        /* ads7846 has a resistor ladder to scale this signal down */
        if (ts->model == 7846)
                retval *= 4;
+
        return retval;
 }
 
 SHOW(in0_input, vaux, vaux_adjust)
 SHOW(in1_input, vbatt, vbatt_adjust)
 
-
 static struct attribute *ads7846_attributes[] = {
        &dev_attr_temp0.attr,
        &dev_attr_temp1.attr,
@@ -498,17 +566,12 @@ static inline void ads784x_hwmon_unregister(struct spi_device *spi,
 }
 #endif
 
-static int is_pen_down(struct device *dev)
-{
-       struct ads7846  *ts = dev_get_drvdata(dev);
-
-       return ts->pendown;
-}
-
 static ssize_t ads7846_pen_down_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       return sprintf(buf, "%u\n", is_pen_down(dev));
+       struct ads7846 *ts = dev_get_drvdata(dev);
+
+       return sprintf(buf, "%u\n", ts->pendown);
 }
 
 static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
@@ -516,7 +579,7 @@ static DEVICE_ATTR(pen_down, S_IRUGO, ads7846_pen_down_show, NULL);
 static ssize_t ads7846_disable_show(struct device *dev,
                                     struct device_attribute *attr, char *buf)
 {
-       struct ads7846  *ts = dev_get_drvdata(dev);
+       struct ads7846 *ts = dev_get_drvdata(dev);
 
        return sprintf(buf, "%u\n", ts->disabled);
 }
@@ -531,15 +594,11 @@ static ssize_t ads7846_disable_store(struct device *dev,
        if (strict_strtoul(buf, 10, &i))
                return -EINVAL;
 
-       spin_lock_irq(&ts->lock);
-
        if (i)
                ads7846_disable(ts);
        else
                ads7846_enable(ts);
 
-       spin_unlock_irq(&ts->lock);
-
        return count;
 }
 
@@ -569,23 +628,141 @@ static void null_wait_for_sync(void)
 {
 }
 
-/*
- * PENIRQ only kicks the timer.  The timer only reissues the SPI transfer,
- * to retrieve touchscreen status.
- *
- * The SPI transfer completion callback does the real work.  It reports
- * touchscreen events and reactivates the timer (or IRQ) as appropriate.
- */
+static int ads7846_debounce_filter(void *ads, int data_idx, int *val)
+{
+       struct ads7846 *ts = ads;
+
+       if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
+               /* Start over collecting consistent readings. */
+               ts->read_rep = 0;
+               /*
+                * Repeat it, if this was the first read or the read
+                * wasn't consistent enough.
+                */
+               if (ts->read_cnt < ts->debounce_max) {
+                       ts->last_read = *val;
+                       ts->read_cnt++;
+                       return ADS7846_FILTER_REPEAT;
+               } else {
+                       /*
+                        * Maximum number of debouncing reached and still
+                        * not enough number of consistent readings. Abort
+                        * the whole sample, repeat it in the next sampling
+                        * period.
+                        */
+                       ts->read_cnt = 0;
+                       return ADS7846_FILTER_IGNORE;
+               }
+       } else {
+               if (++ts->read_rep > ts->debounce_rep) {
+                       /*
+                        * Got a good reading for this coordinate,
+                        * go for the next one.
+                        */
+                       ts->read_cnt = 0;
+                       ts->read_rep = 0;
+                       return ADS7846_FILTER_OK;
+               } else {
+                       /* Read more values that are consistent. */
+                       ts->read_cnt++;
+                       return ADS7846_FILTER_REPEAT;
+               }
+       }
+}
+
+static int ads7846_no_filter(void *ads, int data_idx, int *val)
+{
+       return ADS7846_FILTER_OK;
+}
+
+static int ads7846_get_value(struct ads7846 *ts, struct spi_message *m)
+{
+       struct spi_transfer *t =
+               list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+
+       if (ts->model == 7845) {
+               return be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
+       } else {
+               /*
+                * adjust:  on-wire is a must-ignore bit, a BE12 value, then
+                * padding; built from two 8 bit values written msb-first.
+                */
+               return be16_to_cpup((__be16 *)t->rx_buf) >> 3;
+       }
+}
+
+static void ads7846_update_value(struct spi_message *m, int val)
+{
+       struct spi_transfer *t =
+               list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
+
+       *(u16 *)t->rx_buf = val;
+}
+
+static void ads7846_read_state(struct ads7846 *ts)
+{
+       struct ads7846_packet *packet = ts->packet;
+       struct spi_message *m;
+       int msg_idx = 0;
+       int val;
+       int action;
+       int error;
+
+       while (msg_idx < ts->msg_count) {
+
+               ts->wait_for_sync();
+
+               m = &ts->msg[msg_idx];
+               error = spi_sync(ts->spi, m);
+               if (error) {
+                       dev_err(&ts->spi->dev, "spi_async --> %d\n", error);
+                       packet->tc.ignore = true;
+                       return;
+               }
+
+               /*
+                * Last message is power down request, no need to convert
+                * or filter the value.
+                */
+               if (msg_idx < ts->msg_count - 1) {
 
-static void ads7846_rx(void *ads)
+                       val = ads7846_get_value(ts, m);
+
+                       action = ts->filter(ts->filter_data, msg_idx, &val);
+                       switch (action) {
+                       case ADS7846_FILTER_REPEAT:
+                               continue;
+
+                       case ADS7846_FILTER_IGNORE:
+                               packet->tc.ignore = true;
+                               msg_idx = ts->msg_count - 1;
+                               continue;
+
+                       case ADS7846_FILTER_OK:
+                               ads7846_update_value(m, val);
+                               packet->tc.ignore = false;
+                               msg_idx++;
+                               break;
+
+                       default:
+                               BUG();
+                       }
+               } else {
+                       msg_idx++;
+               }
+       }
+}
+
+static void ads7846_report_state(struct ads7846 *ts)
 {
-       struct ads7846          *ts = ads;
-       struct ads7846_packet   *packet = ts->packet;
-       unsigned                Rt;
-       u16                     x, y, z1, z2;
+       struct ads7846_packet *packet = ts->packet;
+       unsigned int Rt;
+       u16 x, y, z1, z2;
 
-       /* ads7846_rx_val() did in-place conversion (including byteswap) from
-        * on-the-wire format as part of debouncing to get stable readings.
+       /*
+        * ads7846_get_value() does in-place conversion (including byte swap)
+        * from on-the-wire format as part of debouncing to get stable
+        * readings.
         */
        if (ts->model == 7845) {
                x = *(u16 *)packet->tc.x_buf;
@@ -623,19 +800,19 @@ static void ads7846_rx(void *ads)
                Rt = 0;
        }
 
-       /* Sample found inconsistent by debouncing or pressure is beyond
+       /*
+        * Sample found inconsistent by debouncing or pressure is beyond
         * the maximum. Don't report it to user space, repeat at least
         * once more the measurement
         */
        if (packet->tc.ignore || Rt > ts->pressure_max) {
                dev_vdbg(&ts->spi->dev, "ignored %d pressure %d\n",
                         packet->tc.ignore, Rt);
-               hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
-                             HRTIMER_MODE_REL);
                return;
        }
 
-       /* Maybe check the pendown state before reporting. This discards
+       /*
+        * Maybe check the pendown state before reporting. This discards
         * false readings when the pen is lifted.
         */
        if (ts->penirq_recheck_delay_usecs) {
@@ -644,8 +821,9 @@ static void ads7846_rx(void *ads)
                        Rt = 0;
        }
 
-       /* NOTE: We can't rely on the pressure to determine the pen down
-        * state, even this controller has a pressure sensor.  The pressure
+       /*
+        * NOTE: We can't rely on the pressure to determine the pen down
+        * state, even this controller has a pressure sensor. The pressure
         * value can fluctuate for quite a while after lifting the pen and
         * in some cases may not even settle at the expected value.
         *
@@ -655,15 +833,15 @@ static void ads7846_rx(void *ads)
        if (Rt) {
                struct input_dev *input = ts->input;
 
+               if (ts->swap_xy)
+                       swap(x, y);
+
                if (!ts->pendown) {
                        input_report_key(input, BTN_TOUCH, 1);
-                       ts->pendown = 1;
+                       ts->pendown = true;
                        dev_vdbg(&ts->spi->dev, "DOWN\n");
                }
 
-               if (ts->swap_xy)
-                       swap(x, y);
-
                input_report_abs(input, ABS_X, x);
                input_report_abs(input, ABS_Y, y);
                input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt);
@@ -671,246 +849,94 @@ static void ads7846_rx(void *ads)
                input_sync(input);
                dev_vdbg(&ts->spi->dev, "%4d/%4d/%4d\n", x, y, Rt);
        }
-
-       hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD),
-                       HRTIMER_MODE_REL);
-}
-
-static int ads7846_debounce(void *ads, int data_idx, int *val)
-{
-       struct ads7846          *ts = ads;
-
-       if (!ts->read_cnt || (abs(ts->last_read - *val) > ts->debounce_tol)) {
-               /* Start over collecting consistent readings. */
-               ts->read_rep = 0;
-               /* Repeat it, if this was the first read or the read
-                * wasn't consistent enough. */
-               if (ts->read_cnt < ts->debounce_max) {
-                       ts->last_read = *val;
-                       ts->read_cnt++;
-                       return ADS7846_FILTER_REPEAT;
-               } else {
-                       /* Maximum number of debouncing reached and still
-                        * not enough number of consistent readings. Abort
-                        * the whole sample, repeat it in the next sampling
-                        * period.
-                        */
-                       ts->read_cnt = 0;
-                       return ADS7846_FILTER_IGNORE;
-               }
-       } else {
-               if (++ts->read_rep > ts->debounce_rep) {
-                       /* Got a good reading for this coordinate,
-                        * go for the next one. */
-                       ts->read_cnt = 0;
-                       ts->read_rep = 0;
-                       return ADS7846_FILTER_OK;
-               } else {
-                       /* Read more values that are consistent. */
-                       ts->read_cnt++;
-                       return ADS7846_FILTER_REPEAT;
-               }
-       }
 }
 
-static int ads7846_no_filter(void *ads, int data_idx, int *val)
+static irqreturn_t ads7846_hard_irq(int irq, void *handle)
 {
-       return ADS7846_FILTER_OK;
-}
-
-static void ads7846_rx_val(void *ads)
-{
-       struct ads7846 *ts = ads;
-       struct ads7846_packet *packet = ts->packet;
-       struct spi_message *m;
-       struct spi_transfer *t;
-       int val;
-       int action;
-       int status;
-
-       m = &ts->msg[ts->msg_idx];
-       t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list);
-
-       if (ts->model == 7845) {
-               val = be16_to_cpup((__be16 *)&(((char*)t->rx_buf)[1])) >> 3;
-       } else {
-               /* adjust:  on-wire is a must-ignore bit, a BE12 value, then
-                * padding; built from two 8 bit values written msb-first.
-                */
-               val = be16_to_cpup((__be16 *)t->rx_buf) >> 3;
-       }
+       struct ads7846 *ts = handle;
 
-       action = ts->filter(ts->filter_data, ts->msg_idx, &val);
-       switch (action) {
-       case ADS7846_FILTER_REPEAT:
-               break;
-       case ADS7846_FILTER_IGNORE:
-               packet->tc.ignore = 1;
-               /* Last message will contain ads7846_rx() as the
-                * completion function.
-                */
-               m = ts->last_msg;
-               break;
-       case ADS7846_FILTER_OK:
-               *(u16 *)t->rx_buf = val;
-               packet->tc.ignore = 0;
-               m = &ts->msg[++ts->msg_idx];
-               break;
-       default:
-               BUG();
-       }
-       ts->wait_for_sync();
-       status = spi_async(ts->spi, m);
-       if (status)
-               dev_err(&ts->spi->dev, "spi_async --> %d\n",
-                               status);
+       return get_pendown_state(ts) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
 }
 
-static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
-{
-       struct ads7846  *ts = container_of(handle, struct ads7846, timer);
-       int             status = 0;
-
-       spin_lock(&ts->lock);
-
-       if (unlikely(!get_pendown_state(ts) ||
-                    device_suspended(&ts->spi->dev))) {
-               if (ts->pendown) {
-                       struct input_dev *input = ts->input;
-
-                       input_report_key(input, BTN_TOUCH, 0);
-                       input_report_abs(input, ABS_PRESSURE, 0);
-                       input_sync(input);
-
-                       ts->pendown = 0;
-                       dev_vdbg(&ts->spi->dev, "UP\n");
-               }
-
-               /* measurement cycle ended */
-               if (!device_suspended(&ts->spi->dev)) {
-                       ts->irq_disabled = 0;
-                       enable_irq(ts->spi->irq);
-               }
-               ts->pending = 0;
-       } else {
-               /* pen is still down, continue with the measurement */
-               ts->msg_idx = 0;
-               ts->wait_for_sync();
-               status = spi_async(ts->spi, &ts->msg[0]);
-               if (status)
-                       dev_err(&ts->spi->dev, "spi_async --> %d\n", status);
-       }
-
-       spin_unlock(&ts->lock);
-       return HRTIMER_NORESTART;
-}
 
 static irqreturn_t ads7846_irq(int irq, void *handle)
 {
        struct ads7846 *ts = handle;
-       unsigned long flags;
-
-       spin_lock_irqsave(&ts->lock, flags);
-       if (likely(get_pendown_state(ts))) {
-               if (!ts->irq_disabled) {
-                       /* The ARM do_simple_IRQ() dispatcher doesn't act
-                        * like the other dispatchers:  it will report IRQs
-                        * even after they've been disabled.  We work around
-                        * that here.  (The "generic irq" framework may help...)
-                        */
-                       ts->irq_disabled = 1;
-                       disable_irq_nosync(ts->spi->irq);
-                       ts->pending = 1;
-                       hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
-                                       HRTIMER_MODE_REL);
-               }
-       }
-       spin_unlock_irqrestore(&ts->lock, flags);
 
-       return IRQ_HANDLED;
-}
+       /* Start with a small delay before checking pendown state */
+       msleep(TS_POLL_DELAY);
 
-/*--------------------------------------------------------------------------*/
+       while (!ts->stopped && get_pendown_state(ts)) {
 
-/* Must be called with ts->lock held */
-static void ads7846_disable(struct ads7846 *ts)
-{
-       if (ts->disabled)
-               return;
+               /* pen is down, continue with the measurement */
+               ads7846_read_state(ts);
 
-       ts->disabled = 1;
+               if (!ts->stopped)
+                       ads7846_report_state(ts);
 
-       /* are we waiting for IRQ, or polling? */
-       if (!ts->pending) {
-               ts->irq_disabled = 1;
-               disable_irq(ts->spi->irq);
-       } else {
-               /* the timer will run at least once more, and
-                * leave everything in a clean state, IRQ disabled
-                */
-               while (ts->pending) {
-                       spin_unlock_irq(&ts->lock);
-                       msleep(1);
-                       spin_lock_irq(&ts->lock);
-               }
+               wait_event_timeout(ts->wait, ts->stopped,
+                                  msecs_to_jiffies(TS_POLL_PERIOD));
        }
 
-       regulator_disable(ts->reg);
-
-       /* we know the chip's in lowpower mode since we always
-        * leave it that way after every request
-        */
-}
+       if (ts->pendown) {
+               struct input_dev *input = ts->input;
 
-/* Must be called with ts->lock held */
-static void ads7846_enable(struct ads7846 *ts)
-{
-       if (!ts->disabled)
-               return;
+               input_report_key(input, BTN_TOUCH, 0);
+               input_report_abs(input, ABS_PRESSURE, 0);
+               input_sync(input);
 
-       regulator_enable(ts->reg);
+               ts->pendown = false;
+               dev_vdbg(&ts->spi->dev, "UP\n");
+       }
 
-       ts->disabled = 0;
-       ts->irq_disabled = 0;
-       enable_irq(ts->spi->irq);
+       return IRQ_HANDLED;
 }
 
 static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
 {
        struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
-       spin_lock_irq(&ts->lock);
+       mutex_lock(&ts->lock);
 
-       ts->is_suspended = 1;
-       ads7846_disable(ts);
+       if (!ts->suspended) {
 
-       spin_unlock_irq(&ts->lock);
+               if (!ts->disabled)
+                       __ads7846_disable(ts);
 
-       if (device_may_wakeup(&ts->spi->dev))
-               enable_irq_wake(ts->spi->irq);
+               if (device_may_wakeup(&ts->spi->dev))
+                       enable_irq_wake(ts->spi->irq);
 
-       return 0;
+               ts->suspended = true;
+       }
+
+       mutex_unlock(&ts->lock);
 
+       return 0;
 }
 
 static int ads7846_resume(struct spi_device *spi)
 {
        struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
-       if (device_may_wakeup(&ts->spi->dev))
-               disable_irq_wake(ts->spi->irq);
+       mutex_lock(&ts->lock);
+
+       if (ts->suspended) {
 
-       spin_lock_irq(&ts->lock);
+               ts->suspended = false;
 
-       ts->is_suspended = 0;
-       ads7846_enable(ts);
+               if (device_may_wakeup(&ts->spi->dev))
+                       disable_irq_wake(ts->spi->irq);
 
-       spin_unlock_irq(&ts->lock);
+               if (!ts->disabled)
+                       __ads7846_enable(ts);
+       }
+
+       mutex_unlock(&ts->lock);
 
        return 0;
 }
 
-static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
 {
        struct ads7846_platform_data *pdata = spi->dev.platform_data;
        int err;
@@ -932,146 +958,40 @@ static int __devinit setup_pendown(struct spi_device *spi, struct ads7846 *ts)
        err = gpio_request(pdata->gpio_pendown, "ads7846_pendown");
        if (err) {
                dev_err(&spi->dev, "failed to request pendown GPIO%d\n",
-                               pdata->gpio_pendown);
+                       pdata->gpio_pendown);
                return err;
        }
 
        ts->gpio_pendown = pdata->gpio_pendown;
+
        return 0;
 }
 
-static int __devinit ads7846_probe(struct spi_device *spi)
+/*
+ * Set up the transfers to read touchscreen state; this assumes we
+ * use formula #2 for pressure, not #3.
+ */
+static void __devinit ads7846_setup_spi_msg(struct ads7846 *ts,
+                               const struct ads7846_platform_data *pdata)
 {
-       struct ads7846 *ts;
-       struct ads7846_packet *packet;
-       struct input_dev *input_dev;
-       const struct ads7846_platform_data *pdata = spi->dev.platform_data;
-       struct spi_message *m;
-       struct spi_transfer *x;
-       unsigned long irq_flags;
-       int vref;
-       int err;
-
-       if (!spi->irq) {
-               dev_dbg(&spi->dev, "no IRQ?\n");
-               return -ENODEV;
-       }
-
-       if (!pdata) {
-               dev_dbg(&spi->dev, "no platform data?\n");
-               return -ENODEV;
-       }
-
-       /* don't exceed max specified sample rate */
-       if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
-               dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
-                               (spi->max_speed_hz/SAMPLE_BITS)/1000);
-               return -EINVAL;
-       }
-
-       /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except
-        * that even if the hardware can do that, the SPI controller driver
-        * may not.  So we stick to very-portable 8 bit words, both RX and TX.
-        */
-       spi->bits_per_word = 8;
-       spi->mode = SPI_MODE_0;
-       err = spi_setup(spi);
-       if (err < 0)
-               return err;
-
-       ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
-       packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
-       input_dev = input_allocate_device();
-       if (!ts || !packet || !input_dev) {
-               err = -ENOMEM;
-               goto err_free_mem;
-       }
-
-       dev_set_drvdata(&spi->dev, ts);
-
-       ts->packet = packet;
-       ts->spi = spi;
-       ts->input = input_dev;
-       ts->vref_mv = pdata->vref_mv;
-       ts->swap_xy = pdata->swap_xy;
-
-       hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-       ts->timer.function = ads7846_timer;
-
-       spin_lock_init(&ts->lock);
-
-       ts->model = pdata->model ? : 7846;
-       ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
-       ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
-       ts->pressure_max = pdata->pressure_max ? : ~0;
-
-       if (pdata->filter != NULL) {
-               if (pdata->filter_init != NULL) {
-                       err = pdata->filter_init(pdata, &ts->filter_data);
-                       if (err < 0)
-                               goto err_free_mem;
-               }
-               ts->filter = pdata->filter;
-               ts->filter_cleanup = pdata->filter_cleanup;
-       } else if (pdata->debounce_max) {
-               ts->debounce_max = pdata->debounce_max;
-               if (ts->debounce_max < 2)
-                       ts->debounce_max = 2;
-               ts->debounce_tol = pdata->debounce_tol;
-               ts->debounce_rep = pdata->debounce_rep;
-               ts->filter = ads7846_debounce;
-               ts->filter_data = ts;
-       } else
-               ts->filter = ads7846_no_filter;
-
-       err = setup_pendown(spi, ts);
-       if (err)
-               goto err_cleanup_filter;
-
-       if (pdata->penirq_recheck_delay_usecs)
-               ts->penirq_recheck_delay_usecs =
-                               pdata->penirq_recheck_delay_usecs;
-
-       ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
-
-       snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
-       snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
-
-       input_dev->name = ts->name;
-       input_dev->phys = ts->phys;
-       input_dev->dev.parent = &spi->dev;
-
-       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-       input_set_abs_params(input_dev, ABS_X,
-                       pdata->x_min ? : 0,
-                       pdata->x_max ? : MAX_12BIT,
-                       0, 0);
-       input_set_abs_params(input_dev, ABS_Y,
-                       pdata->y_min ? : 0,
-                       pdata->y_max ? : MAX_12BIT,
-                       0, 0);
-       input_set_abs_params(input_dev, ABS_PRESSURE,
-                       pdata->pressure_min, pdata->pressure_max, 0, 0);
-
-       vref = pdata->keep_vref_on;
+       struct spi_message *m = &ts->msg[0];
+       struct spi_transfer *x = ts->xfer;
+       struct ads7846_packet *packet = ts->packet;
+       int vref = pdata->keep_vref_on;
 
        if (ts->model == 7873) {
-               /* The AD7873 is almost identical to the ADS7846
+               /*
+                * The AD7873 is almost identical to the ADS7846
                 * keep VREF off during differential/ratiometric
-                * conversion modes
+                * conversion modes.
                 */
                ts->model = 7846;
                vref = 0;
        }
 
-       /* set up the transfers to read touchscreen state; this assumes we
-        * use formula #2 for pressure, not #3.
-        */
-       m = &ts->msg[0];
-       x = ts->xfer;
-
+       ts->msg_count = 1;
        spi_message_init(m);
+       m->context = ts;
 
        if (ts->model == 7845) {
                packet->read_y_cmd[0] = READ_Y(vref);
@@ -1094,7 +1014,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_add_tail(x, m);
        }
 
-       /* the first sample after switching drivers can be low quality;
+       /*
+        * The first sample after switching drivers can be low quality;
         * optionally discard it, using a second one after the signals
         * have had enough time to stabilize.
         */
@@ -1112,11 +1033,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_add_tail(x, m);
        }
 
-       m->complete = ads7846_rx_val;
-       m->context = ts;
-
+       ts->msg_count++;
        m++;
        spi_message_init(m);
+       m->context = ts;
 
        if (ts->model == 7845) {
                x++;
@@ -1156,13 +1076,12 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                spi_message_add_tail(x, m);
        }
 
-       m->complete = ads7846_rx_val;
-       m->context = ts;
-
        /* turn y+ off, x- on; we'll use formula #2 */
        if (ts->model == 7846) {
+               ts->msg_count++;
                m++;
                spi_message_init(m);
+               m->context = ts;
 
                x++;
                packet->read_z1 = READ_Z1(vref);
@@ -1190,11 +1109,10 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                        spi_message_add_tail(x, m);
                }
 
-               m->complete = ads7846_rx_val;
-               m->context = ts;
-
+               ts->msg_count++;
                m++;
                spi_message_init(m);
+               m->context = ts;
 
                x++;
                packet->read_z2 = READ_Z2(vref);
@@ -1221,14 +1139,13 @@ static int __devinit ads7846_probe(struct spi_device *spi)
                        x->len = 2;
                        spi_message_add_tail(x, m);
                }
-
-               m->complete = ads7846_rx_val;
-               m->context = ts;
        }
 
        /* power down */
+       ts->msg_count++;
        m++;
        spi_message_init(m);
+       m->context = ts;
 
        if (ts->model == 7845) {
                x++;
@@ -1251,11 +1168,119 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        CS_CHANGE(*x);
        spi_message_add_tail(x, m);
+}
 
-       m->complete = ads7846_rx;
-       m->context = ts;
+static int __devinit ads7846_probe(struct spi_device *spi)
+{
+       struct ads7846 *ts;
+       struct ads7846_packet *packet;
+       struct input_dev *input_dev;
+       struct ads7846_platform_data *pdata = spi->dev.platform_data;
+       unsigned long irq_flags;
+       int err;
+
+       if (!spi->irq) {
+               dev_dbg(&spi->dev, "no IRQ?\n");
+               return -ENODEV;
+       }
+
+       if (!pdata) {
+               dev_dbg(&spi->dev, "no platform data?\n");
+               return -ENODEV;
+       }
+
+       /* don't exceed max specified sample rate */
+       if (spi->max_speed_hz > (125000 * SAMPLE_BITS)) {
+               dev_dbg(&spi->dev, "f(sample) %d KHz?\n",
+                               (spi->max_speed_hz/SAMPLE_BITS)/1000);
+               return -EINVAL;
+       }
+
+       /* We'd set TX word size 8 bits and RX word size to 13 bits ... except
+        * that even if the hardware can do that, the SPI controller driver
+        * may not.  So we stick to very-portable 8 bit words, both RX and TX.
+        */
+       spi->bits_per_word = 8;
+       spi->mode = SPI_MODE_0;
+       err = spi_setup(spi);
+       if (err < 0)
+               return err;
 
-       ts->last_msg = m;
+       ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL);
+       packet = kzalloc(sizeof(struct ads7846_packet), GFP_KERNEL);
+       input_dev = input_allocate_device();
+       if (!ts || !packet || !input_dev) {
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       dev_set_drvdata(&spi->dev, ts);
+
+       ts->packet = packet;
+       ts->spi = spi;
+       ts->input = input_dev;
+       ts->vref_mv = pdata->vref_mv;
+       ts->swap_xy = pdata->swap_xy;
+
+       mutex_init(&ts->lock);
+       init_waitqueue_head(&ts->wait);
+
+       ts->model = pdata->model ? : 7846;
+       ts->vref_delay_usecs = pdata->vref_delay_usecs ? : 100;
+       ts->x_plate_ohms = pdata->x_plate_ohms ? : 400;
+       ts->pressure_max = pdata->pressure_max ? : ~0;
+
+       if (pdata->filter != NULL) {
+               if (pdata->filter_init != NULL) {
+                       err = pdata->filter_init(pdata, &ts->filter_data);
+                       if (err < 0)
+                               goto err_free_mem;
+               }
+               ts->filter = pdata->filter;
+               ts->filter_cleanup = pdata->filter_cleanup;
+       } else if (pdata->debounce_max) {
+               ts->debounce_max = pdata->debounce_max;
+               if (ts->debounce_max < 2)
+                       ts->debounce_max = 2;
+               ts->debounce_tol = pdata->debounce_tol;
+               ts->debounce_rep = pdata->debounce_rep;
+               ts->filter = ads7846_debounce_filter;
+               ts->filter_data = ts;
+       } else {
+               ts->filter = ads7846_no_filter;
+       }
+
+       err = ads7846_setup_pendown(spi, ts);
+       if (err)
+               goto err_cleanup_filter;
+
+       if (pdata->penirq_recheck_delay_usecs)
+               ts->penirq_recheck_delay_usecs =
+                               pdata->penirq_recheck_delay_usecs;
+
+       ts->wait_for_sync = pdata->wait_for_sync ? : null_wait_for_sync;
+
+       snprintf(ts->phys, sizeof(ts->phys), "%s/input0", dev_name(&spi->dev));
+       snprintf(ts->name, sizeof(ts->name), "ADS%d Touchscreen", ts->model);
+
+       input_dev->name = ts->name;
+       input_dev->phys = ts->phys;
+       input_dev->dev.parent = &spi->dev;
+
+       input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(input_dev, ABS_X,
+                       pdata->x_min ? : 0,
+                       pdata->x_max ? : MAX_12BIT,
+                       0, 0);
+       input_set_abs_params(input_dev, ABS_Y,
+                       pdata->y_min ? : 0,
+                       pdata->y_max ? : MAX_12BIT,
+                       0, 0);
+       input_set_abs_params(input_dev, ABS_PRESSURE,
+                       pdata->pressure_min, pdata->pressure_max, 0, 0);
+
+       ads7846_setup_spi_msg(ts, pdata);
 
        ts->reg = regulator_get(&spi->dev, "vcc");
        if (IS_ERR(ts->reg)) {
@@ -1271,16 +1296,17 @@ static int __devinit ads7846_probe(struct spi_device *spi)
        }
 
        irq_flags = pdata->irq_flags ? : IRQF_TRIGGER_FALLING;
+       irq_flags |= IRQF_ONESHOT;
 
-       err = request_irq(spi->irq, ads7846_irq, irq_flags,
-                         spi->dev.driver->name, ts);
-
+       err = request_threaded_irq(spi->irq, ads7846_hard_irq, ads7846_irq,
+                                  irq_flags, spi->dev.driver->name, ts);
        if (err && !pdata->irq_flags) {
                dev_info(&spi->dev,
                        "trying pin change workaround on irq %d\n", spi->irq);
-               err = request_irq(spi->irq, ads7846_irq,
-                                 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
-                                 spi->dev.driver->name, ts);
+               irq_flags |= IRQF_TRIGGER_RISING;
+               err = request_threaded_irq(spi->irq,
+                                 ads7846_hard_irq, ads7846_irq,
+                                 irq_flags, spi->dev.driver->name, ts);
        }
 
        if (err) {
@@ -1294,7 +1320,8 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
        dev_info(&spi->dev, "touchscreen, irq %d\n", spi->irq);
 
-       /* take a first sample, leaving nPENIRQ active and vREF off; avoid
+       /*
+        * Take a first sample, leaving nPENIRQ active and vREF off; avoid
         * the touchscreen, in case it's not connected.
         */
        if (ts->model == 7845)
@@ -1340,20 +1367,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
 
 static int __devexit ads7846_remove(struct spi_device *spi)
 {
-       struct ads7846          *ts = dev_get_drvdata(&spi->dev);
+       struct ads7846 *ts = dev_get_drvdata(&spi->dev);
 
        device_init_wakeup(&spi->dev, false);
 
-       ads784x_hwmon_unregister(spi, ts);
-       input_unregister_device(ts->input);
-
-       ads7846_suspend(spi, PMSG_SUSPEND);
-
        sysfs_remove_group(&spi->dev.kobj, &ads784x_attr_group);
 
+       ads7846_disable(ts);
        free_irq(ts->spi->irq, ts);
-       /* suspend left the IRQ disabled */
-       enable_irq(ts->spi->irq);
+
+       input_unregister_device(ts->input);
+
+       ads784x_hwmon_unregister(spi, ts);
 
        regulator_disable(ts->reg);
        regulator_put(ts->reg);
@@ -1368,6 +1393,7 @@ static int __devexit ads7846_remove(struct spi_device *spi)
        kfree(ts);
 
        dev_dbg(&spi->dev, "unregistered touchscreen\n");
+
        return 0;
 }
 
diff --git a/drivers/input/touchscreen/bu21013_ts.c b/drivers/input/touchscreen/bu21013_ts.c
new file mode 100644 (file)
index 0000000..ccde586
--- /dev/null
@@ -0,0 +1,648 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+#include <linux/input/bu21013.h>
+#include <linux/slab.h>
+
+#define PEN_DOWN_INTR  0
+#define MAX_FINGERS    2
+#define RESET_DELAY    30
+#define PENUP_TIMEOUT  (10)
+#define DELTA_MIN      16
+#define MASK_BITS      0x03
+#define SHIFT_8                8
+#define SHIFT_2                2
+#define LENGTH_OF_BUFFER       11
+#define I2C_RETRY_COUNT        5
+
+#define BU21013_SENSORS_BTN_0_7_REG    0x70
+#define BU21013_SENSORS_BTN_8_15_REG   0x71
+#define BU21013_SENSORS_BTN_16_23_REG  0x72
+#define BU21013_X1_POS_MSB_REG         0x73
+#define BU21013_X1_POS_LSB_REG         0x74
+#define BU21013_Y1_POS_MSB_REG         0x75
+#define BU21013_Y1_POS_LSB_REG         0x76
+#define BU21013_X2_POS_MSB_REG         0x77
+#define BU21013_X2_POS_LSB_REG         0x78
+#define BU21013_Y2_POS_MSB_REG         0x79
+#define BU21013_Y2_POS_LSB_REG         0x7A
+#define BU21013_INT_CLR_REG            0xE8
+#define BU21013_INT_MODE_REG           0xE9
+#define BU21013_GAIN_REG               0xEA
+#define BU21013_OFFSET_MODE_REG                0xEB
+#define BU21013_XY_EDGE_REG            0xEC
+#define BU21013_RESET_REG              0xED
+#define BU21013_CALIB_REG              0xEE
+#define BU21013_DONE_REG               0xEF
+#define BU21013_SENSOR_0_7_REG         0xF0
+#define BU21013_SENSOR_8_15_REG                0xF1
+#define BU21013_SENSOR_16_23_REG       0xF2
+#define BU21013_POS_MODE1_REG          0xF3
+#define BU21013_POS_MODE2_REG          0xF4
+#define BU21013_CLK_MODE_REG           0xF5
+#define BU21013_IDLE_REG               0xFA
+#define BU21013_FILTER_REG             0xFB
+#define BU21013_TH_ON_REG              0xFC
+#define BU21013_TH_OFF_REG             0xFD
+
+
+#define BU21013_RESET_ENABLE           0x01
+
+#define BU21013_SENSORS_EN_0_7         0x3F
+#define BU21013_SENSORS_EN_8_15                0xFC
+#define BU21013_SENSORS_EN_16_23       0x1F
+
+#define BU21013_POS_MODE1_0            0x02
+#define BU21013_POS_MODE1_1            0x04
+#define BU21013_POS_MODE1_2            0x08
+
+#define BU21013_POS_MODE2_ZERO         0x01
+#define BU21013_POS_MODE2_AVG1         0x02
+#define BU21013_POS_MODE2_AVG2         0x04
+#define BU21013_POS_MODE2_EN_XY                0x08
+#define BU21013_POS_MODE2_EN_RAW       0x10
+#define BU21013_POS_MODE2_MULTI                0x80
+
+#define BU21013_CLK_MODE_DIV           0x01
+#define BU21013_CLK_MODE_EXT           0x02
+#define BU21013_CLK_MODE_CALIB         0x80
+
+#define BU21013_IDLET_0                        0x01
+#define BU21013_IDLET_1                        0x02
+#define BU21013_IDLET_2                        0x04
+#define BU21013_IDLET_3                        0x08
+#define BU21013_IDLE_INTERMIT_EN       0x10
+
+#define BU21013_DELTA_0_6      0x7F
+#define BU21013_FILTER_EN      0x80
+
+#define BU21013_INT_MODE_LEVEL 0x00
+#define BU21013_INT_MODE_EDGE  0x01
+
+#define BU21013_GAIN_0         0x01
+#define BU21013_GAIN_1         0x02
+#define BU21013_GAIN_2         0x04
+
+#define BU21013_OFFSET_MODE_DEFAULT    0x00
+#define BU21013_OFFSET_MODE_MOVE       0x01
+#define BU21013_OFFSET_MODE_DISABLE    0x02
+
+#define BU21013_TH_ON_0                0x01
+#define BU21013_TH_ON_1                0x02
+#define BU21013_TH_ON_2                0x04
+#define BU21013_TH_ON_3                0x08
+#define BU21013_TH_ON_4                0x10
+#define BU21013_TH_ON_5                0x20
+#define BU21013_TH_ON_6                0x40
+#define BU21013_TH_ON_7                0x80
+#define BU21013_TH_ON_MAX      0xFF
+
+#define BU21013_TH_OFF_0       0x01
+#define BU21013_TH_OFF_1       0x02
+#define BU21013_TH_OFF_2       0x04
+#define BU21013_TH_OFF_3       0x08
+#define BU21013_TH_OFF_4       0x10
+#define BU21013_TH_OFF_5       0x20
+#define BU21013_TH_OFF_6       0x40
+#define BU21013_TH_OFF_7       0x80
+#define BU21013_TH_OFF_MAX     0xFF
+
+#define BU21013_X_EDGE_0       0x01
+#define BU21013_X_EDGE_1       0x02
+#define BU21013_X_EDGE_2       0x04
+#define BU21013_X_EDGE_3       0x08
+#define BU21013_Y_EDGE_0       0x10
+#define BU21013_Y_EDGE_1       0x20
+#define BU21013_Y_EDGE_2       0x40
+#define BU21013_Y_EDGE_3       0x80
+
+#define BU21013_DONE   0x01
+#define BU21013_NUMBER_OF_X_SENSORS    (6)
+#define BU21013_NUMBER_OF_Y_SENSORS    (11)
+
+#define DRIVER_TP      "bu21013_tp"
+
+/**
+ * struct bu21013_ts_data - touch panel data structure
+ * @client: pointer to the i2c client
+ * @wait: variable to wait_queue_head_t structure
+ * @touch_stopped: touch stop flag
+ * @chip: pointer to the touch panel controller
+ * @in_dev: pointer to the input device structure
+ * @intr_pin: interrupt pin value
+ *
+ * Touch panel device data structure
+ */
+struct bu21013_ts_data {
+       struct i2c_client *client;
+       wait_queue_head_t wait;
+       bool touch_stopped;
+       const struct bu21013_platform_device *chip;
+       struct input_dev *in_dev;
+       unsigned int intr_pin;
+};
+
+/**
+ * bu21013_read_block_data(): read the touch co-ordinates
+ * @data: bu21013_ts_data structure pointer
+ * @buf: byte pointer
+ *
+ * Read the touch co-ordinates using i2c read block into buffer
+ * and returns integer.
+ */
+static int bu21013_read_block_data(struct bu21013_ts_data *data, u8 *buf)
+{
+       int ret, i;
+
+       for (i = 0; i < I2C_RETRY_COUNT; i++) {
+               ret = i2c_smbus_read_i2c_block_data
+                       (data->client, BU21013_SENSORS_BTN_0_7_REG,
+                               LENGTH_OF_BUFFER, buf);
+               if (ret == LENGTH_OF_BUFFER)
+                       return 0;
+       }
+       return -EINVAL;
+}
+
+/**
+ * bu21013_do_touch_report(): Get the touch co-ordinates
+ * @data: bu21013_ts_data structure pointer
+ *
+ * Get the touch co-ordinates from touch sensor registers and writes
+ * into device structure and returns integer.
+ */
+static int bu21013_do_touch_report(struct bu21013_ts_data *data)
+{
+       u8      buf[LENGTH_OF_BUFFER];
+       unsigned int pos_x[2], pos_y[2];
+       bool    has_x_sensors, has_y_sensors;
+       int     finger_down_count = 0;
+       int     i;
+
+       if (data == NULL)
+               return -EINVAL;
+
+       if (bu21013_read_block_data(data, buf) < 0)
+               return -EINVAL;
+
+       has_x_sensors = hweight32(buf[0] & BU21013_SENSORS_EN_0_7);
+       has_y_sensors = hweight32(((buf[1] & BU21013_SENSORS_EN_8_15) |
+               ((buf[2] & BU21013_SENSORS_EN_16_23) << SHIFT_8)) >> SHIFT_2);
+       if (!has_x_sensors || !has_y_sensors)
+               return 0;
+
+       for (i = 0; i < MAX_FINGERS; i++) {
+               const u8 *p = &buf[4 * i + 3];
+               unsigned int x = p[0] << SHIFT_2 | (p[1] & MASK_BITS);
+               unsigned int y = p[2] << SHIFT_2 | (p[3] & MASK_BITS);
+               if (x == 0 || y == 0)
+                       continue;
+               pos_x[finger_down_count] = x;
+               pos_y[finger_down_count] = y;
+               finger_down_count++;
+       }
+
+       if (finger_down_count) {
+               if (finger_down_count == 2 &&
+                   (abs(pos_x[0] - pos_x[1]) < DELTA_MIN ||
+                    abs(pos_y[0] - pos_y[1]) < DELTA_MIN)) {
+                       return 0;
+               }
+
+               for (i = 0; i < finger_down_count; i++) {
+                       if (data->chip->x_flip)
+                               pos_x[i] = data->chip->touch_x_max - pos_x[i];
+                       if (data->chip->y_flip)
+                               pos_y[i] = data->chip->touch_y_max - pos_y[i];
+
+                       input_report_abs(data->in_dev,
+                                        ABS_MT_POSITION_X, pos_x[i]);
+                       input_report_abs(data->in_dev,
+                                        ABS_MT_POSITION_Y, pos_y[i]);
+                       input_mt_sync(data->in_dev);
+               }
+       } else
+               input_mt_sync(data->in_dev);
+
+       input_sync(data->in_dev);
+
+       return 0;
+}
+/**
+ * bu21013_gpio_irq() - gpio thread function for touch interrupt
+ * @irq: irq value
+ * @device_data: void pointer
+ *
+ * This gpio thread function for touch interrupt
+ * and returns irqreturn_t.
+ */
+static irqreturn_t bu21013_gpio_irq(int irq, void *device_data)
+{
+       struct bu21013_ts_data *data = device_data;
+       struct i2c_client *i2c = data->client;
+       int retval;
+
+       do {
+               retval = bu21013_do_touch_report(data);
+               if (retval < 0) {
+                       dev_err(&i2c->dev, "bu21013_do_touch_report failed\n");
+                       return IRQ_NONE;
+               }
+
+               data->intr_pin = data->chip->irq_read_val();
+               if (data->intr_pin == PEN_DOWN_INTR)
+                       wait_event_timeout(data->wait, data->touch_stopped,
+                                          msecs_to_jiffies(2));
+       } while (!data->intr_pin && !data->touch_stopped);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * bu21013_init_chip() - power on sequence for the bu21013 controller
+ * @data: device structure pointer
+ *
+ * This function is used to power on
+ * the bu21013 controller and returns integer.
+ */
+static int bu21013_init_chip(struct bu21013_ts_data *data)
+{
+       int retval;
+       struct i2c_client *i2c = data->client;
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_RESET_REG,
+                                       BU21013_RESET_ENABLE);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_RESET reg write failed\n");
+               return retval;
+       }
+       msleep(RESET_DELAY);
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_0_7_REG,
+                                       BU21013_SENSORS_EN_0_7);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_SENSOR_0_7 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_8_15_REG,
+                                               BU21013_SENSORS_EN_8_15);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_SENSOR_8_15 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_SENSOR_16_23_REG,
+                                               BU21013_SENSORS_EN_16_23);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_SENSOR_16_23 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE1_REG,
+                               (BU21013_POS_MODE1_0 | BU21013_POS_MODE1_1));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_POS_MODE1 reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_POS_MODE2_REG,
+                       (BU21013_POS_MODE2_ZERO | BU21013_POS_MODE2_AVG1 |
+                       BU21013_POS_MODE2_AVG2 | BU21013_POS_MODE2_EN_RAW |
+                       BU21013_POS_MODE2_MULTI));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_POS_MODE2 reg write failed\n");
+               return retval;
+       }
+
+       if (data->chip->ext_clk)
+               retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
+                       (BU21013_CLK_MODE_EXT | BU21013_CLK_MODE_CALIB));
+       else
+               retval = i2c_smbus_write_byte_data(i2c, BU21013_CLK_MODE_REG,
+                       (BU21013_CLK_MODE_DIV | BU21013_CLK_MODE_CALIB));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_CLK_MODE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_IDLE_REG,
+                               (BU21013_IDLET_0 | BU21013_IDLE_INTERMIT_EN));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_IDLE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_INT_MODE_REG,
+                                               BU21013_INT_MODE_LEVEL);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_INT_MODE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_FILTER_REG,
+                                               (BU21013_DELTA_0_6 |
+                                                       BU21013_FILTER_EN));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_FILTER reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_ON_REG,
+                                       BU21013_TH_ON_5);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_TH_ON reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_TH_OFF_REG,
+                               BU21013_TH_OFF_4 || BU21013_TH_OFF_3);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_TH_OFF reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_GAIN_REG,
+                                       (BU21013_GAIN_0 | BU21013_GAIN_1));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_GAIN reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_OFFSET_MODE_REG,
+                                       BU21013_OFFSET_MODE_DEFAULT);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_OFFSET_MODE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_XY_EDGE_REG,
+                               (BU21013_X_EDGE_0 | BU21013_X_EDGE_2 |
+                               BU21013_Y_EDGE_1 | BU21013_Y_EDGE_3));
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_XY_EDGE reg write failed\n");
+               return retval;
+       }
+
+       retval = i2c_smbus_write_byte_data(i2c, BU21013_DONE_REG,
+                                                       BU21013_DONE);
+       if (retval < 0) {
+               dev_err(&i2c->dev, "BU21013_REG_DONE reg write failed\n");
+               return retval;
+       }
+
+       return 0;
+}
+
+/**
+ * bu21013_free_irq() - frees IRQ registered for touchscreen
+ * @bu21013_data: device structure pointer
+ *
+ * This function signals interrupt thread to stop processing and
+ * frees interrupt.
+ */
+static void bu21013_free_irq(struct bu21013_ts_data *bu21013_data)
+{
+       bu21013_data->touch_stopped = true;
+       wake_up(&bu21013_data->wait);
+       free_irq(bu21013_data->chip->irq, bu21013_data);
+}
+
+/**
+ * bu21013_probe() - initializes the i2c-client touchscreen driver
+ * @client: i2c client structure pointer
+ * @id: i2c device id pointer
+ *
+ * This function used to initializes the i2c-client touchscreen
+ * driver and returns integer.
+ */
+static int __devinit bu21013_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct bu21013_ts_data *bu21013_data;
+       struct input_dev *in_dev;
+       const struct bu21013_platform_device *pdata =
+                                       client->dev.platform_data;
+       int error;
+
+       if (!i2c_check_functionality(client->adapter,
+                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "i2c smbus byte data not supported\n");
+               return -EIO;
+       }
+
+       if (!pdata) {
+               dev_err(&client->dev, "platform data not defined\n");
+               return -EINVAL;
+       }
+
+       bu21013_data = kzalloc(sizeof(struct bu21013_ts_data), GFP_KERNEL);
+       in_dev = input_allocate_device();
+       if (!bu21013_data || !in_dev) {
+               dev_err(&client->dev, "device memory alloc failed\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       bu21013_data->in_dev = in_dev;
+       bu21013_data->chip = pdata;
+       bu21013_data->client = client;
+       bu21013_data->touch_stopped = false;
+       init_waitqueue_head(&bu21013_data->wait);
+
+       /* configure the gpio pins */
+       if (pdata->cs_en) {
+               error = pdata->cs_en(pdata->cs_pin);
+               if (error < 0) {
+                       dev_err(&client->dev, "chip init failed\n");
+                       goto err_free_mem;
+               }
+       }
+
+       /* configure the touch panel controller */
+       error = bu21013_init_chip(bu21013_data);
+       if (error) {
+               dev_err(&client->dev, "error in bu21013 config\n");
+               goto err_cs_disable;
+       }
+
+       /* register the device to input subsystem */
+       in_dev->name = DRIVER_TP;
+       in_dev->id.bustype = BUS_I2C;
+       in_dev->dev.parent = &client->dev;
+
+       __set_bit(EV_SYN, in_dev->evbit);
+       __set_bit(EV_KEY, in_dev->evbit);
+       __set_bit(EV_ABS, in_dev->evbit);
+
+       input_set_abs_params(in_dev, ABS_MT_POSITION_X, 0,
+                                               pdata->x_max_res, 0, 0);
+       input_set_abs_params(in_dev, ABS_MT_POSITION_Y, 0,
+                                               pdata->y_max_res, 0, 0);
+       input_set_drvdata(in_dev, bu21013_data);
+
+       error = request_threaded_irq(pdata->irq, NULL, bu21013_gpio_irq,
+                                    IRQF_TRIGGER_FALLING | IRQF_SHARED,
+                                    DRIVER_TP, bu21013_data);
+       if (error) {
+               dev_err(&client->dev, "request irq %d failed\n", pdata->irq);
+               goto err_cs_disable;
+       }
+
+       error = input_register_device(in_dev);
+       if (error) {
+               dev_err(&client->dev, "failed to register input device\n");
+               goto err_free_irq;
+       }
+
+       device_init_wakeup(&client->dev, pdata->wakeup);
+       i2c_set_clientdata(client, bu21013_data);
+
+       return 0;
+
+err_free_irq:
+       bu21013_free_irq(bu21013_data);
+err_cs_disable:
+       pdata->cs_dis(pdata->cs_pin);
+err_free_mem:
+       input_free_device(bu21013_data->in_dev);
+       kfree(bu21013_data);
+
+       return error;
+}
+/**
+ * bu21013_remove() - removes the i2c-client touchscreen driver
+ * @client: i2c client structure pointer
+ *
+ * This function uses to remove the i2c-client
+ * touchscreen driver and returns integer.
+ */
+static int __devexit bu21013_remove(struct i2c_client *client)
+{
+       struct bu21013_ts_data *bu21013_data = i2c_get_clientdata(client);
+
+       bu21013_free_irq(bu21013_data);
+
+       bu21013_data->chip->cs_dis(bu21013_data->chip->cs_pin);
+
+       input_unregister_device(bu21013_data->in_dev);
+       kfree(bu21013_data);
+
+       device_init_wakeup(&client->dev, false);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+/**
+ * bu21013_suspend() - suspend the touch screen controller
+ * @dev: pointer to device structure
+ *
+ * This function is used to suspend the
+ * touch panel controller and returns integer
+ */
+static int bu21013_suspend(struct device *dev)
+{
+       struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
+       struct i2c_client *client = bu21013_data->client;
+
+       bu21013_data->touch_stopped = true;
+       if (device_may_wakeup(&client->dev))
+               enable_irq_wake(bu21013_data->chip->irq);
+       else
+               disable_irq(bu21013_data->chip->irq);
+
+       return 0;
+}
+
+/**
+ * bu21013_resume() - resume the touch screen controller
+ * @dev: pointer to device structure
+ *
+ * This function is used to resume the touch panel
+ * controller and returns integer.
+ */
+static int bu21013_resume(struct device *dev)
+{
+       struct bu21013_ts_data *bu21013_data = dev_get_drvdata(dev);
+       struct i2c_client *client = bu21013_data->client;
+       int retval;
+
+       retval = bu21013_init_chip(bu21013_data);
+       if (retval < 0) {
+               dev_err(&client->dev, "bu21013 controller config failed\n");
+               return retval;
+       }
+
+       bu21013_data->touch_stopped = false;
+
+       if (device_may_wakeup(&client->dev))
+               disable_irq_wake(bu21013_data->chip->irq);
+       else
+               enable_irq(bu21013_data->chip->irq);
+
+       return 0;
+}
+
+static const struct dev_pm_ops bu21013_dev_pm_ops = {
+       .suspend = bu21013_suspend,
+       .resume  = bu21013_resume,
+};
+#endif
+
+static const struct i2c_device_id bu21013_id[] = {
+       { DRIVER_TP, 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, bu21013_id);
+
+static struct i2c_driver bu21013_driver = {
+       .driver = {
+               .name   =       DRIVER_TP,
+               .owner  =       THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     =       &bu21013_dev_pm_ops,
+#endif
+       },
+       .probe          =       bu21013_probe,
+       .remove         =       __devexit_p(bu21013_remove),
+       .id_table       =       bu21013_id,
+};
+
+/**
+ * bu21013_init() - initializes the bu21013 touchscreen driver
+ *
+ * This function used to initializes the bu21013
+ * touchscreen driver and returns integer.
+ */
+static int __init bu21013_init(void)
+{
+       return i2c_add_driver(&bu21013_driver);
+}
+
+/**
+ * bu21013_exit() - de-initializes the bu21013 touchscreen driver
+ *
+ * This function uses to de-initializes the bu21013
+ * touchscreen driver and returns none.
+ */
+static void __exit bu21013_exit(void)
+{
+       i2c_del_driver(&bu21013_driver);
+}
+
+module_init(bu21013_init);
+module_exit(bu21013_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Naveen Kumar G <naveen.gaddipati@stericsson.com>");
+MODULE_DESCRIPTION("bu21013 touch screen controller driver");
index 5ec0946..d0c3a72 100644 (file)
@@ -206,9 +206,9 @@ static int __devinit cy8ctmg110_probe(struct i2c_client *client,
        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
        input_set_abs_params(input_dev, ABS_X,
-                       CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 0, 0);
+                       CY8CTMG110_X_MIN, CY8CTMG110_X_MAX, 4, 0);
        input_set_abs_params(input_dev, ABS_Y,
-                       CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 0, 0);
+                       CY8CTMG110_Y_MIN, CY8CTMG110_Y_MAX, 4, 0);
 
        if (ts->reset_pin) {
                err = gpio_request(ts->reset_pin, NULL);
index a89700e..498bd62 100644 (file)
@@ -107,8 +107,7 @@ static int __init hp680_ts_init(void)
        return 0;
 
  fail2:        free_irq(HP680_TS_IRQ, NULL);
-       cancel_delayed_work(&work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&work);
  fail1:        input_free_device(hp680_ts_dev);
        return err;
 }
@@ -116,8 +115,7 @@ static int __init hp680_ts_init(void)
 static void __exit hp680_ts_exit(void)
 {
        free_irq(HP680_TS_IRQ, NULL);
-       cancel_delayed_work(&work);
-       flush_scheduled_work();
+       cancel_delayed_work_sync(&work);
        input_unregister_device(hp680_ts_dev);
 }
 
diff --git a/drivers/input/touchscreen/intel-mid-touch.c b/drivers/input/touchscreen/intel-mid-touch.c
new file mode 100644 (file)
index 0000000..c0307b2
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+ * Intel MID Resistive Touch Screen Driver
+ *
+ * Copyright (C) 2008 Intel Corp
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
+ *                         Ramesh Agarwal (ramesh.agarwal@intel.com)
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * TODO:
+ *     review conversion of r/m/w sequences
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <asm/intel_scu_ipc.h>
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_ID1           0x00 /* PMIC ID1 register */
+
+/* PMIC Interrupt registers */
+#define PMIC_REG_INT           0x04 /* PMIC interrupt register */
+#define PMIC_REG_MINT          0x05 /* PMIC interrupt mask register */
+
+/* ADC Interrupt registers */
+#define PMIC_REG_ADCINT                0x5F /* ADC interrupt register */
+#define PMIC_REG_MADCINT       0x60 /* ADC interrupt mask register */
+
+/* ADC Control registers */
+#define PMIC_REG_ADCCNTL1      0x61 /* ADC control register */
+
+/* ADC Channel Selection registers */
+#define PMICADDR0              0xA4
+#define END_OF_CHANNEL         0x1F
+
+/* ADC Result register */
+#define PMIC_REG_ADCSNS0H      0x64
+
+/* ADC channels for touch screen */
+#define MRST_TS_CHAN10         0xA /* Touch screen X+ connection */
+#define MRST_TS_CHAN11         0xB /* Touch screen X- connection */
+#define MRST_TS_CHAN12         0xC /* Touch screen Y+ connection */
+#define MRST_TS_CHAN13         0xD /* Touch screen Y- connection */
+
+/* Touch screen channel BIAS constants */
+#define MRST_XBIAS             0x20
+#define MRST_YBIAS             0x40
+#define MRST_ZBIAS             0x80
+
+/* Touch screen coordinates */
+#define MRST_X_MIN             10
+#define MRST_X_MAX             1024
+#define MRST_X_FUZZ            5
+#define MRST_Y_MIN             10
+#define MRST_Y_MAX             1024
+#define MRST_Y_FUZZ            5
+#define MRST_PRESSURE_MIN      0
+#define MRST_PRESSURE_NOMINAL  50
+#define MRST_PRESSURE_MAX      100
+
+#define WAIT_ADC_COMPLETION    10 /* msec */
+
+/* PMIC ADC round robin delays */
+#define ADC_LOOP_DELAY0                0x0 /* Continuous loop */
+#define ADC_LOOP_DELAY1                0x1 /* 4.5  ms approximate */
+
+/* PMIC Vendor Identifiers */
+#define PMIC_VENDOR_FS         0 /* PMIC vendor FreeScale */
+#define PMIC_VENDOR_MAXIM      1 /* PMIC vendor MAXIM */
+#define PMIC_VENDOR_NEC                2 /* PMIC vendor NEC */
+#define MRSTOUCH_MAX_CHANNELS  32 /* Maximum ADC channels */
+
+/* Touch screen device structure */
+struct mrstouch_dev {
+       struct device *dev; /* device associated with touch screen */
+       struct input_dev *input;
+       char phys[32];
+       u16 asr;                /* Address selection register */
+       int irq;
+       unsigned int vendor;    /* PMIC vendor */
+       unsigned int rev;       /* PMIC revision */
+
+       int (*read_prepare)(struct mrstouch_dev *tsdev);
+       int (*read)(struct mrstouch_dev *tsdev, u16 *x, u16 *y, u16 *z);
+       int (*read_finish)(struct mrstouch_dev *tsdev);
+};
+
+
+/*************************** NEC and Maxim Interface ************************/
+
+static int mrstouch_nec_adc_read_prepare(struct mrstouch_dev *tsdev)
+{
+       return intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0, 0x20);
+}
+
+/*
+ * Enables PENDET interrupt.
+ */
+static int mrstouch_nec_adc_read_finish(struct mrstouch_dev *tsdev)
+{
+       int err;
+
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x20, 0x20);
+       if (!err)
+               err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, 0, 0x05);
+
+       return err;
+}
+
+/*
+ * Reads PMIC ADC touch screen result
+ * Reads ADC storage registers for higher 7 and lower 3 bits and
+ * converts the two readings into a single value and turns off gain bit
+ */
+static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
+{
+       int err;
+       u16 result;
+       u32 res;
+
+       result = PMIC_REG_ADCSNS0H + offset;
+
+       if (chan == MRST_TS_CHAN12)
+               result += 4;
+
+       err = intel_scu_ipc_ioread32(result, &res);
+       if (err)
+               return err;
+
+       /* Mash the bits up */
+
+       *vp = (res & 0xFF) << 3;        /* Highest 7 bits */
+       *vp |= (res >> 8) & 0x07;       /* Lower 3 bits */
+       *vp &= 0x3FF;
+
+       res >>= 16;
+
+       *vm = (res & 0xFF) << 3;        /* Highest 7 bits */
+       *vm |= (res >> 8) & 0x07;       /* Lower 3 bits */
+       *vm &= 0x3FF;
+
+       return 0;
+}
+
+/*
+ * Enables X, Y and Z bias values
+ * Enables YPYM for X channels and XPXM for Y channels
+ */
+static int mrstouch_ts_bias_set(uint offset, uint bias)
+{
+       int count;
+       u16 chan, start;
+       u16 reg[4];
+       u8 data[4];
+
+       chan = PMICADDR0 + offset;
+       start = MRST_TS_CHAN10;
+
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = bias | (start + count);
+       }
+
+       return intel_scu_ipc_writev(reg, data, 4);
+}
+
+/* To read touch screen channel values */
+static int mrstouch_nec_adc_read(struct mrstouch_dev *tsdev,
+                                u16 *x, u16 *y, u16 *z)
+{
+       int err;
+       u16 xm, ym, zm;
+
+       /* configure Y bias for X channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, MRST_YBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read x+ and x- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, x, &xm);
+       if (err)
+               goto ipc_error;
+
+       /* configure x bias for y channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, MRST_XBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read y+ and y- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, y, &ym);
+       if (err)
+               goto ipc_error;
+
+       /* configure z bias for x and y channels */
+       err = mrstouch_ts_bias_set(tsdev->asr, MRST_ZBIAS);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* read z+ and z- channels */
+       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, z, &zm);
+       if (err)
+               goto ipc_error;
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during adc read\n");
+       return err;
+}
+
+
+/*************************** Freescale Interface ************************/
+
+static int mrstouch_fs_adc_read_prepare(struct mrstouch_dev *tsdev)
+{
+       int err, count;
+       u16 chan;
+       u16 reg[5];
+       u8 data[5];
+
+       /* Stop the ADC */
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
+       if (err)
+               goto ipc_error;
+
+       chan = PMICADDR0 + tsdev->asr;
+
+       /* Set X BIAS */
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = 0x2A;
+       }
+       reg[count] =  chan++; /* Dummy */
+       data[count] = 0;
+
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* Set Y BIAS */
+       for (count = 0; count <= 3; count++) {
+               reg[count] = chan++;
+               data[count] = 0x4A;
+       }
+       reg[count] = chan++; /* Dummy */
+       data[count] = 0;
+
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       /* Set Z BIAS */
+       err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
+       if (err)
+               goto ipc_error;
+
+       msleep(WAIT_ADC_COMPLETION);
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+       return err;
+}
+
+static int mrstouch_fs_adc_read(struct mrstouch_dev *tsdev,
+                               u16 *x, u16 *y, u16 *z)
+{
+       int err;
+       u16 result;
+       u16 reg[4];
+       u8 data[4];
+
+       result = PMIC_REG_ADCSNS0H + tsdev->asr;
+
+       reg[0] = result + 4;
+       reg[1] = result + 5;
+       reg[2] = result + 16;
+       reg[3] = result + 17;
+
+       err = intel_scu_ipc_readv(reg, data, 4);
+       if (err)
+               goto ipc_error;
+
+       *x = data[0] << 3; /* Higher 7 bits */
+       *x |= data[1] & 0x7; /* Lower 3 bits */
+       *x &= 0x3FF;
+
+       *y = data[2] << 3; /* Higher 7 bits */
+       *y |= data[3] & 0x7; /* Lower 3 bits */
+       *y &= 0x3FF;
+
+       /* Read Z value */
+       reg[0] = result + 28;
+       reg[1] = result + 29;
+
+       err = intel_scu_ipc_readv(reg, data, 4);
+       if (err)
+               goto ipc_error;
+
+       *z = data[0] << 3; /* Higher 7 bits */
+       *z |= data[1] & 0x7; /* Lower 3 bits */
+       *z &= 0x3FF;
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+       return err;
+}
+
+static int mrstouch_fs_adc_read_finish(struct mrstouch_dev *tsdev)
+{
+       int err, count;
+       u16 chan;
+       u16 reg[5];
+       u8 data[5];
+
+       /* Clear all TS channels */
+       chan = PMICADDR0 + tsdev->asr;
+       for (count = 0; count <= 4; count++) {
+               reg[count] = chan++;
+               data[count] = 0;
+       }
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       for (count = 0; count <= 4; count++) {
+               reg[count] = chan++;
+               data[count] = 0;
+       }
+       err = intel_scu_ipc_writev(reg, data, 5);
+       if (err)
+               goto ipc_error;
+
+       err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
+       if (err)
+               goto ipc_error;
+
+       /* Start ADC */
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
+       if (err)
+               goto ipc_error;
+
+       return 0;
+
+ipc_error:
+       dev_err(tsdev->dev, "ipc error during %s\n", __func__);
+       return err;
+}
+
+static void mrstouch_report_event(struct input_dev *input,
+                       unsigned int x, unsigned int y, unsigned int z)
+{
+       if (z > MRST_PRESSURE_NOMINAL) {
+               /* Pen touched, report button touch and coordinates */
+               input_report_key(input, BTN_TOUCH, 1);
+               input_report_abs(input, ABS_X, x);
+               input_report_abs(input, ABS_Y, y);
+       } else {
+               input_report_key(input, BTN_TOUCH, 0);
+       }
+
+       input_report_abs(input, ABS_PRESSURE, z);
+       input_sync(input);
+}
+
+/* PENDET interrupt handler */
+static irqreturn_t mrstouch_pendet_irq(int irq, void *dev_id)
+{
+       struct mrstouch_dev *tsdev = dev_id;
+       u16 x, y, z;
+
+       /*
+        * Should we lower thread priority? Probably not, since we are
+        * not spinning but sleeping...
+        */
+
+       if (tsdev->read_prepare(tsdev))
+               goto out;
+
+       do {
+               if (tsdev->read(tsdev, &x, &y, &z))
+                       break;
+
+               mrstouch_report_event(tsdev->input, x, y, z);
+       } while (z > MRST_PRESSURE_NOMINAL);
+
+       tsdev->read_finish(tsdev);
+
+out:
+       return IRQ_HANDLED;
+}
+
+/* Utility to read PMIC ID */
+static int __devinit mrstouch_read_pmic_id(uint *vendor, uint *rev)
+{
+       int err;
+       u8 r;
+
+       err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
+       if (err)
+               return err;
+
+       *vendor = r & 0x7;
+       *rev = (r >> 3) & 0x7;
+
+       return 0;
+}
+
+/*
+ * Parse ADC channels to find end of the channel configured by other ADC user
+ * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
+ */
+static int __devinit mrstouch_chan_parse(struct mrstouch_dev *tsdev)
+{
+       int err, i, found;
+       u8 r8;
+
+       found = -1;
+
+       for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
+               if (found >= 0)
+                       break;
+
+               err = intel_scu_ipc_ioread8(PMICADDR0 + i, &r8);
+               if (err)
+                       return err;
+
+               if (r8 == END_OF_CHANNEL) {
+                       found = i;
+                       break;
+               }
+       }
+       if (found < 0)
+               return 0;
+
+       if (tsdev->vendor == PMIC_VENDOR_FS) {
+               if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
+                       return -ENOSPC;
+       } else {
+               if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
+                       return -ENOSPC;
+       }
+       return found;
+}
+
+
+/*
+ * Writes touch screen channels to ADC address selection registers
+ */
+static int __devinit mrstouch_ts_chan_set(uint offset)
+{
+       u16 chan;
+
+       int ret, count;
+
+       chan = PMICADDR0 + offset;
+       for (count = 0; count <= 3; count++) {
+               ret = intel_scu_ipc_iowrite8(chan++, MRST_TS_CHAN10 + count);
+               if (ret)
+                       return ret;
+       }
+       return intel_scu_ipc_iowrite8(chan++, END_OF_CHANNEL);
+}
+
+/* Initialize ADC */
+static int __devinit mrstouch_adc_init(struct mrstouch_dev *tsdev)
+{
+       int err, start;
+       u8 ra, rm;
+
+       err = mrstouch_read_pmic_id(&tsdev->vendor, &tsdev->rev);
+       if (err) {
+               dev_err(tsdev->dev, "Unable to read PMIC id\n");
+               return err;
+       }
+
+       switch (tsdev->vendor) {
+       case PMIC_VENDOR_NEC:
+       case PMIC_VENDOR_MAXIM:
+               tsdev->read_prepare = mrstouch_nec_adc_read_prepare;
+               tsdev->read = mrstouch_nec_adc_read;
+               tsdev->read_finish = mrstouch_nec_adc_read_finish;
+               break;
+
+       case PMIC_VENDOR_FS:
+               tsdev->read_prepare = mrstouch_fs_adc_read_prepare;
+               tsdev->read = mrstouch_fs_adc_read;
+               tsdev->read_finish = mrstouch_fs_adc_read_finish;
+               break;
+
+       default:
+               dev_err(tsdev->dev,
+                       "Unsupported touchscreen: %d\n", tsdev->vendor);
+               return -ENXIO;
+       }
+
+       start = mrstouch_chan_parse(tsdev);
+       if (start < 0) {
+               dev_err(tsdev->dev, "Unable to parse channels\n");
+               return start;
+       }
+
+       tsdev->asr = start;
+
+       /*
+        * ADC power on, start, enable PENDET and set loop delay
+        * ADC loop delay is set to 4.5 ms approximately
+        * Loop delay more than this results in jitter in adc readings
+        * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
+        * interrupt generation sometimes.
+        */
+
+       if (tsdev->vendor == PMIC_VENDOR_FS) {
+               ra = 0xE0 | ADC_LOOP_DELAY0;
+               rm = 0x5;
+       } else {
+               /* NEC and MAXIm not consistent with loop delay 0 */
+               ra = 0xE0 | ADC_LOOP_DELAY1;
+               rm = 0x0;
+
+               /* configure touch screen channels */
+               err = mrstouch_ts_chan_set(tsdev->asr);
+               if (err)
+                       return err;
+       }
+
+       err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
+       if (err)
+               return err;
+
+       err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+
+/* Probe function for touch screen driver */
+static int __devinit mrstouch_probe(struct platform_device *pdev)
+{
+       struct mrstouch_dev *tsdev;
+       struct input_dev *input;
+       int err;
+       int irq;
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "no interrupt assigned\n");
+               return -EINVAL;
+       }
+
+       tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!tsdev || !input) {
+               dev_err(&pdev->dev, "unable to allocate memory\n");
+               err = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       tsdev->dev = &pdev->dev;
+       tsdev->input = input;
+       tsdev->irq = irq;
+
+       snprintf(tsdev->phys, sizeof(tsdev->phys),
+                "%s/input0", dev_name(tsdev->dev));
+
+       err = mrstouch_adc_init(tsdev);
+       if (err) {
+               dev_err(&pdev->dev, "ADC initialization failed\n");
+               goto err_free_mem;
+       }
+
+       input->name = "mrst_touchscreen";
+       input->phys = tsdev->phys;
+       input->dev.parent = tsdev->dev;
+
+       input->id.vendor = tsdev->vendor;
+       input->id.version = tsdev->rev;
+
+       input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+       input_set_abs_params(tsdev->input, ABS_X,
+                            MRST_X_MIN, MRST_X_MAX, MRST_X_FUZZ, 0);
+       input_set_abs_params(tsdev->input, ABS_Y,
+                            MRST_Y_MIN, MRST_Y_MAX, MRST_Y_FUZZ, 0);
+       input_set_abs_params(tsdev->input, ABS_PRESSURE,
+                            MRST_PRESSURE_MIN, MRST_PRESSURE_MAX, 0, 0);
+
+       err = request_threaded_irq(tsdev->irq, NULL, mrstouch_pendet_irq,
+                                  0, "mrstouch", tsdev);
+       if (err) {
+               dev_err(tsdev->dev, "unable to allocate irq\n");
+               goto err_free_mem;
+       }
+
+       err = input_register_device(tsdev->input);
+       if (err) {
+               dev_err(tsdev->dev, "unable to register input device\n");
+               goto err_free_irq;
+       }
+
+       platform_set_drvdata(pdev, tsdev);
+       return 0;
+
+err_free_irq:
+       free_irq(tsdev->irq, tsdev);
+err_free_mem:
+       input_free_device(input);
+       kfree(tsdev);
+       return err;
+}
+
+static int __devexit mrstouch_remove(struct platform_device *pdev)
+{
+       struct mrstouch_dev *tsdev = platform_get_drvdata(pdev);
+
+       free_irq(tsdev->irq, tsdev);
+       input_unregister_device(tsdev->input);
+       kfree(tsdev);
+
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static struct platform_driver mrstouch_driver = {
+       .driver = {
+               .name   = "pmic_touch",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = mrstouch_probe,
+       .remove         = __devexit_p(mrstouch_remove),
+};
+
+static int __init mrstouch_init(void)
+{
+       return platform_driver_register(&mrstouch_driver);
+}
+module_init(mrstouch_init);
+
+static void __exit mrstouch_exit(void)
+{
+       platform_driver_unregister(&mrstouch_driver);
+}
+module_exit(mrstouch_exit);
+
+MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
+MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/lpc32xx_ts.c b/drivers/input/touchscreen/lpc32xx_ts.c
new file mode 100644 (file)
index 0000000..dcf803f
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * LPC32xx built-in touchscreen driver
+ *
+ * Copyright (C) 2010 NXP Semiconductors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+/*
+ * Touchscreen controller register offsets
+ */
+#define LPC32XX_TSC_STAT                       0x00
+#define LPC32XX_TSC_SEL                                0x04
+#define LPC32XX_TSC_CON                                0x08
+#define LPC32XX_TSC_FIFO                       0x0C
+#define LPC32XX_TSC_DTR                                0x10
+#define LPC32XX_TSC_RTR                                0x14
+#define LPC32XX_TSC_UTR                                0x18
+#define LPC32XX_TSC_TTR                                0x1C
+#define LPC32XX_TSC_DXP                                0x20
+#define LPC32XX_TSC_MIN_X                      0x24
+#define LPC32XX_TSC_MAX_X                      0x28
+#define LPC32XX_TSC_MIN_Y                      0x2C
+#define LPC32XX_TSC_MAX_Y                      0x30
+#define LPC32XX_TSC_AUX_UTR                    0x34
+#define LPC32XX_TSC_AUX_MIN                    0x38
+#define LPC32XX_TSC_AUX_MAX                    0x3C
+
+#define LPC32XX_TSC_STAT_FIFO_OVRRN            (1 << 8)
+#define LPC32XX_TSC_STAT_FIFO_EMPTY            (1 << 7)
+
+#define LPC32XX_TSC_SEL_DEFVAL                 0x0284
+
+#define LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4       (0x1 << 11)
+#define LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(s)    ((10 - (s)) << 7)
+#define LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(s)    ((10 - (s)) << 4)
+#define LPC32XX_TSC_ADCCON_POWER_UP            (1 << 2)
+#define LPC32XX_TSC_ADCCON_AUTO_EN             (1 << 0)
+
+#define LPC32XX_TSC_FIFO_TS_P_LEVEL            (1 << 31)
+#define LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(x)    (((x) & 0x03FF0000) >> 16)
+#define LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(y)    ((y) & 0x000003FF)
+
+#define LPC32XX_TSC_ADCDAT_VALUE_MASK          0x000003FF
+
+#define LPC32XX_TSC_MIN_XY_VAL                 0x0
+#define LPC32XX_TSC_MAX_XY_VAL                 0x3FF
+
+#define MOD_NAME "ts-lpc32xx"
+
+#define tsc_readl(dev, reg) \
+       __raw_readl((dev)->tsc_base + (reg))
+#define tsc_writel(dev, reg, val) \
+       __raw_writel((val), (dev)->tsc_base + (reg))
+
+struct lpc32xx_tsc {
+       struct input_dev *dev;
+       void __iomem *tsc_base;
+       int irq;
+       struct clk *clk;
+};
+
+static void lpc32xx_fifo_clear(struct lpc32xx_tsc *tsc)
+{
+       while (!(tsc_readl(tsc, LPC32XX_TSC_STAT) &
+                       LPC32XX_TSC_STAT_FIFO_EMPTY))
+               tsc_readl(tsc, LPC32XX_TSC_FIFO);
+}
+
+static irqreturn_t lpc32xx_ts_interrupt(int irq, void *dev_id)
+{
+       u32 tmp, rv[4], xs[4], ys[4];
+       int idx;
+       struct lpc32xx_tsc *tsc = dev_id;
+       struct input_dev *input = tsc->dev;
+
+       tmp = tsc_readl(tsc, LPC32XX_TSC_STAT);
+
+       if (tmp & LPC32XX_TSC_STAT_FIFO_OVRRN) {
+               /* FIFO overflow - throw away samples */
+               lpc32xx_fifo_clear(tsc);
+               return IRQ_HANDLED;
+       }
+
+       /*
+        * Gather and normalize 4 samples. Pen-up events may have less
+        * than 4 samples, but its ok to pop 4 and let the last sample
+        * pen status check drop the samples.
+        */
+       idx = 0;
+       while (idx < 4 &&
+              !(tsc_readl(tsc, LPC32XX_TSC_STAT) &
+                       LPC32XX_TSC_STAT_FIFO_EMPTY)) {
+               tmp = tsc_readl(tsc, LPC32XX_TSC_FIFO);
+               xs[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
+                       LPC32XX_TSC_FIFO_NORMALIZE_X_VAL(tmp);
+               ys[idx] = LPC32XX_TSC_ADCDAT_VALUE_MASK -
+                       LPC32XX_TSC_FIFO_NORMALIZE_Y_VAL(tmp);
+               rv[idx] = tmp;
+               idx++;
+       }
+
+       /* Data is only valid if pen is still down in last sample */
+       if (!(rv[3] & LPC32XX_TSC_FIFO_TS_P_LEVEL) && idx == 4) {
+               /* Use average of 2nd and 3rd sample for position */
+               input_report_abs(input, ABS_X, (xs[1] + xs[2]) / 2);
+               input_report_abs(input, ABS_Y, (ys[1] + ys[2]) / 2);
+               input_report_key(input, BTN_TOUCH, 1);
+       } else {
+               input_report_key(input, BTN_TOUCH, 0);
+       }
+
+       input_sync(input);
+
+       return IRQ_HANDLED;
+}
+
+static void lpc32xx_stop_tsc(struct lpc32xx_tsc *tsc)
+{
+       /* Disable auto mode */
+       tsc_writel(tsc, LPC32XX_TSC_CON,
+                  tsc_readl(tsc, LPC32XX_TSC_CON) &
+                            ~LPC32XX_TSC_ADCCON_AUTO_EN);
+
+       clk_disable(tsc->clk);
+}
+
+static void lpc32xx_setup_tsc(struct lpc32xx_tsc *tsc)
+{
+       u32 tmp;
+
+       clk_enable(tsc->clk);
+
+       tmp = tsc_readl(tsc, LPC32XX_TSC_CON) & ~LPC32XX_TSC_ADCCON_POWER_UP;
+
+       /* Set the TSC FIFO depth to 4 samples @ 10-bits per sample (max) */
+       tmp = LPC32XX_TSC_ADCCON_IRQ_TO_FIFO_4 |
+             LPC32XX_TSC_ADCCON_X_SAMPLE_SIZE(10) |
+             LPC32XX_TSC_ADCCON_Y_SAMPLE_SIZE(10);
+       tsc_writel(tsc, LPC32XX_TSC_CON, tmp);
+
+       /* These values are all preset */
+       tsc_writel(tsc, LPC32XX_TSC_SEL, LPC32XX_TSC_SEL_DEFVAL);
+       tsc_writel(tsc, LPC32XX_TSC_MIN_X, LPC32XX_TSC_MIN_XY_VAL);
+       tsc_writel(tsc, LPC32XX_TSC_MAX_X, LPC32XX_TSC_MAX_XY_VAL);
+       tsc_writel(tsc, LPC32XX_TSC_MIN_Y, LPC32XX_TSC_MIN_XY_VAL);
+       tsc_writel(tsc, LPC32XX_TSC_MAX_Y, LPC32XX_TSC_MAX_XY_VAL);
+
+       /* Aux support is not used */
+       tsc_writel(tsc, LPC32XX_TSC_AUX_UTR, 0);
+       tsc_writel(tsc, LPC32XX_TSC_AUX_MIN, 0);
+       tsc_writel(tsc, LPC32XX_TSC_AUX_MAX, 0);
+
+       /*
+        * Set sample rate to about 240Hz per X/Y pair. A single measurement
+        * consists of 4 pairs which gives about a 60Hz sample rate based on
+        * a stable 32768Hz clock source. Values are in clocks.
+        * Rate is (32768 / (RTR + XCONV + RTR + YCONV + DXP + TTR + UTR) / 4
+        */
+       tsc_writel(tsc, LPC32XX_TSC_RTR, 0x2);
+       tsc_writel(tsc, LPC32XX_TSC_DTR, 0x2);
+       tsc_writel(tsc, LPC32XX_TSC_TTR, 0x10);
+       tsc_writel(tsc, LPC32XX_TSC_DXP, 0x4);
+       tsc_writel(tsc, LPC32XX_TSC_UTR, 88);
+
+       lpc32xx_fifo_clear(tsc);
+
+       /* Enable automatic ts event capture */
+       tsc_writel(tsc, LPC32XX_TSC_CON, tmp | LPC32XX_TSC_ADCCON_AUTO_EN);
+}
+
+static int lpc32xx_ts_open(struct input_dev *dev)
+{
+       struct lpc32xx_tsc *tsc = input_get_drvdata(dev);
+
+       lpc32xx_setup_tsc(tsc);
+
+       return 0;
+}
+
+static void lpc32xx_ts_close(struct input_dev *dev)
+{
+       struct lpc32xx_tsc *tsc = input_get_drvdata(dev);
+
+       lpc32xx_stop_tsc(tsc);
+}
+
+static int __devinit lpc32xx_ts_probe(struct platform_device *pdev)
+{
+       struct lpc32xx_tsc *tsc;
+       struct input_dev *input;
+       struct resource *res;
+       resource_size_t size;
+       int irq;
+       int error;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               dev_err(&pdev->dev, "Can't get memory resource\n");
+               return -ENOENT;
+       }
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "Can't get interrupt resource\n");
+               return irq;
+       }
+
+       tsc = kzalloc(sizeof(*tsc), GFP_KERNEL);
+       input = input_allocate_device();
+       if (!tsc || !input) {
+               dev_err(&pdev->dev, "failed allocating memory\n");
+               error = -ENOMEM;
+               goto err_free_mem;
+       }
+
+       tsc->dev = input;
+       tsc->irq = irq;
+
+       size = resource_size(res);
+
+       if (!request_mem_region(res->start, size, pdev->name)) {
+               dev_err(&pdev->dev, "TSC registers are not free\n");
+               error = -EBUSY;
+               goto err_free_mem;
+       }
+
+       tsc->tsc_base = ioremap(res->start, size);
+       if (!tsc->tsc_base) {
+               dev_err(&pdev->dev, "Can't map memory\n");
+               error = -ENOMEM;
+               goto err_release_mem;
+       }
+
+       tsc->clk = clk_get(&pdev->dev, NULL);
+       if (IS_ERR(tsc->clk)) {
+               dev_err(&pdev->dev, "failed getting clock\n");
+               error = PTR_ERR(tsc->clk);
+               goto err_unmap;
+       }
+
+       input->name = MOD_NAME;
+       input->phys = "lpc32xx/input0";
+       input->id.bustype = BUS_HOST;
+       input->id.vendor = 0x0001;
+       input->id.product = 0x0002;
+       input->id.version = 0x0100;
+       input->dev.parent = &pdev->dev;
+       input->open = lpc32xx_ts_open;
+       input->close = lpc32xx_ts_close;
+
+       input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+       input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_set_abs_params(input, ABS_X, LPC32XX_TSC_MIN_XY_VAL,
+                            LPC32XX_TSC_MAX_XY_VAL, 0, 0);
+       input_set_abs_params(input, ABS_Y, LPC32XX_TSC_MIN_XY_VAL,
+                            LPC32XX_TSC_MAX_XY_VAL, 0, 0);
+
+       input_set_drvdata(input, tsc);
+
+       error = request_irq(tsc->irq, lpc32xx_ts_interrupt,
+                           IRQF_DISABLED, pdev->name, tsc);
+       if (error) {
+               dev_err(&pdev->dev, "failed requesting interrupt\n");
+               goto err_put_clock;
+       }
+
+       error = input_register_device(input);
+       if (error) {
+               dev_err(&pdev->dev, "failed registering input device\n");
+               goto err_free_irq;
+       }
+
+       platform_set_drvdata(pdev, tsc);
+       device_init_wakeup(&pdev->dev, 1);
+
+       return 0;
+
+err_free_irq:
+       free_irq(tsc->irq, tsc);
+err_put_clock:
+       clk_put(tsc->clk);
+err_unmap:
+       iounmap(tsc->tsc_base);
+err_release_mem:
+       release_mem_region(res->start, size);
+err_free_mem:
+       input_free_device(input);
+       kfree(tsc);
+
+       return error;
+}
+
+static int __devexit lpc32xx_ts_remove(struct platform_device *pdev)
+{
+       struct lpc32xx_tsc *tsc = platform_get_drvdata(pdev);
+       struct resource *res;
+
+       device_init_wakeup(&pdev->dev, 0);
+       free_irq(tsc->irq, tsc);
+
+       input_unregister_device(tsc->dev);
+
+       clk_put(tsc->clk);
+
+       iounmap(tsc->tsc_base);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(res->start, resource_size(res));
+
+       kfree(tsc);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int lpc32xx_ts_suspend(struct device *dev)
+{
+       struct lpc32xx_tsc *tsc = dev_get_drvdata(dev);
+       struct input_dev *input = tsc->dev;
+
+       /*
+        * Suspend and resume can be called when the device hasn't been
+        * enabled. If there are no users that have the device open, then
+        * avoid calling the TSC stop and start functions as the TSC
+        * isn't yet clocked.
+        */
+       mutex_lock(&input->mutex);
+
+       if (input->users) {
+               if (device_may_wakeup(dev))
+                       enable_irq_wake(tsc->irq);
+               else
+                       lpc32xx_stop_tsc(tsc);
+       }
+
+       mutex_unlock(&input->mutex);
+
+       return 0;
+}
+
+static int lpc32xx_ts_resume(struct device *dev)
+{
+       struct lpc32xx_tsc *tsc = dev_get_drvdata(dev);
+       struct input_dev *input = tsc->dev;
+
+       mutex_lock(&input->mutex);
+
+       if (input->users) {
+               if (device_may_wakeup(dev))
+                       disable_irq_wake(tsc->irq);
+               else
+                       lpc32xx_setup_tsc(tsc);
+       }
+
+       mutex_unlock(&input->mutex);
+
+       return 0;
+}
+
+static const struct dev_pm_ops lpc32xx_ts_pm_ops = {
+       .suspend        = lpc32xx_ts_suspend,
+       .resume         = lpc32xx_ts_resume,
+};
+#define LPC32XX_TS_PM_OPS (&lpc32xx_ts_pm_ops)
+#else
+#define LPC32XX_TS_PM_OPS NULL
+#endif
+
+static struct platform_driver lpc32xx_ts_driver = {
+       .probe          = lpc32xx_ts_probe,
+       .remove         = __devexit_p(lpc32xx_ts_remove),
+       .driver         = {
+               .name   = MOD_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = LPC32XX_TS_PM_OPS,
+       },
+};
+
+static int __init lpc32xx_ts_init(void)
+{
+       return platform_driver_register(&lpc32xx_ts_driver);
+}
+module_init(lpc32xx_ts_init);
+
+static void __exit lpc32xx_ts_exit(void)
+{
+       platform_driver_unregister(&lpc32xx_ts_driver);
+}
+module_exit(lpc32xx_ts_exit);
+
+MODULE_AUTHOR("Kevin Wells <kevin.wells@nxp.com");
+MODULE_DESCRIPTION("LPC32XX TSC Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lpc32xx_ts");
index 6085d12..8feb7f3 100644 (file)
@@ -350,7 +350,7 @@ static int __devinit s3c2410ts_probe(struct platform_device *pdev)
  err_tcirq:
        free_irq(ts.irq_tc, ts.input);
  err_inputdev:
-       input_unregister_device(ts.input);
+       input_free_device(ts.input);
  err_iomap:
        iounmap(ts.io);
  err_clk:
index 656148e..ae88e13 100644 (file)
@@ -268,7 +268,7 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
        struct stmpe_touch *ts;
        struct input_dev *idev;
        struct stmpe_ts_platform_data *ts_pdata = NULL;
-       int ret = 0;
+       int ret;
        int ts_irq;
 
        ts_irq = platform_get_irq_byname(pdev, "FIFO_TH");
@@ -276,12 +276,16 @@ static int __devinit stmpe_input_probe(struct platform_device *pdev)
                return ts_irq;
 
        ts = kzalloc(sizeof(*ts), GFP_KERNEL);
-       if (!ts)
+       if (!ts) {
+               ret = -ENOMEM;
                goto err_out;
+       }
 
        idev = input_allocate_device();
-       if (!idev)
+       if (!idev) {
+               ret = -ENOMEM;
                goto err_free_ts;
+       }
 
        platform_set_drvdata(pdev, ts);
        ts->stmpe = stmpe;
@@ -361,7 +365,6 @@ static int __devexit stmpe_ts_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        input_unregister_device(ts->idev);
-       input_free_device(ts->idev);
 
        kfree(ts);
 
index a644d18..c8c136c 100644 (file)
@@ -335,6 +335,7 @@ static int tps6507x_ts_probe(struct platform_device *pdev)
                dev_err(tsc->dev, "schedule failed");
                goto err2;
         }
+       platform_set_drvdata(pdev, tps6507x_dev);
 
        return 0;
 
@@ -358,7 +359,7 @@ static int __devexit tps6507x_ts_remove(struct platform_device *pdev)
        cancel_delayed_work_sync(&tsc->work);
        destroy_workqueue(tsc->wq);
 
-       input_free_device(input_dev);
+       input_unregister_device(input_dev);
 
        tps6507x_dev->ts = NULL;
        kfree(tsc);
index be23780..80467f2 100644 (file)
@@ -265,7 +265,7 @@ static int __devinit tsc2007_probe(struct i2c_client *client,
                                   const struct i2c_device_id *id)
 {
        struct tsc2007 *ts;
-       struct tsc2007_platform_data *pdata = pdata = client->dev.platform_data;
+       struct tsc2007_platform_data *pdata = client->dev.platform_data;
        struct input_dev *input_dev;
        int err;
 
index 56dc35c..9ae4c7b 100644 (file)
@@ -2,6 +2,7 @@
  * Wacom W8001 penabled serial touchscreen driver
  *
  * Copyright (c) 2008 Jaya Kumar
+ * Copyright (c) 2010 Red Hat, 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
@@ -30,11 +31,24 @@ MODULE_LICENSE("GPL");
 #define W8001_LEAD_BYTE                0x80
 #define W8001_TAB_MASK         0x40
 #define W8001_TAB_BYTE         0x40
+/* set in first byte of touch data packets */
+#define W8001_TOUCH_MASK       (0x10 | W8001_LEAD_MASK)
+#define W8001_TOUCH_BYTE       (0x10 | W8001_LEAD_BYTE)
 
 #define W8001_QUERY_PACKET     0x20
 
 #define W8001_CMD_START                '1'
 #define W8001_CMD_QUERY                '*'
+#define W8001_CMD_TOUCHQUERY   '%'
+
+/* length of data packets in bytes, depends on device. */
+#define W8001_PKTLEN_TOUCH93   5
+#define W8001_PKTLEN_TOUCH9A   7
+#define W8001_PKTLEN_TPCPEN    9
+#define W8001_PKTLEN_TPCCTL    11      /* control packet */
+#define W8001_PKTLEN_TOUCH2FG  13
+
+#define MAX_TRACKING_ID                0xFF    /* arbitrarily chosen */
 
 struct w8001_coord {
        u8 rdy;
@@ -48,6 +62,15 @@ struct w8001_coord {
        u8 tilt_y;
 };
 
+/* touch query reply packet */
+struct w8001_touch_query {
+       u8 panel_res;
+       u8 capacity_res;
+       u8 sensor_id;
+       u16 x;
+       u16 y;
+};
+
 /*
  * Per-touchscreen data.
  */
@@ -62,6 +85,9 @@ struct w8001 {
        unsigned char response[W8001_MAX_LENGTH];
        unsigned char data[W8001_MAX_LENGTH];
        char phys[32];
+       int type;
+       unsigned int pktlen;
+       int trkid[2];
 };
 
 static void parse_data(u8 *data, struct w8001_coord *coord)
@@ -88,11 +114,98 @@ static void parse_data(u8 *data, struct w8001_coord *coord)
        coord->tilt_y = data[8] & 0x7F;
 }
 
+static void parse_touch(struct w8001 *w8001)
+{
+       static int trkid;
+       struct input_dev *dev = w8001->dev;
+       unsigned char *data = w8001->data;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               input_mt_slot(dev, i);
+
+               if (data[0] & (1 << i)) {
+                       int x = (data[6 * i + 1] << 7) | (data[6 * i + 2]);
+                       int y = (data[6 * i + 3] << 7) | (data[6 * i + 4]);
+                       /* data[5,6] and [11,12] is finger capacity */
+
+                       input_report_abs(dev, ABS_MT_POSITION_X, x);
+                       input_report_abs(dev, ABS_MT_POSITION_Y, y);
+                       input_report_abs(dev, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
+                       if (w8001->trkid[i] < 0)
+                               w8001->trkid[i] = trkid++ & MAX_TRACKING_ID;
+               } else {
+                       w8001->trkid[i] = -1;
+               }
+               input_report_abs(dev, ABS_MT_TRACKING_ID, w8001->trkid[i]);
+       }
+
+       input_sync(dev);
+}
+
+static void parse_touchquery(u8 *data, struct w8001_touch_query *query)
+{
+       memset(query, 0, sizeof(*query));
+
+       query->panel_res = data[1];
+       query->sensor_id = data[2] & 0x7;
+       query->capacity_res = data[7];
+
+       query->x = data[3] << 9;
+       query->x |= data[4] << 2;
+       query->x |= (data[2] >> 5) & 0x3;
+
+       query->y = data[5] << 9;
+       query->y |= data[6] << 2;
+       query->y |= (data[2] >> 3) & 0x3;
+}
+
+static void report_pen_events(struct w8001 *w8001, struct w8001_coord *coord)
+{
+       struct input_dev *dev = w8001->dev;
+
+       /*
+        * We have 1 bit for proximity (rdy) and 3 bits for tip, side,
+        * side2/eraser. If rdy && f2 are set, this can be either pen + side2,
+        * or eraser. assume
+        * - if dev is already in proximity and f2 is toggled â†’ pen + side2
+        * - if dev comes into proximity with f2 set â†’ eraser
+        * If f2 disappears after assuming eraser, fake proximity out for
+        * eraser and in for pen.
+        */
+
+       if (!w8001->type) {
+               w8001->type = coord->f2 ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
+       } else if (w8001->type == BTN_TOOL_RUBBER) {
+               if (!coord->f2) {
+                       input_report_abs(dev, ABS_PRESSURE, 0);
+                       input_report_key(dev, BTN_TOUCH, 0);
+                       input_report_key(dev, BTN_STYLUS, 0);
+                       input_report_key(dev, BTN_STYLUS2, 0);
+                       input_report_key(dev, BTN_TOOL_RUBBER, 0);
+                       input_sync(dev);
+                       w8001->type = BTN_TOOL_PEN;
+               }
+       } else {
+               input_report_key(dev, BTN_STYLUS2, coord->f2);
+       }
+
+       input_report_abs(dev, ABS_X, coord->x);
+       input_report_abs(dev, ABS_Y, coord->y);
+       input_report_abs(dev, ABS_PRESSURE, coord->pen_pressure);
+       input_report_key(dev, BTN_TOUCH, coord->tsw);
+       input_report_key(dev, BTN_STYLUS, coord->f1);
+       input_report_key(dev, w8001->type, coord->rdy);
+       input_sync(dev);
+
+       if (!coord->rdy)
+               w8001->type = 0;
+}
+
 static irqreturn_t w8001_interrupt(struct serio *serio,
                                   unsigned char data, unsigned int flags)
 {
        struct w8001 *w8001 = serio_get_drvdata(serio);
-       struct input_dev *dev = w8001->dev;
        struct w8001_coord coord;
        unsigned char tmp;
 
@@ -105,26 +218,45 @@ static irqreturn_t w8001_interrupt(struct serio *serio,
                }
                break;
 
-       case 8:
+       case W8001_PKTLEN_TOUCH93 - 1:
+       case W8001_PKTLEN_TOUCH9A - 1:
+               /* ignore one-finger touch packet. */
+               if (w8001->pktlen == w8001->idx)
+                       w8001->idx = 0;
+               break;
+
+       /* Pen coordinates packet */
+       case W8001_PKTLEN_TPCPEN - 1:
                tmp = w8001->data[0] & W8001_TAB_MASK;
                if (unlikely(tmp == W8001_TAB_BYTE))
                        break;
 
+               tmp = (w8001->data[0] & W8001_TOUCH_BYTE);
+               if (tmp == W8001_TOUCH_BYTE)
+                       break;
+
                w8001->idx = 0;
                parse_data(w8001->data, &coord);
-               input_report_abs(dev, ABS_X, coord.x);
-               input_report_abs(dev, ABS_Y, coord.y);
-               input_report_abs(dev, ABS_PRESSURE, coord.pen_pressure);
-               input_report_key(dev, BTN_TOUCH, coord.tsw);
-               input_sync(dev);
+               report_pen_events(w8001, &coord);
                break;
 
-       case 10:
+       /* control packet */
+       case W8001_PKTLEN_TPCCTL - 1:
+               tmp = (w8001->data[0] & W8001_TOUCH_MASK);
+               if (tmp == W8001_TOUCH_BYTE)
+                       break;
+
                w8001->idx = 0;
                memcpy(w8001->response, w8001->data, W8001_MAX_LENGTH);
                w8001->response_type = W8001_QUERY_PACKET;
                complete(&w8001->cmd_done);
                break;
+
+       /* 2 finger touch packet */
+       case W8001_PKTLEN_TOUCH2FG - 1:
+               w8001->idx = 0;
+               parse_touch(w8001);
+               break;
        }
 
        return IRQ_HANDLED;
@@ -167,6 +299,38 @@ static int w8001_setup(struct w8001 *w8001)
        input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0);
        input_set_abs_params(dev, ABS_TILT_Y, 0, coord.tilt_y, 0, 0);
 
+       error = w8001_command(w8001, W8001_CMD_TOUCHQUERY, true);
+       if (!error) {
+               struct w8001_touch_query touch;
+
+               parse_touchquery(w8001->response, &touch);
+
+               switch (touch.sensor_id) {
+               case 0:
+               case 2:
+                       w8001->pktlen = W8001_PKTLEN_TOUCH93;
+                       break;
+               case 1:
+               case 3:
+               case 4:
+                       w8001->pktlen = W8001_PKTLEN_TOUCH9A;
+                       break;
+               case 5:
+                       w8001->pktlen = W8001_PKTLEN_TOUCH2FG;
+
+                       input_mt_create_slots(dev, 2);
+                       input_set_abs_params(dev, ABS_MT_TRACKING_ID,
+                                               0, MAX_TRACKING_ID, 0, 0);
+                       input_set_abs_params(dev, ABS_MT_POSITION_X,
+                                               0, touch.x, 0, 0);
+                       input_set_abs_params(dev, ABS_MT_POSITION_Y,
+                                               0, touch.y, 0, 0);
+                       input_set_abs_params(dev, ABS_MT_TOOL_TYPE,
+                                               0, 0, 0, 0);
+                       break;
+               }
+       }
+
        return w8001_command(w8001, W8001_CMD_START, false);
 }
 
@@ -208,6 +372,7 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
        w8001->serio = serio;
        w8001->id = serio->id.id;
        w8001->dev = input_dev;
+       w8001->trkid[0] = w8001->trkid[1] = -1;
        init_completion(&w8001->cmd_done);
        snprintf(w8001->phys, sizeof(w8001->phys), "%s/input0", serio->phys);
 
@@ -221,6 +386,10 @@ static int w8001_connect(struct serio *serio, struct serio_driver *drv)
 
        input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
        input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+       input_dev->keybit[BIT_WORD(BTN_TOOL_PEN)] |= BIT_MASK(BTN_TOOL_PEN);
+       input_dev->keybit[BIT_WORD(BTN_TOOL_RUBBER)] |= BIT_MASK(BTN_TOOL_RUBBER);
+       input_dev->keybit[BIT_WORD(BTN_STYLUS)] |= BIT_MASK(BTN_STYLUS);
+       input_dev->keybit[BIT_WORD(BTN_STYLUS2)] |= BIT_MASK(BTN_STYLUS2);
 
        serio_set_drvdata(serio, w8001);
        err = serio_open(serio, drv);
index cbfef1e..6b75c9f 100644 (file)
@@ -125,6 +125,8 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
 {
        int power_adc = 0, auxval;
        u16 power = 0;
+       int rc = 0;
+       int timeout = 0;
 
        /* get codec */
        mutex_lock(&wm->codec_mutex);
@@ -143,7 +145,9 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
 
        /* Turn polling mode on to read AUX ADC */
        wm->pen_probably_down = 1;
-       wm->codec->poll_sample(wm, adcsel, &auxval);
+
+       while (rc != RC_VALID && timeout++ < 5)
+               rc = wm->codec->poll_sample(wm, adcsel, &auxval);
 
        if (power_adc)
                wm97xx_reg_write(wm, AC97_EXTENDED_MID, power | 0x8000);
@@ -152,8 +156,15 @@ int wm97xx_read_aux_adc(struct wm97xx *wm, u16 adcsel)
 
        wm->pen_probably_down = 0;
 
+       if (timeout >= 5) {
+               dev_err(wm->dev,
+                       "timeout reading auxadc %d, disabling digitiser\n",
+                       adcsel);
+               wm->codec->dig_enable(wm, false);
+       }
+
        mutex_unlock(&wm->codec_mutex);
-       return auxval & 0xfff;
+       return (rc == RC_VALID ? auxval & 0xfff : -EBUSY);
 }
 EXPORT_SYMBOL_GPL(wm97xx_read_aux_adc);
 
@@ -684,8 +695,7 @@ static int wm97xx_probe(struct device *dev)
  touch_reg_err:
        platform_device_put(wm->touch_dev);
  touch_err:
-       platform_device_unregister(wm->battery_dev);
-       wm->battery_dev = NULL;
+       platform_device_del(wm->battery_dev);
  batt_reg_err:
        platform_device_put(wm->battery_dev);
  batt_err:
index 7961d59..c06b4d5 100644 (file)
 /* FIXME: IR_KEYPRESS_TIMEOUT should be protocol specific */
 #define IR_KEYPRESS_TIMEOUT 250
 
+/**
+ * ir_create_table() - initializes a scancode table
+ * @rc_tab:    the ir_scancode_table to initialize
+ * @name:      name to assign to the table
+ * @ir_type:   ir type to assign to the new table
+ * @size:      initial size of the table
+ * @return:    zero on success or a negative error code
+ *
+ * This routine will initialize the ir_scancode_table and will allocate
+ * memory to hold at least the specified number elements.
+ */
+static int ir_create_table(struct ir_scancode_table *rc_tab,
+                          const char *name, u64 ir_type, size_t size)
+{
+       rc_tab->name = name;
+       rc_tab->ir_type = ir_type;
+       rc_tab->alloc = roundup_pow_of_two(size * sizeof(struct ir_scancode));
+       rc_tab->size = rc_tab->alloc / sizeof(struct ir_scancode);
+       rc_tab->scan = kmalloc(rc_tab->alloc, GFP_KERNEL);
+       if (!rc_tab->scan)
+               return -ENOMEM;
+
+       IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+                  rc_tab->size, rc_tab->alloc);
+       return 0;
+}
+
+/**
+ * ir_free_table() - frees memory allocated by a scancode table
+ * @rc_tab:    the table whose mappings need to be freed
+ *
+ * This routine will free memory alloctaed for key mappings used by given
+ * scancode table.
+ */
+static void ir_free_table(struct ir_scancode_table *rc_tab)
+{
+       rc_tab->size = 0;
+       kfree(rc_tab->scan);
+       rc_tab->scan = NULL;
+}
+
 /**
  * ir_resize_table() - resizes a scancode table if necessary
  * @rc_tab:    the ir_scancode_table to resize
+ * @gfp_flags: gfp flags to use when allocating memory
  * @return:    zero on success or a negative error code
  *
  * This routine will shrink the ir_scancode_table if it has lots of
  * unused entries and grow it if it is full.
  */
-static int ir_resize_table(struct ir_scancode_table *rc_tab)
+static int ir_resize_table(struct ir_scancode_table *rc_tab, gfp_t gfp_flags)
 {
        unsigned int oldalloc = rc_tab->alloc;
        unsigned int newalloc = oldalloc;
@@ -57,7 +99,7 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab)
        if (newalloc == oldalloc)
                return 0;
 
-       newscan = kmalloc(newalloc, GFP_ATOMIC);
+       newscan = kmalloc(newalloc, gfp_flags);
        if (!newscan) {
                IR_dprintk(1, "Failed to kmalloc %u bytes\n", newalloc);
                return -ENOMEM;
@@ -72,26 +114,78 @@ static int ir_resize_table(struct ir_scancode_table *rc_tab)
 }
 
 /**
- * ir_do_setkeycode() - internal function to set a keycode in the
- *                     scancode->keycode table
+ * ir_update_mapping() - set a keycode in the scancode->keycode table
  * @dev:       the struct input_dev device descriptor
- * @rc_tab:    the struct ir_scancode_table to set the keycode in
- * @scancode:  the scancode for the ir command
- * @keycode:   the keycode for the ir command
- * @resize:    whether the keytable may be shrunk
- * @return:    -EINVAL if the keycode could not be inserted, otherwise zero.
+ * @rc_tab:    scancode table to be adjusted
+ * @index:     index of the mapping that needs to be updated
+ * @keycode:   the desired keycode
+ * @return:    previous keycode assigned to the mapping
+ *
+ * This routine is used to update scancode->keycopde mapping at given
+ * position.
+ */
+static unsigned int ir_update_mapping(struct input_dev *dev,
+                                     struct ir_scancode_table *rc_tab,
+                                     unsigned int index,
+                                     unsigned int new_keycode)
+{
+       int old_keycode = rc_tab->scan[index].keycode;
+       int i;
+
+       /* Did the user wish to remove the mapping? */
+       if (new_keycode == KEY_RESERVED || new_keycode == KEY_UNKNOWN) {
+               IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
+                          index, rc_tab->scan[index].scancode);
+               rc_tab->len--;
+               memmove(&rc_tab->scan[index], &rc_tab->scan[index+ 1],
+                       (rc_tab->len - index) * sizeof(struct ir_scancode));
+       } else {
+               IR_dprintk(1, "#%d: %s scan 0x%04x with key 0x%04x\n",
+                          index,
+                          old_keycode == KEY_RESERVED ? "New" : "Replacing",
+                          rc_tab->scan[index].scancode, new_keycode);
+               rc_tab->scan[index].keycode = new_keycode;
+               __set_bit(new_keycode, dev->keybit);
+       }
+
+       if (old_keycode != KEY_RESERVED) {
+               /* A previous mapping was updated... */
+               __clear_bit(old_keycode, dev->keybit);
+               /* ... but another scancode might use the same keycode */
+               for (i = 0; i < rc_tab->len; i++) {
+                       if (rc_tab->scan[i].keycode == old_keycode) {
+                               __set_bit(old_keycode, dev->keybit);
+                               break;
+                       }
+               }
+
+               /* Possibly shrink the keytable, failure is not a problem */
+               ir_resize_table(rc_tab, GFP_ATOMIC);
+       }
+
+       return old_keycode;
+}
+
+/**
+ * ir_locate_scancode() - set a keycode in the scancode->keycode table
+ * @ir_dev:    the struct ir_input_dev device descriptor
+ * @rc_tab:    scancode table to be searched
+ * @scancode:  the desired scancode
+ * @resize:    controls whether we allowed to resize the table to
+ *             accomodate not yet present scancodes
+ * @return:    index of the mapping containing scancode in question
+ *             or -1U in case of failure.
  *
- * This routine is used internally to manipulate the scancode->keycode table.
- * The caller has to hold @rc_tab->lock.
+ * This routine is used to locate given scancode in ir_scancode_table.
+ * If scancode is not yet present the routine will allocate a new slot
+ * for it.
  */
-static int ir_do_setkeycode(struct input_dev *dev,
-                           struct ir_scancode_table *rc_tab,
-                           unsigned scancode, unsigned keycode,
-                           bool resize)
+static unsigned int ir_establish_scancode(struct ir_input_dev *ir_dev,
+                                         struct ir_scancode_table *rc_tab,
+                                         unsigned int scancode,
+                                         bool resize)
 {
        unsigned int i;
-       int old_keycode = KEY_RESERVED;
-       struct ir_input_dev *ir_dev = input_get_drvdata(dev);
 
        /*
         * Unfortunately, some hardware-based IR decoders don't provide
@@ -100,65 +194,34 @@ static int ir_do_setkeycode(struct input_dev *dev,
         * the provided IR with another one, it is needed to allow loading
         * IR tables from other remotes. So,
         */
-       if (ir_dev->props && ir_dev->props->scanmask) {
+       if (ir_dev->props && ir_dev->props->scanmask)
                scancode &= ir_dev->props->scanmask;
-       }
 
        /* First check if we already have a mapping for this ir command */
        for (i = 0; i < rc_tab->len; i++) {
+               if (rc_tab->scan[i].scancode == scancode)
+                       return i;
+
                /* Keytable is sorted from lowest to highest scancode */
-               if (rc_tab->scan[i].scancode > scancode)
+               if (rc_tab->scan[i].scancode >= scancode)
                        break;
-               else if (rc_tab->scan[i].scancode < scancode)
-                       continue;
-
-               old_keycode = rc_tab->scan[i].keycode;
-               rc_tab->scan[i].keycode = keycode;
-
-               /* Did the user wish to remove the mapping? */
-               if (keycode == KEY_RESERVED || keycode == KEY_UNKNOWN) {
-                       IR_dprintk(1, "#%d: Deleting scan 0x%04x\n",
-                                  i, scancode);
-                       rc_tab->len--;
-                       memmove(&rc_tab->scan[i], &rc_tab->scan[i + 1],
-                               (rc_tab->len - i) * sizeof(struct ir_scancode));
-               }
-
-               /* Possibly shrink the keytable, failure is not a problem */
-               ir_resize_table(rc_tab);
-               break;
        }
 
-       if (old_keycode == KEY_RESERVED && keycode != KEY_RESERVED) {
-               /* No previous mapping found, we might need to grow the table */
-               if (resize && ir_resize_table(rc_tab))
-                       return -ENOMEM;
-
-               IR_dprintk(1, "#%d: New scan 0x%04x with key 0x%04x\n",
-                          i, scancode, keycode);
+       /* No previous mapping found, we might need to grow the table */
+       if (rc_tab->size == rc_tab->len) {
+               if (!resize || ir_resize_table(rc_tab, GFP_ATOMIC))
+                       return -1U;
+       }
 
-               /* i is the proper index to insert our new keycode */
+       /* i is the proper index to insert our new keycode */
+       if (i < rc_tab->len)
                memmove(&rc_tab->scan[i + 1], &rc_tab->scan[i],
                        (rc_tab->len - i) * sizeof(struct ir_scancode));
-               rc_tab->scan[i].scancode = scancode;
-               rc_tab->scan[i].keycode = keycode;
-               rc_tab->len++;
-               set_bit(keycode, dev->keybit);
-       } else {
-               IR_dprintk(1, "#%d: Replacing scan 0x%04x with key 0x%04x\n",
-                          i, scancode, keycode);
-               /* A previous mapping was updated... */
-               clear_bit(old_keycode, dev->keybit);
-               /* ...but another scancode might use the same keycode */
-               for (i = 0; i < rc_tab->len; i++) {
-                       if (rc_tab->scan[i].keycode == old_keycode) {
-                               set_bit(old_keycode, dev->keybit);
-                               break;
-                       }
-               }
-       }
+       rc_tab->scan[i].scancode = scancode;
+       rc_tab->scan[i].keycode = KEY_RESERVED;
+       rc_tab->len++;
 
-       return 0;
+       return i;
 }
 
 /**
@@ -171,17 +234,41 @@ static int ir_do_setkeycode(struct input_dev *dev,
  * This routine is used to handle evdev EVIOCSKEY ioctl.
  */
 static int ir_setkeycode(struct input_dev *dev,
-                        unsigned int scancode, unsigned int keycode)
+                        const struct input_keymap_entry *ke,
+                        unsigned int *old_keycode)
 {
-       int rc;
-       unsigned long flags;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+       unsigned int index;
+       unsigned int scancode;
+       int retval;
+       unsigned long flags;
 
        spin_lock_irqsave(&rc_tab->lock, flags);
-       rc = ir_do_setkeycode(dev, rc_tab, scancode, keycode, true);
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+               if (index >= rc_tab->len) {
+                       retval = -EINVAL;
+                       goto out;
+               }
+       } else {
+               retval = input_scancode_to_scalar(ke, &scancode);
+               if (retval)
+                       goto out;
+
+               index = ir_establish_scancode(ir_dev, rc_tab, scancode, true);
+               if (index >= rc_tab->len) {
+                       retval = -ENOMEM;
+                       goto out;
+               }
+       }
+
+       *old_keycode = ir_update_mapping(dev, rc_tab, index, ke->keycode);
+
+out:
        spin_unlock_irqrestore(&rc_tab->lock, flags);
-       return rc;
+       return retval;
 }
 
 /**
@@ -189,31 +276,72 @@ static int ir_setkeycode(struct input_dev *dev,
  * @dev:       the struct input_dev device descriptor
  * @to:                the struct ir_scancode_table to copy entries to
  * @from:      the struct ir_scancode_table to copy entries from
- * @return:    -EINVAL if all keycodes could not be inserted, otherwise zero.
+ * @return:    -ENOMEM if all keycodes could not be inserted, otherwise zero.
  *
  * This routine is used to handle table initialization.
  */
-static int ir_setkeytable(struct input_dev *dev,
-                         struct ir_scancode_table *to,
+static int ir_setkeytable(struct ir_input_dev *ir_dev,
                          const struct ir_scancode_table *from)
 {
-       struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
-       unsigned long flags;
-       unsigned int i;
-       int rc = 0;
+       unsigned int i, index;
+       int rc;
+
+       rc = ir_create_table(&ir_dev->rc_tab,
+                            from->name, from->ir_type, from->size);
+       if (rc)
+               return rc;
+
+       IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
+                  rc_tab->size, rc_tab->alloc);
 
-       spin_lock_irqsave(&rc_tab->lock, flags);
        for (i = 0; i < from->size; i++) {
-               rc = ir_do_setkeycode(dev, to, from->scan[i].scancode,
-                                     from->scan[i].keycode, false);
-               if (rc)
+               index = ir_establish_scancode(ir_dev, rc_tab,
+                                             from->scan[i].scancode, false);
+               if (index >= rc_tab->len) {
+                       rc = -ENOMEM;
                        break;
+               }
+
+               ir_update_mapping(ir_dev->input_dev, rc_tab, index,
+                                 from->scan[i].keycode);
        }
-       spin_unlock_irqrestore(&rc_tab->lock, flags);
+
+       if (rc)
+               ir_free_table(rc_tab);
+
        return rc;
 }
 
+/**
+ * ir_lookup_by_scancode() - locate mapping by scancode
+ * @rc_tab:    the &struct ir_scancode_table to search
+ * @scancode:  scancode to look for in the table
+ * @return:    index in the table, -1U if not found
+ *
+ * This routine performs binary search in RC keykeymap table for
+ * given scancode.
+ */
+static unsigned int ir_lookup_by_scancode(const struct ir_scancode_table *rc_tab,
+                                         unsigned int scancode)
+{
+       unsigned int start = 0;
+       unsigned int end = rc_tab->len - 1;
+       unsigned int mid;
+
+       while (start <= end) {
+               mid = (start + end) / 2;
+               if (rc_tab->scan[mid].scancode < scancode)
+                       start = mid + 1;
+               else if (rc_tab->scan[mid].scancode > scancode)
+                       end = mid - 1;
+               else
+                       return mid;
+       }
+
+       return -1U;
+}
+
 /**
  * ir_getkeycode() - get a keycode from the scancode->keycode table
  * @dev:       the struct input_dev device descriptor
@@ -224,36 +352,46 @@ static int ir_setkeytable(struct input_dev *dev,
  * This routine is used to handle evdev EVIOCGKEY ioctl.
  */
 static int ir_getkeycode(struct input_dev *dev,
-                        unsigned int scancode, unsigned int *keycode)
+                        struct input_keymap_entry *ke)
 {
-       int start, end, mid;
-       unsigned long flags;
-       int key = KEY_RESERVED;
        struct ir_input_dev *ir_dev = input_get_drvdata(dev);
        struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+       struct ir_scancode *entry;
+       unsigned long flags;
+       unsigned int index;
+       unsigned int scancode;
+       int retval;
 
        spin_lock_irqsave(&rc_tab->lock, flags);
-       start = 0;
-       end = rc_tab->len - 1;
-       while (start <= end) {
-               mid = (start + end) / 2;
-               if (rc_tab->scan[mid].scancode < scancode)
-                       start = mid + 1;
-               else if (rc_tab->scan[mid].scancode > scancode)
-                       end = mid - 1;
-               else {
-                       key = rc_tab->scan[mid].keycode;
-                       break;
-               }
+
+       if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+               index = ke->index;
+       } else {
+               retval = input_scancode_to_scalar(ke, &scancode);
+               if (retval)
+                       goto out;
+
+               index = ir_lookup_by_scancode(rc_tab, scancode);
+       }
+
+       if (index >= rc_tab->len) {
+               if (!(ke->flags & INPUT_KEYMAP_BY_INDEX))
+                       IR_dprintk(1, "unknown key for scancode 0x%04x\n",
+                                  scancode);
+               retval = -EINVAL;
+               goto out;
        }
-       spin_unlock_irqrestore(&rc_tab->lock, flags);
 
-       if (key == KEY_RESERVED)
-               IR_dprintk(1, "unknown key for scancode 0x%04x\n",
-                          scancode);
+       entry = &rc_tab->scan[index];
 
-       *keycode = key;
-       return 0;
+       ke->index = index;
+       ke->keycode = entry->keycode;
+       ke->len = sizeof(entry->scancode);
+       memcpy(ke->scancode, &entry->scancode, sizeof(entry->scancode));
+
+out:
+       spin_unlock_irqrestore(&rc_tab->lock, flags);
+       return retval;
 }
 
 /**
@@ -268,12 +406,24 @@ static int ir_getkeycode(struct input_dev *dev,
  */
 u32 ir_g_keycode_from_table(struct input_dev *dev, u32 scancode)
 {
-       int keycode;
+       struct ir_input_dev *ir_dev = input_get_drvdata(dev);
+       struct ir_scancode_table *rc_tab = &ir_dev->rc_tab;
+       unsigned int keycode;
+       unsigned int index;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rc_tab->lock, flags);
+
+       index = ir_lookup_by_scancode(rc_tab, scancode);
+       keycode = index < rc_tab->len ?
+                       rc_tab->scan[index].keycode : KEY_RESERVED;
+
+       spin_unlock_irqrestore(&rc_tab->lock, flags);
 
-       ir_getkeycode(dev, scancode, &keycode);
        if (keycode != KEY_RESERVED)
                IR_dprintk(1, "%s: scancode 0x%04x keycode 0x%02x\n",
                           dev->name, scancode, keycode);
+
        return keycode;
 }
 EXPORT_SYMBOL_GPL(ir_g_keycode_from_table);
@@ -453,8 +603,8 @@ int __ir_input_register(struct input_dev *input_dev,
                goto out_dev;
        }
 
-       input_dev->getkeycode = ir_getkeycode;
-       input_dev->setkeycode = ir_setkeycode;
+       input_dev->getkeycode_new = ir_getkeycode;
+       input_dev->setkeycode_new = ir_setkeycode;
        input_set_drvdata(input_dev, ir_dev);
        ir_dev->input_dev = input_dev;
 
@@ -462,12 +612,6 @@ int __ir_input_register(struct input_dev *input_dev,
        spin_lock_init(&ir_dev->keylock);
        setup_timer(&ir_dev->timer_keyup, ir_timer_keyup, (unsigned long)ir_dev);
 
-       ir_dev->rc_tab.name = rc_tab->name;
-       ir_dev->rc_tab.ir_type = rc_tab->ir_type;
-       ir_dev->rc_tab.alloc = roundup_pow_of_two(rc_tab->size *
-                                                 sizeof(struct ir_scancode));
-       ir_dev->rc_tab.scan = kmalloc(ir_dev->rc_tab.alloc, GFP_KERNEL);
-       ir_dev->rc_tab.size = ir_dev->rc_tab.alloc / sizeof(struct ir_scancode);
        if (props) {
                ir_dev->props = props;
                if (props->open)
@@ -476,23 +620,14 @@ int __ir_input_register(struct input_dev *input_dev,
                        input_dev->close = ir_close;
        }
 
-       if (!ir_dev->rc_tab.scan) {
-               rc = -ENOMEM;
-               goto out_name;
-       }
-
-       IR_dprintk(1, "Allocated space for %u keycode entries (%u bytes)\n",
-                  ir_dev->rc_tab.size, ir_dev->rc_tab.alloc);
-
        set_bit(EV_KEY, input_dev->evbit);
        set_bit(EV_REP, input_dev->evbit);
        set_bit(EV_MSC, input_dev->evbit);
        set_bit(MSC_SCAN, input_dev->mscbit);
 
-       if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
-               rc = -ENOMEM;
-               goto out_table;
-       }
+       rc = ir_setkeytable(ir_dev, rc_tab);
+       if (rc)
+               goto out_name;
 
        rc = ir_register_class(input_dev);
        if (rc < 0)
@@ -522,7 +657,7 @@ int __ir_input_register(struct input_dev *input_dev,
 out_event:
        ir_unregister_class(input_dev);
 out_table:
-       kfree(ir_dev->rc_tab.scan);
+       ir_free_table(&ir_dev->rc_tab);
 out_name:
        kfree(ir_dev->driver_name);
 out_dev:
@@ -540,7 +675,6 @@ EXPORT_SYMBOL_GPL(__ir_input_register);
 void ir_input_unregister(struct input_dev *input_dev)
 {
        struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
-       struct ir_scancode_table *rc_tab;
 
        if (!ir_dev)
                return;
@@ -552,10 +686,7 @@ void ir_input_unregister(struct input_dev *input_dev)
                if (ir_dev->props->driver_type == RC_DRIVER_IR_RAW)
                        ir_raw_event_unregister(input_dev);
 
-       rc_tab = &ir_dev->rc_tab;
-       rc_tab->size = 0;
-       kfree(rc_tab->scan);
-       rc_tab->scan = NULL;
+       ir_free_table(&ir_dev->rc_tab);
 
        ir_unregister_class(input_dev);
 
index defa786..b8c4b80 100644 (file)
@@ -338,6 +338,21 @@ static struct resource ab8500_rtc_resources[] = {
        },
 };
 
+static struct resource ab8500_poweronkey_db_resources[] = {
+       {
+               .name   = "ONKEY_DBF",
+               .start  = AB8500_INT_PON_KEY1DB_F,
+               .end    = AB8500_INT_PON_KEY1DB_F,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .name   = "ONKEY_DBR",
+               .start  = AB8500_INT_PON_KEY1DB_R,
+               .end    = AB8500_INT_PON_KEY1DB_R,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
 static struct mfd_cell ab8500_devs[] = {
        {
                .name = "ab8500-gpadc",
@@ -354,6 +369,11 @@ static struct mfd_cell ab8500_devs[] = {
        { .name = "ab8500-usb", },
        { .name = "ab8500-pwm", },
        { .name = "ab8500-regulator", },
+       {
+               .name = "ab8500-poweron-key",
+               .num_resources = ARRAY_SIZE(ab8500_poweronkey_db_resources),
+               .resources = ab8500_poweronkey_db_resources,
+       },
 };
 
 int __devinit ab8500_init(struct ab8500 *ab8500)
index cd16459..49b4d06 100644 (file)
@@ -65,7 +65,7 @@ static void sh_mobile_sdhi_set_pwr(struct platform_device *tmio, int state)
                p->set_pwr(pdev, state);
 }
 
-static int __init sh_mobile_sdhi_probe(struct platform_device *pdev)
+static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
 {
        struct sh_mobile_sdhi *priv;
        struct tmio_mmc_data *mmc_data;
index 6f512b5..ea22520 100644 (file)
@@ -924,6 +924,13 @@ static int __devinit m25p_probe(struct spi_device *spi)
                        nr_parts = data->nr_parts;
                }
 
+#ifdef CONFIG_OF
+               if (nr_parts <= 0 && spi->dev.of_node) {
+                       nr_parts = of_mtd_parse_partitions(&spi->dev,
+                                       spi->dev.of_node, &parts);
+               }
+#endif
+
                if (nr_parts > 0) {
                        for (i = 0; i < nr_parts; i++) {
                                DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
index fe63f6b..ec3edf6 100644 (file)
@@ -294,7 +294,7 @@ static int __devinit of_flash_probe(struct platform_device *dev,
                info->list[i].map.name = dev_name(&dev->dev);
                info->list[i].map.phys = res.start;
                info->list[i].map.size = res_size;
-               info->list[i].map.bankwidth = *width;
+               info->list[i].map.bankwidth = be32_to_cpup(width);
 
                err = -ENOMEM;
                info->list[i].map.virt = ioremap(info->list[i].map.phys,
index 8bf7dc6..7bd171e 100644 (file)
@@ -53,8 +53,8 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
                        continue;
                }
 
-               (*pparts)[i].offset = reg[0];
-               (*pparts)[i].size = reg[1];
+               (*pparts)[i].offset = be32_to_cpu(reg[0]);
+               (*pparts)[i].size = be32_to_cpu(reg[1]);
 
                partname = of_get_property(pp, "label", &len);
                if (!partname)
index 6acbff3..aa675eb 100644 (file)
@@ -4,7 +4,7 @@ config DTC
 config OF
        bool
 
-menu "Flattened Device Tree and Open Firmware support"
+menu "Device Tree and Open Firmware support"
        depends on OF
 
 config PROC_DEVICETREE
@@ -19,6 +19,9 @@ config OF_FLATTREE
        bool
        select DTC
 
+config OF_PROMTREE
+       bool
+
 config OF_DYNAMIC
        def_bool y
        depends on PPC_OF
index 0052c40..7888155 100644 (file)
@@ -1,5 +1,6 @@
 obj-y = base.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
+obj-$(CONFIG_OF_PROMTREE) += pdt.o
 obj-$(CONFIG_OF_ADDRESS)  += address.o
 obj-$(CONFIG_OF_IRQ)    += irq.o
 obj-$(CONFIG_OF_DEVICE) += device.o platform.o
index fcadb72..3a1c7e7 100644 (file)
@@ -163,7 +163,7 @@ static int of_bus_pci_translate(u32 *addr, u64 offset, int na)
 const u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size,
                        unsigned int *flags)
 {
-       const u32 *prop;
+       const __be32 *prop;
        unsigned int psize;
        struct device_node *parent;
        struct of_bus *bus;
index aa80525..710b53b 100644 (file)
@@ -33,7 +33,7 @@ DEFINE_RWLOCK(devtree_lock);
 
 int of_n_addr_cells(struct device_node *np)
 {
-       const int *ip;
+       const __be32 *ip;
 
        do {
                if (np->parent)
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(of_n_addr_cells);
 
 int of_n_size_cells(struct device_node *np)
 {
-       const int *ip;
+       const __be32 *ip;
 
        do {
                if (np->parent)
index 92de0eb..45d8653 100644 (file)
@@ -81,29 +81,10 @@ struct device_attribute of_platform_device_attrs[] = {
        __ATTR_NULL
 };
 
-/**
- * of_release_dev - free an of device structure when all users of it are finished.
- * @dev: device that's been disconnected
- *
- * Will be called only by the device core when all users of this of device are
- * done.
- */
-void of_release_dev(struct device *dev)
-{
-       struct platform_device *ofdev;
-
-       ofdev = to_platform_device(dev);
-       of_node_put(ofdev->dev.of_node);
-       kfree(ofdev);
-}
-EXPORT_SYMBOL(of_release_dev);
-
-int of_device_register(struct platform_device *ofdev)
+int of_device_add(struct platform_device *ofdev)
 {
        BUG_ON(ofdev->dev.of_node == NULL);
 
-       device_initialize(&ofdev->dev);
-
        /* name and id have to be set so that the platform bus doesn't get
         * confused on matching */
        ofdev->name = dev_name(&ofdev->dev);
@@ -117,6 +98,12 @@ int of_device_register(struct platform_device *ofdev)
 
        return device_add(&ofdev->dev);
 }
+
+int of_device_register(struct platform_device *pdev)
+{
+       device_initialize(&pdev->dev);
+       return of_device_add(pdev);
+}
 EXPORT_SYMBOL(of_device_register);
 
 void of_device_unregister(struct platform_device *ofdev)
index 65da5ae..c1360e0 100644 (file)
@@ -533,8 +533,6 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
                strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 #endif /* CONFIG_CMDLINE */
 
-       early_init_dt_scan_chosen_arch(node);
-
        pr_debug("Command line is: %s\n", cmd_line);
 
        /* break now */
index 6e595e5..75b0d3c 100644 (file)
 #include <linux/of_irq.h>
 #include <linux/string.h>
 
+/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */
+#ifndef NO_IRQ
+#define NO_IRQ 0
+#endif
+
 /**
  * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
  * @device: Device node of the device whose interrupt is to be mapped
@@ -347,3 +352,37 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
        return irq;
 }
 EXPORT_SYMBOL_GPL(of_irq_to_resource);
+
+/**
+ * of_irq_count - Count the number of IRQs a node uses
+ * @dev: pointer to device tree node
+ */
+int of_irq_count(struct device_node *dev)
+{
+       int nr = 0;
+
+       while (of_irq_to_resource(dev, nr, NULL) != NO_IRQ)
+               nr++;
+
+       return nr;
+}
+
+/**
+ * of_irq_to_resource_table - Fill in resource table with node's IRQ info
+ * @dev: pointer to device tree node
+ * @res: array of resources to fill in
+ * @nr_irqs: the number of IRQs (and upper bound for num of @res elements)
+ *
+ * Returns the size of the filled in table (up to @nr_irqs).
+ */
+int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
+               int nr_irqs)
+{
+       int i;
+
+       for (i = 0; i < nr_irqs; i++, res++)
+               if (of_irq_to_resource(dev, i, res) == NO_IRQ)
+                       break;
+
+       return i;
+}
index 0a694de..c85d3c7 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/i2c.h>
+#include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_i2c.h>
 #include <linux/of_irq.h>
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
new file mode 100644 (file)
index 0000000..28295d0
--- /dev/null
@@ -0,0 +1,276 @@
+/* pdt.c: OF PROM device tree support code.
+ *
+ * Paul Mackerras      August 1996.
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
+ *    {engebret|bergner}@us.ibm.com
+ *
+ *  Adapted for sparc by David S. Miller davem@davemloft.net
+ *  Adapted for multiple architectures by Andres Salomon <dilinger@queued.net>
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_pdt.h>
+#include <asm/prom.h>
+
+static struct of_pdt_ops *of_pdt_prom_ops __initdata;
+
+void __initdata (*of_pdt_build_more)(struct device_node *dp,
+               struct device_node ***nextp);
+
+#if defined(CONFIG_SPARC)
+unsigned int of_pdt_unique_id __initdata;
+
+#define of_pdt_incr_unique_id(p) do { \
+       (p)->unique_id = of_pdt_unique_id++; \
+} while (0)
+
+static inline const char *of_pdt_node_name(struct device_node *dp)
+{
+       return dp->path_component_name;
+}
+
+#else
+
+static inline void of_pdt_incr_unique_id(void *p) { }
+static inline void irq_trans_init(struct device_node *dp) { }
+
+static inline const char *of_pdt_node_name(struct device_node *dp)
+{
+       return dp->name;
+}
+
+#endif /* !CONFIG_SPARC */
+
+static struct property * __init of_pdt_build_one_prop(phandle node, char *prev,
+                                              char *special_name,
+                                              void *special_val,
+                                              int special_len)
+{
+       static struct property *tmp = NULL;
+       struct property *p;
+       int err;
+
+       if (tmp) {
+               p = tmp;
+               memset(p, 0, sizeof(*p) + 32);
+               tmp = NULL;
+       } else {
+               p = prom_early_alloc(sizeof(struct property) + 32);
+               of_pdt_incr_unique_id(p);
+       }
+
+       p->name = (char *) (p + 1);
+       if (special_name) {
+               strcpy(p->name, special_name);
+               p->length = special_len;
+               p->value = prom_early_alloc(special_len);
+               memcpy(p->value, special_val, special_len);
+       } else {
+               err = of_pdt_prom_ops->nextprop(node, prev, p->name);
+               if (err) {
+                       tmp = p;
+                       return NULL;
+               }
+               p->length = of_pdt_prom_ops->getproplen(node, p->name);
+               if (p->length <= 0) {
+                       p->length = 0;
+               } else {
+                       int len;
+
+                       p->value = prom_early_alloc(p->length + 1);
+                       len = of_pdt_prom_ops->getproperty(node, p->name,
+                                       p->value, p->length);
+                       if (len <= 0)
+                               p->length = 0;
+                       ((unsigned char *)p->value)[p->length] = '\0';
+               }
+       }
+       return p;
+}
+
+static struct property * __init of_pdt_build_prop_list(phandle node)
+{
+       struct property *head, *tail;
+
+       head = tail = of_pdt_build_one_prop(node, NULL,
+                                    ".node", &node, sizeof(node));
+
+       tail->next = of_pdt_build_one_prop(node, NULL, NULL, NULL, 0);
+       tail = tail->next;
+       while(tail) {
+               tail->next = of_pdt_build_one_prop(node, tail->name,
+                                           NULL, NULL, 0);
+               tail = tail->next;
+       }
+
+       return head;
+}
+
+static char * __init of_pdt_get_one_property(phandle node, const char *name)
+{
+       char *buf = "<NULL>";
+       int len;
+
+       len = of_pdt_prom_ops->getproplen(node, name);
+       if (len > 0) {
+               buf = prom_early_alloc(len);
+               len = of_pdt_prom_ops->getproperty(node, name, buf, len);
+       }
+
+       return buf;
+}
+
+static char * __init of_pdt_try_pkg2path(phandle node)
+{
+       char *res, *buf = NULL;
+       int len;
+
+       if (!of_pdt_prom_ops->pkg2path)
+               return NULL;
+
+       if (of_pdt_prom_ops->pkg2path(node, buf, 0, &len))
+               return NULL;
+       buf = prom_early_alloc(len + 1);
+       if (of_pdt_prom_ops->pkg2path(node, buf, len, &len)) {
+               pr_err("%s: package-to-path failed\n", __func__);
+               return NULL;
+       }
+
+       res = strrchr(buf, '/');
+       if (!res) {
+               pr_err("%s: couldn't find / in %s\n", __func__, buf);
+               return NULL;
+       }
+       return res+1;
+}
+
+/*
+ * When fetching the node's name, first try using package-to-path; if
+ * that fails (either because the arch hasn't supplied a PROM callback,
+ * or some other random failure), fall back to just looking at the node's
+ * 'name' property.
+ */
+static char * __init of_pdt_build_name(phandle node)
+{
+       char *buf;
+
+       buf = of_pdt_try_pkg2path(node);
+       if (!buf)
+               buf = of_pdt_get_one_property(node, "name");
+
+       return buf;
+}
+
+static struct device_node * __init of_pdt_create_node(phandle node,
+                                                   struct device_node *parent)
+{
+       struct device_node *dp;
+
+       if (!node)
+               return NULL;
+
+       dp = prom_early_alloc(sizeof(*dp));
+       of_pdt_incr_unique_id(dp);
+       dp->parent = parent;
+
+       kref_init(&dp->kref);
+
+       dp->name = of_pdt_build_name(node);
+       dp->type = of_pdt_get_one_property(node, "device_type");
+       dp->phandle = node;
+
+       dp->properties = of_pdt_build_prop_list(node);
+
+       irq_trans_init(dp);
+
+       return dp;
+}
+
+static char * __init of_pdt_build_full_name(struct device_node *dp)
+{
+       int len, ourlen, plen;
+       char *n;
+
+       plen = strlen(dp->parent->full_name);
+       ourlen = strlen(of_pdt_node_name(dp));
+       len = ourlen + plen + 2;
+
+       n = prom_early_alloc(len);
+       strcpy(n, dp->parent->full_name);
+       if (!of_node_is_root(dp->parent)) {
+               strcpy(n + plen, "/");
+               plen++;
+       }
+       strcpy(n + plen, of_pdt_node_name(dp));
+
+       return n;
+}
+
+static struct device_node * __init of_pdt_build_tree(struct device_node *parent,
+                                                  phandle node,
+                                                  struct device_node ***nextp)
+{
+       struct device_node *ret = NULL, *prev_sibling = NULL;
+       struct device_node *dp;
+
+       while (1) {
+               dp = of_pdt_create_node(node, parent);
+               if (!dp)
+                       break;
+
+               if (prev_sibling)
+                       prev_sibling->sibling = dp;
+
+               if (!ret)
+                       ret = dp;
+               prev_sibling = dp;
+
+               *(*nextp) = dp;
+               *nextp = &dp->allnext;
+
+#if defined(CONFIG_SPARC)
+               dp->path_component_name = build_path_component(dp);
+#endif
+               dp->full_name = of_pdt_build_full_name(dp);
+
+               dp->child = of_pdt_build_tree(dp,
+                               of_pdt_prom_ops->getchild(node), nextp);
+
+               if (of_pdt_build_more)
+                       of_pdt_build_more(dp, nextp);
+
+               node = of_pdt_prom_ops->getsibling(node);
+       }
+
+       return ret;
+}
+
+void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
+{
+       struct device_node **nextp;
+
+       BUG_ON(!ops);
+       of_pdt_prom_ops = ops;
+
+       allnodes = of_pdt_create_node(root_node, NULL);
+#if defined(CONFIG_SPARC)
+       allnodes->path_component_name = "";
+#endif
+       allnodes->full_name = "/";
+
+       nextp = &allnodes->allnext;
+       allnodes->child = of_pdt_build_tree(allnodes,
+                       of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+}
index bb72223..5b4a07f 100644 (file)
@@ -584,34 +584,33 @@ struct platform_device *of_device_alloc(struct device_node *np,
                                  struct device *parent)
 {
        struct platform_device *dev;
-       int rc, i, num_reg = 0, num_irq = 0;
+       int rc, i, num_reg = 0, num_irq;
        struct resource *res, temp_res;
 
-       /* First count how many resources are needed */
-       while (of_address_to_resource(np, num_reg, &temp_res) == 0)
-               num_reg++;
-       while (of_irq_to_resource(np, num_irq, &temp_res) != NO_IRQ)
-               num_irq++;
-
-       /* Allocate memory for both the struct device and the resource table */
-       dev = kzalloc(sizeof(*dev) + (sizeof(*res) * (num_reg + num_irq)),
-                     GFP_KERNEL);
+       dev = platform_device_alloc("", -1);
        if (!dev)
                return NULL;
-       res = (struct resource *) &dev[1];
+
+       /* count the io and irq resources */
+       while (of_address_to_resource(np, num_reg, &temp_res) == 0)
+               num_reg++;
+       num_irq = of_irq_count(np);
 
        /* Populate the resource table */
        if (num_irq || num_reg) {
+               res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
+               if (!res) {
+                       platform_device_put(dev);
+                       return NULL;
+               }
+
                dev->num_resources = num_reg + num_irq;
                dev->resource = res;
                for (i = 0; i < num_reg; i++, res++) {
                        rc = of_address_to_resource(np, i, res);
                        WARN_ON(rc);
                }
-               for (i = 0; i < num_irq; i++, res++) {
-                       rc = of_irq_to_resource(np, i, res);
-                       WARN_ON(rc == NO_IRQ);
-               }
+               WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq);
        }
 
        dev->dev.of_node = of_node_get(np);
@@ -619,7 +618,6 @@ struct platform_device *of_device_alloc(struct device_node *np,
        dev->dev.dma_mask = &dev->archdata.dma_mask;
 #endif
        dev->dev.parent = parent;
-       dev->dev.release = of_release_dev;
 
        if (bus_id)
                dev_set_name(&dev->dev, "%s", bus_id);
@@ -657,8 +655,8 @@ struct platform_device *of_platform_device_create(struct device_node *np,
         * to do such, possibly using a device notifier
         */
 
-       if (of_device_register(dev) != 0) {
-               of_device_free(dev);
+       if (of_device_add(dev) != 0) {
+               platform_device_put(dev);
                return NULL;
        }
 
index cff7cc2..faec777 100644 (file)
@@ -92,6 +92,7 @@ config DELL_WMI
        tristate "Dell WMI extras"
        depends on ACPI_WMI
        depends on INPUT
+       select INPUT_SPARSEKMAP
        ---help---
          Say Y here if you want to support WMI-based hotkeys on Dell laptops.
 
@@ -140,6 +141,7 @@ config HP_WMI
        depends on ACPI_WMI
        depends on INPUT
        depends on RFKILL || RFKILL = n
+       select INPUT_SPARSEKMAP
        help
         Say Y here if you want to support WMI-based hotkeys on HP laptops and
         to read data from WMI such as docking or ambient light sensor state.
@@ -171,6 +173,7 @@ config PANASONIC_LAPTOP
        tristate "Panasonic Laptop Extras"
        depends on INPUT && ACPI
        depends on BACKLIGHT_CLASS_DEVICE
+       select INPUT_SPARSEKMAP
        ---help---
          This driver adds support for access to backlight control and hotkeys
          on Panasonic Let's Note laptops.
@@ -219,8 +222,8 @@ config SONYPI_COMPAT
          ---help---
          Build the sonypi driver compatibility code into the sony-laptop driver.
 
-config IDEAPAD_ACPI
-       tristate "Lenovo IdeaPad ACPI Laptop Extras"
+config IDEAPAD_LAPTOP
+       tristate "Lenovo IdeaPad Laptop Extras"
        depends on ACPI
        depends on RFKILL
        help
@@ -365,6 +368,26 @@ config THINKPAD_ACPI_HOTKEY_POLL
          If you are not sure, say Y here.  The driver enables polling only if
          it is strictly necessary to do so.
 
+config SENSORS_HDAPS
+       tristate "Thinkpad Hard Drive Active Protection System (hdaps)"
+       depends on INPUT && X86
+       select INPUT_POLLDEV
+       default n
+       help
+         This driver provides support for the IBM Hard Drive Active Protection
+         System (hdaps), which provides an accelerometer and other misc. data.
+         ThinkPads starting with the R50, T41, and X40 are supported.  The
+         accelerometer data is readable via sysfs.
+
+         This driver also provides an absolute input class device, allowing
+         the laptop to act as a pinball machine-esque joystick.
+
+         If your ThinkPad is not recognized by the driver, please update to latest
+         BIOS. This is especially the case for some R52 ThinkPads.
+
+         Say Y here if you have an applicable laptop and want to experience
+         the awesome power of hdaps.
+
 config INTEL_MENLOW
        tristate "Thermal Management driver for Intel menlow platform"
        depends on ACPI_THERMAL
@@ -478,6 +501,7 @@ config TOPSTAR_LAPTOP
        tristate "Topstar Laptop Extras"
        depends on ACPI
        depends on INPUT
+       select INPUT_SPARSEKMAP
        ---help---
          This driver adds support for hotkeys found on Topstar laptops.
 
@@ -492,6 +516,7 @@ config ACPI_TOSHIBA
        depends on INPUT
        depends on RFKILL || RFKILL = n
        select INPUT_POLLDEV
+       select INPUT_SPARSEKMAP
        ---help---
          This driver adds support for access to certain system settings
          on "legacy free" Toshiba laptops.  These laptops can be recognized by
@@ -590,4 +615,28 @@ config INTEL_IPS
          functionality.  If in doubt, say Y here; it will only load on
          supported platforms.
 
+config IBM_RTL
+       tristate "Device driver to enable PRTL support"
+       depends on X86 && PCI
+       ---help---
+        Enable support for IBM Premium Real Time Mode (PRTM).
+        This module will allow you the enter and exit PRTM in the BIOS via
+        sysfs on platforms that support this feature.  System in PRTM will
+        not receive CPU-generated SMIs for recoverable errors.  Use of this
+        feature without proper support may void your hardware warranty.
+
+        If the proper BIOS support is found the driver will load and create
+        /sys/devices/system/ibm_rtl/.  The "state" variable will indicate
+        whether or not the BIOS is in PRTM.
+        state = 0 (BIOS SMIs on)
+        state = 1 (BIOS SMIs off)
+
+config XO1_RFKILL
+       tristate "OLPC XO-1 software RF kill switch"
+       depends on OLPC
+       depends on RFKILL
+       ---help---
+         Support for enabling/disabling the WLAN interface on the OLPC XO-1
+         laptop.
+
 endif # X86_PLATFORM_DEVICES
index 85fb2b8..9950ccc 100644 (file)
@@ -15,8 +15,9 @@ obj-$(CONFIG_ACERHDF)         += acerhdf.o
 obj-$(CONFIG_HP_WMI)           += hp-wmi.o
 obj-$(CONFIG_TC1100_WMI)       += tc1100-wmi.o
 obj-$(CONFIG_SONY_LAPTOP)      += sony-laptop.o
-obj-$(CONFIG_IDEAPAD_ACPI)     += ideapad_acpi.o
+obj-$(CONFIG_IDEAPAD_LAPTOP)   += ideapad-laptop.o
 obj-$(CONFIG_THINKPAD_ACPI)    += thinkpad_acpi.o
+obj-$(CONFIG_SENSORS_HDAPS)    += hdaps.o
 obj-$(CONFIG_FUJITSU_LAPTOP)   += fujitsu-laptop.o
 obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o
 obj-$(CONFIG_INTEL_MENLOW)     += intel_menlow.o
@@ -30,4 +31,5 @@ obj-$(CONFIG_INTEL_SCU_IPC)   += intel_scu_ipc.o
 obj-$(CONFIG_RAR_REGISTER)     += intel_rar_register.o
 obj-$(CONFIG_INTEL_IPS)                += intel_ips.o
 obj-$(CONFIG_GPIO_INTEL_PMIC)  += intel_pmic_gpio.o
-
+obj-$(CONFIG_XO1_RFKILL)       += xo1-rfkill.o
+obj-$(CONFIG_IBM_RTL)          += ibm_rtl.o
index 2badee2..c8c6537 100644 (file)
@@ -1314,7 +1314,7 @@ static int __init acer_wmi_init(void)
                AMW0_find_mailled();
 
        if (!interface) {
-               printk(ACER_ERR "No or unsupported WMI interface, unable to "
+               printk(ACER_INFO "No or unsupported WMI interface, unable to "
                                "load\n");
                return -ENODEV;
        }
index b756e07..60a5a5c 100644 (file)
@@ -236,7 +236,6 @@ struct asus_laptop {
        u8 light_level;         /* light sensor level */
        u8 light_switch;        /* light sensor switch value */
        u16 event_count[128];   /* count for each event TODO make this better */
-       u16 *keycode_map;
 };
 
 static const struct key_entry asus_keymap[] = {
@@ -278,6 +277,7 @@ static const struct key_entry asus_keymap[] = {
        {KE_KEY, 0x99, { KEY_PHONE } },
        {KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
        {KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
+       {KE_KEY, 0xb5, { KEY_CALC } },
        {KE_END, 0},
 };
 
@@ -639,29 +639,29 @@ static int asus_backlight_notify(struct asus_laptop *asus)
 static int asus_backlight_init(struct asus_laptop *asus)
 {
        struct backlight_device *bd;
-       struct device *dev = &asus->platform_device->dev;
        struct backlight_properties props;
 
-       if (!acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) &&
-           lcd_switch_handle) {
-               memset(&props, 0, sizeof(struct backlight_properties));
-               props.max_brightness = 15;
-
-               bd = backlight_device_register(ASUS_LAPTOP_FILE, dev,
-                                              asus, &asusbl_ops, &props);
-               if (IS_ERR(bd)) {
-                       pr_err("Could not register asus backlight device\n");
-                       asus->backlight_device = NULL;
-                       return PTR_ERR(bd);
-               }
+       if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) ||
+           acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) ||
+           !lcd_switch_handle)
+               return 0;
 
-               asus->backlight_device = bd;
+       memset(&props, 0, sizeof(struct backlight_properties));
+       props.max_brightness = 15;
 
-               bd->props.power = FB_BLANK_UNBLANK;
-               bd->props.brightness = asus_read_brightness(bd);
-               backlight_update_status(bd);
+       bd = backlight_device_register(ASUS_LAPTOP_FILE,
+                                      &asus->platform_device->dev, asus,
+                                      &asusbl_ops, &props);
+       if (IS_ERR(bd)) {
+               pr_err("Could not register asus backlight device\n");
+               asus->backlight_device = NULL;
+               return PTR_ERR(bd);
        }
+
+       asus->backlight_device = bd;
+       bd->props.brightness = asus_read_brightness(bd);
+       bd->props.power = FB_BLANK_UNBLANK;
+       backlight_update_status(bd);
        return 0;
 }
 
@@ -1065,9 +1065,9 @@ static ssize_t store_gps(struct device *dev, struct device_attribute *attr,
  */
 static int asus_gps_rfkill_set(void *data, bool blocked)
 {
-       acpi_handle handle = data;
+       struct asus_laptop *asus = data;
 
-       return asus_gps_switch(handle, !blocked);
+       return asus_gps_switch(asus, !blocked);
 }
 
 static const struct rfkill_ops asus_gps_rfkill_ops = {
@@ -1094,7 +1094,7 @@ static int asus_rfkill_init(struct asus_laptop *asus)
 
        asus->gps_rfkill = rfkill_alloc("asus-gps", &asus->platform_device->dev,
                                        RFKILL_TYPE_GPS,
-                                       &asus_gps_rfkill_ops, NULL);
+                                       &asus_gps_rfkill_ops, asus);
        if (!asus->gps_rfkill)
                return -EINVAL;
 
@@ -1130,7 +1130,6 @@ static int asus_input_init(struct asus_laptop *asus)
        input->phys = ASUS_LAPTOP_FILE "/input0";
        input->id.bustype = BUS_HOST;
        input->dev.parent = &asus->platform_device->dev;
-       input_set_drvdata(input, asus);
 
        error = sparse_keymap_setup(input, asus_keymap, NULL);
        if (error) {
@@ -1159,6 +1158,7 @@ static void asus_input_exit(struct asus_laptop *asus)
                sparse_keymap_free(asus->inputdev);
                input_unregister_device(asus->inputdev);
        }
+       asus->inputdev = NULL;
 }
 
 /*
@@ -1200,111 +1200,100 @@ static void asus_acpi_notify(struct acpi_device *device, u32 event)
 
 static DEVICE_ATTR(infos, S_IRUGO, show_infos, NULL);
 static DEVICE_ATTR(wlan, S_IRUGO | S_IWUSR, show_wlan, store_wlan);
-static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR, show_bluetooth,
-                  store_bluetooth);
+static DEVICE_ATTR(bluetooth, S_IRUGO | S_IWUSR,
+                  show_bluetooth, store_bluetooth);
 static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
 static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
 static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
 static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
 static DEVICE_ATTR(gps, S_IRUGO | S_IWUSR, show_gps, store_gps);
 
-static void asus_sysfs_exit(struct asus_laptop *asus)
-{
-       struct platform_device *device = asus->platform_device;
-
-       device_remove_file(&device->dev, &dev_attr_infos);
-       device_remove_file(&device->dev, &dev_attr_wlan);
-       device_remove_file(&device->dev, &dev_attr_bluetooth);
-       device_remove_file(&device->dev, &dev_attr_display);
-       device_remove_file(&device->dev, &dev_attr_ledd);
-       device_remove_file(&device->dev, &dev_attr_ls_switch);
-       device_remove_file(&device->dev, &dev_attr_ls_level);
-       device_remove_file(&device->dev, &dev_attr_gps);
-}
+static struct attribute *asus_attributes[] = {
+       &dev_attr_infos.attr,
+       &dev_attr_wlan.attr,
+       &dev_attr_bluetooth.attr,
+       &dev_attr_display.attr,
+       &dev_attr_ledd.attr,
+       &dev_attr_ls_level.attr,
+       &dev_attr_ls_switch.attr,
+       &dev_attr_gps.attr,
+       NULL
+};
 
-static int asus_sysfs_init(struct asus_laptop *asus)
+static mode_t asus_sysfs_is_visible(struct kobject *kobj,
+                                   struct attribute *attr,
+                                   int idx)
 {
-       struct platform_device *device = asus->platform_device;
-       int err;
+       struct device *dev = container_of(kobj, struct device, kobj);
+       struct platform_device *pdev = to_platform_device(dev);
+       struct asus_laptop *asus = platform_get_drvdata(pdev);
+       acpi_handle handle = asus->handle;
+       bool supported;
 
-       err = device_create_file(&device->dev, &dev_attr_infos);
-       if (err)
-               return err;
+       if (attr == &dev_attr_wlan.attr) {
+               supported = !acpi_check_handle(handle, METHOD_WLAN, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_WLAN, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_wlan);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_bluetooth.attr) {
+               supported = !acpi_check_handle(handle, METHOD_BLUETOOTH, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_BLUETOOTH, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_bluetooth);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_display.attr) {
+               supported = !acpi_check_handle(handle, METHOD_SWITCH_DISPLAY, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_SWITCH_DISPLAY, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_display);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_ledd.attr) {
+               supported = !acpi_check_handle(handle, METHOD_LEDD, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_LEDD, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_ledd);
-               if (err)
-                       return err;
-       }
-
-       if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_ls_switch);
-               if (err)
-                       return err;
-               err = device_create_file(&device->dev, &dev_attr_ls_level);
-               if (err)
-                       return err;
-       }
+       } else if (attr == &dev_attr_ls_switch.attr ||
+                  attr == &dev_attr_ls_level.attr) {
+               supported = !acpi_check_handle(handle, METHOD_ALS_CONTROL, NULL) &&
+                           !acpi_check_handle(handle, METHOD_ALS_LEVEL, NULL);
 
-       if (!acpi_check_handle(asus->handle, METHOD_GPS_ON, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_GPS_OFF, NULL) &&
-           !acpi_check_handle(asus->handle, METHOD_GPS_STATUS, NULL)) {
-               err = device_create_file(&device->dev, &dev_attr_gps);
-               if (err)
-                       return err;
+       } else if (attr == &dev_attr_gps.attr) {
+               supported = !acpi_check_handle(handle, METHOD_GPS_ON, NULL) &&
+                           !acpi_check_handle(handle, METHOD_GPS_OFF, NULL) &&
+                           !acpi_check_handle(handle, METHOD_GPS_STATUS, NULL);
+       } else {
+               supported = true;
        }
 
-       return err;
+       return supported ? attr->mode : 0;
 }
 
+
+static const struct attribute_group asus_attr_group = {
+       .is_visible     = asus_sysfs_is_visible,
+       .attrs          = asus_attributes,
+};
+
 static int asus_platform_init(struct asus_laptop *asus)
 {
-       int err;
+       int result;
 
        asus->platform_device = platform_device_alloc(ASUS_LAPTOP_FILE, -1);
        if (!asus->platform_device)
                return -ENOMEM;
        platform_set_drvdata(asus->platform_device, asus);
 
-       err = platform_device_add(asus->platform_device);
-       if (err)
+       result = platform_device_add(asus->platform_device);
+       if (result)
                goto fail_platform_device;
 
-       err = asus_sysfs_init(asus);
-       if (err)
+       result = sysfs_create_group(&asus->platform_device->dev.kobj,
+                                   &asus_attr_group);
+       if (result)
                goto fail_sysfs;
+
        return 0;
 
 fail_sysfs:
-       asus_sysfs_exit(asus);
        platform_device_del(asus->platform_device);
 fail_platform_device:
        platform_device_put(asus->platform_device);
-       return err;
+       return result;
 }
 
 static void asus_platform_exit(struct asus_laptop *asus)
 {
-       asus_sysfs_exit(asus);
+       sysfs_remove_group(&asus->platform_device->dev.kobj, &asus_attr_group);
        platform_device_unregister(asus->platform_device);
 }
 
@@ -1428,8 +1417,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
        return AE_OK;
 }
 
-static bool asus_device_present;
-
 static int __devinit asus_acpi_init(struct asus_laptop *asus)
 {
        int result = 0;
@@ -1474,6 +1461,8 @@ static int __devinit asus_acpi_init(struct asus_laptop *asus)
        return result;
 }
 
+static bool asus_device_present;
+
 static int __devinit asus_acpi_add(struct acpi_device *device)
 {
        struct asus_laptop *asus;
index 4413975..cf8a89a 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/mm.h>
 #include <linux/i8042.h>
 #include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 #include "../../firmware/dcdbas.h"
 
 #define BRIGHTNESS_TOKEN 0x7d
@@ -325,6 +327,75 @@ static const struct rfkill_ops dell_rfkill_ops = {
        .query = dell_rfkill_query,
 };
 
+static struct dentry *dell_laptop_dir;
+
+static int dell_debugfs_show(struct seq_file *s, void *data)
+{
+       int status;
+
+       get_buffer();
+       dell_send_request(buffer, 17, 11);
+       status = buffer->output[1];
+       release_buffer();
+
+       seq_printf(s, "status:\t0x%X\n", status);
+       seq_printf(s, "Bit 0 : Hardware switch supported:   %lu\n",
+                  status & BIT(0));
+       seq_printf(s, "Bit 1 : Wifi locator supported:      %lu\n",
+                 (status & BIT(1)) >> 1);
+       seq_printf(s, "Bit 2 : Wifi is supported:           %lu\n",
+                 (status & BIT(2)) >> 2);
+       seq_printf(s, "Bit 3 : Bluetooth is supported:      %lu\n",
+                 (status & BIT(3)) >> 3);
+       seq_printf(s, "Bit 4 : WWAN is supported:           %lu\n",
+                 (status & BIT(4)) >> 4);
+       seq_printf(s, "Bit 5 : Wireless keyboard supported: %lu\n",
+                 (status & BIT(5)) >> 5);
+       seq_printf(s, "Bit 8 : Wifi is installed:           %lu\n",
+                 (status & BIT(8)) >> 8);
+       seq_printf(s, "Bit 9 : Bluetooth is installed:      %lu\n",
+                 (status & BIT(9)) >> 9);
+       seq_printf(s, "Bit 10: WWAN is installed:           %lu\n",
+                 (status & BIT(10)) >> 10);
+       seq_printf(s, "Bit 16: Hardware switch is on:       %lu\n",
+                 (status & BIT(16)) >> 16);
+       seq_printf(s, "Bit 17: Wifi is blocked:             %lu\n",
+                 (status & BIT(17)) >> 17);
+       seq_printf(s, "Bit 18: Bluetooth is blocked:        %lu\n",
+                 (status & BIT(18)) >> 18);
+       seq_printf(s, "Bit 19: WWAN is blocked:             %lu\n",
+                 (status & BIT(19)) >> 19);
+
+       seq_printf(s, "\nhwswitch_state:\t0x%X\n", hwswitch_state);
+       seq_printf(s, "Bit 0 : Wifi controlled by switch:      %lu\n",
+                  hwswitch_state & BIT(0));
+       seq_printf(s, "Bit 1 : Bluetooth controlled by switch: %lu\n",
+                  (hwswitch_state & BIT(1)) >> 1);
+       seq_printf(s, "Bit 2 : WWAN controlled by switch:      %lu\n",
+                  (hwswitch_state & BIT(2)) >> 2);
+       seq_printf(s, "Bit 7 : Wireless switch config locked:  %lu\n",
+                  (hwswitch_state & BIT(7)) >> 7);
+       seq_printf(s, "Bit 8 : Wifi locator enabled:           %lu\n",
+                  (hwswitch_state & BIT(8)) >> 8);
+       seq_printf(s, "Bit 15: Wifi locator setting locked:    %lu\n",
+                  (hwswitch_state & BIT(15)) >> 15);
+
+       return 0;
+}
+
+static int dell_debugfs_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dell_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations dell_debugfs_fops = {
+       .owner = THIS_MODULE,
+       .open = dell_debugfs_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
 static void dell_update_rfkill(struct work_struct *ignored)
 {
        if (wifi_rfkill)
@@ -556,6 +627,11 @@ static int __init dell_init(void)
                goto fail_filter;
        }
 
+       dell_laptop_dir = debugfs_create_dir("dell_laptop", NULL);
+       if (dell_laptop_dir != NULL)
+               debugfs_create_file("rfkill", 0444, dell_laptop_dir, NULL,
+                                   &dell_debugfs_fops);
+
 #ifdef CONFIG_ACPI
        /* In the event of an ACPI backlight being available, don't
         * register the platform controller.
@@ -615,6 +691,7 @@ fail_platform_driver:
 
 static void __exit dell_exit(void)
 {
+       debugfs_remove_recursive(dell_laptop_dir);
        i8042_remove_filter(dell_laptop_i8042_filter);
        cancel_delayed_work_sync(&dell_rfkill_work);
        backlight_device_unregister(dell_backlight_device);
index 08fb70f..77f1d55 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/acpi.h>
 #include <linux/string.h>
@@ -44,78 +45,70 @@ static int acpi_video;
 
 MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
 
-struct key_entry {
-       char type;              /* See KE_* below */
-       u16 code;
-       u16 keycode;
-};
-
-enum { KE_KEY, KE_SW, KE_IGNORE, KE_END };
-
 /*
  * Certain keys are flagged as KE_IGNORE. All of these are either
  * notifications (rather than requests for change) or are also sent
  * via the keyboard controller so should not be sent again.
  */
 
-static struct key_entry dell_legacy_wmi_keymap[] = {
-       {KE_KEY, 0xe045, KEY_PROG1},
-       {KE_KEY, 0xe009, KEY_EJECTCD},
+static const struct key_entry dell_wmi_legacy_keymap[] __initconst = {
+       { KE_KEY, 0xe045, { KEY_PROG1 } },
+       { KE_KEY, 0xe009, { KEY_EJECTCD } },
 
        /* These also contain the brightness level at offset 6 */
-       {KE_KEY, 0xe006, KEY_BRIGHTNESSUP},
-       {KE_KEY, 0xe005, KEY_BRIGHTNESSDOWN},
+       { KE_KEY, 0xe006, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0xe005, { KEY_BRIGHTNESSDOWN } },
 
        /* Battery health status button */
-       {KE_KEY, 0xe007, KEY_BATTERY},
+       { KE_KEY, 0xe007, { KEY_BATTERY } },
 
        /* This is actually for all radios. Although physically a
         * switch, the notification does not provide an indication of
         * state and so it should be reported as a key */
-       {KE_KEY, 0xe008, KEY_WLAN},
+       { KE_KEY, 0xe008, { KEY_WLAN } },
 
        /* The next device is at offset 6, the active devices are at
           offset 8 and the attached devices at offset 10 */
-       {KE_KEY, 0xe00b, KEY_SWITCHVIDEOMODE},
+       { KE_KEY, 0xe00b, { KEY_SWITCHVIDEOMODE } },
 
-       {KE_IGNORE, 0xe00c, KEY_KBDILLUMTOGGLE},
+       { KE_IGNORE, 0xe00c, { KEY_KBDILLUMTOGGLE } },
 
        /* BIOS error detected */
-       {KE_IGNORE, 0xe00d, KEY_RESERVED},
+       { KE_IGNORE, 0xe00d, { KEY_RESERVED } },
 
        /* Wifi Catcher */
-       {KE_KEY, 0xe011, KEY_PROG2},
+       { KE_KEY, 0xe011, {KEY_PROG2 } },
 
        /* Ambient light sensor toggle */
-       {KE_IGNORE, 0xe013, KEY_RESERVED},
-
-       {KE_IGNORE, 0xe020, KEY_MUTE},
-       {KE_IGNORE, 0xe02e, KEY_VOLUMEDOWN},
-       {KE_IGNORE, 0xe030, KEY_VOLUMEUP},
-       {KE_IGNORE, 0xe033, KEY_KBDILLUMUP},
-       {KE_IGNORE, 0xe034, KEY_KBDILLUMDOWN},
-       {KE_IGNORE, 0xe03a, KEY_CAPSLOCK},
-       {KE_IGNORE, 0xe045, KEY_NUMLOCK},
-       {KE_IGNORE, 0xe046, KEY_SCROLLLOCK},
-       {KE_END, 0}
+       { KE_IGNORE, 0xe013, { KEY_RESERVED } },
+
+       { KE_IGNORE, 0xe020, { KEY_MUTE } },
+       { KE_IGNORE, 0xe02e, { KEY_VOLUMEDOWN } },
+       { KE_IGNORE, 0xe030, { KEY_VOLUMEUP } },
+       { KE_IGNORE, 0xe033, { KEY_KBDILLUMUP } },
+       { KE_IGNORE, 0xe034, { KEY_KBDILLUMDOWN } },
+       { KE_IGNORE, 0xe03a, { KEY_CAPSLOCK } },
+       { KE_IGNORE, 0xe045, { KEY_NUMLOCK } },
+       { KE_IGNORE, 0xe046, { KEY_SCROLLLOCK } },
+       { KE_END, 0 }
 };
 
 static bool dell_new_hk_type;
 
-struct dell_new_keymap_entry {
+struct dell_bios_keymap_entry {
        u16 scancode;
        u16 keycode;
 };
 
-struct dell_hotkey_table {
+struct dell_bios_hotkey_table {
        struct dmi_header header;
-       struct dell_new_keymap_entry keymap[];
+       struct dell_bios_keymap_entry keymap[];
 
 };
 
-static struct key_entry *dell_new_wmi_keymap;
+static const struct dell_bios_hotkey_table *dell_bios_hotkey_table;
 
-static u16 bios_to_linux_keycode[256] = {
+static const u16 bios_to_linux_keycode[256] __initconst = {
 
        KEY_MEDIA,      KEY_NEXTSONG,   KEY_PLAYPAUSE, KEY_PREVIOUSSONG,
        KEY_STOPCD,     KEY_UNKNOWN,    KEY_UNKNOWN,    KEY_UNKNOWN,
@@ -138,68 +131,11 @@ static u16 bios_to_linux_keycode[256] = {
        KEY_PROG3
 };
 
-
-static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap;
-
 static struct input_dev *dell_wmi_input_dev;
 
-static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = dell_wmi_keymap; key->type != KE_END; key++)
-               if (code == key->code)
-                       return key;
-
-       return NULL;
-}
-
-static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode)
-{
-       struct key_entry *key;
-
-       for (key = dell_wmi_keymap; key->type != KE_END; key++)
-               if (key->type == KE_KEY && keycode == key->keycode)
-                       return key;
-
-       return NULL;
-}
-
-static int dell_wmi_getkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int *keycode)
-{
-       struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode);
-
-       if (key && key->type == KE_KEY) {
-               *keycode = key->keycode;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int dell_wmi_setkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int keycode)
-{
-       struct key_entry *key;
-       unsigned int old_keycode;
-
-       key = dell_wmi_get_entry_by_scancode(scancode);
-       if (key && key->type == KE_KEY) {
-               old_keycode = key->keycode;
-               key->keycode = keycode;
-               set_bit(keycode, dev->keybit);
-               if (!dell_wmi_get_entry_by_keycode(old_keycode))
-                       clear_bit(old_keycode, dev->keybit);
-               return 0;
-       }
-       return -EINVAL;
-}
-
 static void dell_wmi_notify(u32 value, void *context)
 {
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-       static struct key_entry *key;
        union acpi_object *obj;
        acpi_status status;
 
@@ -212,8 +148,10 @@ static void dell_wmi_notify(u32 value, void *context)
        obj = (union acpi_object *)response.pointer;
 
        if (obj && obj->type == ACPI_TYPE_BUFFER) {
+               const struct key_entry *key;
                int reported_key;
                u16 *buffer_entry = (u16 *)obj->buffer.pointer;
+
                if (dell_new_hk_type && (buffer_entry[1] != 0x10)) {
                        printk(KERN_INFO "dell-wmi: Received unknown WMI event"
                                         " (0x%x)\n", buffer_entry[1]);
@@ -226,8 +164,8 @@ static void dell_wmi_notify(u32 value, void *context)
                else
                        reported_key = (int)buffer_entry[1] & 0xffff;
 
-               key = dell_wmi_get_entry_by_scancode(reported_key);
-
+               key = sparse_keymap_entry_from_scancode(dell_wmi_input_dev,
+                                                       reported_key);
                if (!key) {
                        printk(KERN_INFO "dell-wmi: Unknown key %x pressed\n",
                                reported_key);
@@ -237,92 +175,98 @@ static void dell_wmi_notify(u32 value, void *context)
                         * come via ACPI */
                        ;
                } else {
-                       input_report_key(dell_wmi_input_dev, key->keycode, 1);
-                       input_sync(dell_wmi_input_dev);
-                       input_report_key(dell_wmi_input_dev, key->keycode, 0);
-                       input_sync(dell_wmi_input_dev);
+                       sparse_keymap_report_entry(dell_wmi_input_dev, key,
+                                                  1, true);
                }
        }
        kfree(obj);
 }
 
-
-static void setup_new_hk_map(const struct dmi_header *dm)
+static const struct key_entry * __init dell_wmi_prepare_new_keymap(void)
 {
-
+       int hotkey_num = (dell_bios_hotkey_table->header.length - 4) /
+                               sizeof(struct dell_bios_keymap_entry);
+       struct key_entry *keymap;
        int i;
-       int hotkey_num = (dm->length-4)/sizeof(struct dell_new_keymap_entry);
-       struct dell_hotkey_table *table =
-               container_of(dm, struct dell_hotkey_table, header);
 
-       dell_new_wmi_keymap = kzalloc((hotkey_num+1) *
-                                     sizeof(struct key_entry), GFP_KERNEL);
+       keymap = kcalloc(hotkey_num + 1, sizeof(struct key_entry), GFP_KERNEL);
+       if (!keymap)
+               return NULL;
 
        for (i = 0; i < hotkey_num; i++) {
-               dell_new_wmi_keymap[i].type = KE_KEY;
-               dell_new_wmi_keymap[i].code = table->keymap[i].scancode;
-               dell_new_wmi_keymap[i].keycode =
-                       (table->keymap[i].keycode > 255) ? 0 :
-                       bios_to_linux_keycode[table->keymap[i].keycode];
+               const struct dell_bios_keymap_entry *bios_entry =
+                                       &dell_bios_hotkey_table->keymap[i];
+               keymap[i].type = KE_KEY;
+               keymap[i].code = bios_entry->scancode;
+               keymap[i].keycode = bios_entry->keycode < 256 ?
+                                   bios_to_linux_keycode[bios_entry->keycode] :
+                                   KEY_RESERVED;
        }
 
-       dell_new_wmi_keymap[i].type = KE_END;
-       dell_new_wmi_keymap[i].code = 0;
-       dell_new_wmi_keymap[i].keycode = 0;
-
-       dell_wmi_keymap = dell_new_wmi_keymap;
+       keymap[hotkey_num].type = KE_END;
 
+       return keymap;
 }
 
-
-static void find_hk_type(const struct dmi_header *dm, void *dummy)
-{
-
-       if ((dm->type == 0xb2) && (dm->length > 6)) {
-               dell_new_hk_type = true;
-               setup_new_hk_map(dm);
-       }
-
-}
-
-
 static int __init dell_wmi_input_setup(void)
 {
-       struct key_entry *key;
        int err;
 
        dell_wmi_input_dev = input_allocate_device();
-
        if (!dell_wmi_input_dev)
                return -ENOMEM;
 
        dell_wmi_input_dev->name = "Dell WMI hotkeys";
        dell_wmi_input_dev->phys = "wmi/input0";
        dell_wmi_input_dev->id.bustype = BUS_HOST;
-       dell_wmi_input_dev->getkeycode = dell_wmi_getkeycode;
-       dell_wmi_input_dev->setkeycode = dell_wmi_setkeycode;
-
-       for (key = dell_wmi_keymap; key->type != KE_END; key++) {
-               switch (key->type) {
-               case KE_KEY:
-                       set_bit(EV_KEY, dell_wmi_input_dev->evbit);
-                       set_bit(key->keycode, dell_wmi_input_dev->keybit);
-                       break;
-               case KE_SW:
-                       set_bit(EV_SW, dell_wmi_input_dev->evbit);
-                       set_bit(key->keycode, dell_wmi_input_dev->swbit);
-                       break;
+
+       if (dell_new_hk_type) {
+               const struct key_entry *keymap = dell_wmi_prepare_new_keymap();
+               if (!keymap) {
+                       err = -ENOMEM;
+                       goto err_free_dev;
                }
-       }
 
-       err = input_register_device(dell_wmi_input_dev);
+               err = sparse_keymap_setup(dell_wmi_input_dev, keymap, NULL);
 
-       if (err) {
-               input_free_device(dell_wmi_input_dev);
-               return err;
+               /*
+                * Sparse keymap library makes a copy of keymap so we
+                * don't need the original one that was allocated.
+                */
+               kfree(keymap);
+       } else {
+               err = sparse_keymap_setup(dell_wmi_input_dev,
+                                         dell_wmi_legacy_keymap, NULL);
        }
+       if (err)
+               goto err_free_dev;
+
+       err = input_register_device(dell_wmi_input_dev);
+       if (err)
+               goto err_free_keymap;
 
        return 0;
+
+ err_free_keymap:
+       sparse_keymap_free(dell_wmi_input_dev);
+ err_free_dev:
+       input_free_device(dell_wmi_input_dev);
+       return err;
+}
+
+static void dell_wmi_input_destroy(void)
+{
+       sparse_keymap_free(dell_wmi_input_dev);
+       input_unregister_device(dell_wmi_input_dev);
+}
+
+static void __init find_hk_type(const struct dmi_header *dm, void *dummy)
+{
+       if (dm->type == 0xb2 && dm->length > 6) {
+               dell_new_hk_type = true;
+               dell_bios_hotkey_table =
+                       container_of(dm, struct dell_bios_hotkey_table, header);
+       }
 }
 
 static int __init dell_wmi_init(void)
@@ -339,18 +283,13 @@ static int __init dell_wmi_init(void)
        acpi_video = acpi_video_backlight_support();
 
        err = dell_wmi_input_setup();
-       if (err) {
-               if (dell_new_hk_type)
-                       kfree(dell_wmi_keymap);
+       if (err)
                return err;
-       }
 
        status = wmi_install_notify_handler(DELL_EVENT_GUID,
                                         dell_wmi_notify, NULL);
        if (ACPI_FAILURE(status)) {
-               input_unregister_device(dell_wmi_input_dev);
-               if (dell_new_hk_type)
-                       kfree(dell_wmi_keymap);
+               dell_wmi_input_destroy();
                printk(KERN_ERR
                        "dell-wmi: Unable to register notify handler - %d\n",
                        status);
@@ -359,14 +298,11 @@ static int __init dell_wmi_init(void)
 
        return 0;
 }
+module_init(dell_wmi_init);
 
 static void __exit dell_wmi_exit(void)
 {
        wmi_remove_notify_handler(DELL_EVENT_GUID);
-       input_unregister_device(dell_wmi_input_dev);
-       if (dell_new_hk_type)
-               kfree(dell_wmi_keymap);
+       dell_wmi_input_destroy();
 }
-
-module_init(dell_wmi_init);
 module_exit(dell_wmi_exit);
index 6b8e062..b2edfdc 100644 (file)
@@ -165,6 +165,7 @@ struct eeepc_laptop {
        u16 event_count[128];           /* count for each event */
 
        struct platform_device *platform_device;
+       struct acpi_device *device;             /* the device we are in */
        struct device *hwmon_device;
        struct backlight_device *backlight_device;
 
@@ -1193,9 +1194,9 @@ static int eeepc_input_init(struct eeepc_laptop *eeepc)
        eeepc->inputdev = input;
        return 0;
 
- err_free_keymap:
+err_free_keymap:
        sparse_keymap_free(input);
- err_free_dev:
+err_free_dev:
        input_free_device(input);
        return error;
 }
@@ -1206,6 +1207,7 @@ static void eeepc_input_exit(struct eeepc_laptop *eeepc)
                sparse_keymap_free(eeepc->inputdev);
                input_unregister_device(eeepc->inputdev);
        }
+       eeepc->inputdev = NULL;
 }
 
 /*
@@ -1326,16 +1328,15 @@ static void cmsg_quirks(struct eeepc_laptop *eeepc)
        cmsg_quirk(eeepc, CM_ASL_TPD, "TPD");
 }
 
-static int eeepc_acpi_init(struct eeepc_laptop *eeepc,
-                          struct acpi_device *device)
+static int __devinit eeepc_acpi_init(struct eeepc_laptop *eeepc)
 {
        unsigned int init_flags;
        int result;
 
-       result = acpi_bus_get_status(device);
+       result = acpi_bus_get_status(eeepc->device);
        if (result)
                return result;
-       if (!device->status.present) {
+       if (!eeepc->device->status.present) {
                pr_err("Hotkey device not present, aborting\n");
                return -ENODEV;
        }
@@ -1384,12 +1385,13 @@ static int __devinit eeepc_acpi_add(struct acpi_device *device)
        strcpy(acpi_device_name(device), EEEPC_ACPI_DEVICE_NAME);
        strcpy(acpi_device_class(device), EEEPC_ACPI_CLASS);
        device->driver_data = eeepc;
+       eeepc->device = device;
 
        eeepc->hotplug_disabled = hotplug_disabled;
 
        eeepc_dmi_check(eeepc);
 
-       result = eeepc_acpi_init(eeepc, device);
+       result = eeepc_acpi_init(eeepc);
        if (result)
                goto fail_platform;
        eeepc_enable_camera(eeepc);
index 9dc50fb..462ceab 100644 (file)
@@ -57,6 +57,7 @@ MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
 
 #define EEEPC_WMI_METHODID_DEVS        0x53564544
 #define EEEPC_WMI_METHODID_DSTS        0x53544344
+#define EEEPC_WMI_METHODID_CFVS        0x53564643
 
 #define EEEPC_WMI_DEVID_BACKLIGHT      0x00050012
 
@@ -69,6 +70,11 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
        { KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
        { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
+       { KE_KEY, 0xe1, { KEY_F14 } },
+       { KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
+       { KE_KEY, 0xe0, { KEY_PROG1 } },
+       { KE_KEY, 0x5c, { KEY_F15 } },
        { KE_END, 0},
 };
 
@@ -292,6 +298,49 @@ static void eeepc_wmi_notify(u32 value, void *context)
        kfree(obj);
 }
 
+static int store_cpufv(struct device *dev, struct device_attribute *attr,
+                      const char *buf, size_t count)
+{
+       int value;
+       struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
+       acpi_status status;
+
+       if (!count || sscanf(buf, "%i", &value) != 1)
+               return -EINVAL;
+       if (value < 0 || value > 2)
+               return -EINVAL;
+
+       status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
+                                    1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
+
+       if (ACPI_FAILURE(status))
+               return -EIO;
+       else
+               return count;
+}
+
+static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
+
+static void eeepc_wmi_sysfs_exit(struct platform_device *device)
+{
+       device_remove_file(&device->dev, &dev_attr_cpufv);
+}
+
+static int eeepc_wmi_sysfs_init(struct platform_device *device)
+{
+       int retval = -ENOMEM;
+
+       retval = device_create_file(&device->dev, &dev_attr_cpufv);
+       if (retval)
+               goto error_sysfs;
+
+       return 0;
+
+error_sysfs:
+       eeepc_wmi_sysfs_exit(platform_device);
+       return retval;
+}
+
 static int __devinit eeepc_wmi_platform_probe(struct platform_device *device)
 {
        struct eeepc_wmi *eeepc;
@@ -387,8 +436,14 @@ static int __init eeepc_wmi_init(void)
                goto del_dev;
        }
 
+       err = eeepc_wmi_sysfs_init(platform_device);
+       if (err)
+               goto del_sysfs;
+
        return 0;
 
+del_sysfs:
+       eeepc_wmi_sysfs_exit(platform_device);
 del_dev:
        platform_device_del(platform_device);
 put_dev:
@@ -403,6 +458,7 @@ static void __exit eeepc_wmi_exit(void)
 {
        struct eeepc_wmi *eeepc;
 
+       eeepc_wmi_sysfs_exit(platform_device);
        eeepc = platform_get_drvdata(platform_device);
        platform_driver_unregister(&platform_driver);
        platform_device_unregister(platform_device);
diff --git a/drivers/platform/x86/hdaps.c b/drivers/platform/x86/hdaps.c
new file mode 100644 (file)
index 0000000..067bf36
--- /dev/null
@@ -0,0 +1,637 @@
+/*
+ * hdaps.c - driver for IBM's Hard Drive Active Protection System
+ *
+ * Copyright (C) 2005 Robert Love <rml@novell.com>
+ * Copyright (C) 2005 Jesper Juhl <jesper.juhl@gmail.com>
+ *
+ * The HardDisk Active Protection System (hdaps) is present in IBM ThinkPads
+ * starting with the R40, T41, and X40.  It provides a basic two-axis
+ * accelerometer and other data, such as the device's temperature.
+ *
+ * This driver is based on the document by Mark A. Smith available at
+ * http://www.almaden.ibm.com/cs/people/marksmith/tpaps.html and a lot of trial
+ * and error.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License v2 as published by the
+ * Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/input-polldev.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/dmi.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+
+#define HDAPS_LOW_PORT         0x1600  /* first port used by hdaps */
+#define HDAPS_NR_PORTS         0x30    /* number of ports: 0x1600 - 0x162f */
+
+#define HDAPS_PORT_STATE       0x1611  /* device state */
+#define HDAPS_PORT_YPOS                0x1612  /* y-axis position */
+#define        HDAPS_PORT_XPOS         0x1614  /* x-axis position */
+#define HDAPS_PORT_TEMP1       0x1616  /* device temperature, in Celsius */
+#define HDAPS_PORT_YVAR                0x1617  /* y-axis variance (what is this?) */
+#define HDAPS_PORT_XVAR                0x1619  /* x-axis variance (what is this?) */
+#define HDAPS_PORT_TEMP2       0x161b  /* device temperature (again?) */
+#define HDAPS_PORT_UNKNOWN     0x161c  /* what is this? */
+#define HDAPS_PORT_KMACT       0x161d  /* keyboard or mouse activity */
+
+#define STATE_FRESH            0x50    /* accelerometer data is fresh */
+
+#define KEYBD_MASK             0x20    /* set if keyboard activity */
+#define MOUSE_MASK             0x40    /* set if mouse activity */
+#define KEYBD_ISSET(n)         (!! (n & KEYBD_MASK))   /* keyboard used? */
+#define MOUSE_ISSET(n)         (!! (n & MOUSE_MASK))   /* mouse used? */
+
+#define INIT_TIMEOUT_MSECS     4000    /* wait up to 4s for device init ... */
+#define INIT_WAIT_MSECS                200     /* ... in 200ms increments */
+
+#define HDAPS_POLL_INTERVAL    50      /* poll for input every 1/20s (50 ms)*/
+#define HDAPS_INPUT_FUZZ       4       /* input event threshold */
+#define HDAPS_INPUT_FLAT       4
+
+#define HDAPS_X_AXIS           (1 << 0)
+#define HDAPS_Y_AXIS           (1 << 1)
+#define HDAPS_BOTH_AXES                (HDAPS_X_AXIS | HDAPS_Y_AXIS)
+
+static struct platform_device *pdev;
+static struct input_polled_dev *hdaps_idev;
+static unsigned int hdaps_invert;
+static u8 km_activity;
+static int rest_x;
+static int rest_y;
+
+static DEFINE_MUTEX(hdaps_mtx);
+
+/*
+ * __get_latch - Get the value from a given port.  Callers must hold hdaps_mtx.
+ */
+static inline u8 __get_latch(u16 port)
+{
+       return inb(port) & 0xff;
+}
+
+/*
+ * __check_latch - Check a port latch for a given value.  Returns zero if the
+ * port contains the given value.  Callers must hold hdaps_mtx.
+ */
+static inline int __check_latch(u16 port, u8 val)
+{
+       if (__get_latch(port) == val)
+               return 0;
+       return -EINVAL;
+}
+
+/*
+ * __wait_latch - Wait up to 100us for a port latch to get a certain value,
+ * returning zero if the value is obtained.  Callers must hold hdaps_mtx.
+ */
+static int __wait_latch(u16 port, u8 val)
+{
+       unsigned int i;
+
+       for (i = 0; i < 20; i++) {
+               if (!__check_latch(port, val))
+                       return 0;
+               udelay(5);
+       }
+
+       return -EIO;
+}
+
+/*
+ * __device_refresh - request a refresh from the accelerometer.  Does not wait
+ * for refresh to complete.  Callers must hold hdaps_mtx.
+ */
+static void __device_refresh(void)
+{
+       udelay(200);
+       if (inb(0x1604) != STATE_FRESH) {
+               outb(0x11, 0x1610);
+               outb(0x01, 0x161f);
+       }
+}
+
+/*
+ * __device_refresh_sync - request a synchronous refresh from the
+ * accelerometer.  We wait for the refresh to complete.  Returns zero if
+ * successful and nonzero on error.  Callers must hold hdaps_mtx.
+ */
+static int __device_refresh_sync(void)
+{
+       __device_refresh();
+       return __wait_latch(0x1604, STATE_FRESH);
+}
+
+/*
+ * __device_complete - indicate to the accelerometer that we are done reading
+ * data, and then initiate an async refresh.  Callers must hold hdaps_mtx.
+ */
+static inline void __device_complete(void)
+{
+       inb(0x161f);
+       inb(0x1604);
+       __device_refresh();
+}
+
+/*
+ * hdaps_readb_one - reads a byte from a single I/O port, placing the value in
+ * the given pointer.  Returns zero on success or a negative error on failure.
+ * Can sleep.
+ */
+static int hdaps_readb_one(unsigned int port, u8 *val)
+{
+       int ret;
+
+       mutex_lock(&hdaps_mtx);
+
+       /* do a sync refresh -- we need to be sure that we read fresh data */
+       ret = __device_refresh_sync();
+       if (ret)
+               goto out;
+
+       *val = inb(port);
+       __device_complete();
+
+out:
+       mutex_unlock(&hdaps_mtx);
+       return ret;
+}
+
+/* __hdaps_read_pair - internal lockless helper for hdaps_read_pair(). */
+static int __hdaps_read_pair(unsigned int port1, unsigned int port2,
+                            int *x, int *y)
+{
+       /* do a sync refresh -- we need to be sure that we read fresh data */
+       if (__device_refresh_sync())
+               return -EIO;
+
+       *y = inw(port2);
+       *x = inw(port1);
+       km_activity = inb(HDAPS_PORT_KMACT);
+       __device_complete();
+
+       /* hdaps_invert is a bitvector to negate the axes */
+       if (hdaps_invert & HDAPS_X_AXIS)
+               *x = -*x;
+       if (hdaps_invert & HDAPS_Y_AXIS)
+               *y = -*y;
+
+       return 0;
+}
+
+/*
+ * hdaps_read_pair - reads the values from a pair of ports, placing the values
+ * in the given pointers.  Returns zero on success.  Can sleep.
+ */
+static int hdaps_read_pair(unsigned int port1, unsigned int port2,
+                          int *val1, int *val2)
+{
+       int ret;
+
+       mutex_lock(&hdaps_mtx);
+       ret = __hdaps_read_pair(port1, port2, val1, val2);
+       mutex_unlock(&hdaps_mtx);
+
+       return ret;
+}
+
+/*
+ * hdaps_device_init - initialize the accelerometer.  Returns zero on success
+ * and negative error code on failure.  Can sleep.
+ */
+static int hdaps_device_init(void)
+{
+       int total, ret = -ENXIO;
+
+       mutex_lock(&hdaps_mtx);
+
+       outb(0x13, 0x1610);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+
+       /*
+        * Most ThinkPads return 0x01.
+        *
+        * Others--namely the R50p, T41p, and T42p--return 0x03.  These laptops
+        * have "inverted" axises.
+        *
+        * The 0x02 value occurs when the chip has been previously initialized.
+        */
+       if (__check_latch(0x1611, 0x03) &&
+                    __check_latch(0x1611, 0x02) &&
+                    __check_latch(0x1611, 0x01))
+               goto out;
+
+       printk(KERN_DEBUG "hdaps: initial latch check good (0x%02x).\n",
+              __get_latch(0x1611));
+
+       outb(0x17, 0x1610);
+       outb(0x81, 0x1611);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+       if (__wait_latch(0x1611, 0x00))
+               goto out;
+       if (__wait_latch(0x1612, 0x60))
+               goto out;
+       if (__wait_latch(0x1613, 0x00))
+               goto out;
+       outb(0x14, 0x1610);
+       outb(0x01, 0x1611);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+       outb(0x10, 0x1610);
+       outb(0xc8, 0x1611);
+       outb(0x00, 0x1612);
+       outb(0x02, 0x1613);
+       outb(0x01, 0x161f);
+       if (__wait_latch(0x161f, 0x00))
+               goto out;
+       if (__device_refresh_sync())
+               goto out;
+       if (__wait_latch(0x1611, 0x00))
+               goto out;
+
+       /* we have done our dance, now let's wait for the applause */
+       for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) {
+               int x, y;
+
+               /* a read of the device helps push it into action */
+               __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
+               if (!__wait_latch(0x1611, 0x02)) {
+                       ret = 0;
+                       break;
+               }
+
+               msleep(INIT_WAIT_MSECS);
+       }
+
+out:
+       mutex_unlock(&hdaps_mtx);
+       return ret;
+}
+
+
+/* Device model stuff */
+
+static int hdaps_probe(struct platform_device *dev)
+{
+       int ret;
+
+       ret = hdaps_device_init();
+       if (ret)
+               return ret;
+
+       printk(KERN_INFO "hdaps: device successfully initialized.\n");
+       return 0;
+}
+
+static int hdaps_resume(struct platform_device *dev)
+{
+       return hdaps_device_init();
+}
+
+static struct platform_driver hdaps_driver = {
+       .probe = hdaps_probe,
+       .resume = hdaps_resume,
+       .driver = {
+               .name = "hdaps",
+               .owner = THIS_MODULE,
+       },
+};
+
+/*
+ * hdaps_calibrate - Set our "resting" values.  Callers must hold hdaps_mtx.
+ */
+static void hdaps_calibrate(void)
+{
+       __hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &rest_x, &rest_y);
+}
+
+static void hdaps_mousedev_poll(struct input_polled_dev *dev)
+{
+       struct input_dev *input_dev = dev->input;
+       int x, y;
+
+       mutex_lock(&hdaps_mtx);
+
+       if (__hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y))
+               goto out;
+
+       input_report_abs(input_dev, ABS_X, x - rest_x);
+       input_report_abs(input_dev, ABS_Y, y - rest_y);
+       input_sync(input_dev);
+
+out:
+       mutex_unlock(&hdaps_mtx);
+}
+
+
+/* Sysfs Files */
+
+static ssize_t hdaps_position_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int ret, x, y;
+
+       ret = hdaps_read_pair(HDAPS_PORT_XPOS, HDAPS_PORT_YPOS, &x, &y);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_variance_show(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       int ret, x, y;
+
+       ret = hdaps_read_pair(HDAPS_PORT_XVAR, HDAPS_PORT_YVAR, &x, &y);
+       if (ret)
+               return ret;
+
+       return sprintf(buf, "(%d,%d)\n", x, y);
+}
+
+static ssize_t hdaps_temp1_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u8 temp;
+       int ret;
+
+       ret = hdaps_readb_one(HDAPS_PORT_TEMP1, &temp);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_temp2_show(struct device *dev,
+                               struct device_attribute *attr, char *buf)
+{
+       u8 temp;
+       int ret;
+
+       ret = hdaps_readb_one(HDAPS_PORT_TEMP2, &temp);
+       if (ret < 0)
+               return ret;
+
+       return sprintf(buf, "%u\n", temp);
+}
+
+static ssize_t hdaps_keyboard_activity_show(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       return sprintf(buf, "%u\n", KEYBD_ISSET(km_activity));
+}
+
+static ssize_t hdaps_mouse_activity_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *buf)
+{
+       return sprintf(buf, "%u\n", MOUSE_ISSET(km_activity));
+}
+
+static ssize_t hdaps_calibrate_show(struct device *dev,
+                                   struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "(%d,%d)\n", rest_x, rest_y);
+}
+
+static ssize_t hdaps_calibrate_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       mutex_lock(&hdaps_mtx);
+       hdaps_calibrate();
+       mutex_unlock(&hdaps_mtx);
+
+       return count;
+}
+
+static ssize_t hdaps_invert_show(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%u\n", hdaps_invert);
+}
+
+static ssize_t hdaps_invert_store(struct device *dev,
+                                 struct device_attribute *attr,
+                                 const char *buf, size_t count)
+{
+       int invert;
+
+       if (sscanf(buf, "%d", &invert) != 1 ||
+           invert < 0 || invert > HDAPS_BOTH_AXES)
+               return -EINVAL;
+
+       hdaps_invert = invert;
+       hdaps_calibrate();
+
+       return count;
+}
+
+static DEVICE_ATTR(position, 0444, hdaps_position_show, NULL);
+static DEVICE_ATTR(variance, 0444, hdaps_variance_show, NULL);
+static DEVICE_ATTR(temp1, 0444, hdaps_temp1_show, NULL);
+static DEVICE_ATTR(temp2, 0444, hdaps_temp2_show, NULL);
+static DEVICE_ATTR(keyboard_activity, 0444, hdaps_keyboard_activity_show, NULL);
+static DEVICE_ATTR(mouse_activity, 0444, hdaps_mouse_activity_show, NULL);
+static DEVICE_ATTR(calibrate, 0644, hdaps_calibrate_show,hdaps_calibrate_store);
+static DEVICE_ATTR(invert, 0644, hdaps_invert_show, hdaps_invert_store);
+
+static struct attribute *hdaps_attributes[] = {
+       &dev_attr_position.attr,
+       &dev_attr_variance.attr,
+       &dev_attr_temp1.attr,
+       &dev_attr_temp2.attr,
+       &dev_attr_keyboard_activity.attr,
+       &dev_attr_mouse_activity.attr,
+       &dev_attr_calibrate.attr,
+       &dev_attr_invert.attr,
+       NULL,
+};
+
+static struct attribute_group hdaps_attribute_group = {
+       .attrs = hdaps_attributes,
+};
+
+
+/* Module stuff */
+
+/* hdaps_dmi_match - found a match.  return one, short-circuiting the hunt. */
+static int __init hdaps_dmi_match(const struct dmi_system_id *id)
+{
+       printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
+       return 1;
+}
+
+/* hdaps_dmi_match_invert - found an inverted match. */
+static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id)
+{
+       hdaps_invert = (unsigned long)id->driver_data;
+       printk(KERN_INFO "hdaps: inverting axis (%u) readings.\n",
+              hdaps_invert);
+       return hdaps_dmi_match(id);
+}
+
+#define HDAPS_DMI_MATCH_INVERT(vendor, model, axes) {  \
+       .ident = vendor " " model,                      \
+       .callback = hdaps_dmi_match_invert,             \
+       .driver_data = (void *)axes,                    \
+       .matches = {                                    \
+               DMI_MATCH(DMI_BOARD_VENDOR, vendor),    \
+               DMI_MATCH(DMI_PRODUCT_VERSION, model)   \
+       }                                               \
+}
+
+#define HDAPS_DMI_MATCH_NORMAL(vendor, model)          \
+       HDAPS_DMI_MATCH_INVERT(vendor, model, 0)
+
+/* Note that HDAPS_DMI_MATCH_NORMAL("ThinkPad T42") would match
+   "ThinkPad T42p", so the order of the entries matters.
+   If your ThinkPad is not recognized, please update to latest
+   BIOS. This is especially the case for some R52 ThinkPads. */
+static struct dmi_system_id __initdata hdaps_whitelist[] = {
+       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad R50p", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
+       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T42"),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T43"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T400", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T60", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61p", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad T61", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad X40"),
+       HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad X41", HDAPS_Y_AXIS),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X60", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61s", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad X61", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad Z60m"),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61m", HDAPS_BOTH_AXES),
+       HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad Z61p", HDAPS_BOTH_AXES),
+       { .ident = NULL }
+};
+
+static int __init hdaps_init(void)
+{
+       struct input_dev *idev;
+       int ret;
+
+       if (!dmi_check_system(hdaps_whitelist)) {
+               printk(KERN_WARNING "hdaps: supported laptop not found!\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       if (!request_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS, "hdaps")) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       ret = platform_driver_register(&hdaps_driver);
+       if (ret)
+               goto out_region;
+
+       pdev = platform_device_register_simple("hdaps", -1, NULL, 0);
+       if (IS_ERR(pdev)) {
+               ret = PTR_ERR(pdev);
+               goto out_driver;
+       }
+
+       ret = sysfs_create_group(&pdev->dev.kobj, &hdaps_attribute_group);
+       if (ret)
+               goto out_device;
+
+       hdaps_idev = input_allocate_polled_device();
+       if (!hdaps_idev) {
+               ret = -ENOMEM;
+               goto out_group;
+       }
+
+       hdaps_idev->poll = hdaps_mousedev_poll;
+       hdaps_idev->poll_interval = HDAPS_POLL_INTERVAL;
+
+       /* initial calibrate for the input device */
+       hdaps_calibrate();
+
+       /* initialize the input class */
+       idev = hdaps_idev->input;
+       idev->name = "hdaps";
+       idev->phys = "isa1600/input0";
+       idev->id.bustype = BUS_ISA;
+       idev->dev.parent = &pdev->dev;
+       idev->evbit[0] = BIT_MASK(EV_ABS);
+       input_set_abs_params(idev, ABS_X,
+                       -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
+       input_set_abs_params(idev, ABS_Y,
+                       -256, 256, HDAPS_INPUT_FUZZ, HDAPS_INPUT_FLAT);
+
+       ret = input_register_polled_device(hdaps_idev);
+       if (ret)
+               goto out_idev;
+
+       printk(KERN_INFO "hdaps: driver successfully loaded.\n");
+       return 0;
+
+out_idev:
+       input_free_polled_device(hdaps_idev);
+out_group:
+       sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
+out_device:
+       platform_device_unregister(pdev);
+out_driver:
+       platform_driver_unregister(&hdaps_driver);
+out_region:
+       release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+out:
+       printk(KERN_WARNING "hdaps: driver init failed (ret=%d)!\n", ret);
+       return ret;
+}
+
+static void __exit hdaps_exit(void)
+{
+       input_unregister_polled_device(hdaps_idev);
+       input_free_polled_device(hdaps_idev);
+       sysfs_remove_group(&pdev->dev.kobj, &hdaps_attribute_group);
+       platform_device_unregister(pdev);
+       platform_driver_unregister(&hdaps_driver);
+       release_region(HDAPS_LOW_PORT, HDAPS_NR_PORTS);
+
+       printk(KERN_INFO "hdaps: driver unloaded.\n");
+}
+
+module_init(hdaps_init);
+module_exit(hdaps_exit);
+
+module_param_named(invert, hdaps_invert, int, 0);
+MODULE_PARM_DESC(invert, "invert data along each axis. 1 invert x-axis, "
+                "2 invert y-axis, 3 invert both axes.");
+
+MODULE_AUTHOR("Robert Love");
+MODULE_DESCRIPTION("IBM Hard Drive Active Protection System (HDAPS) driver");
+MODULE_LICENSE("GPL v2");
index c174114..1dac659 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/platform_device.h>
 #include <linux/acpi.h>
 #include <linux/rfkill.h>
@@ -88,24 +89,16 @@ struct bios_return {
        u32 value;
 };
 
-struct key_entry {
-       char type;              /* See KE_* below */
-       u16 code;
-       u16 keycode;
-};
-
-enum { KE_KEY, KE_END };
-
-static struct key_entry hp_wmi_keymap[] = {
-       {KE_KEY, 0x02, KEY_BRIGHTNESSUP},
-       {KE_KEY, 0x03, KEY_BRIGHTNESSDOWN},
-       {KE_KEY, 0x20e6, KEY_PROG1},
-       {KE_KEY, 0x20e8, KEY_MEDIA},
-       {KE_KEY, 0x2142, KEY_MEDIA},
-       {KE_KEY, 0x213b, KEY_INFO},
-       {KE_KEY, 0x2169, KEY_DIRECTION},
-       {KE_KEY, 0x231b, KEY_HELP},
-       {KE_END, 0}
+static const struct key_entry hp_wmi_keymap[] = {
+       { KE_KEY, 0x02,   { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0x03,   { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0x20e6, { KEY_PROG1 } },
+       { KE_KEY, 0x20e8, { KEY_MEDIA } },
+       { KE_KEY, 0x2142, { KEY_MEDIA } },
+       { KE_KEY, 0x213b, { KEY_INFO } },
+       { KE_KEY, 0x2169, { KEY_DIRECTION } },
+       { KE_KEY, 0x231b, { KEY_HELP } },
+       { KE_END, 0 }
 };
 
 static struct input_dev *hp_wmi_input_dev;
@@ -347,64 +340,9 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als);
 static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL);
 static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL);
 
-static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = hp_wmi_keymap; key->type != KE_END; key++)
-               if (code == key->code)
-                       return key;
-
-       return NULL;
-}
-
-static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode)
-{
-       struct key_entry *key;
-
-       for (key = hp_wmi_keymap; key->type != KE_END; key++)
-               if (key->type == KE_KEY && keycode == key->keycode)
-                       return key;
-
-       return NULL;
-}
-
-static int hp_wmi_getkeycode(struct input_dev *dev,
-                            unsigned int scancode, unsigned int *keycode)
-{
-       struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode);
-
-       if (key && key->type == KE_KEY) {
-               *keycode = key->keycode;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int hp_wmi_setkeycode(struct input_dev *dev,
-                            unsigned int scancode, unsigned int keycode)
-{
-       struct key_entry *key;
-       unsigned int old_keycode;
-
-       key = hp_wmi_get_entry_by_scancode(scancode);
-       if (key && key->type == KE_KEY) {
-               old_keycode = key->keycode;
-               key->keycode = keycode;
-               set_bit(keycode, dev->keybit);
-               if (!hp_wmi_get_entry_by_keycode(old_keycode))
-                       clear_bit(old_keycode, dev->keybit);
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
 static void hp_wmi_notify(u32 value, void *context)
 {
        struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-       static struct key_entry *key;
        union acpi_object *obj;
        u32 event_id, event_data;
        int key_code = 0, ret;
@@ -465,19 +403,9 @@ static void hp_wmi_notify(u32 value, void *context)
                                           sizeof(key_code));
                if (ret)
                        break;
-               key = hp_wmi_get_entry_by_scancode(key_code);
-               if (key) {
-                       switch (key->type) {
-                       case KE_KEY:
-                               input_report_key(hp_wmi_input_dev,
-                                                key->keycode, 1);
-                               input_sync(hp_wmi_input_dev);
-                               input_report_key(hp_wmi_input_dev,
-                                                key->keycode, 0);
-                               input_sync(hp_wmi_input_dev);
-                               break;
-                       }
-               } else
+
+               if (!sparse_keymap_report_event(hp_wmi_input_dev,
+                                               key_code, 1, true))
                        printk(KERN_INFO PREFIX "Unknown key code - 0x%x\n",
                               key_code);
                break;
@@ -510,7 +438,7 @@ static void hp_wmi_notify(u32 value, void *context)
 
 static int __init hp_wmi_input_setup(void)
 {
-       struct key_entry *key;
+       acpi_status status;
        int err;
 
        hp_wmi_input_dev = input_allocate_device();
@@ -520,21 +448,14 @@ static int __init hp_wmi_input_setup(void)
        hp_wmi_input_dev->name = "HP WMI hotkeys";
        hp_wmi_input_dev->phys = "wmi/input0";
        hp_wmi_input_dev->id.bustype = BUS_HOST;
-       hp_wmi_input_dev->getkeycode = hp_wmi_getkeycode;
-       hp_wmi_input_dev->setkeycode = hp_wmi_setkeycode;
-
-       for (key = hp_wmi_keymap; key->type != KE_END; key++) {
-               switch (key->type) {
-               case KE_KEY:
-                       set_bit(EV_KEY, hp_wmi_input_dev->evbit);
-                       set_bit(key->keycode, hp_wmi_input_dev->keybit);
-                       break;
-               }
-       }
 
-       set_bit(EV_SW, hp_wmi_input_dev->evbit);
-       set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
-       set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+       __set_bit(EV_SW, hp_wmi_input_dev->evbit);
+       __set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
+       __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
+
+       err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL);
+       if (err)
+               goto err_free_dev;
 
        /* Set initial hardware state */
        input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state());
@@ -542,14 +463,32 @@ static int __init hp_wmi_input_setup(void)
                            hp_wmi_tablet_state());
        input_sync(hp_wmi_input_dev);
 
-       err = input_register_device(hp_wmi_input_dev);
-
-       if (err) {
-               input_free_device(hp_wmi_input_dev);
-               return err;
+       status = wmi_install_notify_handler(HPWMI_EVENT_GUID, hp_wmi_notify, NULL);
+       if (ACPI_FAILURE(status)) {
+               err = -EIO;
+               goto err_free_keymap;
        }
 
+       err = input_register_device(hp_wmi_input_dev);
+       if (err)
+               goto err_uninstall_notifier;
+
        return 0;
+
+ err_uninstall_notifier:
+       wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+ err_free_keymap:
+       sparse_keymap_free(hp_wmi_input_dev);
+ err_free_dev:
+       input_free_device(hp_wmi_input_dev);
+       return err;
+}
+
+static void hp_wmi_input_destroy(void)
+{
+       wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+       sparse_keymap_free(hp_wmi_input_dev);
+       input_unregister_device(hp_wmi_input_dev);
 }
 
 static void cleanup_sysfs(struct platform_device *device)
@@ -704,15 +643,9 @@ static int __init hp_wmi_init(void)
        int bios_capable = wmi_has_guid(HPWMI_BIOS_GUID);
 
        if (event_capable) {
-               err = wmi_install_notify_handler(HPWMI_EVENT_GUID,
-                                                hp_wmi_notify, NULL);
-               if (ACPI_FAILURE(err))
-                       return -EINVAL;
                err = hp_wmi_input_setup();
-               if (err) {
-                       wmi_remove_notify_handler(HPWMI_EVENT_GUID);
+               if (err)
                        return err;
-               }
        }
 
        if (bios_capable) {
@@ -739,20 +672,17 @@ err_device_add:
 err_device_alloc:
        platform_driver_unregister(&hp_wmi_driver);
 err_driver_reg:
-       if (wmi_has_guid(HPWMI_EVENT_GUID)) {
-               input_unregister_device(hp_wmi_input_dev);
-               wmi_remove_notify_handler(HPWMI_EVENT_GUID);
-       }
+       if (event_capable)
+               hp_wmi_input_destroy();
 
        return err;
 }
 
 static void __exit hp_wmi_exit(void)
 {
-       if (wmi_has_guid(HPWMI_EVENT_GUID)) {
-               wmi_remove_notify_handler(HPWMI_EVENT_GUID);
-               input_unregister_device(hp_wmi_input_dev);
-       }
+       if (wmi_has_guid(HPWMI_EVENT_GUID))
+               hp_wmi_input_destroy();
+
        if (hp_wmi_platform_dev) {
                platform_device_unregister(hp_wmi_platform_dev);
                platform_driver_unregister(&hp_wmi_driver);
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
new file mode 100644 (file)
index 0000000..3c2c6b9
--- /dev/null
@@ -0,0 +1,341 @@
+/*
+ * IBM Real-Time Linux driver
+ *
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2010
+ *
+ * Author: Keith Mannthey <kmannth@us.ibm.com>
+ *         Vernon Mauery <vernux@us.ibm.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/dmi.h>
+#include <linux/mutex.h>
+#include <asm/bios_ebda.h>
+
+static bool force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
+
+static bool debug;
+module_param(debug, bool, 0644);
+MODULE_PARM_DESC(debug, "Show debug output");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>");
+MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>");
+
+#define RTL_ADDR_TYPE_IO    1
+#define RTL_ADDR_TYPE_MMIO  2
+
+#define RTL_CMD_ENTER_PRTM  1
+#define RTL_CMD_EXIT_PRTM   2
+
+/* The RTL table as presented by the EBDA: */
+struct ibm_rtl_table {
+       char signature[5]; /* signature should be "_RTL_" */
+       u8 version;
+       u8 rt_status;
+       u8 command;
+       u8 command_status;
+       u8 cmd_address_type;
+       u8 cmd_granularity;
+       u8 cmd_offset;
+       u16 reserve1;
+       u32 cmd_port_address; /* platform dependent address */
+       u32 cmd_port_value;   /* platform dependent value */
+} __attribute__((packed));
+
+/* to locate "_RTL_" signature do a masked 5-byte integer compare */
+#define RTL_SIGNATURE 0x0000005f4c54525fULL
+#define RTL_MASK      0x000000ffffffffffULL
+
+#define RTL_DEBUG(A, ...) do { \
+       if (debug) \
+               pr_info("ibm-rtl: " A, ##__VA_ARGS__ ); \
+} while (0)
+
+static DEFINE_MUTEX(rtl_lock);
+static struct ibm_rtl_table __iomem *rtl_table;
+static void __iomem *ebda_map;
+static void __iomem *rtl_cmd_addr;
+static u8 rtl_cmd_type;
+static u8 rtl_cmd_width;
+
+static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
+{
+       if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
+               return ioremap(addr, len);
+       return ioport_map(addr, len);
+}
+
+static void rtl_port_unmap(void __iomem *addr)
+{
+       if (addr && rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
+               iounmap(addr);
+       else
+               ioport_unmap(addr);
+}
+
+static int ibm_rtl_write(u8 value)
+{
+       int ret = 0, count = 0;
+       static u32 cmd_port_val;
+
+       RTL_DEBUG("%s(%d)\n", __FUNCTION__, value);
+
+       value = value == 1 ? RTL_CMD_ENTER_PRTM : RTL_CMD_EXIT_PRTM;
+
+       mutex_lock(&rtl_lock);
+
+       if (ioread8(&rtl_table->rt_status) != value) {
+               iowrite8(value, &rtl_table->command);
+
+               switch (rtl_cmd_width) {
+               case 8:
+                       cmd_port_val = ioread8(&rtl_table->cmd_port_value);
+                       RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
+                       iowrite8((u8)cmd_port_val, rtl_cmd_addr);
+                       break;
+               case 16:
+                       cmd_port_val = ioread16(&rtl_table->cmd_port_value);
+                       RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
+                       iowrite16((u16)cmd_port_val, rtl_cmd_addr);
+                       break;
+               case 32:
+                       cmd_port_val = ioread32(&rtl_table->cmd_port_value);
+                       RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
+                       iowrite32(cmd_port_val, rtl_cmd_addr);
+                       break;
+               }
+
+               while (ioread8(&rtl_table->command)) {
+                       msleep(10);
+                       if (count++ > 500) {
+                               pr_err("ibm-rtl: Hardware not responding to "
+                                       "mode switch request\n");
+                               ret = -EIO;
+                               break;
+                       }
+
+               }
+
+               if (ioread8(&rtl_table->command_status)) {
+                       RTL_DEBUG("command_status reports failed command\n");
+                       ret = -EIO;
+               }
+       }
+
+       mutex_unlock(&rtl_lock);
+       return ret;
+}
+
+static ssize_t rtl_show_version(struct sysdev_class * dev,
+                                struct sysdev_class_attribute *attr,
+                                char *buf)
+{
+       return sprintf(buf, "%d\n", (int)ioread8(&rtl_table->version));
+}
+
+static ssize_t rtl_show_state(struct sysdev_class *dev,
+                              struct sysdev_class_attribute *attr,
+                              char *buf)
+{
+       return sprintf(buf, "%d\n", ioread8(&rtl_table->rt_status));
+}
+
+static ssize_t rtl_set_state(struct sysdev_class *dev,
+                             struct sysdev_class_attribute *attr,
+                             const char *buf,
+                             size_t count)
+{
+       ssize_t ret;
+
+       if (count < 1 || count > 2)
+               return -EINVAL;
+
+       switch (buf[0]) {
+       case '0':
+               ret = ibm_rtl_write(0);
+               break;
+       case '1':
+               ret = ibm_rtl_write(1);
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       if (ret >= 0)
+               ret = count;
+
+       return ret;
+}
+
+static struct sysdev_class class_rtl = {
+       .name = "ibm_rtl",
+};
+
+static SYSDEV_CLASS_ATTR(version, S_IRUGO, rtl_show_version, NULL);
+static SYSDEV_CLASS_ATTR(state, 0600, rtl_show_state, rtl_set_state);
+
+static struct sysdev_class_attribute *rtl_attributes[] = {
+       &attr_version,
+       &attr_state,
+       NULL
+};
+
+
+static int rtl_setup_sysfs(void) {
+       int ret, i;
+       ret = sysdev_class_register(&class_rtl);
+
+       if (!ret) {
+               for (i = 0; rtl_attributes[i]; i ++)
+                       sysdev_class_create_file(&class_rtl, rtl_attributes[i]);
+       }
+       return ret;
+}
+
+static void rtl_teardown_sysfs(void) {
+       int i;
+       for (i = 0; rtl_attributes[i]; i ++)
+               sysdev_class_remove_file(&class_rtl, rtl_attributes[i]);
+       sysdev_class_unregister(&class_rtl);
+}
+
+static int dmi_check_cb(const struct dmi_system_id *id)
+{
+       RTL_DEBUG("found IBM server '%s'\n", id->ident);
+       return 0;
+}
+
+#define ibm_dmi_entry(NAME, TYPE)                  \
+{                                                  \
+       .ident = NAME,                             \
+       .matches = {                               \
+               DMI_MATCH(DMI_SYS_VENDOR, "IBM"),  \
+               DMI_MATCH(DMI_PRODUCT_NAME, TYPE), \
+       },                                         \
+       .callback = dmi_check_cb                   \
+}
+
+static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = {
+       ibm_dmi_entry("BladeCenter LS21", "7971"),
+       ibm_dmi_entry("BladeCenter LS22", "7901"),
+       ibm_dmi_entry("BladeCenter HS21 XM", "7995"),
+       ibm_dmi_entry("BladeCenter HS22", "7870"),
+       ibm_dmi_entry("BladeCenter HS22V", "7871"),
+       ibm_dmi_entry("System x3550 M2", "7946"),
+       ibm_dmi_entry("System x3650 M2", "7947"),
+       ibm_dmi_entry("System x3550 M3", "7944"),
+       ibm_dmi_entry("System x3650 M3", "7945"),
+       { }
+};
+
+static int __init ibm_rtl_init(void) {
+       unsigned long ebda_addr, ebda_size;
+       unsigned int ebda_kb;
+       int ret = -ENODEV, i;
+
+       if (force)
+               pr_warning("ibm-rtl: module loaded by force\n");
+       /* first ensure that we are running on IBM HW */
+       else if (!dmi_check_system(ibm_rtl_dmi_table))
+               return -ENODEV;
+
+       /* Get the address for the Extended BIOS Data Area */
+       ebda_addr = get_bios_ebda();
+       if (!ebda_addr) {
+               RTL_DEBUG("no BIOS EBDA found\n");
+               return -ENODEV;
+       }
+
+       ebda_map = ioremap(ebda_addr, 4);
+       if (!ebda_map)
+               return -ENOMEM;
+
+       /* First word in the EDBA is the Size in KB */
+       ebda_kb = ioread16(ebda_map);
+       RTL_DEBUG("EBDA is %d kB\n", ebda_kb);
+
+       if (ebda_kb == 0)
+               goto out;
+
+       iounmap(ebda_map);
+       ebda_size = ebda_kb*1024;
+
+       /* Remap the whole table */
+       ebda_map = ioremap(ebda_addr, ebda_size);
+       if (!ebda_map)
+               return -ENOMEM;
+
+       /* search for the _RTL_ signature at the start of the table */
+       for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
+               struct ibm_rtl_table __iomem * tmp;
+               tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
+               if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
+                       phys_addr_t addr;
+                       unsigned int plen;
+                       RTL_DEBUG("found RTL_SIGNATURE at %#llx\n", (u64)tmp);
+                       rtl_table = tmp;
+                       /* The address, value, width and offset are platform
+                        * dependent and found in the ibm_rtl_table */
+                       rtl_cmd_width = ioread8(&rtl_table->cmd_granularity);
+                       rtl_cmd_type = ioread8(&rtl_table->cmd_address_type);
+                       RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
+                             rtl_cmd_width, rtl_cmd_type);
+                       addr = ioread32(&rtl_table->cmd_port_address);
+                       RTL_DEBUG("addr = %#llx\n", addr);
+                       plen = rtl_cmd_width/sizeof(char);
+                       rtl_cmd_addr = rtl_port_map(addr, plen);
+                       RTL_DEBUG("rtl_cmd_addr = %#llx\n", (u64)rtl_cmd_addr);
+                       if (!rtl_cmd_addr) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       ret = rtl_setup_sysfs();
+                       break;
+               }
+       }
+
+out:
+       if (ret) {
+               iounmap(ebda_map);
+               rtl_port_unmap(rtl_cmd_addr);
+       }
+
+       return ret;
+}
+
+static void __exit ibm_rtl_exit(void)
+{
+       if (rtl_table) {
+               RTL_DEBUG("cleaning up");
+               /* do not leave the machine in SMI-free mode */
+               ibm_rtl_write(0);
+               /* unmap, unlink and remove all traces */
+               rtl_teardown_sysfs();
+               iounmap(ebda_map);
+               rtl_port_unmap(rtl_cmd_addr);
+       }
+}
+
+module_init(ibm_rtl_init);
+module_exit(ibm_rtl_exit);
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
new file mode 100644 (file)
index 0000000..5ff1220
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ *  ideapad_acpi.c - Lenovo IdeaPad ACPI Extras
+ *
+ *  Copyright Â© 2010 Intel Corporation
+ *  Copyright Â© 2010 David Woodhouse <dwmw2@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ *  02110-1301, USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/rfkill.h>
+
+#define IDEAPAD_DEV_CAMERA     0
+#define IDEAPAD_DEV_WLAN       1
+#define IDEAPAD_DEV_BLUETOOTH  2
+#define IDEAPAD_DEV_3G         3
+#define IDEAPAD_DEV_KILLSW     4
+
+struct ideapad_private {
+       acpi_handle handle;
+       struct rfkill *rfk[5];
+} *ideapad_priv;
+
+static struct {
+       char *name;
+       int cfgbit;
+       int opcode;
+       int type;
+} ideapad_rfk_data[] = {
+       { "ideapad_camera",     19, 0x1E, NUM_RFKILL_TYPES },
+       { "ideapad_wlan",       18, 0x15, RFKILL_TYPE_WLAN },
+       { "ideapad_bluetooth",  16, 0x17, RFKILL_TYPE_BLUETOOTH },
+       { "ideapad_3g",         17, 0x20, RFKILL_TYPE_WWAN },
+       { "ideapad_killsw",     0,  0,    RFKILL_TYPE_WLAN }
+};
+
+static bool no_bt_rfkill;
+module_param(no_bt_rfkill, bool, 0444);
+MODULE_PARM_DESC(no_bt_rfkill, "No rfkill for bluetooth.");
+
+/*
+ * ACPI Helpers
+ */
+#define IDEAPAD_EC_TIMEOUT (100) /* in ms */
+
+static int read_method_int(acpi_handle handle, const char *method, int *val)
+{
+       acpi_status status;
+       unsigned long long result;
+
+       status = acpi_evaluate_integer(handle, (char *)method, NULL, &result);
+       if (ACPI_FAILURE(status)) {
+               *val = -1;
+               return -1;
+       } else {
+               *val = result;
+               return 0;
+       }
+}
+
+static int method_vpcr(acpi_handle handle, int cmd, int *ret)
+{
+       acpi_status status;
+       unsigned long long result;
+       struct acpi_object_list params;
+       union acpi_object in_obj;
+
+       params.count = 1;
+       params.pointer = &in_obj;
+       in_obj.type = ACPI_TYPE_INTEGER;
+       in_obj.integer.value = cmd;
+
+       status = acpi_evaluate_integer(handle, "VPCR", &params, &result);
+
+       if (ACPI_FAILURE(status)) {
+               *ret = -1;
+               return -1;
+       } else {
+               *ret = result;
+               return 0;
+       }
+}
+
+static int method_vpcw(acpi_handle handle, int cmd, int data)
+{
+       struct acpi_object_list params;
+       union acpi_object in_obj[2];
+       acpi_status status;
+
+       params.count = 2;
+       params.pointer = in_obj;
+       in_obj[0].type = ACPI_TYPE_INTEGER;
+       in_obj[0].integer.value = cmd;
+       in_obj[1].type = ACPI_TYPE_INTEGER;
+       in_obj[1].integer.value = data;
+
+       status = acpi_evaluate_object(handle, "VPCW", &params, NULL);
+       if (status != AE_OK)
+               return -1;
+       return 0;
+}
+
+static int read_ec_data(acpi_handle handle, int cmd, unsigned long *data)
+{
+       int val;
+       unsigned long int end_jiffies;
+
+       if (method_vpcw(handle, 1, cmd))
+               return -1;
+
+       for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
+            time_before(jiffies, end_jiffies);) {
+               schedule();
+               if (method_vpcr(handle, 1, &val))
+                       return -1;
+               if (val == 0) {
+                       if (method_vpcr(handle, 0, &val))
+                               return -1;
+                       *data = val;
+                       return 0;
+               }
+       }
+       pr_err("timeout in read_ec_cmd\n");
+       return -1;
+}
+
+static int write_ec_cmd(acpi_handle handle, int cmd, unsigned long data)
+{
+       int val;
+       unsigned long int end_jiffies;
+
+       if (method_vpcw(handle, 0, data))
+               return -1;
+       if (method_vpcw(handle, 1, cmd))
+               return -1;
+
+       for (end_jiffies = jiffies+(HZ)*IDEAPAD_EC_TIMEOUT/1000+1;
+            time_before(jiffies, end_jiffies);) {
+               schedule();
+               if (method_vpcr(handle, 1, &val))
+                       return -1;
+               if (val == 0)
+                       return 0;
+       }
+       pr_err("timeout in write_ec_cmd\n");
+       return -1;
+}
+/* the above is ACPI helpers */
+
+static ssize_t show_ideapad_cam(struct device *dev,
+                               struct device_attribute *attr,
+                               char *buf)
+{
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+       acpi_handle handle = priv->handle;
+       unsigned long result;
+
+       if (read_ec_data(handle, 0x1D, &result))
+               return sprintf(buf, "-1\n");
+       return sprintf(buf, "%lu\n", result);
+}
+
+static ssize_t store_ideapad_cam(struct device *dev,
+                                struct device_attribute *attr,
+                                const char *buf, size_t count)
+{
+       struct ideapad_private *priv = dev_get_drvdata(dev);
+       acpi_handle handle = priv->handle;
+       int ret, state;
+
+       if (!count)
+               return 0;
+       if (sscanf(buf, "%i", &state) != 1)
+               return -EINVAL;
+       ret = write_ec_cmd(handle, 0x1E, state);
+       if (ret < 0)
+               return ret;
+       return count;
+}
+
+static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
+
+static int ideapad_rfk_set(void *data, bool blocked)
+{
+       int device = (unsigned long)data;
+
+       if (device == IDEAPAD_DEV_KILLSW)
+               return -EINVAL;
+
+       return write_ec_cmd(ideapad_priv->handle,
+                           ideapad_rfk_data[device].opcode,
+                           !blocked);
+}
+
+static struct rfkill_ops ideapad_rfk_ops = {
+       .set_block = ideapad_rfk_set,
+};
+
+static void ideapad_sync_rfk_state(struct acpi_device *adevice)
+{
+       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
+       acpi_handle handle = priv->handle;
+       unsigned long hw_blocked;
+       int i;
+
+       if (read_ec_data(handle, 0x23, &hw_blocked))
+               return;
+       hw_blocked = !hw_blocked;
+
+       for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++)
+               if (priv->rfk[i])
+                       rfkill_set_hw_state(priv->rfk[i], hw_blocked);
+}
+
+static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
+{
+       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
+       int ret;
+       unsigned long sw_blocked;
+
+       if (no_bt_rfkill &&
+           (ideapad_rfk_data[dev].type == RFKILL_TYPE_BLUETOOTH)) {
+               /* Force to enable bluetooth when no_bt_rfkill=1 */
+               write_ec_cmd(ideapad_priv->handle,
+                            ideapad_rfk_data[dev].opcode, 1);
+               return 0;
+       }
+
+       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev].name, &adevice->dev,
+                                     ideapad_rfk_data[dev].type, &ideapad_rfk_ops,
+                                     (void *)(long)dev);
+       if (!priv->rfk[dev])
+               return -ENOMEM;
+
+       if (read_ec_data(ideapad_priv->handle, ideapad_rfk_data[dev].opcode-1,
+                        &sw_blocked)) {
+               rfkill_init_sw_state(priv->rfk[dev], 0);
+       } else {
+               sw_blocked = !sw_blocked;
+               rfkill_init_sw_state(priv->rfk[dev], sw_blocked);
+       }
+
+       ret = rfkill_register(priv->rfk[dev]);
+       if (ret) {
+               rfkill_destroy(priv->rfk[dev]);
+               return ret;
+       }
+       return 0;
+}
+
+static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
+{
+       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
+
+       if (!priv->rfk[dev])
+               return;
+
+       rfkill_unregister(priv->rfk[dev]);
+       rfkill_destroy(priv->rfk[dev]);
+}
+
+static const struct acpi_device_id ideapad_device_ids[] = {
+       { "VPC2004", 0},
+       { "", 0},
+};
+MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
+
+static int ideapad_acpi_add(struct acpi_device *adevice)
+{
+       int i, cfg;
+       int devs_present[5];
+       struct ideapad_private *priv;
+
+       if (read_method_int(adevice->handle, "_CFG", &cfg))
+               return -ENODEV;
+
+       for (i = IDEAPAD_DEV_CAMERA; i < IDEAPAD_DEV_KILLSW; i++) {
+               if (test_bit(ideapad_rfk_data[i].cfgbit, (unsigned long *)&cfg))
+                       devs_present[i] = 1;
+               else
+                       devs_present[i] = 0;
+       }
+
+       /* The hardware switch is always present */
+       devs_present[IDEAPAD_DEV_KILLSW] = 1;
+
+       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       if (devs_present[IDEAPAD_DEV_CAMERA]) {
+               int ret = device_create_file(&adevice->dev, &dev_attr_camera_power);
+               if (ret) {
+                       kfree(priv);
+                       return ret;
+               }
+       }
+
+       priv->handle = adevice->handle;
+       dev_set_drvdata(&adevice->dev, priv);
+       ideapad_priv = priv;
+       for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) {
+               if (!devs_present[i])
+                       continue;
+
+               ideapad_register_rfkill(adevice, i);
+       }
+       ideapad_sync_rfk_state(adevice);
+       return 0;
+}
+
+static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
+{
+       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
+       int i;
+
+       device_remove_file(&adevice->dev, &dev_attr_camera_power);
+
+       for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++)
+               ideapad_unregister_rfkill(adevice, i);
+
+       dev_set_drvdata(&adevice->dev, NULL);
+       kfree(priv);
+       return 0;
+}
+
+static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
+{
+       acpi_handle handle = adevice->handle;
+       unsigned long vpc1, vpc2, vpc_bit;
+
+       if (read_ec_data(handle, 0x10, &vpc1))
+               return;
+       if (read_ec_data(handle, 0x1A, &vpc2))
+               return;
+
+       vpc1 = (vpc2 << 8) | vpc1;
+       for (vpc_bit = 0; vpc_bit < 16; vpc_bit++) {
+               if (test_bit(vpc_bit, &vpc1)) {
+                       if (vpc_bit == 9)
+                               ideapad_sync_rfk_state(adevice);
+               }
+       }
+}
+
+static struct acpi_driver ideapad_acpi_driver = {
+       .name = "ideapad_acpi",
+       .class = "IdeaPad",
+       .ids = ideapad_device_ids,
+       .ops.add = ideapad_acpi_add,
+       .ops.remove = ideapad_acpi_remove,
+       .ops.notify = ideapad_acpi_notify,
+       .owner = THIS_MODULE,
+};
+
+
+static int __init ideapad_acpi_module_init(void)
+{
+       acpi_bus_register_driver(&ideapad_acpi_driver);
+
+       return 0;
+}
+
+
+static void __exit ideapad_acpi_module_exit(void)
+{
+       acpi_bus_unregister_driver(&ideapad_acpi_driver);
+
+}
+
+MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
+MODULE_DESCRIPTION("IdeaPad ACPI Extras");
+MODULE_LICENSE("GPL");
+
+module_init(ideapad_acpi_module_init);
+module_exit(ideapad_acpi_module_exit);
diff --git a/drivers/platform/x86/ideapad_acpi.c b/drivers/platform/x86/ideapad_acpi.c
deleted file mode 100644 (file)
index 7984963..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- *  ideapad_acpi.c - Lenovo IdeaPad ACPI Extras
- *
- *  Copyright Â© 2010 Intel Corporation
- *  Copyright Â© 2010 David Woodhouse <dwmw2@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.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- *  02110-1301, USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
-#include <linux/rfkill.h>
-
-#define IDEAPAD_DEV_CAMERA     0
-#define IDEAPAD_DEV_WLAN       1
-#define IDEAPAD_DEV_BLUETOOTH  2
-#define IDEAPAD_DEV_3G         3
-#define IDEAPAD_DEV_KILLSW     4
-
-struct ideapad_private {
-       struct rfkill *rfk[5];
-};
-
-static struct {
-       char *name;
-       int type;
-} ideapad_rfk_data[] = {
-       /* camera has no rfkill */
-       { "ideapad_wlan",       RFKILL_TYPE_WLAN },
-       { "ideapad_bluetooth",  RFKILL_TYPE_BLUETOOTH },
-       { "ideapad_3g",         RFKILL_TYPE_WWAN },
-       { "ideapad_killsw",     RFKILL_TYPE_WLAN }
-};
-
-static int ideapad_dev_exists(int device)
-{
-       acpi_status status;
-       union acpi_object in_param;
-       struct acpi_object_list input = { 1, &in_param };
-       struct acpi_buffer output;
-       union acpi_object out_obj;
-
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
-
-       in_param.type = ACPI_TYPE_INTEGER;
-       in_param.integer.value = device + 1;
-
-       status = acpi_evaluate_object(NULL, "\\_SB_.DECN", &input, &output);
-       if (ACPI_FAILURE(status)) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method failed %d. Is this an IdeaPAD?\n", status);
-               return -ENODEV;
-       }
-       if (out_obj.type != ACPI_TYPE_INTEGER) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.DECN method returned unexpected type\n");
-               return -ENODEV;
-       }
-       return out_obj.integer.value;
-}
-
-static int ideapad_dev_get_state(int device)
-{
-       acpi_status status;
-       union acpi_object in_param;
-       struct acpi_object_list input = { 1, &in_param };
-       struct acpi_buffer output;
-       union acpi_object out_obj;
-
-       output.length = sizeof(out_obj);
-       output.pointer = &out_obj;
-
-       in_param.type = ACPI_TYPE_INTEGER;
-       in_param.integer.value = device + 1;
-
-       status = acpi_evaluate_object(NULL, "\\_SB_.GECN", &input, &output);
-       if (ACPI_FAILURE(status)) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method failed %d\n", status);
-               return -ENODEV;
-       }
-       if (out_obj.type != ACPI_TYPE_INTEGER) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.GECN method returned unexpected type\n");
-               return -ENODEV;
-       }
-       return out_obj.integer.value;
-}
-
-static int ideapad_dev_set_state(int device, int state)
-{
-       acpi_status status;
-       union acpi_object in_params[2];
-       struct acpi_object_list input = { 2, in_params };
-
-       in_params[0].type = ACPI_TYPE_INTEGER;
-       in_params[0].integer.value = device + 1;
-       in_params[1].type = ACPI_TYPE_INTEGER;
-       in_params[1].integer.value = state;
-
-       status = acpi_evaluate_object(NULL, "\\_SB_.SECN", &input, NULL);
-       if (ACPI_FAILURE(status)) {
-               printk(KERN_WARNING "IdeaPAD \\_SB_.SECN method failed %d\n", status);
-               return -ENODEV;
-       }
-       return 0;
-}
-static ssize_t show_ideapad_cam(struct device *dev,
-                               struct device_attribute *attr,
-                               char *buf)
-{
-       int state = ideapad_dev_get_state(IDEAPAD_DEV_CAMERA);
-       if (state < 0)
-               return state;
-
-       return sprintf(buf, "%d\n", state);
-}
-
-static ssize_t store_ideapad_cam(struct device *dev,
-                                struct device_attribute *attr,
-                                const char *buf, size_t count)
-{
-       int ret, state;
-
-       if (!count)
-               return 0;
-       if (sscanf(buf, "%i", &state) != 1)
-               return -EINVAL;
-       ret = ideapad_dev_set_state(IDEAPAD_DEV_CAMERA, !!state);
-       if (ret < 0)
-               return ret;
-       return count;
-}
-
-static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
-
-static int ideapad_rfk_set(void *data, bool blocked)
-{
-       int device = (unsigned long)data;
-
-       if (device == IDEAPAD_DEV_KILLSW)
-               return -EINVAL;
-       return ideapad_dev_set_state(device, !blocked);
-}
-
-static struct rfkill_ops ideapad_rfk_ops = {
-       .set_block = ideapad_rfk_set,
-};
-
-static void ideapad_sync_rfk_state(struct acpi_device *adevice)
-{
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-       int hw_blocked = !ideapad_dev_get_state(IDEAPAD_DEV_KILLSW);
-       int i;
-
-       rfkill_set_hw_state(priv->rfk[IDEAPAD_DEV_KILLSW], hw_blocked);
-       for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++)
-               if (priv->rfk[i])
-                       rfkill_set_hw_state(priv->rfk[i], hw_blocked);
-       if (hw_blocked)
-               return;
-
-       for (i = IDEAPAD_DEV_WLAN; i < IDEAPAD_DEV_KILLSW; i++)
-               if (priv->rfk[i])
-                       rfkill_set_sw_state(priv->rfk[i], !ideapad_dev_get_state(i));
-}
-
-static int ideapad_register_rfkill(struct acpi_device *adevice, int dev)
-{
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-       int ret;
-
-       priv->rfk[dev] = rfkill_alloc(ideapad_rfk_data[dev-1].name, &adevice->dev,
-                                     ideapad_rfk_data[dev-1].type, &ideapad_rfk_ops,
-                                     (void *)(long)dev);
-       if (!priv->rfk[dev])
-               return -ENOMEM;
-
-       ret = rfkill_register(priv->rfk[dev]);
-       if (ret) {
-               rfkill_destroy(priv->rfk[dev]);
-               return ret;
-       }
-       return 0;
-}
-
-static void ideapad_unregister_rfkill(struct acpi_device *adevice, int dev)
-{
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-
-       if (!priv->rfk[dev])
-               return;
-
-       rfkill_unregister(priv->rfk[dev]);
-       rfkill_destroy(priv->rfk[dev]);
-}
-
-static const struct acpi_device_id ideapad_device_ids[] = {
-       { "VPC2004", 0},
-       { "", 0},
-};
-MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
-
-static int ideapad_acpi_add(struct acpi_device *adevice)
-{
-       int i;
-       int devs_present[5];
-       struct ideapad_private *priv;
-
-       for (i = IDEAPAD_DEV_CAMERA; i < IDEAPAD_DEV_KILLSW; i++) {
-               devs_present[i] = ideapad_dev_exists(i);
-               if (devs_present[i] < 0)
-                       return devs_present[i];
-       }
-
-       /* The hardware switch is always present */
-       devs_present[IDEAPAD_DEV_KILLSW] = 1;
-
-       priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       if (devs_present[IDEAPAD_DEV_CAMERA]) {
-               int ret = device_create_file(&adevice->dev, &dev_attr_camera_power);
-               if (ret) {
-                       kfree(priv);
-                       return ret;
-               }
-       }
-
-       dev_set_drvdata(&adevice->dev, priv);
-       for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++) {
-               if (!devs_present[i])
-                       continue;
-
-               ideapad_register_rfkill(adevice, i);
-       }
-       ideapad_sync_rfk_state(adevice);
-       return 0;
-}
-
-static int ideapad_acpi_remove(struct acpi_device *adevice, int type)
-{
-       struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
-       int i;
-
-       device_remove_file(&adevice->dev, &dev_attr_camera_power);
-
-       for (i = IDEAPAD_DEV_WLAN; i <= IDEAPAD_DEV_KILLSW; i++)
-               ideapad_unregister_rfkill(adevice, i);
-
-       dev_set_drvdata(&adevice->dev, NULL);
-       kfree(priv);
-       return 0;
-}
-
-static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
-{
-       ideapad_sync_rfk_state(adevice);
-}
-
-static struct acpi_driver ideapad_acpi_driver = {
-       .name = "ideapad_acpi",
-       .class = "IdeaPad",
-       .ids = ideapad_device_ids,
-       .ops.add = ideapad_acpi_add,
-       .ops.remove = ideapad_acpi_remove,
-       .ops.notify = ideapad_acpi_notify,
-       .owner = THIS_MODULE,
-};
-
-
-static int __init ideapad_acpi_module_init(void)
-{
-       acpi_bus_register_driver(&ideapad_acpi_driver);
-
-       return 0;
-}
-
-
-static void __exit ideapad_acpi_module_exit(void)
-{
-       acpi_bus_unregister_driver(&ideapad_acpi_driver);
-
-}
-
-MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
-MODULE_DESCRIPTION("IdeaPad ACPI Extras");
-MODULE_LICENSE("GPL");
-
-module_init(ideapad_acpi_module_init);
-module_exit(ideapad_acpi_module_exit);
index 5cdcff6..f540ff9 100644 (file)
@@ -142,16 +142,16 @@ static int pmic_gpio_direction_output(struct gpio_chip *chip,
 
        if (offset < 8)/* it is GPIO */
                rc = intel_scu_ipc_update_register(GPIO0 + offset,
-                               GPIO_DRV | GPIO_DOU | GPIO_DIR,
-                               GPIO_DRV | (value ? GPIO_DOU : 0));
+                               GPIO_DRV | (value ? GPIO_DOU : 0),
+                               GPIO_DRV | GPIO_DOU | GPIO_DIR);
        else if (offset < 16)/* it is GPOSW */
                rc = intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
-                               GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV,
-                               GPOSW_DRV | (value ? GPOSW_DOU : 0));
+                               GPOSW_DRV | (value ? GPOSW_DOU : 0),
+                               GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
        else if (offset > 15 && offset < 24)/* it is GPO */
                rc = intel_scu_ipc_update_register(GPO,
-                               1 << (offset - 16),
-                               value ? 1 << (offset - 16) : 0);
+                               value ? 1 << (offset - 16) : 0,
+                               1 << (offset - 16));
        else {
                printk(KERN_ERR
                        "%s: invalid PMIC GPIO pin %d!\n", __func__, offset);
@@ -179,16 +179,16 @@ static void pmic_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 {
        if (offset < 8)/* it is GPIO */
                intel_scu_ipc_update_register(GPIO0 + offset,
-                       GPIO_DRV | GPIO_DOU,
-                       GPIO_DRV | (value ? GPIO_DOU : 0));
+                       GPIO_DRV | (value ? GPIO_DOU : 0),
+                       GPIO_DRV | GPIO_DOU);
        else if (offset < 16)/* it is GPOSW */
                intel_scu_ipc_update_register(GPOSWCTL0 + offset - 8,
-                       GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV,
-                       GPOSW_DRV | (value ? GPOSW_DOU : 0));
+                       GPOSW_DRV | (value ? GPOSW_DOU : 0),
+                       GPOSW_DRV | GPOSW_DOU | GPOSW_RDRV);
        else if (offset > 15 && offset < 24) /* it is GPO */
                intel_scu_ipc_update_register(GPO,
-                       1 << (offset - 16),
-                       value ? 1 << (offset - 16) : 0);
+                       value ? 1 << (offset - 16) : 0,
+                       1 << (offset - 16));
 }
 
 static int pmic_irq_type(unsigned irq, unsigned type)
@@ -197,7 +197,7 @@ static int pmic_irq_type(unsigned irq, unsigned type)
        u32 gpio = irq - pg->irq_base;
        unsigned long flags;
 
-       if (gpio > pg->chip.ngpio)
+       if (gpio >= pg->chip.ngpio)
                return -EINVAL;
 
        spin_lock_irqsave(&pg->irqtypes.lock, flags);
index 6abe18e..41a9e34 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/pm.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/sfi.h>
 #include <asm/mrst.h>
 #include <asm/intel_scu_ipc.h>
 
index ec01c3d..cc1e0ba 100644 (file)
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 
 #ifndef ACPI_HOTKEY_COMPONENT
@@ -200,30 +201,29 @@ static struct acpi_driver acpi_pcc_driver = {
                        },
 };
 
-#define KEYMAP_SIZE            11
-static const unsigned int initial_keymap[KEYMAP_SIZE] = {
-       /*  0 */ KEY_RESERVED,
-       /*  1 */ KEY_BRIGHTNESSDOWN,
-       /*  2 */ KEY_BRIGHTNESSUP,
-       /*  3 */ KEY_DISPLAYTOGGLE,
-       /*  4 */ KEY_MUTE,
-       /*  5 */ KEY_VOLUMEDOWN,
-       /*  6 */ KEY_VOLUMEUP,
-       /*  7 */ KEY_SLEEP,
-       /*  8 */ KEY_PROG1, /* Change CPU boost */
-       /*  9 */ KEY_BATTERY,
-       /* 10 */ KEY_SUSPEND,
+static const struct key_entry panasonic_keymap[] = {
+       { KE_KEY, 0, { KEY_RESERVED } },
+       { KE_KEY, 1, { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 2, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 3, { KEY_DISPLAYTOGGLE } },
+       { KE_KEY, 4, { KEY_MUTE } },
+       { KE_KEY, 5, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 6, { KEY_VOLUMEUP } },
+       { KE_KEY, 7, { KEY_SLEEP } },
+       { KE_KEY, 8, { KEY_PROG1 } }, /* Change CPU boost */
+       { KE_KEY, 9, { KEY_BATTERY } },
+       { KE_KEY, 10, { KEY_SUSPEND } },
+       { KE_END, 0 }
 };
 
 struct pcc_acpi {
        acpi_handle             handle;
        unsigned long           num_sifr;
        int                     sticky_mode;
-       u32                     *sinf;
+       u32                     *sinf;
        struct acpi_device      *device;
        struct input_dev        *input_dev;
        struct backlight_device *backlight;
-       unsigned int            keymap[KEYMAP_SIZE];
 };
 
 struct pcc_keyinput {
@@ -267,7 +267,7 @@ static inline int acpi_pcc_get_sqty(struct acpi_device *device)
        }
 }
 
-static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
+static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc)
 {
        acpi_status status;
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
@@ -285,6 +285,7 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
        hkey = buffer.pointer;
        if (!hkey || (hkey->type != ACPI_TYPE_PACKAGE)) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid HKEY.SINF\n"));
+               status = AE_ERROR;
                goto end;
        }
 
@@ -298,12 +299,12 @@ static int acpi_pcc_retrieve_biosdata(struct pcc_acpi *pcc, u32 *sinf)
        for (i = 0; i < hkey->package.count; i++) {
                union acpi_object *element = &(hkey->package.elements[i]);
                if (likely(element->type == ACPI_TYPE_INTEGER)) {
-                       sinf[i] = element->integer.value;
+                       pcc->sinf[i] = element->integer.value;
                } else
                        ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                         "Invalid HKEY.SINF data\n"));
        }
-       sinf[hkey->package.count] = -1;
+       pcc->sinf[hkey->package.count] = -1;
 
 end:
        kfree(buffer.pointer);
@@ -321,7 +322,7 @@ static int bl_get(struct backlight_device *bd)
 {
        struct pcc_acpi *pcc = bl_get_data(bd);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return pcc->sinf[SINF_AC_CUR_BRIGHT];
@@ -333,7 +334,7 @@ static int bl_set_status(struct backlight_device *bd)
        int bright = bd->props.brightness;
        int rc;
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        if (bright < pcc->sinf[SINF_AC_MIN_BRIGHT])
@@ -367,7 +368,7 @@ static ssize_t show_numbatt(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_NUM_BATTERIES]);
@@ -379,7 +380,7 @@ static ssize_t show_lcdtype(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_LCD_TYPE]);
@@ -391,7 +392,7 @@ static ssize_t show_mute(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_MUTE]);
@@ -403,7 +404,7 @@ static ssize_t show_sticky(struct device *dev, struct device_attribute *attr,
        struct acpi_device *acpi = to_acpi_device(dev);
        struct pcc_acpi *pcc = acpi_driver_data(acpi);
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf))
+       if (!acpi_pcc_retrieve_biosdata(pcc))
                return -EIO;
 
        return snprintf(buf, PAGE_SIZE, "%u\n", pcc->sinf[SINF_STICKY_KEY]);
@@ -446,56 +447,10 @@ static struct attribute_group pcc_attr_group = {
 
 /* hotkey input device driver */
 
-static int pcc_getkeycode(struct input_dev *dev,
-                         unsigned int scancode, unsigned int *keycode)
-{
-       struct pcc_acpi *pcc = input_get_drvdata(dev);
-
-       if (scancode >= ARRAY_SIZE(pcc->keymap))
-               return -EINVAL;
-
-       *keycode = pcc->keymap[scancode];
-
-       return 0;
-}
-
-static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++) {
-               if (pcc->keymap[i] == keycode)
-                       return i+1;
-       }
-
-       return 0;
-}
-
-static int pcc_setkeycode(struct input_dev *dev,
-                         unsigned int scancode, unsigned int keycode)
-{
-       struct pcc_acpi *pcc = input_get_drvdata(dev);
-       int oldkeycode;
-
-       if (scancode >= ARRAY_SIZE(pcc->keymap))
-               return -EINVAL;
-
-       oldkeycode = pcc->keymap[scancode];
-       pcc->keymap[scancode] = keycode;
-
-       set_bit(keycode, dev->keybit);
-
-       if (!keymap_get_by_keycode(pcc, oldkeycode))
-               clear_bit(oldkeycode, dev->keybit);
-
-       return 0;
-}
-
 static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 {
        struct input_dev *hotk_input_dev = pcc->input_dev;
        int rc;
-       int key_code, hkey_num;
        unsigned long long result;
 
        rc = acpi_evaluate_integer(pcc->handle, METHOD_HKEY_QUERY,
@@ -508,25 +463,10 @@ static void acpi_pcc_generate_keyinput(struct pcc_acpi *pcc)
 
        acpi_bus_generate_proc_event(pcc->device, HKEY_NOTIFY, result);
 
-       hkey_num = result & 0xf;
-
-       if (hkey_num < 0 || hkey_num >= ARRAY_SIZE(pcc->keymap)) {
+       if (!sparse_keymap_report_event(hotk_input_dev,
+                                       result & 0xf, result & 0x80, false))
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
-                                 "hotkey number out of range: %d\n",
-                                 hkey_num));
-               return;
-       }
-
-       key_code = pcc->keymap[hkey_num];
-
-       if (key_code != KEY_RESERVED) {
-               int pushed = (result & 0x80) ? TRUE : FALSE;
-
-               input_report_key(hotk_input_dev, key_code, pushed);
-               input_sync(hotk_input_dev);
-       }
-
-       return;
+                                 "Unknown hotkey event: %d\n", result));
 }
 
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
@@ -545,40 +485,55 @@ static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event)
 
 static int acpi_pcc_init_input(struct pcc_acpi *pcc)
 {
-       int i, rc;
+       struct input_dev *input_dev;
+       int error;
 
-       pcc->input_dev = input_allocate_device();
-       if (!pcc->input_dev) {
+       input_dev = input_allocate_device();
+       if (!input_dev) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Couldn't allocate input device for hotkey"));
                return -ENOMEM;
        }
 
-       pcc->input_dev->evbit[0] = BIT(EV_KEY);
-
-       pcc->input_dev->name = ACPI_PCC_DRIVER_NAME;
-       pcc->input_dev->phys = ACPI_PCC_INPUT_PHYS;
-       pcc->input_dev->id.bustype = BUS_HOST;
-       pcc->input_dev->id.vendor = 0x0001;
-       pcc->input_dev->id.product = 0x0001;
-       pcc->input_dev->id.version = 0x0100;
-       pcc->input_dev->getkeycode = pcc_getkeycode;
-       pcc->input_dev->setkeycode = pcc_setkeycode;
+       input_dev->name = ACPI_PCC_DRIVER_NAME;
+       input_dev->phys = ACPI_PCC_INPUT_PHYS;
+       input_dev->id.bustype = BUS_HOST;
+       input_dev->id.vendor = 0x0001;
+       input_dev->id.product = 0x0001;
+       input_dev->id.version = 0x0100;
 
-       /* load initial keymap */
-       memcpy(pcc->keymap, initial_keymap, sizeof(pcc->keymap));
+       error = sparse_keymap_setup(input_dev, panasonic_keymap, NULL);
+       if (error) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Unable to setup input device keymap\n"));
+               goto err_free_dev;
+       }
 
-       for (i = 0; i < ARRAY_SIZE(pcc->keymap); i++)
-               __set_bit(pcc->keymap[i], pcc->input_dev->keybit);
-       __clear_bit(KEY_RESERVED, pcc->input_dev->keybit);
+       error = input_register_device(input_dev);
+       if (error) {
+               ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
+                                 "Unable to register input device\n"));
+               goto err_free_keymap;
+       }
 
-       input_set_drvdata(pcc->input_dev, pcc);
+       pcc->input_dev = input_dev;
+       return 0;
 
-       rc = input_register_device(pcc->input_dev);
-       if (rc < 0)
-               input_free_device(pcc->input_dev);
+ err_free_keymap:
+       sparse_keymap_free(input_dev);
+ err_free_dev:
+       input_free_device(input_dev);
+       return error;
+}
 
-       return rc;
+static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
+{
+       sparse_keymap_free(pcc->input_dev);
+       input_unregister_device(pcc->input_dev);
+       /*
+        * No need to input_free_device() since core input API refcounts
+        * and free()s the device.
+        */
 }
 
 /* kernel module interface */
@@ -636,12 +591,13 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
        if (result) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                  "Error installing keyinput handler\n"));
-               goto out_hotkey;
+               goto out_sinf;
        }
 
-       if (!acpi_pcc_retrieve_biosdata(pcc, pcc->sinf)) {
+       if (!acpi_pcc_retrieve_biosdata(pcc)) {
                ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
                                 "Couldn't retrieve BIOS data\n"));
+               result = -EIO;
                goto out_input;
        }
        /* initialize backlight */
@@ -651,7 +607,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
                                                   &pcc_backlight_ops, &props);
        if (IS_ERR(pcc->backlight)) {
                result = PTR_ERR(pcc->backlight);
-               goto out_sinf;
+               goto out_input;
        }
 
        /* read the initial brightness setting from the hardware */
@@ -669,12 +625,10 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
 
 out_backlight:
        backlight_device_unregister(pcc->backlight);
+out_input:
+       acpi_pcc_destroy_input(pcc);
 out_sinf:
        kfree(pcc->sinf);
-out_input:
-       input_unregister_device(pcc->input_dev);
-       /* no need to input_free_device() since core input API refcount and
-        * free()s the device */
 out_hotkey:
        kfree(pcc);
 
@@ -709,9 +663,7 @@ static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type)
 
        backlight_device_unregister(pcc->backlight);
 
-       input_unregister_device(pcc->input_dev);
-       /* no need to input_free_device() since core input API refcount and
-        * free()s the device */
+       acpi_pcc_destroy_input(pcc);
 
        kfree(pcc->sinf);
        kfree(pcc);
index ff4b476..1d07d6d 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/acpi.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 #define ACPI_TOPSTAR_CLASS "topstar"
 
@@ -26,52 +27,37 @@ struct topstar_hkey {
        struct input_dev *inputdev;
 };
 
-struct tps_key_entry {
-       u8 code;
-       u16 keycode;
-};
-
-static struct tps_key_entry topstar_keymap[] = {
-       { 0x80, KEY_BRIGHTNESSUP },
-       { 0x81, KEY_BRIGHTNESSDOWN },
-       { 0x83, KEY_VOLUMEUP },
-       { 0x84, KEY_VOLUMEDOWN },
-       { 0x85, KEY_MUTE },
-       { 0x86, KEY_SWITCHVIDEOMODE },
-       { 0x87, KEY_F13 }, /* touchpad enable/disable key */
-       { 0x88, KEY_WLAN },
-       { 0x8a, KEY_WWW },
-       { 0x8b, KEY_MAIL },
-       { 0x8c, KEY_MEDIA },
-       { 0x96, KEY_F14 }, /* G key? */
-       { }
-};
-
-static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code)
-{
-       struct tps_key_entry *key;
-
-       for (key = topstar_keymap; key->code; key++)
-               if (code == key->code)
-                       return key;
+static const struct key_entry topstar_keymap[] = {
+       { KE_KEY, 0x80, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0x81, { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0x83, { KEY_VOLUMEUP } },
+       { KE_KEY, 0x84, { KEY_VOLUMEDOWN } },
+       { KE_KEY, 0x85, { KEY_MUTE } },
+       { KE_KEY, 0x86, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x87, { KEY_F13 } }, /* touchpad enable/disable key */
+       { KE_KEY, 0x88, { KEY_WLAN } },
+       { KE_KEY, 0x8a, { KEY_WWW } },
+       { KE_KEY, 0x8b, { KEY_MAIL } },
+       { KE_KEY, 0x8c, { KEY_MEDIA } },
 
-       return NULL;
-}
-
-static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code)
-{
-       struct tps_key_entry *key;
+       /* Known non hotkey events don't handled or that we don't care yet */
+       { KE_IGNORE, 0x8e, },
+       { KE_IGNORE, 0x8f, },
+       { KE_IGNORE, 0x90, },
 
-       for (key = topstar_keymap; key->code; key++)
-               if (code == key->keycode)
-                       return key;
+       /*
+        * 'G key' generate two event codes, convert to only
+        * one event/key code for now, consider replacing by
+        * a switch (3G switch - SW_3G?)
+        */
+       { KE_KEY, 0x96, { KEY_F14 } },
+       { KE_KEY, 0x97, { KEY_F14 } },
 
-       return NULL;
-}
+       { KE_END, 0 }
+};
 
 static void acpi_topstar_notify(struct acpi_device *device, u32 event)
 {
-       struct tps_key_entry *key;
        static bool dup_evnt[2];
        bool *dup;
        struct topstar_hkey *hkey = acpi_driver_data(device);
@@ -86,27 +72,8 @@ static void acpi_topstar_notify(struct acpi_device *device, u32 event)
                *dup = true;
        }
 
-       /*
-        * 'G key' generate two event codes, convert to only
-        * one event/key code for now (3G switch?)
-        */
-       if (event == 0x97)
-               event = 0x96;
-
-       key = tps_get_key_by_scancode(event);
-       if (key) {
-               input_report_key(hkey->inputdev, key->keycode, 1);
-               input_sync(hkey->inputdev);
-               input_report_key(hkey->inputdev, key->keycode, 0);
-               input_sync(hkey->inputdev);
-               return;
-       }
-
-       /* Known non hotkey events don't handled or that we don't care yet */
-       if (event == 0x8e || event == 0x8f || event == 0x90)
-               return;
-
-       pr_info("unknown event = 0x%02x\n", event);
+       if (!sparse_keymap_report_event(hkey->inputdev, event, 1, true))
+               pr_info("unknown event = 0x%02x\n", event);
 }
 
 static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
@@ -127,62 +94,41 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state)
        return 0;
 }
 
-static int topstar_getkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int *keycode)
-{
-       struct tps_key_entry *key = tps_get_key_by_scancode(scancode);
-
-       if (!key)
-               return -EINVAL;
-
-       *keycode = key->keycode;
-       return 0;
-}
-
-static int topstar_setkeycode(struct input_dev *dev,
-                               unsigned int scancode, unsigned int keycode)
-{
-       struct tps_key_entry *key;
-       int old_keycode;
-
-       key = tps_get_key_by_scancode(scancode);
-
-       if (!key)
-               return -EINVAL;
-
-       old_keycode = key->keycode;
-       key->keycode = keycode;
-       set_bit(keycode, dev->keybit);
-       if (!tps_get_key_by_keycode(old_keycode))
-               clear_bit(old_keycode, dev->keybit);
-       return 0;
-}
-
 static int acpi_topstar_init_hkey(struct topstar_hkey *hkey)
 {
-       struct tps_key_entry *key;
+       struct input_dev *input;
+       int error;
 
-       hkey->inputdev = input_allocate_device();
-       if (!hkey->inputdev) {
+       input = input_allocate_device();
+       if (!input) {
                pr_err("Unable to allocate input device\n");
-               return -ENODEV;
+               return -ENOMEM;
        }
-       hkey->inputdev->name = "Topstar Laptop extra buttons";
-       hkey->inputdev->phys = "topstar/input0";
-       hkey->inputdev->id.bustype = BUS_HOST;
-       hkey->inputdev->getkeycode = topstar_getkeycode;
-       hkey->inputdev->setkeycode = topstar_setkeycode;
-       for (key = topstar_keymap; key->code; key++) {
-               set_bit(EV_KEY, hkey->inputdev->evbit);
-               set_bit(key->keycode, hkey->inputdev->keybit);
+
+       input->name = "Topstar Laptop extra buttons";
+       input->phys = "topstar/input0";
+       input->id.bustype = BUS_HOST;
+
+       error = sparse_keymap_setup(input, topstar_keymap, NULL);
+       if (error) {
+               pr_err("Unable to setup input device keymap\n");
+               goto err_free_dev;
        }
-       if (input_register_device(hkey->inputdev)) {
+
+       error = input_register_device(input);
+       if (error) {
                pr_err("Unable to register input device\n");
-               input_free_device(hkey->inputdev);
-               return -ENODEV;
+               goto err_free_keymap;
        }
 
+       hkey->inputdev = input;
        return 0;
+
+ err_free_keymap:
+       sparse_keymap_free(input);
+ err_free_dev:
+       input_free_device(input);
+       return error;
 }
 
 static int acpi_topstar_add(struct acpi_device *device)
@@ -216,6 +162,7 @@ static int acpi_topstar_remove(struct acpi_device *device, int type)
 
        acpi_topstar_fncx_switch(device, false);
 
+       sparse_keymap_free(tps_hkey->inputdev);
        input_unregister_device(tps_hkey->inputdev);
        kfree(tps_hkey);
 
index 7d67a45..06f304f 100644 (file)
@@ -48,6 +48,7 @@
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
 #include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 #include <linux/leds.h>
 #include <linux/slab.h>
 
@@ -121,36 +122,28 @@ static const struct acpi_device_id toshiba_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, toshiba_device_ids);
 
-struct key_entry {
-       char type;
-       u16 code;
-       u16 keycode;
-};
-
-enum {KE_KEY, KE_END};
-
-static struct key_entry toshiba_acpi_keymap[]  = {
-       {KE_KEY, 0x101, KEY_MUTE},
-       {KE_KEY, 0x102, KEY_ZOOMOUT},
-       {KE_KEY, 0x103, KEY_ZOOMIN},
-       {KE_KEY, 0x13b, KEY_COFFEE},
-       {KE_KEY, 0x13c, KEY_BATTERY},
-       {KE_KEY, 0x13d, KEY_SLEEP},
-       {KE_KEY, 0x13e, KEY_SUSPEND},
-       {KE_KEY, 0x13f, KEY_SWITCHVIDEOMODE},
-       {KE_KEY, 0x140, KEY_BRIGHTNESSDOWN},
-       {KE_KEY, 0x141, KEY_BRIGHTNESSUP},
-       {KE_KEY, 0x142, KEY_WLAN},
-       {KE_KEY, 0x143, KEY_PROG1},
-       {KE_KEY, 0xb05, KEY_PROG2},
-       {KE_KEY, 0xb06, KEY_WWW},
-       {KE_KEY, 0xb07, KEY_MAIL},
-       {KE_KEY, 0xb30, KEY_STOP},
-       {KE_KEY, 0xb31, KEY_PREVIOUSSONG},
-       {KE_KEY, 0xb32, KEY_NEXTSONG},
-       {KE_KEY, 0xb33, KEY_PLAYPAUSE},
-       {KE_KEY, 0xb5a, KEY_MEDIA},
-       {KE_END, 0, 0},
+static const struct key_entry toshiba_acpi_keymap[] __initconst = {
+       { KE_KEY, 0x101, { KEY_MUTE } },
+       { KE_KEY, 0x102, { KEY_ZOOMOUT } },
+       { KE_KEY, 0x103, { KEY_ZOOMIN } },
+       { KE_KEY, 0x13b, { KEY_COFFEE } },
+       { KE_KEY, 0x13c, { KEY_BATTERY } },
+       { KE_KEY, 0x13d, { KEY_SLEEP } },
+       { KE_KEY, 0x13e, { KEY_SUSPEND } },
+       { KE_KEY, 0x13f, { KEY_SWITCHVIDEOMODE } },
+       { KE_KEY, 0x140, { KEY_BRIGHTNESSDOWN } },
+       { KE_KEY, 0x141, { KEY_BRIGHTNESSUP } },
+       { KE_KEY, 0x142, { KEY_WLAN } },
+       { KE_KEY, 0x143, { KEY_PROG1 } },
+       { KE_KEY, 0xb05, { KEY_PROG2 } },
+       { KE_KEY, 0xb06, { KEY_WWW } },
+       { KE_KEY, 0xb07, { KEY_MAIL } },
+       { KE_KEY, 0xb30, { KEY_STOP } },
+       { KE_KEY, 0xb31, { KEY_PREVIOUSSONG } },
+       { KE_KEY, 0xb32, { KEY_NEXTSONG } },
+       { KE_KEY, 0xb33, { KEY_PLAYPAUSE } },
+       { KE_KEY, 0xb5a, { KEY_MEDIA } },
+       { KE_END, 0 },
 };
 
 /* utility
@@ -852,64 +845,9 @@ static struct backlight_ops toshiba_backlight_data = {
         .update_status  = set_lcd_status,
 };
 
-static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
-               if (code == key->code)
-                       return key;
-
-       return NULL;
-}
-
-static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code)
-{
-       struct key_entry *key;
-
-       for (key = toshiba_acpi_keymap; key->type != KE_END; key++)
-               if (code == key->keycode && key->type == KE_KEY)
-                       return key;
-
-       return NULL;
-}
-
-static int toshiba_acpi_getkeycode(struct input_dev *dev,
-                                  unsigned int scancode, unsigned int *keycode)
-{
-       struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode);
-
-       if (key && key->type == KE_KEY) {
-               *keycode = key->keycode;
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
-static int toshiba_acpi_setkeycode(struct input_dev *dev,
-                                  unsigned int scancode, unsigned int keycode)
-{
-       struct key_entry *key;
-       unsigned int old_keycode;
-
-       key = toshiba_acpi_get_entry_by_scancode(scancode);
-       if (key && key->type == KE_KEY) {
-               old_keycode = key->keycode;
-               key->keycode = keycode;
-               set_bit(keycode, dev->keybit);
-               if (!toshiba_acpi_get_entry_by_keycode(old_keycode))
-                       clear_bit(old_keycode, dev->keybit);
-               return 0;
-       }
-
-       return -EINVAL;
-}
-
 static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
 {
        u32 hci_result, value;
-       struct key_entry *key;
 
        if (event != 0x80)
                return;
@@ -922,19 +860,11 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
                        if (value & 0x80)
                                continue;
 
-                       key = toshiba_acpi_get_entry_by_scancode
-                               (value);
-                       if (!key) {
+                       if (!sparse_keymap_report_event(toshiba_acpi.hotkey_dev,
+                                                       value, 1, true)) {
                                printk(MY_INFO "Unknown key %x\n",
                                       value);
-                               continue;
                        }
-                       input_report_key(toshiba_acpi.hotkey_dev,
-                                        key->keycode, 1);
-                       input_sync(toshiba_acpi.hotkey_dev);
-                       input_report_key(toshiba_acpi.hotkey_dev,
-                                        key->keycode, 0);
-                       input_sync(toshiba_acpi.hotkey_dev);
                } else if (hci_result == HCI_NOT_SUPPORTED) {
                        /* This is a workaround for an unresolved issue on
                         * some machines where system events sporadically
@@ -945,34 +875,17 @@ static void toshiba_acpi_notify(acpi_handle handle, u32 event, void *context)
        } while (hci_result != HCI_EMPTY);
 }
 
-static int toshiba_acpi_setup_keyboard(char *device)
+static int __init toshiba_acpi_setup_keyboard(char *device)
 {
        acpi_status status;
-       acpi_handle handle;
-       int result;
-       const struct key_entry *key;
+       int error;
 
-       status = acpi_get_handle(NULL, device, &handle);
+       status = acpi_get_handle(NULL, device, &toshiba_acpi.handle);
        if (ACPI_FAILURE(status)) {
                printk(MY_INFO "Unable to get notification device\n");
                return -ENODEV;
        }
 
-       toshiba_acpi.handle = handle;
-
-       status = acpi_evaluate_object(handle, "ENAB", NULL, NULL);
-       if (ACPI_FAILURE(status)) {
-               printk(MY_INFO "Unable to enable hotkeys\n");
-               return -ENODEV;
-       }
-
-       status = acpi_install_notify_handler(handle, ACPI_DEVICE_NOTIFY,
-                                             toshiba_acpi_notify, NULL);
-       if (ACPI_FAILURE(status)) {
-               printk(MY_INFO "Unable to install hotkey notification\n");
-               return -ENODEV;
-       }
-
        toshiba_acpi.hotkey_dev = input_allocate_device();
        if (!toshiba_acpi.hotkey_dev) {
                printk(MY_INFO "Unable to register input device\n");
@@ -982,27 +895,54 @@ static int toshiba_acpi_setup_keyboard(char *device)
        toshiba_acpi.hotkey_dev->name = "Toshiba input device";
        toshiba_acpi.hotkey_dev->phys = device;
        toshiba_acpi.hotkey_dev->id.bustype = BUS_HOST;
-       toshiba_acpi.hotkey_dev->getkeycode = toshiba_acpi_getkeycode;
-       toshiba_acpi.hotkey_dev->setkeycode = toshiba_acpi_setkeycode;
 
-       for (key = toshiba_acpi_keymap; key->type != KE_END; key++) {
-               set_bit(EV_KEY, toshiba_acpi.hotkey_dev->evbit);
-               set_bit(key->keycode, toshiba_acpi.hotkey_dev->keybit);
+       error = sparse_keymap_setup(toshiba_acpi.hotkey_dev,
+                                   toshiba_acpi_keymap, NULL);
+       if (error)
+               goto err_free_dev;
+
+       status = acpi_install_notify_handler(toshiba_acpi.handle,
+                               ACPI_DEVICE_NOTIFY, toshiba_acpi_notify, NULL);
+       if (ACPI_FAILURE(status)) {
+               printk(MY_INFO "Unable to install hotkey notification\n");
+               error = -ENODEV;
+               goto err_free_keymap;
+       }
+
+       status = acpi_evaluate_object(toshiba_acpi.handle, "ENAB", NULL, NULL);
+       if (ACPI_FAILURE(status)) {
+               printk(MY_INFO "Unable to enable hotkeys\n");
+               error = -ENODEV;
+               goto err_remove_notify;
        }
 
-       result = input_register_device(toshiba_acpi.hotkey_dev);
-       if (result) {
+       error = input_register_device(toshiba_acpi.hotkey_dev);
+       if (error) {
                printk(MY_INFO "Unable to register input device\n");
-               return result;
+               goto err_remove_notify;
        }
 
        return 0;
+
+ err_remove_notify:
+       acpi_remove_notify_handler(toshiba_acpi.handle,
+                                  ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
+ err_free_keymap:
+       sparse_keymap_free(toshiba_acpi.hotkey_dev);
+ err_free_dev:
+       input_free_device(toshiba_acpi.hotkey_dev);
+       toshiba_acpi.hotkey_dev = NULL;
+       return error;
 }
 
 static void toshiba_acpi_exit(void)
 {
-       if (toshiba_acpi.hotkey_dev)
+       if (toshiba_acpi.hotkey_dev) {
+               acpi_remove_notify_handler(toshiba_acpi.handle,
+                               ACPI_DEVICE_NOTIFY, toshiba_acpi_notify);
+               sparse_keymap_free(toshiba_acpi.hotkey_dev);
                input_unregister_device(toshiba_acpi.hotkey_dev);
+       }
 
        if (toshiba_acpi.bt_rfk) {
                rfkill_unregister(toshiba_acpi.bt_rfk);
@@ -1017,9 +957,6 @@ static void toshiba_acpi_exit(void)
        if (toshiba_proc_dir)
                remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
 
-       acpi_remove_notify_handler(toshiba_acpi.handle, ACPI_DEVICE_NOTIFY,
-                                  toshiba_acpi_notify);
-
        if (toshiba_acpi.illumination_installed)
                led_classdev_unregister(&toshiba_led);
 
index b2978a0..104b77c 100644 (file)
@@ -27,6 +27,8 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#define pr_fmt(fmt)    KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -44,9 +46,8 @@ MODULE_LICENSE("GPL");
 
 #define ACPI_WMI_CLASS "wmi"
 
-#define PREFIX "ACPI: WMI: "
-
 static DEFINE_MUTEX(wmi_data_lock);
+static LIST_HEAD(wmi_block_list);
 
 struct guid_block {
        char guid[16];
@@ -67,10 +68,9 @@ struct wmi_block {
        acpi_handle handle;
        wmi_notify_handler handler;
        void *handler_data;
-       struct device *dev;
+       struct device dev;
 };
 
-static struct wmi_block wmi_blocks;
 
 /*
  * If the GUID data block is marked as expensive, we must enable and
@@ -110,7 +110,7 @@ static struct acpi_driver acpi_wmi_driver = {
                .add = acpi_wmi_add,
                .remove = acpi_wmi_remove,
                .notify = acpi_wmi_notify,
-               },
+       },
 };
 
 /*
@@ -128,30 +128,18 @@ static struct acpi_driver acpi_wmi_driver = {
  */
 static int wmi_parse_hexbyte(const u8 *src)
 {
-       unsigned int x; /* For correct wrapping */
        int h;
+       int value;
 
        /* high part */
-       x = src[0];
-       if (x - '0' <= '9' - '0') {
-               h = x - '0';
-       } else if (x - 'a' <= 'f' - 'a') {
-               h = x - 'a' + 10;
-       } else if (x - 'A' <= 'F' - 'A') {
-               h = x - 'A' + 10;
-       } else {
+       h = value = hex_to_bin(src[0]);
+       if (value < 0)
                return -1;
-       }
-       h <<= 4;
 
        /* low part */
-       x = src[1];
-       if (x - '0' <= '9' - '0')
-               return h | (x - '0');
-       if (x - 'a' <= 'f' - 'a')
-               return h | (x - 'a' + 10);
-       if (x - 'A' <= 'F' - 'A')
-               return h | (x - 'A' + 10);
+       value = hex_to_bin(src[1]);
+       if (value >= 0)
+               return (h << 4) | value;
        return -1;
 }
 
@@ -232,7 +220,7 @@ static int wmi_gtoa(const char *in, char *out)
        for (i = 10; i <= 15; i++)
                out += sprintf(out, "%02X", in[i] & 0xFF);
 
-       out = '\0';
+       *out = '\0';
        return 0;
 }
 
@@ -246,7 +234,7 @@ static bool find_guid(const char *guid_string, struct wmi_block **out)
        wmi_parse_guid(guid_string, tmp);
        wmi_swap_bytes(tmp, guid_input);
 
-       list_for_each(p, &wmi_blocks.list) {
+       list_for_each(p, &wmi_block_list) {
                wblock = list_entry(p, struct wmi_block, list);
                block = &wblock->gblock;
 
@@ -487,30 +475,29 @@ const struct acpi_buffer *in)
 }
 EXPORT_SYMBOL_GPL(wmi_set_block);
 
-static void wmi_dump_wdg(struct guid_block *g)
+static void wmi_dump_wdg(const struct guid_block *g)
 {
        char guid_string[37];
 
        wmi_gtoa(g->guid, guid_string);
-       printk(KERN_INFO PREFIX "%s:\n", guid_string);
-       printk(KERN_INFO PREFIX "\tobject_id: %c%c\n",
-              g->object_id[0], g->object_id[1]);
-       printk(KERN_INFO PREFIX "\tnotify_id: %02X\n", g->notify_id);
-       printk(KERN_INFO PREFIX "\treserved: %02X\n", g->reserved);
-       printk(KERN_INFO PREFIX "\tinstance_count: %d\n", g->instance_count);
-       printk(KERN_INFO PREFIX "\tflags: %#x", g->flags);
+
+       pr_info("%s:\n", guid_string);
+       pr_info("\tobject_id: %c%c\n", g->object_id[0], g->object_id[1]);
+       pr_info("\tnotify_id: %02X\n", g->notify_id);
+       pr_info("\treserved: %02X\n", g->reserved);
+       pr_info("\tinstance_count: %d\n", g->instance_count);
+       pr_info("\tflags: %#x ", g->flags);
        if (g->flags) {
-               printk(" ");
                if (g->flags & ACPI_WMI_EXPENSIVE)
-                       printk("ACPI_WMI_EXPENSIVE ");
+                       pr_cont("ACPI_WMI_EXPENSIVE ");
                if (g->flags & ACPI_WMI_METHOD)
-                       printk("ACPI_WMI_METHOD ");
+                       pr_cont("ACPI_WMI_METHOD ");
                if (g->flags & ACPI_WMI_STRING)
-                       printk("ACPI_WMI_STRING ");
+                       pr_cont("ACPI_WMI_STRING ");
                if (g->flags & ACPI_WMI_EVENT)
-                       printk("ACPI_WMI_EVENT ");
+                       pr_cont("ACPI_WMI_EVENT ");
        }
-       printk("\n");
+       pr_cont("\n");
 
 }
 
@@ -522,7 +509,7 @@ static void wmi_notify_debug(u32 value, void *context)
 
        status = wmi_get_event_data(value, &response);
        if (status != AE_OK) {
-               printk(KERN_INFO "wmi: bad event status 0x%x\n", status);
+               pr_info("bad event status 0x%x\n", status);
                return;
        }
 
@@ -531,22 +518,22 @@ static void wmi_notify_debug(u32 value, void *context)
        if (!obj)
                return;
 
-       printk(KERN_INFO PREFIX "DEBUG Event ");
+       pr_info("DEBUG Event ");
        switch(obj->type) {
        case ACPI_TYPE_BUFFER:
-               printk("BUFFER_TYPE - length %d\n", obj->buffer.length);
+               pr_cont("BUFFER_TYPE - length %d\n", obj->buffer.length);
                break;
        case ACPI_TYPE_STRING:
-               printk("STRING_TYPE - %s\n", obj->string.pointer);
+               pr_cont("STRING_TYPE - %s\n", obj->string.pointer);
                break;
        case ACPI_TYPE_INTEGER:
-               printk("INTEGER_TYPE - %llu\n", obj->integer.value);
+               pr_cont("INTEGER_TYPE - %llu\n", obj->integer.value);
                break;
        case ACPI_TYPE_PACKAGE:
-               printk("PACKAGE_TYPE - %d elements\n", obj->package.count);
+               pr_cont("PACKAGE_TYPE - %d elements\n", obj->package.count);
                break;
        default:
-               printk("object type 0x%X\n", obj->type);
+               pr_cont("object type 0x%X\n", obj->type);
        }
        kfree(obj);
 }
@@ -633,7 +620,7 @@ acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
        params[0].type = ACPI_TYPE_INTEGER;
        params[0].integer.value = event;
 
-       list_for_each(p, &wmi_blocks.list) {
+       list_for_each(p, &wmi_block_list) {
                wblock = list_entry(p, struct wmi_block, list);
                gblock = &wblock->gblock;
 
@@ -662,7 +649,7 @@ EXPORT_SYMBOL_GPL(wmi_has_guid);
 /*
  * sysfs interface
  */
-static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        char guid_string[37];
@@ -676,7 +663,11 @@ static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
 
        return sprintf(buf, "wmi:%s\n", guid_string);
 }
-static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
+
+static struct device_attribute wmi_dev_attrs[] = {
+       __ATTR_RO(modalias),
+       __ATTR_NULL
+};
 
 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 {
@@ -702,108 +693,71 @@ static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
 
 static void wmi_dev_free(struct device *dev)
 {
-       kfree(dev);
+       struct wmi_block *wmi_block = container_of(dev, struct wmi_block, dev);
+
+       kfree(wmi_block);
 }
 
 static struct class wmi_class = {
        .name = "wmi",
        .dev_release = wmi_dev_free,
        .dev_uevent = wmi_dev_uevent,
+       .dev_attrs = wmi_dev_attrs,
 };
 
-static int wmi_create_devs(void)
+static struct wmi_block *wmi_create_device(const struct guid_block *gblock,
+                                          acpi_handle handle)
 {
-       int result;
-       char guid_string[37];
-       struct guid_block *gblock;
        struct wmi_block *wblock;
-       struct list_head *p;
-       struct device *guid_dev;
-
-       /* Create devices for all the GUIDs */
-       list_for_each(p, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
-
-               guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
-               if (!guid_dev)
-                       return -ENOMEM;
-
-               wblock->dev = guid_dev;
-
-               guid_dev->class = &wmi_class;
-               dev_set_drvdata(guid_dev, wblock);
-
-               gblock = &wblock->gblock;
-
-               wmi_gtoa(gblock->guid, guid_string);
-               dev_set_name(guid_dev, guid_string);
-
-               result = device_register(guid_dev);
-               if (result)
-                       return result;
+       int error;
+       char guid_string[37];
 
-               result = device_create_file(guid_dev, &dev_attr_modalias);
-               if (result)
-                       return result;
+       wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
+       if (!wblock) {
+               error = -ENOMEM;
+               goto err_out;
        }
 
-       return 0;
-}
+       wblock->handle = handle;
+       wblock->gblock = *gblock;
 
-static void wmi_remove_devs(void)
-{
-       struct guid_block *gblock;
-       struct wmi_block *wblock;
-       struct list_head *p;
-       struct device *guid_dev;
+       wblock->dev.class = &wmi_class;
 
-       /* Delete devices for all the GUIDs */
-       list_for_each(p, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
+       wmi_gtoa(gblock->guid, guid_string);
+       dev_set_name(&wblock->dev, guid_string);
 
-               guid_dev = wblock->dev;
-               gblock = &wblock->gblock;
+       dev_set_drvdata(&wblock->dev, wblock);
 
-               device_remove_file(guid_dev, &dev_attr_modalias);
+       error = device_register(&wblock->dev);
+       if (error)
+               goto err_free;
 
-               device_unregister(guid_dev);
-       }
-}
+       list_add_tail(&wblock->list, &wmi_block_list);
+       return wblock;
 
-static void wmi_class_exit(void)
-{
-       wmi_remove_devs();
-       class_unregister(&wmi_class);
+err_free:
+       kfree(wblock);
+err_out:
+       return ERR_PTR(error);
 }
 
-static int wmi_class_init(void)
+static void wmi_free_devices(void)
 {
-       int ret;
-
-       ret = class_register(&wmi_class);
-       if (ret)
-               return ret;
+       struct wmi_block *wblock, *next;
 
-       ret = wmi_create_devs();
-       if (ret)
-               wmi_class_exit();
-
-       return ret;
+       /* Delete devices for all the GUIDs */
+       list_for_each_entry_safe(wblock, next, &wmi_block_list, list)
+               device_unregister(&wblock->dev);
 }
 
 static bool guid_already_parsed(const char *guid_string)
 {
-       struct guid_block *gblock;
        struct wmi_block *wblock;
-       struct list_head *p;
 
-       list_for_each(p, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
-               gblock = &wblock->gblock;
-
-               if (strncmp(gblock->guid, guid_string, 16) == 0)
+       list_for_each_entry(wblock, &wmi_block_list, list)
+               if (strncmp(wblock->gblock.guid, guid_string, 16) == 0)
                        return true;
-       }
+
        return false;
 }
 
@@ -814,30 +768,29 @@ static acpi_status parse_wdg(acpi_handle handle)
 {
        struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
        union acpi_object *obj;
-       struct guid_block *gblock;
+       const struct guid_block *gblock;
        struct wmi_block *wblock;
        char guid_string[37];
        acpi_status status;
+       int retval;
        u32 i, total;
 
        status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
-
        if (ACPI_FAILURE(status))
-               return status;
+               return -ENXIO;
 
        obj = (union acpi_object *) out.pointer;
+       if (!obj)
+               return -ENXIO;
 
-       if (obj->type != ACPI_TYPE_BUFFER)
-               return AE_ERROR;
-
-       total = obj->buffer.length / sizeof(struct guid_block);
-
-       gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
-       if (!gblock) {
-               status = AE_NO_MEMORY;
+       if (obj->type != ACPI_TYPE_BUFFER) {
+               retval = -ENXIO;
                goto out_free_pointer;
        }
 
+       gblock = (const struct guid_block *)obj->buffer.pointer;
+       total = obj->buffer.length / sizeof(struct guid_block);
+
        for (i = 0; i < total; i++) {
                /*
                  Some WMI devices, like those for nVidia hooks, have a
@@ -848,34 +801,32 @@ static acpi_status parse_wdg(acpi_handle handle)
                */
                if (guid_already_parsed(gblock[i].guid) == true) {
                        wmi_gtoa(gblock[i].guid, guid_string);
-                       printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n",
-                               guid_string);
+                       pr_info("Skipping duplicate GUID %s\n", guid_string);
                        continue;
                }
+
                if (debug_dump_wdg)
                        wmi_dump_wdg(&gblock[i]);
 
-               wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
-               if (!wblock) {
-                       status = AE_NO_MEMORY;
-                       goto out_free_gblock;
+               wblock = wmi_create_device(&gblock[i], handle);
+               if (IS_ERR(wblock)) {
+                       retval = PTR_ERR(wblock);
+                       wmi_free_devices();
+                       break;
                }
 
-               wblock->gblock = gblock[i];
-               wblock->handle = handle;
                if (debug_event) {
                        wblock->handler = wmi_notify_debug;
-                       status = wmi_method_enable(wblock, 1);
+                       wmi_method_enable(wblock, 1);
                }
-               list_add_tail(&wblock->list, &wmi_blocks.list);
        }
 
-out_free_gblock:
-       kfree(gblock);
+       retval = 0;
+
 out_free_pointer:
        kfree(out.pointer);
 
-       return status;
+       return retval;
 }
 
 /*
@@ -929,7 +880,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
        struct list_head *p;
        char guid_string[37];
 
-       list_for_each(p, &wmi_blocks.list) {
+       list_for_each(p, &wmi_block_list) {
                wblock = list_entry(p, struct wmi_block, list);
                block = &wblock->gblock;
 
@@ -939,8 +890,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event)
                                wblock->handler(event, wblock->handler_data);
                        if (debug_event) {
                                wmi_gtoa(wblock->gblock.guid, guid_string);
-                               printk(KERN_INFO PREFIX "DEBUG Event GUID:"
-                                      " %s\n", guid_string);
+                               pr_info("DEBUG Event GUID: %s\n", guid_string);
                        }
 
                        acpi_bus_generate_netlink_event(
@@ -955,6 +905,7 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
 {
        acpi_remove_address_space_handler(device->handle,
                                ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
+       wmi_free_devices();
 
        return 0;
 }
@@ -962,68 +913,57 @@ static int acpi_wmi_remove(struct acpi_device *device, int type)
 static int acpi_wmi_add(struct acpi_device *device)
 {
        acpi_status status;
-       int result = 0;
+       int error;
 
        status = acpi_install_address_space_handler(device->handle,
                                                    ACPI_ADR_SPACE_EC,
                                                    &acpi_wmi_ec_space_handler,
                                                    NULL, NULL);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
-
-       status = parse_wdg(device->handle);
        if (ACPI_FAILURE(status)) {
-               printk(KERN_ERR PREFIX "Error installing EC region handler\n");
+               pr_err("Error installing EC region handler\n");
                return -ENODEV;
        }
 
-       return result;
+       error = parse_wdg(device->handle);
+       if (error) {
+               acpi_remove_address_space_handler(device->handle,
+                                                 ACPI_ADR_SPACE_EC,
+                                                 &acpi_wmi_ec_space_handler);
+               pr_err("Failed to parse WDG method\n");
+               return error;
+       }
+
+       return 0;
 }
 
 static int __init acpi_wmi_init(void)
 {
-       int result;
-
-       INIT_LIST_HEAD(&wmi_blocks.list);
+       int error;
 
        if (acpi_disabled)
                return -ENODEV;
 
-       result = acpi_bus_register_driver(&acpi_wmi_driver);
+       error = class_register(&wmi_class);
+       if (error)
+               return error;
 
-       if (result < 0) {
-               printk(KERN_INFO PREFIX "Error loading mapper\n");
-               return -ENODEV;
+       error = acpi_bus_register_driver(&acpi_wmi_driver);
+       if (error) {
+               pr_err("Error loading mapper\n");
+               class_unregister(&wmi_class);
+               return error;
        }
 
-       result = wmi_class_init();
-       if (result) {
-               acpi_bus_unregister_driver(&acpi_wmi_driver);
-               return result;
-       }
-
-       printk(KERN_INFO PREFIX "Mapper loaded\n");
-
-       return result;
+       pr_info("Mapper loaded\n");
+       return 0;
 }
 
 static void __exit acpi_wmi_exit(void)
 {
-       struct list_head *p, *tmp;
-       struct wmi_block *wblock;
-
-       wmi_class_exit();
-
        acpi_bus_unregister_driver(&acpi_wmi_driver);
+       class_unregister(&wmi_class);
 
-       list_for_each_safe(p, tmp, &wmi_blocks.list) {
-               wblock = list_entry(p, struct wmi_block, list);
-
-               list_del(p);
-               kfree(wblock);
-       }
-
-       printk(KERN_INFO PREFIX "Mapper unloaded\n");
+       pr_info("Mapper unloaded\n");
 }
 
 subsys_initcall(acpi_wmi_init);
diff --git a/drivers/platform/x86/xo1-rfkill.c b/drivers/platform/x86/xo1-rfkill.c
new file mode 100644 (file)
index 0000000..e549eee
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Support for rfkill through the OLPC XO-1 laptop embedded controller
+ *
+ * Copyright (C) 2010 One Laptop per Child
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rfkill.h>
+
+#include <asm/olpc.h>
+
+static int rfkill_set_block(void *data, bool blocked)
+{
+       unsigned char cmd;
+       if (blocked)
+               cmd = EC_WLAN_ENTER_RESET;
+       else
+               cmd = EC_WLAN_LEAVE_RESET;
+
+       return olpc_ec_cmd(cmd, NULL, 0, NULL, 0);
+}
+
+static const struct rfkill_ops rfkill_ops = {
+       .set_block = rfkill_set_block,
+};
+
+static int __devinit xo1_rfkill_probe(struct platform_device *pdev)
+{
+       struct rfkill *rfk;
+       int r;
+
+       rfk = rfkill_alloc(pdev->name, &pdev->dev, RFKILL_TYPE_WLAN,
+                          &rfkill_ops, NULL);
+       if (!rfk)
+               return -ENOMEM;
+
+       r = rfkill_register(rfk);
+       if (r) {
+               rfkill_destroy(rfk);
+               return r;
+       }
+
+       platform_set_drvdata(pdev, rfk);
+       return 0;
+}
+
+static int __devexit xo1_rfkill_remove(struct platform_device *pdev)
+{
+       struct rfkill *rfk = platform_get_drvdata(pdev);
+       rfkill_unregister(rfk);
+       rfkill_destroy(rfk);
+       return 0;
+}
+
+static struct platform_driver xo1_rfkill_driver = {
+       .driver = {
+               .name = "xo1-rfkill",
+               .owner = THIS_MODULE,
+       },
+       .probe          = xo1_rfkill_probe,
+       .remove         = __devexit_p(xo1_rfkill_remove),
+};
+
+static int __init xo1_rfkill_init(void)
+{
+       return platform_driver_register(&xo1_rfkill_driver);
+}
+
+static void __exit xo1_rfkill_exit(void)
+{
+       platform_driver_unregister(&xo1_rfkill_driver);
+}
+
+MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:xo1-rfkill");
+
+module_init(xo1_rfkill_init);
+module_exit(xo1_rfkill_exit);
index 13f48e2..a624f5a 100644 (file)
@@ -461,7 +461,7 @@ static int jsflash_init(void)
 {
        int rc;
        struct jsflash *jsf;
-       int node;
+       phandle node;
        char banner[128];
        struct linux_prom_registers reg0;
 
index 58aa215..664ceb0 100644 (file)
@@ -181,13 +181,8 @@ struct m68k_serial {
 /* 
  * Define the number of ports supported and their irqs.
  */
-#ifndef CONFIG_68328_SERIAL_UART2
 #define NR_PORTS 1
 #define UART_IRQ_DEFNS {UART_IRQ_NUM}
-#else
-#define NR_PORTS 2
-#define UART_IRQ_DEFNS {UART1_IRQ_NUM, UART2_IRQ_NUM}
-#endif
 
 #endif /* __KERNEL__ */
 #endif /* !(_MC683XX_SERIAL_H) */
index 2af8fd1..17849dc 100644 (file)
@@ -31,8 +31,8 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
 {
        struct resource resource;
        struct device_node *np = ofdev->dev.of_node;
-       const unsigned int *clk, *spd;
-       const u32 *prop;
+       const __be32 *clk, *spd;
+       const __be32 *prop;
        int ret, prop_size;
 
        memset(port, 0, sizeof *port);
@@ -55,23 +55,23 @@ static int __devinit of_platform_serial_setup(struct platform_device *ofdev,
        /* Check for shifted address mapping */
        prop = of_get_property(np, "reg-offset", &prop_size);
        if (prop && (prop_size == sizeof(u32)))
-               port->mapbase += *prop;
+               port->mapbase += be32_to_cpup(prop);
 
        /* Check for registers offset within the devices address range */
        prop = of_get_property(np, "reg-shift", &prop_size);
        if (prop && (prop_size == sizeof(u32)))
-               port->regshift = *prop;
+               port->regshift = be32_to_cpup(prop);
 
        port->irq = irq_of_parse_and_map(np, 0);
        port->iotype = UPIO_MEM;
        port->type = type;
-       port->uartclk = *clk;
+       port->uartclk = be32_to_cpup(clk);
        port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
                | UPF_FIXED_PORT | UPF_FIXED_TYPE;
        port->dev = &ofdev->dev;
        /* If current-speed was set, then try not to change it. */
        if (spd)
-               port->custom_divisor = *clk / (16 * (*spd));
+               port->custom_divisor = be32_to_cpup(clk) / (16 * (be32_to_cpup(spd)));
 
        return 0;
 }
index 9b52f77..d2352ac 100644 (file)
 # define SCSPTR0       0xffe00024      /* 16 bit SCIF */
 # define SCSPTR1       0xffe10024      /* 16 bit SCIF */
 # define SCIF_ORER     0x0001          /* Overrun error bit */
-# define SCSCR_INIT(port)      0x3a    /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
+
+#if defined(CONFIG_SH_SH2007)
+/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=0 */
+# define SCSCR_INIT(port)      0x38
+#else
+/* TIE=0,RIE=0,TE=1,RE=1,REIE=1,CKE1=1 */
+# define SCSCR_INIT(port)      0x3a
+#endif
+
 #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
       defined(CONFIG_CPU_SUBTYPE_SH7786)
 # define SCSPTR0       0xffea0024      /* 16 bit SCIF */
@@ -616,9 +624,10 @@ static inline int sci_rxd_in(struct uart_port *port)
  * -- Mitch Davis - 15 Jul 2000
  */
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7780) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7785) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7786)
+#if (defined(CONFIG_CPU_SUBTYPE_SH7780)  || \
+     defined(CONFIG_CPU_SUBTYPE_SH7785)  || \
+     defined(CONFIG_CPU_SUBTYPE_SH7786)) && \
+    !defined(CONFIG_SH_SH2007)
 #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1)
 #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \
       defined(CONFIG_CPU_SUBTYPE_SH7720) || \
index a54de0b..f168a61 100644 (file)
@@ -1,24 +1,5 @@
-config INTC_USERIMASK
-       bool "Userspace interrupt masking support"
-       depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A)
-       help
-         This enables support for hardware-assisted userspace hardirq
-         masking.
+menu "SuperH / SH-Mobile Driver Options"
 
-         SH-4A and newer interrupt blocks all support a special shadowed
-         page with all non-masking registers obscured when mapped in to
-         userspace. This is primarily for use by userspace device
-         drivers that are using special priority levels.
+source "drivers/sh/intc/Kconfig"
 
-         If in doubt, say N.
-
-config INTC_BALANCING
-       bool "Hardware IRQ balancing support"
-       depends on SMP && SUPERH && CPU_SUBTYPE_SH7786
-       help
-         This enables support for IRQ auto-distribution mode on SH-X3
-         SMP parts. All of the balancing and CPU wakeup decisions are
-         taken care of automatically by hardware for distributed
-         vectors.
-
-         If in doubt, say N.
+endmenu
index 08fc653..24e6cec 100644 (file)
@@ -1,10 +1,9 @@
 #
 # Makefile for the SuperH specific drivers.
 #
-obj-y  := clk.o intc.o
+obj-y  := intc/
 
-obj-$(CONFIG_SUPERHYWAY)       += superhyway/
+obj-$(CONFIG_HAVE_CLK)         += clk/
 obj-$(CONFIG_MAPLE)            += maple/
-
+obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_GENERIC_GPIO)     += pfc.o
-obj-$(CONFIG_SH_CLK_CPG)       += clk-cpg.o
diff --git a/drivers/sh/clk-cpg.c b/drivers/sh/clk-cpg.c
deleted file mode 100644 (file)
index 8c024b9..0000000
+++ /dev/null
@@ -1,352 +0,0 @@
-#include <linux/clk.h>
-#include <linux/compiler.h>
-#include <linux/slab.h>
-#include <linux/io.h>
-#include <linux/sh_clk.h>
-
-static int sh_clk_mstp32_enable(struct clk *clk)
-{
-       __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
-                    clk->enable_reg);
-       return 0;
-}
-
-static void sh_clk_mstp32_disable(struct clk *clk)
-{
-       __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
-                    clk->enable_reg);
-}
-
-static struct clk_ops sh_clk_mstp32_clk_ops = {
-       .enable         = sh_clk_mstp32_enable,
-       .disable        = sh_clk_mstp32_disable,
-       .recalc         = followparent_recalc,
-};
-
-int __init sh_clk_mstp32_register(struct clk *clks, int nr)
-{
-       struct clk *clkp;
-       int ret = 0;
-       int k;
-
-       for (k = 0; !ret && (k < nr); k++) {
-               clkp = clks + k;
-               clkp->ops = &sh_clk_mstp32_clk_ops;
-               ret |= clk_register(clkp);
-       }
-
-       return ret;
-}
-
-static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
-{
-       return clk_rate_table_round(clk, clk->freq_table, rate);
-}
-
-static int sh_clk_div6_divisors[64] = {
-       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
-       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
-       33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-       49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
-};
-
-static struct clk_div_mult_table sh_clk_div6_table = {
-       .divisors = sh_clk_div6_divisors,
-       .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
-};
-
-static unsigned long sh_clk_div6_recalc(struct clk *clk)
-{
-       struct clk_div_mult_table *table = &sh_clk_div6_table;
-       unsigned int idx;
-
-       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-                            table, NULL);
-
-       idx = __raw_readl(clk->enable_reg) & 0x003f;
-
-       return clk->freq_table[idx].frequency;
-}
-
-static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
-{
-       struct clk_div_mult_table *table = &sh_clk_div6_table;
-       u32 value;
-       int ret, i;
-
-       if (!clk->parent_table || !clk->parent_num)
-               return -EINVAL;
-
-       /* Search the parent */
-       for (i = 0; i < clk->parent_num; i++)
-               if (clk->parent_table[i] == parent)
-                       break;
-
-       if (i == clk->parent_num)
-               return -ENODEV;
-
-       ret = clk_reparent(clk, parent);
-       if (ret < 0)
-               return ret;
-
-       value = __raw_readl(clk->enable_reg) &
-               ~(((1 << clk->src_width) - 1) << clk->src_shift);
-
-       __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
-
-       /* Rebuild the frequency table */
-       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-                            table, &clk->arch_flags);
-
-       return 0;
-}
-
-static int sh_clk_div6_set_rate(struct clk *clk,
-                               unsigned long rate, int algo_id)
-{
-       unsigned long value;
-       int idx;
-
-       idx = clk_rate_table_find(clk, clk->freq_table, rate);
-       if (idx < 0)
-               return idx;
-
-       value = __raw_readl(clk->enable_reg);
-       value &= ~0x3f;
-       value |= idx;
-       __raw_writel(value, clk->enable_reg);
-       return 0;
-}
-
-static int sh_clk_div6_enable(struct clk *clk)
-{
-       unsigned long value;
-       int ret;
-
-       ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
-       if (ret == 0) {
-               value = __raw_readl(clk->enable_reg);
-               value &= ~0x100; /* clear stop bit to enable clock */
-               __raw_writel(value, clk->enable_reg);
-       }
-       return ret;
-}
-
-static void sh_clk_div6_disable(struct clk *clk)
-{
-       unsigned long value;
-
-       value = __raw_readl(clk->enable_reg);
-       value |= 0x100; /* stop clock */
-       value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
-       __raw_writel(value, clk->enable_reg);
-}
-
-static struct clk_ops sh_clk_div6_clk_ops = {
-       .recalc         = sh_clk_div6_recalc,
-       .round_rate     = sh_clk_div_round_rate,
-       .set_rate       = sh_clk_div6_set_rate,
-       .enable         = sh_clk_div6_enable,
-       .disable        = sh_clk_div6_disable,
-};
-
-static struct clk_ops sh_clk_div6_reparent_clk_ops = {
-       .recalc         = sh_clk_div6_recalc,
-       .round_rate     = sh_clk_div_round_rate,
-       .set_rate       = sh_clk_div6_set_rate,
-       .enable         = sh_clk_div6_enable,
-       .disable        = sh_clk_div6_disable,
-       .set_parent     = sh_clk_div6_set_parent,
-};
-
-static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
-                                          struct clk_ops *ops)
-{
-       struct clk *clkp;
-       void *freq_table;
-       int nr_divs = sh_clk_div6_table.nr_divisors;
-       int freq_table_size = sizeof(struct cpufreq_frequency_table);
-       int ret = 0;
-       int k;
-
-       freq_table_size *= (nr_divs + 1);
-       freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
-       if (!freq_table) {
-               pr_err("sh_clk_div6_register: unable to alloc memory\n");
-               return -ENOMEM;
-       }
-
-       for (k = 0; !ret && (k < nr); k++) {
-               clkp = clks + k;
-
-               clkp->ops = ops;
-               clkp->id = -1;
-               clkp->freq_table = freq_table + (k * freq_table_size);
-               clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-
-               ret = clk_register(clkp);
-       }
-
-       return ret;
-}
-
-int __init sh_clk_div6_register(struct clk *clks, int nr)
-{
-       return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
-}
-
-int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
-{
-       return sh_clk_div6_register_ops(clks, nr,
-                                       &sh_clk_div6_reparent_clk_ops);
-}
-
-static unsigned long sh_clk_div4_recalc(struct clk *clk)
-{
-       struct clk_div4_table *d4t = clk->priv;
-       struct clk_div_mult_table *table = d4t->div_mult_table;
-       unsigned int idx;
-
-       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-                            table, &clk->arch_flags);
-
-       idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
-
-       return clk->freq_table[idx].frequency;
-}
-
-static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
-{
-       struct clk_div4_table *d4t = clk->priv;
-       struct clk_div_mult_table *table = d4t->div_mult_table;
-       u32 value;
-       int ret;
-
-       /* we really need a better way to determine parent index, but for
-        * now assume internal parent comes with CLK_ENABLE_ON_INIT set,
-        * no CLK_ENABLE_ON_INIT means external clock...
-        */
-
-       if (parent->flags & CLK_ENABLE_ON_INIT)
-               value = __raw_readl(clk->enable_reg) & ~(1 << 7);
-       else
-               value = __raw_readl(clk->enable_reg) | (1 << 7);
-
-       ret = clk_reparent(clk, parent);
-       if (ret < 0)
-               return ret;
-
-       __raw_writel(value, clk->enable_reg);
-
-       /* Rebiuld the frequency table */
-       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-                            table, &clk->arch_flags);
-
-       return 0;
-}
-
-static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
-{
-       struct clk_div4_table *d4t = clk->priv;
-       unsigned long value;
-       int idx = clk_rate_table_find(clk, clk->freq_table, rate);
-       if (idx < 0)
-               return idx;
-
-       value = __raw_readl(clk->enable_reg);
-       value &= ~(0xf << clk->enable_bit);
-       value |= (idx << clk->enable_bit);
-       __raw_writel(value, clk->enable_reg);
-
-       if (d4t->kick)
-               d4t->kick(clk);
-
-       return 0;
-}
-
-static int sh_clk_div4_enable(struct clk *clk)
-{
-       __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
-       return 0;
-}
-
-static void sh_clk_div4_disable(struct clk *clk)
-{
-       __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
-}
-
-static struct clk_ops sh_clk_div4_clk_ops = {
-       .recalc         = sh_clk_div4_recalc,
-       .set_rate       = sh_clk_div4_set_rate,
-       .round_rate     = sh_clk_div_round_rate,
-};
-
-static struct clk_ops sh_clk_div4_enable_clk_ops = {
-       .recalc         = sh_clk_div4_recalc,
-       .set_rate       = sh_clk_div4_set_rate,
-       .round_rate     = sh_clk_div_round_rate,
-       .enable         = sh_clk_div4_enable,
-       .disable        = sh_clk_div4_disable,
-};
-
-static struct clk_ops sh_clk_div4_reparent_clk_ops = {
-       .recalc         = sh_clk_div4_recalc,
-       .set_rate       = sh_clk_div4_set_rate,
-       .round_rate     = sh_clk_div_round_rate,
-       .enable         = sh_clk_div4_enable,
-       .disable        = sh_clk_div4_disable,
-       .set_parent     = sh_clk_div4_set_parent,
-};
-
-static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
-                       struct clk_div4_table *table, struct clk_ops *ops)
-{
-       struct clk *clkp;
-       void *freq_table;
-       int nr_divs = table->div_mult_table->nr_divisors;
-       int freq_table_size = sizeof(struct cpufreq_frequency_table);
-       int ret = 0;
-       int k;
-
-       freq_table_size *= (nr_divs + 1);
-       freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
-       if (!freq_table) {
-               pr_err("sh_clk_div4_register: unable to alloc memory\n");
-               return -ENOMEM;
-       }
-
-       for (k = 0; !ret && (k < nr); k++) {
-               clkp = clks + k;
-
-               clkp->ops = ops;
-               clkp->id = -1;
-               clkp->priv = table;
-
-               clkp->freq_table = freq_table + (k * freq_table_size);
-               clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-
-               ret = clk_register(clkp);
-       }
-
-       return ret;
-}
-
-int __init sh_clk_div4_register(struct clk *clks, int nr,
-                               struct clk_div4_table *table)
-{
-       return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
-}
-
-int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
-                               struct clk_div4_table *table)
-{
-       return sh_clk_div4_register_ops(clks, nr, table,
-                                       &sh_clk_div4_enable_clk_ops);
-}
-
-int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
-                               struct clk_div4_table *table)
-{
-       return sh_clk_div4_register_ops(clks, nr, table,
-                                       &sh_clk_div4_reparent_clk_ops);
-}
diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c
deleted file mode 100644 (file)
index 5d84ada..0000000
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * drivers/sh/clk.c - SuperH clock framework
- *
- *  Copyright (C) 2005 - 2009  Paul Mundt
- *
- * This clock framework is derived from the OMAP version by:
- *
- *     Copyright (C) 2004 - 2008 Nokia Corporation
- *     Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
- *
- *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
- *
- * 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/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <linux/kobject.h>
-#include <linux/sysdev.h>
-#include <linux/seq_file.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/sh_clk.h>
-
-static LIST_HEAD(clock_list);
-static DEFINE_SPINLOCK(clock_lock);
-static DEFINE_MUTEX(clock_list_sem);
-
-void clk_rate_table_build(struct clk *clk,
-                         struct cpufreq_frequency_table *freq_table,
-                         int nr_freqs,
-                         struct clk_div_mult_table *src_table,
-                         unsigned long *bitmap)
-{
-       unsigned long mult, div;
-       unsigned long freq;
-       int i;
-
-       for (i = 0; i < nr_freqs; i++) {
-               div = 1;
-               mult = 1;
-
-               if (src_table->divisors && i < src_table->nr_divisors)
-                       div = src_table->divisors[i];
-
-               if (src_table->multipliers && i < src_table->nr_multipliers)
-                       mult = src_table->multipliers[i];
-
-               if (!div || !mult || (bitmap && !test_bit(i, bitmap)))
-                       freq = CPUFREQ_ENTRY_INVALID;
-               else
-                       freq = clk->parent->rate * mult / div;
-
-               freq_table[i].index = i;
-               freq_table[i].frequency = freq;
-       }
-
-       /* Termination entry */
-       freq_table[i].index = i;
-       freq_table[i].frequency = CPUFREQ_TABLE_END;
-}
-
-long clk_rate_table_round(struct clk *clk,
-                         struct cpufreq_frequency_table *freq_table,
-                         unsigned long rate)
-{
-       unsigned long rate_error, rate_error_prev = ~0UL;
-       unsigned long rate_best_fit = rate;
-       unsigned long highest, lowest;
-       int i;
-
-       highest = lowest = 0;
-
-       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-               unsigned long freq = freq_table[i].frequency;
-
-               if (freq == CPUFREQ_ENTRY_INVALID)
-                       continue;
-
-               if (freq > highest)
-                       highest = freq;
-               if (freq < lowest)
-                       lowest = freq;
-
-               rate_error = abs(freq - rate);
-               if (rate_error < rate_error_prev) {
-                       rate_best_fit = freq;
-                       rate_error_prev = rate_error;
-               }
-
-               if (rate_error == 0)
-                       break;
-       }
-
-       if (rate >= highest)
-               rate_best_fit = highest;
-       if (rate <= lowest)
-               rate_best_fit = lowest;
-
-       return rate_best_fit;
-}
-
-int clk_rate_table_find(struct clk *clk,
-                       struct cpufreq_frequency_table *freq_table,
-                       unsigned long rate)
-{
-       int i;
-
-       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
-               unsigned long freq = freq_table[i].frequency;
-
-               if (freq == CPUFREQ_ENTRY_INVALID)
-                       continue;
-
-               if (freq == rate)
-                       return i;
-       }
-
-       return -ENOENT;
-}
-
-/* Used for clocks that always have same value as the parent clock */
-unsigned long followparent_recalc(struct clk *clk)
-{
-       return clk->parent ? clk->parent->rate : 0;
-}
-
-int clk_reparent(struct clk *child, struct clk *parent)
-{
-       list_del_init(&child->sibling);
-       if (parent)
-               list_add(&child->sibling, &parent->children);
-       child->parent = parent;
-
-       /* now do the debugfs renaming to reattach the child
-          to the proper parent */
-
-       return 0;
-}
-
-/* Propagate rate to children */
-void propagate_rate(struct clk *tclk)
-{
-       struct clk *clkp;
-
-       list_for_each_entry(clkp, &tclk->children, sibling) {
-               if (clkp->ops && clkp->ops->recalc)
-                       clkp->rate = clkp->ops->recalc(clkp);
-
-               propagate_rate(clkp);
-       }
-}
-
-static void __clk_disable(struct clk *clk)
-{
-       if (WARN(!clk->usecount, "Trying to disable clock %s with 0 usecount\n",
-                clk->name))
-               return;
-
-       if (!(--clk->usecount)) {
-               if (likely(clk->ops && clk->ops->disable))
-                       clk->ops->disable(clk);
-               if (likely(clk->parent))
-                       __clk_disable(clk->parent);
-       }
-}
-
-void clk_disable(struct clk *clk)
-{
-       unsigned long flags;
-
-       if (!clk)
-               return;
-
-       spin_lock_irqsave(&clock_lock, flags);
-       __clk_disable(clk);
-       spin_unlock_irqrestore(&clock_lock, flags);
-}
-EXPORT_SYMBOL_GPL(clk_disable);
-
-static int __clk_enable(struct clk *clk)
-{
-       int ret = 0;
-
-       if (clk->usecount++ == 0) {
-               if (clk->parent) {
-                       ret = __clk_enable(clk->parent);
-                       if (unlikely(ret))
-                               goto err;
-               }
-
-               if (clk->ops && clk->ops->enable) {
-                       ret = clk->ops->enable(clk);
-                       if (ret) {
-                               if (clk->parent)
-                                       __clk_disable(clk->parent);
-                               goto err;
-                       }
-               }
-       }
-
-       return ret;
-err:
-       clk->usecount--;
-       return ret;
-}
-
-int clk_enable(struct clk *clk)
-{
-       unsigned long flags;
-       int ret;
-
-       if (!clk)
-               return -EINVAL;
-
-       spin_lock_irqsave(&clock_lock, flags);
-       ret = __clk_enable(clk);
-       spin_unlock_irqrestore(&clock_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(clk_enable);
-
-static LIST_HEAD(root_clks);
-
-/**
- * recalculate_root_clocks - recalculate and propagate all root clocks
- *
- * Recalculates all root clocks (clocks with no parent), which if the
- * clock's .recalc is set correctly, should also propagate their rates.
- * Called at init.
- */
-void recalculate_root_clocks(void)
-{
-       struct clk *clkp;
-
-       list_for_each_entry(clkp, &root_clks, sibling) {
-               if (clkp->ops && clkp->ops->recalc)
-                       clkp->rate = clkp->ops->recalc(clkp);
-               propagate_rate(clkp);
-       }
-}
-
-int clk_register(struct clk *clk)
-{
-       if (clk == NULL || IS_ERR(clk))
-               return -EINVAL;
-
-       /*
-        * trap out already registered clocks
-        */
-       if (clk->node.next || clk->node.prev)
-               return 0;
-
-       mutex_lock(&clock_list_sem);
-
-       INIT_LIST_HEAD(&clk->children);
-       clk->usecount = 0;
-
-       if (clk->parent)
-               list_add(&clk->sibling, &clk->parent->children);
-       else
-               list_add(&clk->sibling, &root_clks);
-
-       list_add(&clk->node, &clock_list);
-       if (clk->ops && clk->ops->init)
-               clk->ops->init(clk);
-       mutex_unlock(&clock_list_sem);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
-       mutex_lock(&clock_list_sem);
-       list_del(&clk->sibling);
-       list_del(&clk->node);
-       mutex_unlock(&clock_list_sem);
-}
-EXPORT_SYMBOL_GPL(clk_unregister);
-
-void clk_enable_init_clocks(void)
-{
-       struct clk *clkp;
-
-       list_for_each_entry(clkp, &clock_list, node)
-               if (clkp->flags & CLK_ENABLE_ON_INIT)
-                       clk_enable(clkp);
-}
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-       return clk->rate;
-}
-EXPORT_SYMBOL_GPL(clk_get_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-       return clk_set_rate_ex(clk, rate, 0);
-}
-EXPORT_SYMBOL_GPL(clk_set_rate);
-
-int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
-{
-       int ret = -EOPNOTSUPP;
-       unsigned long flags;
-
-       spin_lock_irqsave(&clock_lock, flags);
-
-       if (likely(clk->ops && clk->ops->set_rate)) {
-               ret = clk->ops->set_rate(clk, rate, algo_id);
-               if (ret != 0)
-                       goto out_unlock;
-       } else {
-               clk->rate = rate;
-               ret = 0;
-       }
-
-       if (clk->ops && clk->ops->recalc)
-               clk->rate = clk->ops->recalc(clk);
-
-       propagate_rate(clk);
-
-out_unlock:
-       spin_unlock_irqrestore(&clock_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(clk_set_rate_ex);
-
-int clk_set_parent(struct clk *clk, struct clk *parent)
-{
-       unsigned long flags;
-       int ret = -EINVAL;
-
-       if (!parent || !clk)
-               return ret;
-       if (clk->parent == parent)
-               return 0;
-
-       spin_lock_irqsave(&clock_lock, flags);
-       if (clk->usecount == 0) {
-               if (clk->ops->set_parent)
-                       ret = clk->ops->set_parent(clk, parent);
-               else
-                       ret = clk_reparent(clk, parent);
-
-               if (ret == 0) {
-                       pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
-                                clk->name, clk->parent->name, clk->rate);
-                       if (clk->ops->recalc)
-                               clk->rate = clk->ops->recalc(clk);
-                       propagate_rate(clk);
-               }
-       } else
-               ret = -EBUSY;
-       spin_unlock_irqrestore(&clock_lock, flags);
-
-       return ret;
-}
-EXPORT_SYMBOL_GPL(clk_set_parent);
-
-struct clk *clk_get_parent(struct clk *clk)
-{
-       return clk->parent;
-}
-EXPORT_SYMBOL_GPL(clk_get_parent);
-
-long clk_round_rate(struct clk *clk, unsigned long rate)
-{
-       if (likely(clk->ops && clk->ops->round_rate)) {
-               unsigned long flags, rounded;
-
-               spin_lock_irqsave(&clock_lock, flags);
-               rounded = clk->ops->round_rate(clk, rate);
-               spin_unlock_irqrestore(&clock_lock, flags);
-
-               return rounded;
-       }
-
-       return clk_get_rate(clk);
-}
-EXPORT_SYMBOL_GPL(clk_round_rate);
-
-#ifdef CONFIG_PM
-static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
-{
-       static pm_message_t prev_state;
-       struct clk *clkp;
-
-       switch (state.event) {
-       case PM_EVENT_ON:
-               /* Resumeing from hibernation */
-               if (prev_state.event != PM_EVENT_FREEZE)
-                       break;
-
-               list_for_each_entry(clkp, &clock_list, node) {
-                       if (likely(clkp->ops)) {
-                               unsigned long rate = clkp->rate;
-
-                               if (likely(clkp->ops->set_parent))
-                                       clkp->ops->set_parent(clkp,
-                                               clkp->parent);
-                               if (likely(clkp->ops->set_rate))
-                                       clkp->ops->set_rate(clkp,
-                                               rate, NO_CHANGE);
-                               else if (likely(clkp->ops->recalc))
-                                       clkp->rate = clkp->ops->recalc(clkp);
-                       }
-               }
-               break;
-       case PM_EVENT_FREEZE:
-               break;
-       case PM_EVENT_SUSPEND:
-               break;
-       }
-
-       prev_state = state;
-       return 0;
-}
-
-static int clks_sysdev_resume(struct sys_device *dev)
-{
-       return clks_sysdev_suspend(dev, PMSG_ON);
-}
-
-static struct sysdev_class clks_sysdev_class = {
-       .name = "clks",
-};
-
-static struct sysdev_driver clks_sysdev_driver = {
-       .suspend = clks_sysdev_suspend,
-       .resume = clks_sysdev_resume,
-};
-
-static struct sys_device clks_sysdev_dev = {
-       .cls = &clks_sysdev_class,
-};
-
-static int __init clk_sysdev_init(void)
-{
-       sysdev_class_register(&clks_sysdev_class);
-       sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver);
-       sysdev_register(&clks_sysdev_dev);
-
-       return 0;
-}
-subsys_initcall(clk_sysdev_init);
-#endif
-
-/*
- *     debugfs support to trace clock tree hierarchy and attributes
- */
-static struct dentry *clk_debugfs_root;
-
-static int clk_debugfs_register_one(struct clk *c)
-{
-       int err;
-       struct dentry *d, *child, *child_tmp;
-       struct clk *pa = c->parent;
-       char s[255];
-       char *p = s;
-
-       p += sprintf(p, "%s", c->name);
-       if (c->id >= 0)
-               sprintf(p, ":%d", c->id);
-       d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
-       if (!d)
-               return -ENOMEM;
-       c->dentry = d;
-
-       d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       return 0;
-
-err_out:
-       d = c->dentry;
-       list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
-               debugfs_remove(child);
-       debugfs_remove(c->dentry);
-       return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
-       int err;
-       struct clk *pa = c->parent;
-
-       if (pa && !pa->dentry) {
-               err = clk_debugfs_register(pa);
-               if (err)
-                       return err;
-       }
-
-       if (!c->dentry && c->name) {
-               err = clk_debugfs_register_one(c);
-               if (err)
-                       return err;
-       }
-       return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
-       struct clk *c;
-       struct dentry *d;
-       int err;
-
-       d = debugfs_create_dir("clock", NULL);
-       if (!d)
-               return -ENOMEM;
-       clk_debugfs_root = d;
-
-       list_for_each_entry(c, &clock_list, node) {
-               err = clk_debugfs_register(c);
-               if (err)
-                       goto err_out;
-       }
-       return 0;
-err_out:
-       debugfs_remove_recursive(clk_debugfs_root);
-       return err;
-}
-late_initcall(clk_debugfs_init);
diff --git a/drivers/sh/clk/Makefile b/drivers/sh/clk/Makefile
new file mode 100644 (file)
index 0000000..5d15ebf
--- /dev/null
@@ -0,0 +1,3 @@
+obj-y  := core.o
+
+obj-$(CONFIG_SH_CLK_CPG)       += cpg.o
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
new file mode 100644 (file)
index 0000000..fd0d1b9
--- /dev/null
@@ -0,0 +1,694 @@
+/*
+ * SuperH clock framework
+ *
+ *  Copyright (C) 2005 - 2010  Paul Mundt
+ *
+ * This clock framework is derived from the OMAP version by:
+ *
+ *     Copyright (C) 2004 - 2008 Nokia Corporation
+ *     Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
+ *
+ *  Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com>
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "clock: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/sysdev.h>
+#include <linux/seq_file.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/cpufreq.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
+
+static LIST_HEAD(clock_list);
+static DEFINE_SPINLOCK(clock_lock);
+static DEFINE_MUTEX(clock_list_sem);
+
+void clk_rate_table_build(struct clk *clk,
+                         struct cpufreq_frequency_table *freq_table,
+                         int nr_freqs,
+                         struct clk_div_mult_table *src_table,
+                         unsigned long *bitmap)
+{
+       unsigned long mult, div;
+       unsigned long freq;
+       int i;
+
+       clk->nr_freqs = nr_freqs;
+
+       for (i = 0; i < nr_freqs; i++) {
+               div = 1;
+               mult = 1;
+
+               if (src_table->divisors && i < src_table->nr_divisors)
+                       div = src_table->divisors[i];
+
+               if (src_table->multipliers && i < src_table->nr_multipliers)
+                       mult = src_table->multipliers[i];
+
+               if (!div || !mult || (bitmap && !test_bit(i, bitmap)))
+                       freq = CPUFREQ_ENTRY_INVALID;
+               else
+                       freq = clk->parent->rate * mult / div;
+
+               freq_table[i].index = i;
+               freq_table[i].frequency = freq;
+       }
+
+       /* Termination entry */
+       freq_table[i].index = i;
+       freq_table[i].frequency = CPUFREQ_TABLE_END;
+}
+
+struct clk_rate_round_data;
+
+struct clk_rate_round_data {
+       unsigned long rate;
+       unsigned int min, max;
+       long (*func)(unsigned int, struct clk_rate_round_data *);
+       void *arg;
+};
+
+#define for_each_frequency(pos, r, freq)                       \
+       for (pos = r->min, freq = r->func(pos, r);              \
+            pos <= r->max; pos++, freq = r->func(pos, r))      \
+               if (unlikely(freq == 0))                        \
+                       ;                                       \
+               else
+
+static long clk_rate_round_helper(struct clk_rate_round_data *rounder)
+{
+       unsigned long rate_error, rate_error_prev = ~0UL;
+       unsigned long rate_best_fit = rounder->rate;
+       unsigned long highest, lowest, freq;
+       int i;
+
+       highest = 0;
+       lowest = ~0UL;
+
+       for_each_frequency(i, rounder, freq) {
+               if (freq > highest)
+                       highest = freq;
+               if (freq < lowest)
+                       lowest = freq;
+
+               rate_error = abs(freq - rounder->rate);
+               if (rate_error < rate_error_prev) {
+                       rate_best_fit = freq;
+                       rate_error_prev = rate_error;
+               }
+
+               if (rate_error == 0)
+                       break;
+       }
+
+       if (rounder->rate >= highest)
+               rate_best_fit = highest;
+       if (rounder->rate <= lowest)
+               rate_best_fit = lowest;
+
+       return rate_best_fit;
+}
+
+static long clk_rate_table_iter(unsigned int pos,
+                               struct clk_rate_round_data *rounder)
+{
+       struct cpufreq_frequency_table *freq_table = rounder->arg;
+       unsigned long freq = freq_table[pos].frequency;
+
+       if (freq == CPUFREQ_ENTRY_INVALID)
+               freq = 0;
+
+       return freq;
+}
+
+long clk_rate_table_round(struct clk *clk,
+                         struct cpufreq_frequency_table *freq_table,
+                         unsigned long rate)
+{
+       struct clk_rate_round_data table_round = {
+               .min    = 0,
+               .max    = clk->nr_freqs - 1,
+               .func   = clk_rate_table_iter,
+               .arg    = freq_table,
+               .rate   = rate,
+       };
+
+       if (clk->nr_freqs < 1)
+               return 0;
+
+       return clk_rate_round_helper(&table_round);
+}
+
+static long clk_rate_div_range_iter(unsigned int pos,
+                                   struct clk_rate_round_data *rounder)
+{
+       return clk_get_rate(rounder->arg) / pos;
+}
+
+long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
+                             unsigned int div_max, unsigned long rate)
+{
+       struct clk_rate_round_data div_range_round = {
+               .min    = div_min,
+               .max    = div_max,
+               .func   = clk_rate_div_range_iter,
+               .arg    = clk_get_parent(clk),
+               .rate   = rate,
+       };
+
+       return clk_rate_round_helper(&div_range_round);
+}
+
+int clk_rate_table_find(struct clk *clk,
+                       struct cpufreq_frequency_table *freq_table,
+                       unsigned long rate)
+{
+       int i;
+
+       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+               unsigned long freq = freq_table[i].frequency;
+
+               if (freq == CPUFREQ_ENTRY_INVALID)
+                       continue;
+
+               if (freq == rate)
+                       return i;
+       }
+
+       return -ENOENT;
+}
+
+/* Used for clocks that always have same value as the parent clock */
+unsigned long followparent_recalc(struct clk *clk)
+{
+       return clk->parent ? clk->parent->rate : 0;
+}
+
+int clk_reparent(struct clk *child, struct clk *parent)
+{
+       list_del_init(&child->sibling);
+       if (parent)
+               list_add(&child->sibling, &parent->children);
+       child->parent = parent;
+
+       /* now do the debugfs renaming to reattach the child
+          to the proper parent */
+
+       return 0;
+}
+
+/* Propagate rate to children */
+void propagate_rate(struct clk *tclk)
+{
+       struct clk *clkp;
+
+       list_for_each_entry(clkp, &tclk->children, sibling) {
+               if (clkp->ops && clkp->ops->recalc)
+                       clkp->rate = clkp->ops->recalc(clkp);
+
+               propagate_rate(clkp);
+       }
+}
+
+static void __clk_disable(struct clk *clk)
+{
+       if (WARN(!clk->usecount, "Trying to disable clock %p with 0 usecount\n",
+                clk))
+               return;
+
+       if (!(--clk->usecount)) {
+               if (likely(clk->ops && clk->ops->disable))
+                       clk->ops->disable(clk);
+               if (likely(clk->parent))
+                       __clk_disable(clk->parent);
+       }
+}
+
+void clk_disable(struct clk *clk)
+{
+       unsigned long flags;
+
+       if (!clk)
+               return;
+
+       spin_lock_irqsave(&clock_lock, flags);
+       __clk_disable(clk);
+       spin_unlock_irqrestore(&clock_lock, flags);
+}
+EXPORT_SYMBOL_GPL(clk_disable);
+
+static int __clk_enable(struct clk *clk)
+{
+       int ret = 0;
+
+       if (clk->usecount++ == 0) {
+               if (clk->parent) {
+                       ret = __clk_enable(clk->parent);
+                       if (unlikely(ret))
+                               goto err;
+               }
+
+               if (clk->ops && clk->ops->enable) {
+                       ret = clk->ops->enable(clk);
+                       if (ret) {
+                               if (clk->parent)
+                                       __clk_disable(clk->parent);
+                               goto err;
+                       }
+               }
+       }
+
+       return ret;
+err:
+       clk->usecount--;
+       return ret;
+}
+
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+       int ret;
+
+       if (!clk)
+               return -EINVAL;
+
+       spin_lock_irqsave(&clock_lock, flags);
+       ret = __clk_enable(clk);
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_enable);
+
+static LIST_HEAD(root_clks);
+
+/**
+ * recalculate_root_clocks - recalculate and propagate all root clocks
+ *
+ * Recalculates all root clocks (clocks with no parent), which if the
+ * clock's .recalc is set correctly, should also propagate their rates.
+ * Called at init.
+ */
+void recalculate_root_clocks(void)
+{
+       struct clk *clkp;
+
+       list_for_each_entry(clkp, &root_clks, sibling) {
+               if (clkp->ops && clkp->ops->recalc)
+                       clkp->rate = clkp->ops->recalc(clkp);
+               propagate_rate(clkp);
+       }
+}
+
+static struct clk_mapping dummy_mapping;
+
+static struct clk *lookup_root_clock(struct clk *clk)
+{
+       while (clk->parent)
+               clk = clk->parent;
+
+       return clk;
+}
+
+static int clk_establish_mapping(struct clk *clk)
+{
+       struct clk_mapping *mapping = clk->mapping;
+
+       /*
+        * Propagate mappings.
+        */
+       if (!mapping) {
+               struct clk *clkp;
+
+               /*
+                * dummy mapping for root clocks with no specified ranges
+                */
+               if (!clk->parent) {
+                       clk->mapping = &dummy_mapping;
+                       return 0;
+               }
+
+               /*
+                * If we're on a child clock and it provides no mapping of its
+                * own, inherit the mapping from its root clock.
+                */
+               clkp = lookup_root_clock(clk);
+               mapping = clkp->mapping;
+               BUG_ON(!mapping);
+       }
+
+       /*
+        * Establish initial mapping.
+        */
+       if (!mapping->base && mapping->phys) {
+               kref_init(&mapping->ref);
+
+               mapping->base = ioremap_nocache(mapping->phys, mapping->len);
+               if (unlikely(!mapping->base))
+                       return -ENXIO;
+       } else if (mapping->base) {
+               /*
+                * Bump the refcount for an existing mapping
+                */
+               kref_get(&mapping->ref);
+       }
+
+       clk->mapping = mapping;
+       return 0;
+}
+
+static void clk_destroy_mapping(struct kref *kref)
+{
+       struct clk_mapping *mapping;
+
+       mapping = container_of(kref, struct clk_mapping, ref);
+
+       iounmap(mapping->base);
+}
+
+static void clk_teardown_mapping(struct clk *clk)
+{
+       struct clk_mapping *mapping = clk->mapping;
+
+       /* Nothing to do */
+       if (mapping == &dummy_mapping)
+               return;
+
+       kref_put(&mapping->ref, clk_destroy_mapping);
+       clk->mapping = NULL;
+}
+
+int clk_register(struct clk *clk)
+{
+       int ret;
+
+       if (clk == NULL || IS_ERR(clk))
+               return -EINVAL;
+
+       /*
+        * trap out already registered clocks
+        */
+       if (clk->node.next || clk->node.prev)
+               return 0;
+
+       mutex_lock(&clock_list_sem);
+
+       INIT_LIST_HEAD(&clk->children);
+       clk->usecount = 0;
+
+       ret = clk_establish_mapping(clk);
+       if (unlikely(ret))
+               goto out_unlock;
+
+       if (clk->parent)
+               list_add(&clk->sibling, &clk->parent->children);
+       else
+               list_add(&clk->sibling, &root_clks);
+
+       list_add(&clk->node, &clock_list);
+       if (clk->ops && clk->ops->init)
+               clk->ops->init(clk);
+
+out_unlock:
+       mutex_unlock(&clock_list_sem);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+       mutex_lock(&clock_list_sem);
+       list_del(&clk->sibling);
+       list_del(&clk->node);
+       clk_teardown_mapping(clk);
+       mutex_unlock(&clock_list_sem);
+}
+EXPORT_SYMBOL_GPL(clk_unregister);
+
+void clk_enable_init_clocks(void)
+{
+       struct clk *clkp;
+
+       list_for_each_entry(clkp, &clock_list, node)
+               if (clkp->flags & CLK_ENABLE_ON_INIT)
+                       clk_enable(clkp);
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+       return clk->rate;
+}
+EXPORT_SYMBOL_GPL(clk_get_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+       return clk_set_rate_ex(clk, rate, 0);
+}
+EXPORT_SYMBOL_GPL(clk_set_rate);
+
+int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id)
+{
+       int ret = -EOPNOTSUPP;
+       unsigned long flags;
+
+       spin_lock_irqsave(&clock_lock, flags);
+
+       if (likely(clk->ops && clk->ops->set_rate)) {
+               ret = clk->ops->set_rate(clk, rate, algo_id);
+               if (ret != 0)
+                       goto out_unlock;
+       } else {
+               clk->rate = rate;
+               ret = 0;
+       }
+
+       if (clk->ops && clk->ops->recalc)
+               clk->rate = clk->ops->recalc(clk);
+
+       propagate_rate(clk);
+
+out_unlock:
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_rate_ex);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+       unsigned long flags;
+       int ret = -EINVAL;
+
+       if (!parent || !clk)
+               return ret;
+       if (clk->parent == parent)
+               return 0;
+
+       spin_lock_irqsave(&clock_lock, flags);
+       if (clk->usecount == 0) {
+               if (clk->ops->set_parent)
+                       ret = clk->ops->set_parent(clk, parent);
+               else
+                       ret = clk_reparent(clk, parent);
+
+               if (ret == 0) {
+                       if (clk->ops->recalc)
+                               clk->rate = clk->ops->recalc(clk);
+                       pr_debug("set parent of %p to %p (new rate %ld)\n",
+                                clk, clk->parent, clk->rate);
+                       propagate_rate(clk);
+               }
+       } else
+               ret = -EBUSY;
+       spin_unlock_irqrestore(&clock_lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(clk_set_parent);
+
+struct clk *clk_get_parent(struct clk *clk)
+{
+       return clk->parent;
+}
+EXPORT_SYMBOL_GPL(clk_get_parent);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+       if (likely(clk->ops && clk->ops->round_rate)) {
+               unsigned long flags, rounded;
+
+               spin_lock_irqsave(&clock_lock, flags);
+               rounded = clk->ops->round_rate(clk, rate);
+               spin_unlock_irqrestore(&clock_lock, flags);
+
+               return rounded;
+       }
+
+       return clk_get_rate(clk);
+}
+EXPORT_SYMBOL_GPL(clk_round_rate);
+
+#ifdef CONFIG_PM
+static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
+{
+       static pm_message_t prev_state;
+       struct clk *clkp;
+
+       switch (state.event) {
+       case PM_EVENT_ON:
+               /* Resumeing from hibernation */
+               if (prev_state.event != PM_EVENT_FREEZE)
+                       break;
+
+               list_for_each_entry(clkp, &clock_list, node) {
+                       if (likely(clkp->ops)) {
+                               unsigned long rate = clkp->rate;
+
+                               if (likely(clkp->ops->set_parent))
+                                       clkp->ops->set_parent(clkp,
+                                               clkp->parent);
+                               if (likely(clkp->ops->set_rate))
+                                       clkp->ops->set_rate(clkp,
+                                               rate, NO_CHANGE);
+                               else if (likely(clkp->ops->recalc))
+                                       clkp->rate = clkp->ops->recalc(clkp);
+                       }
+               }
+               break;
+       case PM_EVENT_FREEZE:
+               break;
+       case PM_EVENT_SUSPEND:
+               break;
+       }
+
+       prev_state = state;
+       return 0;
+}
+
+static int clks_sysdev_resume(struct sys_device *dev)
+{
+       return clks_sysdev_suspend(dev, PMSG_ON);
+}
+
+static struct sysdev_class clks_sysdev_class = {
+       .name = "clks",
+};
+
+static struct sysdev_driver clks_sysdev_driver = {
+       .suspend = clks_sysdev_suspend,
+       .resume = clks_sysdev_resume,
+};
+
+static struct sys_device clks_sysdev_dev = {
+       .cls = &clks_sysdev_class,
+};
+
+static int __init clk_sysdev_init(void)
+{
+       sysdev_class_register(&clks_sysdev_class);
+       sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver);
+       sysdev_register(&clks_sysdev_dev);
+
+       return 0;
+}
+subsys_initcall(clk_sysdev_init);
+#endif
+
+/*
+ *     debugfs support to trace clock tree hierarchy and attributes
+ */
+static struct dentry *clk_debugfs_root;
+
+static int clk_debugfs_register_one(struct clk *c)
+{
+       int err;
+       struct dentry *d, *child, *child_tmp;
+       struct clk *pa = c->parent;
+       char s[255];
+       char *p = s;
+
+       p += sprintf(p, "%p", c);
+       d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
+       if (!d)
+               return -ENOMEM;
+       c->dentry = d;
+
+       d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
+       if (!d) {
+               err = -ENOMEM;
+               goto err_out;
+       }
+       d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
+       if (!d) {
+               err = -ENOMEM;
+               goto err_out;
+       }
+       d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
+       if (!d) {
+               err = -ENOMEM;
+               goto err_out;
+       }
+       return 0;
+
+err_out:
+       d = c->dentry;
+       list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
+               debugfs_remove(child);
+       debugfs_remove(c->dentry);
+       return err;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+       int err;
+       struct clk *pa = c->parent;
+
+       if (pa && !pa->dentry) {
+               err = clk_debugfs_register(pa);
+               if (err)
+                       return err;
+       }
+
+       if (!c->dentry) {
+               err = clk_debugfs_register_one(c);
+               if (err)
+                       return err;
+       }
+       return 0;
+}
+
+static int __init clk_debugfs_init(void)
+{
+       struct clk *c;
+       struct dentry *d;
+       int err;
+
+       d = debugfs_create_dir("clock", NULL);
+       if (!d)
+               return -ENOMEM;
+       clk_debugfs_root = d;
+
+       list_for_each_entry(c, &clock_list, node) {
+               err = clk_debugfs_register(c);
+               if (err)
+                       goto err_out;
+       }
+       return 0;
+err_out:
+       debugfs_remove_recursive(clk_debugfs_root);
+       return err;
+}
+late_initcall(clk_debugfs_init);
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
new file mode 100644 (file)
index 0000000..3aea5f0
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Helper routines for SuperH Clock Pulse Generator blocks (CPG).
+ *
+ *  Copyright (C) 2010  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/clk.h>
+#include <linux/compiler.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/sh_clk.h>
+
+static int sh_clk_mstp32_enable(struct clk *clk)
+{
+       __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
+                    clk->enable_reg);
+       return 0;
+}
+
+static void sh_clk_mstp32_disable(struct clk *clk)
+{
+       __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
+                    clk->enable_reg);
+}
+
+static struct clk_ops sh_clk_mstp32_clk_ops = {
+       .enable         = sh_clk_mstp32_enable,
+       .disable        = sh_clk_mstp32_disable,
+       .recalc         = followparent_recalc,
+};
+
+int __init sh_clk_mstp32_register(struct clk *clks, int nr)
+{
+       struct clk *clkp;
+       int ret = 0;
+       int k;
+
+       for (k = 0; !ret && (k < nr); k++) {
+               clkp = clks + k;
+               clkp->ops = &sh_clk_mstp32_clk_ops;
+               ret |= clk_register(clkp);
+       }
+
+       return ret;
+}
+
+static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
+{
+       return clk_rate_table_round(clk, clk->freq_table, rate);
+}
+
+static int sh_clk_div6_divisors[64] = {
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+       33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+       49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
+};
+
+static struct clk_div_mult_table sh_clk_div6_table = {
+       .divisors = sh_clk_div6_divisors,
+       .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
+};
+
+static unsigned long sh_clk_div6_recalc(struct clk *clk)
+{
+       struct clk_div_mult_table *table = &sh_clk_div6_table;
+       unsigned int idx;
+
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, NULL);
+
+       idx = __raw_readl(clk->enable_reg) & 0x003f;
+
+       return clk->freq_table[idx].frequency;
+}
+
+static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+{
+       struct clk_div_mult_table *table = &sh_clk_div6_table;
+       u32 value;
+       int ret, i;
+
+       if (!clk->parent_table || !clk->parent_num)
+               return -EINVAL;
+
+       /* Search the parent */
+       for (i = 0; i < clk->parent_num; i++)
+               if (clk->parent_table[i] == parent)
+                       break;
+
+       if (i == clk->parent_num)
+               return -ENODEV;
+
+       ret = clk_reparent(clk, parent);
+       if (ret < 0)
+               return ret;
+
+       value = __raw_readl(clk->enable_reg) &
+               ~(((1 << clk->src_width) - 1) << clk->src_shift);
+
+       __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
+
+       /* Rebuild the frequency table */
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, &clk->arch_flags);
+
+       return 0;
+}
+
+static int sh_clk_div6_set_rate(struct clk *clk,
+                               unsigned long rate, int algo_id)
+{
+       unsigned long value;
+       int idx;
+
+       idx = clk_rate_table_find(clk, clk->freq_table, rate);
+       if (idx < 0)
+               return idx;
+
+       value = __raw_readl(clk->enable_reg);
+       value &= ~0x3f;
+       value |= idx;
+       __raw_writel(value, clk->enable_reg);
+       return 0;
+}
+
+static int sh_clk_div6_enable(struct clk *clk)
+{
+       unsigned long value;
+       int ret;
+
+       ret = sh_clk_div6_set_rate(clk, clk->rate, 0);
+       if (ret == 0) {
+               value = __raw_readl(clk->enable_reg);
+               value &= ~0x100; /* clear stop bit to enable clock */
+               __raw_writel(value, clk->enable_reg);
+       }
+       return ret;
+}
+
+static void sh_clk_div6_disable(struct clk *clk)
+{
+       unsigned long value;
+
+       value = __raw_readl(clk->enable_reg);
+       value |= 0x100; /* stop clock */
+       value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
+       __raw_writel(value, clk->enable_reg);
+}
+
+static struct clk_ops sh_clk_div6_clk_ops = {
+       .recalc         = sh_clk_div6_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+       .set_rate       = sh_clk_div6_set_rate,
+       .enable         = sh_clk_div6_enable,
+       .disable        = sh_clk_div6_disable,
+};
+
+static struct clk_ops sh_clk_div6_reparent_clk_ops = {
+       .recalc         = sh_clk_div6_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+       .set_rate       = sh_clk_div6_set_rate,
+       .enable         = sh_clk_div6_enable,
+       .disable        = sh_clk_div6_disable,
+       .set_parent     = sh_clk_div6_set_parent,
+};
+
+static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
+                                          struct clk_ops *ops)
+{
+       struct clk *clkp;
+       void *freq_table;
+       int nr_divs = sh_clk_div6_table.nr_divisors;
+       int freq_table_size = sizeof(struct cpufreq_frequency_table);
+       int ret = 0;
+       int k;
+
+       freq_table_size *= (nr_divs + 1);
+       freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
+       if (!freq_table) {
+               pr_err("sh_clk_div6_register: unable to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       for (k = 0; !ret && (k < nr); k++) {
+               clkp = clks + k;
+
+               clkp->ops = ops;
+               clkp->freq_table = freq_table + (k * freq_table_size);
+               clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
+
+               ret = clk_register(clkp);
+       }
+
+       return ret;
+}
+
+int __init sh_clk_div6_register(struct clk *clks, int nr)
+{
+       return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
+}
+
+int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
+{
+       return sh_clk_div6_register_ops(clks, nr,
+                                       &sh_clk_div6_reparent_clk_ops);
+}
+
+static unsigned long sh_clk_div4_recalc(struct clk *clk)
+{
+       struct clk_div4_table *d4t = clk->priv;
+       struct clk_div_mult_table *table = d4t->div_mult_table;
+       unsigned int idx;
+
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, &clk->arch_flags);
+
+       idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+
+       return clk->freq_table[idx].frequency;
+}
+
+static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
+{
+       struct clk_div4_table *d4t = clk->priv;
+       struct clk_div_mult_table *table = d4t->div_mult_table;
+       u32 value;
+       int ret;
+
+       /* we really need a better way to determine parent index, but for
+        * now assume internal parent comes with CLK_ENABLE_ON_INIT set,
+        * no CLK_ENABLE_ON_INIT means external clock...
+        */
+
+       if (parent->flags & CLK_ENABLE_ON_INIT)
+               value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+       else
+               value = __raw_readl(clk->enable_reg) | (1 << 7);
+
+       ret = clk_reparent(clk, parent);
+       if (ret < 0)
+               return ret;
+
+       __raw_writel(value, clk->enable_reg);
+
+       /* Rebiuld the frequency table */
+       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+                            table, &clk->arch_flags);
+
+       return 0;
+}
+
+static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id)
+{
+       struct clk_div4_table *d4t = clk->priv;
+       unsigned long value;
+       int idx = clk_rate_table_find(clk, clk->freq_table, rate);
+       if (idx < 0)
+               return idx;
+
+       value = __raw_readl(clk->enable_reg);
+       value &= ~(0xf << clk->enable_bit);
+       value |= (idx << clk->enable_bit);
+       __raw_writel(value, clk->enable_reg);
+
+       if (d4t->kick)
+               d4t->kick(clk);
+
+       return 0;
+}
+
+static int sh_clk_div4_enable(struct clk *clk)
+{
+       __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+       return 0;
+}
+
+static void sh_clk_div4_disable(struct clk *clk)
+{
+       __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+}
+
+static struct clk_ops sh_clk_div4_clk_ops = {
+       .recalc         = sh_clk_div4_recalc,
+       .set_rate       = sh_clk_div4_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+};
+
+static struct clk_ops sh_clk_div4_enable_clk_ops = {
+       .recalc         = sh_clk_div4_recalc,
+       .set_rate       = sh_clk_div4_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+       .enable         = sh_clk_div4_enable,
+       .disable        = sh_clk_div4_disable,
+};
+
+static struct clk_ops sh_clk_div4_reparent_clk_ops = {
+       .recalc         = sh_clk_div4_recalc,
+       .set_rate       = sh_clk_div4_set_rate,
+       .round_rate     = sh_clk_div_round_rate,
+       .enable         = sh_clk_div4_enable,
+       .disable        = sh_clk_div4_disable,
+       .set_parent     = sh_clk_div4_set_parent,
+};
+
+static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
+                       struct clk_div4_table *table, struct clk_ops *ops)
+{
+       struct clk *clkp;
+       void *freq_table;
+       int nr_divs = table->div_mult_table->nr_divisors;
+       int freq_table_size = sizeof(struct cpufreq_frequency_table);
+       int ret = 0;
+       int k;
+
+       freq_table_size *= (nr_divs + 1);
+       freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
+       if (!freq_table) {
+               pr_err("sh_clk_div4_register: unable to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       for (k = 0; !ret && (k < nr); k++) {
+               clkp = clks + k;
+
+               clkp->ops = ops;
+               clkp->priv = table;
+
+               clkp->freq_table = freq_table + (k * freq_table_size);
+               clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
+
+               ret = clk_register(clkp);
+       }
+
+       return ret;
+}
+
+int __init sh_clk_div4_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+{
+       return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
+}
+
+int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+{
+       return sh_clk_div4_register_ops(clks, nr, table,
+                                       &sh_clk_div4_enable_clk_ops);
+}
+
+int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
+                               struct clk_div4_table *table)
+{
+       return sh_clk_div4_register_ops(clks, nr, table,
+                                       &sh_clk_div4_reparent_clk_ops);
+}
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c
deleted file mode 100644 (file)
index e91a23e..0000000
+++ /dev/null
@@ -1,1390 +0,0 @@
-/*
- * Shared interrupt handling code for IPR and INTC2 types of IRQs.
- *
- * Copyright (C) 2007, 2008 Magnus Damm
- * Copyright (C) 2009, 2010 Paul Mundt
- *
- * Based on intc2.c and ipr.c
- *
- * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
- * Copyright (C) 2000  Kazumoto Kojima
- * Copyright (C) 2001  David J. Mckay (david.mckay@st.com)
- * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
- * Copyright (C) 2005, 2006  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.
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <linux/module.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/sh_intc.h>
-#include <linux/sysdev.h>
-#include <linux/list.h>
-#include <linux/topology.h>
-#include <linux/bitmap.h>
-#include <linux/cpumask.h>
-#include <asm/sizes.h>
-
-#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
-       ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
-        ((addr_e) << 16) | ((addr_d << 24)))
-
-#define _INTC_SHIFT(h) (h & 0x1f)
-#define _INTC_WIDTH(h) ((h >> 5) & 0xf)
-#define _INTC_FN(h) ((h >> 9) & 0xf)
-#define _INTC_MODE(h) ((h >> 13) & 0x7)
-#define _INTC_ADDR_E(h) ((h >> 16) & 0xff)
-#define _INTC_ADDR_D(h) ((h >> 24) & 0xff)
-
-struct intc_handle_int {
-       unsigned int irq;
-       unsigned long handle;
-};
-
-struct intc_window {
-       phys_addr_t phys;
-       void __iomem *virt;
-       unsigned long size;
-};
-
-struct intc_desc_int {
-       struct list_head list;
-       struct sys_device sysdev;
-       pm_message_t state;
-       unsigned long *reg;
-#ifdef CONFIG_SMP
-       unsigned long *smp;
-#endif
-       unsigned int nr_reg;
-       struct intc_handle_int *prio;
-       unsigned int nr_prio;
-       struct intc_handle_int *sense;
-       unsigned int nr_sense;
-       struct intc_window *window;
-       unsigned int nr_windows;
-       struct irq_chip chip;
-};
-
-static LIST_HEAD(intc_list);
-
-/*
- * The intc_irq_map provides a global map of bound IRQ vectors for a
- * given platform. Allocation of IRQs are either static through the CPU
- * vector map, or dynamic in the case of board mux vectors or MSI.
- *
- * As this is a central point for all IRQ controllers on the system,
- * each of the available sources are mapped out here. This combined with
- * sparseirq makes it quite trivial to keep the vector map tightly packed
- * when dynamically creating IRQs, as well as tying in to otherwise
- * unused irq_desc positions in the sparse array.
- */
-static DECLARE_BITMAP(intc_irq_map, NR_IRQS);
-static DEFINE_SPINLOCK(vector_lock);
-
-#ifdef CONFIG_SMP
-#define IS_SMP(x) x.smp
-#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
-#define SMP_NR(d, x) ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
-#else
-#define IS_SMP(x) 0
-#define INTC_REG(d, x, c) (d->reg[(x)])
-#define SMP_NR(d, x) 1
-#endif
-
-static unsigned int intc_prio_level[NR_IRQS];  /* for now */
-static unsigned int default_prio_level = 2;    /* 2 - 16 */
-static unsigned long ack_handle[NR_IRQS];
-#ifdef CONFIG_INTC_BALANCING
-static unsigned long dist_handle[NR_IRQS];
-#endif
-
-static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
-{
-       struct irq_chip *chip = get_irq_chip(irq);
-       return container_of(chip, struct intc_desc_int, chip);
-}
-
-static unsigned long intc_phys_to_virt(struct intc_desc_int *d,
-                                      unsigned long address)
-{
-       struct intc_window *window;
-       int k;
-
-       /* scan through physical windows and convert address */
-       for (k = 0; k < d->nr_windows; k++) {
-               window = d->window + k;
-
-               if (address < window->phys)
-                       continue;
-
-               if (address >= (window->phys + window->size))
-                       continue;
-
-               address -= window->phys;
-               address += (unsigned long)window->virt;
-
-               return address;
-       }
-
-       /* no windows defined, register must be 1:1 mapped virt:phys */
-       return address;
-}
-
-static unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address)
-{
-       unsigned int k;
-
-       address = intc_phys_to_virt(d, address);
-
-       for (k = 0; k < d->nr_reg; k++) {
-               if (d->reg[k] == address)
-                       return k;
-       }
-
-       BUG();
-       return 0;
-}
-
-static inline unsigned int set_field(unsigned int value,
-                                    unsigned int field_value,
-                                    unsigned int handle)
-{
-       unsigned int width = _INTC_WIDTH(handle);
-       unsigned int shift = _INTC_SHIFT(handle);
-
-       value &= ~(((1 << width) - 1) << shift);
-       value |= field_value << shift;
-       return value;
-}
-
-static void write_8(unsigned long addr, unsigned long h, unsigned long data)
-{
-       __raw_writeb(set_field(0, data, h), addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
-}
-
-static void write_16(unsigned long addr, unsigned long h, unsigned long data)
-{
-       __raw_writew(set_field(0, data, h), addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
-}
-
-static void write_32(unsigned long addr, unsigned long h, unsigned long data)
-{
-       __raw_writel(set_field(0, data, h), addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
-}
-
-static void modify_8(unsigned long addr, unsigned long h, unsigned long data)
-{
-       unsigned long flags;
-       local_irq_save(flags);
-       __raw_writeb(set_field(__raw_readb(addr), data, h), addr);
-       (void)__raw_readb(addr);        /* Defeat write posting */
-       local_irq_restore(flags);
-}
-
-static void modify_16(unsigned long addr, unsigned long h, unsigned long data)
-{
-       unsigned long flags;
-       local_irq_save(flags);
-       __raw_writew(set_field(__raw_readw(addr), data, h), addr);
-       (void)__raw_readw(addr);        /* Defeat write posting */
-       local_irq_restore(flags);
-}
-
-static void modify_32(unsigned long addr, unsigned long h, unsigned long data)
-{
-       unsigned long flags;
-       local_irq_save(flags);
-       __raw_writel(set_field(__raw_readl(addr), data, h), addr);
-       (void)__raw_readl(addr);        /* Defeat write posting */
-       local_irq_restore(flags);
-}
-
-enum { REG_FN_ERR = 0, REG_FN_WRITE_BASE = 1, REG_FN_MODIFY_BASE = 5 };
-
-static void (*intc_reg_fns[])(unsigned long addr,
-                             unsigned long h,
-                             unsigned long data) = {
-       [REG_FN_WRITE_BASE + 0] = write_8,
-       [REG_FN_WRITE_BASE + 1] = write_16,
-       [REG_FN_WRITE_BASE + 3] = write_32,
-       [REG_FN_MODIFY_BASE + 0] = modify_8,
-       [REG_FN_MODIFY_BASE + 1] = modify_16,
-       [REG_FN_MODIFY_BASE + 3] = modify_32,
-};
-
-enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
-       MODE_MASK_REG,       /* Bit(s) set -> interrupt disabled */
-       MODE_DUAL_REG,       /* Two registers, set bit to enable / disable */
-       MODE_PRIO_REG,       /* Priority value written to enable interrupt */
-       MODE_PCLR_REG,       /* Above plus all bits set to disable interrupt */
-};
-
-static void intc_mode_field(unsigned long addr,
-                           unsigned long handle,
-                           void (*fn)(unsigned long,
-                                      unsigned long,
-                                      unsigned long),
-                           unsigned int irq)
-{
-       fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
-}
-
-static void intc_mode_zero(unsigned long addr,
-                          unsigned long handle,
-                          void (*fn)(unsigned long,
-                                      unsigned long,
-                                      unsigned long),
-                          unsigned int irq)
-{
-       fn(addr, handle, 0);
-}
-
-static void intc_mode_prio(unsigned long addr,
-                          unsigned long handle,
-                          void (*fn)(unsigned long,
-                                      unsigned long,
-                                      unsigned long),
-                          unsigned int irq)
-{
-       fn(addr, handle, intc_prio_level[irq]);
-}
-
-static void (*intc_enable_fns[])(unsigned long addr,
-                                unsigned long handle,
-                                void (*fn)(unsigned long,
-                                           unsigned long,
-                                           unsigned long),
-                                unsigned int irq) = {
-       [MODE_ENABLE_REG] = intc_mode_field,
-       [MODE_MASK_REG] = intc_mode_zero,
-       [MODE_DUAL_REG] = intc_mode_field,
-       [MODE_PRIO_REG] = intc_mode_prio,
-       [MODE_PCLR_REG] = intc_mode_prio,
-};
-
-static void (*intc_disable_fns[])(unsigned long addr,
-                                 unsigned long handle,
-                                 void (*fn)(unsigned long,
-                                            unsigned long,
-                                            unsigned long),
-                                 unsigned int irq) = {
-       [MODE_ENABLE_REG] = intc_mode_zero,
-       [MODE_MASK_REG] = intc_mode_field,
-       [MODE_DUAL_REG] = intc_mode_field,
-       [MODE_PRIO_REG] = intc_mode_zero,
-       [MODE_PCLR_REG] = intc_mode_field,
-};
-
-#ifdef CONFIG_INTC_BALANCING
-static inline void intc_balancing_enable(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = dist_handle[irq];
-       unsigned long addr;
-
-       if (irq_balancing_disabled(irq) || !handle)
-               return;
-
-       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-       intc_reg_fns[_INTC_FN(handle)](addr, handle, 1);
-}
-
-static inline void intc_balancing_disable(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = dist_handle[irq];
-       unsigned long addr;
-
-       if (irq_balancing_disabled(irq) || !handle)
-               return;
-
-       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-       intc_reg_fns[_INTC_FN(handle)](addr, handle, 0);
-}
-
-static unsigned int intc_dist_data(struct intc_desc *desc,
-                                  struct intc_desc_int *d,
-                                  intc_enum enum_id)
-{
-       struct intc_mask_reg *mr = desc->hw.mask_regs;
-       unsigned int i, j, fn, mode;
-       unsigned long reg_e, reg_d;
-
-       for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) {
-               mr = desc->hw.mask_regs + i;
-
-               /*
-                * Skip this entry if there's no auto-distribution
-                * register associated with it.
-                */
-               if (!mr->dist_reg)
-                       continue;
-
-               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
-                       if (mr->enum_ids[j] != enum_id)
-                               continue;
-
-                       fn = REG_FN_MODIFY_BASE;
-                       mode = MODE_ENABLE_REG;
-                       reg_e = mr->dist_reg;
-                       reg_d = mr->dist_reg;
-
-                       fn += (mr->reg_width >> 3) - 1;
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       1,
-                                       (mr->reg_width - 1) - j);
-               }
-       }
-
-       /*
-        * It's possible we've gotten here with no distribution options
-        * available for the IRQ in question, so we just skip over those.
-        */
-       return 0;
-}
-#else
-static inline void intc_balancing_enable(unsigned int irq)
-{
-}
-
-static inline void intc_balancing_disable(unsigned int irq)
-{
-}
-#endif
-
-static inline void _intc_enable(unsigned int irq, unsigned long handle)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long addr;
-       unsigned int cpu;
-
-       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
-#ifdef CONFIG_SMP
-               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
-                       continue;
-#endif
-               addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
-               intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
-                                                   [_INTC_FN(handle)], irq);
-       }
-
-       intc_balancing_enable(irq);
-}
-
-static void intc_enable(unsigned int irq)
-{
-       _intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
-}
-
-static void intc_disable(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = (unsigned long)get_irq_chip_data(irq);
-       unsigned long addr;
-       unsigned int cpu;
-
-       intc_balancing_disable(irq);
-
-       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
-#ifdef CONFIG_SMP
-               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
-                       continue;
-#endif
-               addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
-               intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
-                                                    [_INTC_FN(handle)], irq);
-       }
-}
-
-static void (*intc_enable_noprio_fns[])(unsigned long addr,
-                                       unsigned long handle,
-                                       void (*fn)(unsigned long,
-                                                  unsigned long,
-                                                  unsigned long),
-                                       unsigned int irq) = {
-       [MODE_ENABLE_REG] = intc_mode_field,
-       [MODE_MASK_REG] = intc_mode_zero,
-       [MODE_DUAL_REG] = intc_mode_field,
-       [MODE_PRIO_REG] = intc_mode_field,
-       [MODE_PCLR_REG] = intc_mode_field,
-};
-
-static void intc_enable_disable(struct intc_desc_int *d,
-                               unsigned long handle, int do_enable)
-{
-       unsigned long addr;
-       unsigned int cpu;
-       void (*fn)(unsigned long, unsigned long,
-                  void (*)(unsigned long, unsigned long, unsigned long),
-                  unsigned int);
-
-       if (do_enable) {
-               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
-                       addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
-                       fn = intc_enable_noprio_fns[_INTC_MODE(handle)];
-                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
-               }
-       } else {
-               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
-                       addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
-                       fn = intc_disable_fns[_INTC_MODE(handle)];
-                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
-               }
-       }
-}
-
-static int intc_set_wake(unsigned int irq, unsigned int on)
-{
-       return 0; /* allow wakeup, but setup hardware in intc_suspend() */
-}
-
-#ifdef CONFIG_SMP
-/*
- * This is held with the irq desc lock held, so we don't require any
- * additional locking here at the intc desc level. The affinity mask is
- * later tested in the enable/disable paths.
- */
-static int intc_set_affinity(unsigned int irq, const struct cpumask *cpumask)
-{
-       if (!cpumask_intersects(cpumask, cpu_online_mask))
-               return -1;
-
-       cpumask_copy(irq_to_desc(irq)->affinity, cpumask);
-
-       return 0;
-}
-#endif
-
-static void intc_mask_ack(unsigned int irq)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned long handle = ack_handle[irq];
-       unsigned long addr;
-
-       intc_disable(irq);
-
-       /* read register and write zero only to the associated bit */
-       if (handle) {
-               addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
-               switch (_INTC_FN(handle)) {
-               case REG_FN_MODIFY_BASE + 0:    /* 8bit */
-                       __raw_readb(addr);
-                       __raw_writeb(0xff ^ set_field(0, 1, handle), addr);
-                       break;
-               case REG_FN_MODIFY_BASE + 1:    /* 16bit */
-                       __raw_readw(addr);
-                       __raw_writew(0xffff ^ set_field(0, 1, handle), addr);
-                       break;
-               case REG_FN_MODIFY_BASE + 3:    /* 32bit */
-                       __raw_readl(addr);
-                       __raw_writel(0xffffffff ^ set_field(0, 1, handle), addr);
-                       break;
-               default:
-                       BUG();
-                       break;
-               }
-       }
-}
-
-static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
-                                            unsigned int nr_hp,
-                                            unsigned int irq)
-{
-       int i;
-
-       /*
-        * this doesn't scale well, but...
-        *
-        * this function should only be used for cerain uncommon
-        * operations such as intc_set_priority() and intc_set_sense()
-        * and in those rare cases performance doesn't matter that much.
-        * keeping the memory footprint low is more important.
-        *
-        * one rather simple way to speed this up and still keep the
-        * memory footprint down is to make sure the array is sorted
-        * and then perform a bisect to lookup the irq.
-        */
-       for (i = 0; i < nr_hp; i++) {
-               if ((hp + i)->irq != irq)
-                       continue;
-
-               return hp + i;
-       }
-
-       return NULL;
-}
-
-int intc_set_priority(unsigned int irq, unsigned int prio)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       struct intc_handle_int *ihp;
-
-       if (!intc_prio_level[irq] || prio <= 1)
-               return -EINVAL;
-
-       ihp = intc_find_irq(d->prio, d->nr_prio, irq);
-       if (ihp) {
-               if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
-                       return -EINVAL;
-
-               intc_prio_level[irq] = prio;
-
-               /*
-                * only set secondary masking method directly
-                * primary masking method is using intc_prio_level[irq]
-                * priority level will be set during next enable()
-                */
-               if (_INTC_FN(ihp->handle) != REG_FN_ERR)
-                       _intc_enable(irq, ihp->handle);
-       }
-       return 0;
-}
-
-#define VALID(x) (x | 0x80)
-
-static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
-       [IRQ_TYPE_EDGE_FALLING] = VALID(0),
-       [IRQ_TYPE_EDGE_RISING] = VALID(1),
-       [IRQ_TYPE_LEVEL_LOW] = VALID(2),
-       /* SH7706, SH7707 and SH7709 do not support high level triggered */
-#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
-    !defined(CONFIG_CPU_SUBTYPE_SH7709)
-       [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
-#endif
-};
-
-static int intc_set_sense(unsigned int irq, unsigned int type)
-{
-       struct intc_desc_int *d = get_intc_desc(irq);
-       unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
-       struct intc_handle_int *ihp;
-       unsigned long addr;
-
-       if (!value)
-               return -EINVAL;
-
-       ihp = intc_find_irq(d->sense, d->nr_sense, irq);
-       if (ihp) {
-               addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
-               intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
-       }
-       return 0;
-}
-
-static intc_enum __init intc_grp_id(struct intc_desc *desc,
-                                   intc_enum enum_id)
-{
-       struct intc_group *g = desc->hw.groups;
-       unsigned int i, j;
-
-       for (i = 0; g && enum_id && i < desc->hw.nr_groups; i++) {
-               g = desc->hw.groups + i;
-
-               for (j = 0; g->enum_ids[j]; j++) {
-                       if (g->enum_ids[j] != enum_id)
-                               continue;
-
-                       return g->enum_id;
-               }
-       }
-
-       return 0;
-}
-
-static unsigned int __init _intc_mask_data(struct intc_desc *desc,
-                                          struct intc_desc_int *d,
-                                          intc_enum enum_id,
-                                          unsigned int *reg_idx,
-                                          unsigned int *fld_idx)
-{
-       struct intc_mask_reg *mr = desc->hw.mask_regs;
-       unsigned int fn, mode;
-       unsigned long reg_e, reg_d;
-
-       while (mr && enum_id && *reg_idx < desc->hw.nr_mask_regs) {
-               mr = desc->hw.mask_regs + *reg_idx;
-
-               for (; *fld_idx < ARRAY_SIZE(mr->enum_ids); (*fld_idx)++) {
-                       if (mr->enum_ids[*fld_idx] != enum_id)
-                               continue;
-
-                       if (mr->set_reg && mr->clr_reg) {
-                               fn = REG_FN_WRITE_BASE;
-                               mode = MODE_DUAL_REG;
-                               reg_e = mr->clr_reg;
-                               reg_d = mr->set_reg;
-                       } else {
-                               fn = REG_FN_MODIFY_BASE;
-                               if (mr->set_reg) {
-                                       mode = MODE_ENABLE_REG;
-                                       reg_e = mr->set_reg;
-                                       reg_d = mr->set_reg;
-                               } else {
-                                       mode = MODE_MASK_REG;
-                                       reg_e = mr->clr_reg;
-                                       reg_d = mr->clr_reg;
-                               }
-                       }
-
-                       fn += (mr->reg_width >> 3) - 1;
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       1,
-                                       (mr->reg_width - 1) - *fld_idx);
-               }
-
-               *fld_idx = 0;
-               (*reg_idx)++;
-       }
-
-       return 0;
-}
-
-static unsigned int __init intc_mask_data(struct intc_desc *desc,
-                                         struct intc_desc_int *d,
-                                         intc_enum enum_id, int do_grps)
-{
-       unsigned int i = 0;
-       unsigned int j = 0;
-       unsigned int ret;
-
-       ret = _intc_mask_data(desc, d, enum_id, &i, &j);
-       if (ret)
-               return ret;
-
-       if (do_grps)
-               return intc_mask_data(desc, d, intc_grp_id(desc, enum_id), 0);
-
-       return 0;
-}
-
-static unsigned int __init _intc_prio_data(struct intc_desc *desc,
-                                          struct intc_desc_int *d,
-                                          intc_enum enum_id,
-                                          unsigned int *reg_idx,
-                                          unsigned int *fld_idx)
-{
-       struct intc_prio_reg *pr = desc->hw.prio_regs;
-       unsigned int fn, n, mode, bit;
-       unsigned long reg_e, reg_d;
-
-       while (pr && enum_id && *reg_idx < desc->hw.nr_prio_regs) {
-               pr = desc->hw.prio_regs + *reg_idx;
-
-               for (; *fld_idx < ARRAY_SIZE(pr->enum_ids); (*fld_idx)++) {
-                       if (pr->enum_ids[*fld_idx] != enum_id)
-                               continue;
-
-                       if (pr->set_reg && pr->clr_reg) {
-                               fn = REG_FN_WRITE_BASE;
-                               mode = MODE_PCLR_REG;
-                               reg_e = pr->set_reg;
-                               reg_d = pr->clr_reg;
-                       } else {
-                               fn = REG_FN_MODIFY_BASE;
-                               mode = MODE_PRIO_REG;
-                               if (!pr->set_reg)
-                                       BUG();
-                               reg_e = pr->set_reg;
-                               reg_d = pr->set_reg;
-                       }
-
-                       fn += (pr->reg_width >> 3) - 1;
-                       n = *fld_idx + 1;
-
-                       BUG_ON(n * pr->field_width > pr->reg_width);
-
-                       bit = pr->reg_width - (n * pr->field_width);
-
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       pr->field_width, bit);
-               }
-
-               *fld_idx = 0;
-               (*reg_idx)++;
-       }
-
-       return 0;
-}
-
-static unsigned int __init intc_prio_data(struct intc_desc *desc,
-                                         struct intc_desc_int *d,
-                                         intc_enum enum_id, int do_grps)
-{
-       unsigned int i = 0;
-       unsigned int j = 0;
-       unsigned int ret;
-
-       ret = _intc_prio_data(desc, d, enum_id, &i, &j);
-       if (ret)
-               return ret;
-
-       if (do_grps)
-               return intc_prio_data(desc, d, intc_grp_id(desc, enum_id), 0);
-
-       return 0;
-}
-
-static void __init intc_enable_disable_enum(struct intc_desc *desc,
-                                           struct intc_desc_int *d,
-                                           intc_enum enum_id, int enable)
-{
-       unsigned int i, j, data;
-
-       /* go through and enable/disable all mask bits */
-       i = j = 0;
-       do {
-               data = _intc_mask_data(desc, d, enum_id, &i, &j);
-               if (data)
-                       intc_enable_disable(d, data, enable);
-               j++;
-       } while (data);
-
-       /* go through and enable/disable all priority fields */
-       i = j = 0;
-       do {
-               data = _intc_prio_data(desc, d, enum_id, &i, &j);
-               if (data)
-                       intc_enable_disable(d, data, enable);
-
-               j++;
-       } while (data);
-}
-
-static unsigned int __init intc_ack_data(struct intc_desc *desc,
-                                         struct intc_desc_int *d,
-                                         intc_enum enum_id)
-{
-       struct intc_mask_reg *mr = desc->hw.ack_regs;
-       unsigned int i, j, fn, mode;
-       unsigned long reg_e, reg_d;
-
-       for (i = 0; mr && enum_id && i < desc->hw.nr_ack_regs; i++) {
-               mr = desc->hw.ack_regs + i;
-
-               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
-                       if (mr->enum_ids[j] != enum_id)
-                               continue;
-
-                       fn = REG_FN_MODIFY_BASE;
-                       mode = MODE_ENABLE_REG;
-                       reg_e = mr->set_reg;
-                       reg_d = mr->set_reg;
-
-                       fn += (mr->reg_width >> 3) - 1;
-                       return _INTC_MK(fn, mode,
-                                       intc_get_reg(d, reg_e),
-                                       intc_get_reg(d, reg_d),
-                                       1,
-                                       (mr->reg_width - 1) - j);
-               }
-       }
-
-       return 0;
-}
-
-static unsigned int __init intc_sense_data(struct intc_desc *desc,
-                                          struct intc_desc_int *d,
-                                          intc_enum enum_id)
-{
-       struct intc_sense_reg *sr = desc->hw.sense_regs;
-       unsigned int i, j, fn, bit;
-
-       for (i = 0; sr && enum_id && i < desc->hw.nr_sense_regs; i++) {
-               sr = desc->hw.sense_regs + i;
-
-               for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
-                       if (sr->enum_ids[j] != enum_id)
-                               continue;
-
-                       fn = REG_FN_MODIFY_BASE;
-                       fn += (sr->reg_width >> 3) - 1;
-
-                       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);
-               }
-       }
-
-       return 0;
-}
-
-static void __init intc_register_irq(struct intc_desc *desc,
-                                    struct intc_desc_int *d,
-                                    intc_enum enum_id,
-                                    unsigned int irq)
-{
-       struct intc_handle_int *hp;
-       unsigned int data[2], primary;
-
-       /*
-        * Register the IRQ position with the global IRQ map
-        */
-       set_bit(irq, intc_irq_map);
-
-       /*
-        * Prefer single interrupt source bitmap over other combinations:
-        *
-        * 1. bitmap, single interrupt source
-        * 2. priority, single interrupt source
-        * 3. bitmap, multiple interrupt sources (groups)
-        * 4. priority, multiple interrupt sources (groups)
-        */
-       data[0] = intc_mask_data(desc, d, enum_id, 0);
-       data[1] = intc_prio_data(desc, d, enum_id, 0);
-
-       primary = 0;
-       if (!data[0] && data[1])
-               primary = 1;
-
-       if (!data[0] && !data[1])
-               pr_warning("missing unique irq mask for irq %d (vect 0x%04x)\n",
-                          irq, irq2evt(irq));
-
-       data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1);
-       data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1);
-
-       if (!data[primary])
-               primary ^= 1;
-
-       BUG_ON(!data[primary]); /* must have primary masking method */
-
-       disable_irq_nosync(irq);
-       set_irq_chip_and_handler_name(irq, &d->chip,
-                                     handle_level_irq, "level");
-       set_irq_chip_data(irq, (void *)data[primary]);
-
-       /*
-        * set priority level
-        * - this needs to be at least 2 for 5-bit priorities on 7780
-        */
-       intc_prio_level[irq] = default_prio_level;
-
-       /* enable secondary masking method if present */
-       if (data[!primary])
-               _intc_enable(irq, data[!primary]);
-
-       /* add irq to d->prio list if priority is available */
-       if (data[1]) {
-               hp = d->prio + d->nr_prio;
-               hp->irq = irq;
-               hp->handle = data[1];
-
-               if (primary) {
-                       /*
-                        * only secondary priority should access registers, so
-                        * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
-                        */
-                       hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
-                       hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
-               }
-               d->nr_prio++;
-       }
-
-       /* add irq to d->sense list if sense is available */
-       data[0] = intc_sense_data(desc, d, enum_id);
-       if (data[0]) {
-               (d->sense + d->nr_sense)->irq = irq;
-               (d->sense + d->nr_sense)->handle = data[0];
-               d->nr_sense++;
-       }
-
-       /* irq should be disabled by default */
-       d->chip.mask(irq);
-
-       if (desc->hw.ack_regs)
-               ack_handle[irq] = intc_ack_data(desc, d, enum_id);
-
-#ifdef CONFIG_INTC_BALANCING
-       if (desc->hw.mask_regs)
-               dist_handle[irq] = intc_dist_data(desc, d, enum_id);
-#endif
-
-#ifdef CONFIG_ARM
-       set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
-#endif
-}
-
-static unsigned int __init save_reg(struct intc_desc_int *d,
-                                   unsigned int cnt,
-                                   unsigned long value,
-                                   unsigned int smp)
-{
-       if (value) {
-               value = intc_phys_to_virt(d, value);
-
-               d->reg[cnt] = value;
-#ifdef CONFIG_SMP
-               d->smp[cnt] = smp;
-#endif
-               return 1;
-       }
-
-       return 0;
-}
-
-static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
-{
-       generic_handle_irq((unsigned int)get_irq_data(irq));
-}
-
-int __init register_intc_controller(struct intc_desc *desc)
-{
-       unsigned int i, k, smp;
-       struct intc_hw_desc *hw = &desc->hw;
-       struct intc_desc_int *d;
-       struct resource *res;
-
-       pr_info("Registered controller '%s' with %u IRQs\n",
-               desc->name, hw->nr_vectors);
-
-       d = kzalloc(sizeof(*d), GFP_NOWAIT);
-       if (!d)
-               goto err0;
-
-       INIT_LIST_HEAD(&d->list);
-       list_add(&d->list, &intc_list);
-
-       if (desc->num_resources) {
-               d->nr_windows = desc->num_resources;
-               d->window = kzalloc(d->nr_windows * sizeof(*d->window),
-                                   GFP_NOWAIT);
-               if (!d->window)
-                       goto err1;
-
-               for (k = 0; k < d->nr_windows; k++) {
-                       res = desc->resource + k;
-                       WARN_ON(resource_type(res) != IORESOURCE_MEM);
-                       d->window[k].phys = res->start;
-                       d->window[k].size = resource_size(res);
-                       d->window[k].virt = ioremap_nocache(res->start,
-                                                        resource_size(res));
-                       if (!d->window[k].virt)
-                               goto err2;
-               }
-       }
-
-       d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0;
-#ifdef CONFIG_INTC_BALANCING
-       if (d->nr_reg)
-               d->nr_reg += hw->nr_mask_regs;
-#endif
-       d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0;
-       d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0;
-       d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0;
-
-       d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
-       if (!d->reg)
-               goto err2;
-
-#ifdef CONFIG_SMP
-       d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
-       if (!d->smp)
-               goto err3;
-#endif
-       k = 0;
-
-       if (hw->mask_regs) {
-               for (i = 0; i < hw->nr_mask_regs; i++) {
-                       smp = IS_SMP(hw->mask_regs[i]);
-                       k += save_reg(d, k, hw->mask_regs[i].set_reg, smp);
-                       k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp);
-#ifdef CONFIG_INTC_BALANCING
-                       k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0);
-#endif
-               }
-       }
-
-       if (hw->prio_regs) {
-               d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio),
-                                 GFP_NOWAIT);
-               if (!d->prio)
-                       goto err4;
-
-               for (i = 0; i < hw->nr_prio_regs; i++) {
-                       smp = IS_SMP(hw->prio_regs[i]);
-                       k += save_reg(d, k, hw->prio_regs[i].set_reg, smp);
-                       k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp);
-               }
-       }
-
-       if (hw->sense_regs) {
-               d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense),
-                                  GFP_NOWAIT);
-               if (!d->sense)
-                       goto err5;
-
-               for (i = 0; i < hw->nr_sense_regs; i++)
-                       k += save_reg(d, k, hw->sense_regs[i].reg, 0);
-       }
-
-       d->chip.name = desc->name;
-       d->chip.mask = intc_disable;
-       d->chip.unmask = intc_enable;
-       d->chip.mask_ack = intc_disable;
-       d->chip.enable = intc_enable;
-       d->chip.disable = intc_disable;
-       d->chip.shutdown = intc_disable;
-       d->chip.set_type = intc_set_sense;
-       d->chip.set_wake = intc_set_wake;
-#ifdef CONFIG_SMP
-       d->chip.set_affinity = intc_set_affinity;
-#endif
-
-       if (hw->ack_regs) {
-               for (i = 0; i < hw->nr_ack_regs; i++)
-                       k += save_reg(d, k, hw->ack_regs[i].set_reg, 0);
-
-               d->chip.mask_ack = intc_mask_ack;
-       }
-
-       /* disable bits matching force_disable before registering irqs */
-       if (desc->force_disable)
-               intc_enable_disable_enum(desc, d, desc->force_disable, 0);
-
-       /* disable bits matching force_enable before registering irqs */
-       if (desc->force_enable)
-               intc_enable_disable_enum(desc, d, desc->force_enable, 0);
-
-       BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
-
-       /* register the vectors one by one */
-       for (i = 0; i < hw->nr_vectors; i++) {
-               struct intc_vect *vect = hw->vectors + i;
-               unsigned int irq = evt2irq(vect->vect);
-               struct irq_desc *irq_desc;
-
-               if (!vect->enum_id)
-                       continue;
-
-               irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
-               if (unlikely(!irq_desc)) {
-                       pr_err("can't get irq_desc for %d\n", irq);
-                       continue;
-               }
-
-               intc_register_irq(desc, d, vect->enum_id, irq);
-
-               for (k = i + 1; k < hw->nr_vectors; k++) {
-                       struct intc_vect *vect2 = hw->vectors + k;
-                       unsigned int irq2 = evt2irq(vect2->vect);
-
-                       if (vect->enum_id != vect2->enum_id)
-                               continue;
-
-                       /*
-                        * In the case of multi-evt handling and sparse
-                        * IRQ support, each vector still needs to have
-                        * its own backing irq_desc.
-                        */
-                       irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id());
-                       if (unlikely(!irq_desc)) {
-                               pr_err("can't get irq_desc for %d\n", irq2);
-                               continue;
-                       }
-
-                       vect2->enum_id = 0;
-
-                       /* redirect this interrupts to the first one */
-                       set_irq_chip(irq2, &dummy_irq_chip);
-                       set_irq_chained_handler(irq2, intc_redirect_irq);
-                       set_irq_data(irq2, (void *)irq);
-               }
-       }
-
-       /* enable bits matching force_enable after registering irqs */
-       if (desc->force_enable)
-               intc_enable_disable_enum(desc, d, desc->force_enable, 1);
-
-       return 0;
-err5:
-       kfree(d->prio);
-err4:
-#ifdef CONFIG_SMP
-       kfree(d->smp);
-err3:
-#endif
-       kfree(d->reg);
-err2:
-       for (k = 0; k < d->nr_windows; k++)
-               if (d->window[k].virt)
-                       iounmap(d->window[k].virt);
-
-       kfree(d->window);
-err1:
-       kfree(d);
-err0:
-       pr_err("unable to allocate INTC memory\n");
-
-       return -ENOMEM;
-}
-
-#ifdef CONFIG_INTC_USERIMASK
-static void __iomem *uimask;
-
-int register_intc_userimask(unsigned long addr)
-{
-       if (unlikely(uimask))
-               return -EBUSY;
-
-       uimask = ioremap_nocache(addr, SZ_4K);
-       if (unlikely(!uimask))
-               return -ENOMEM;
-
-       pr_info("userimask support registered for levels 0 -> %d\n",
-               default_prio_level - 1);
-
-       return 0;
-}
-
-static ssize_t
-show_intc_userimask(struct sysdev_class *cls,
-                   struct sysdev_class_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf);
-}
-
-static ssize_t
-store_intc_userimask(struct sysdev_class *cls,
-                    struct sysdev_class_attribute *attr,
-                    const char *buf, size_t count)
-{
-       unsigned long level;
-
-       level = simple_strtoul(buf, NULL, 10);
-
-       /*
-        * Minimal acceptable IRQ levels are in the 2 - 16 range, but
-        * these are chomped so as to not interfere with normal IRQs.
-        *
-        * Level 1 is a special case on some CPUs in that it's not
-        * directly settable, but given that USERIMASK cuts off below a
-        * certain level, we don't care about this limitation here.
-        * Level 0 on the other hand equates to user masking disabled.
-        *
-        * We use default_prio_level as a cut off so that only special
-        * case opt-in IRQs can be mangled.
-        */
-       if (level >= default_prio_level)
-               return -EINVAL;
-
-       __raw_writel(0xa5 << 24 | level << 4, uimask);
-
-       return count;
-}
-
-static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR,
-                        show_intc_userimask, store_intc_userimask);
-#endif
-
-static ssize_t
-show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
-{
-       struct intc_desc_int *d;
-
-       d = container_of(dev, struct intc_desc_int, sysdev);
-
-       return sprintf(buf, "%s\n", d->chip.name);
-}
-
-static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
-
-static int intc_suspend(struct sys_device *dev, pm_message_t state)
-{
-       struct intc_desc_int *d;
-       struct irq_desc *desc;
-       int irq;
-
-       /* get intc controller associated with this sysdev */
-       d = container_of(dev, struct intc_desc_int, sysdev);
-
-       switch (state.event) {
-       case PM_EVENT_ON:
-               if (d->state.event != PM_EVENT_FREEZE)
-                       break;
-               for_each_irq_desc(irq, desc) {
-                       if (desc->handle_irq == intc_redirect_irq)
-                               continue;
-                       if (desc->chip != &d->chip)
-                               continue;
-                       if (desc->status & IRQ_DISABLED)
-                               intc_disable(irq);
-                       else
-                               intc_enable(irq);
-               }
-               break;
-       case PM_EVENT_FREEZE:
-               /* nothing has to be done */
-               break;
-       case PM_EVENT_SUSPEND:
-               /* enable wakeup irqs belonging to this intc controller */
-               for_each_irq_desc(irq, desc) {
-                       if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip))
-                               intc_enable(irq);
-               }
-               break;
-       }
-       d->state = state;
-
-       return 0;
-}
-
-static int intc_resume(struct sys_device *dev)
-{
-       return intc_suspend(dev, PMSG_ON);
-}
-
-static struct sysdev_class intc_sysdev_class = {
-       .name = "intc",
-       .suspend = intc_suspend,
-       .resume = intc_resume,
-};
-
-/* register this intc as sysdev to allow suspend/resume */
-static int __init register_intc_sysdevs(void)
-{
-       struct intc_desc_int *d;
-       int error;
-       int id = 0;
-
-       error = sysdev_class_register(&intc_sysdev_class);
-#ifdef CONFIG_INTC_USERIMASK
-       if (!error && uimask)
-               error = sysdev_class_create_file(&intc_sysdev_class,
-                                                &attr_userimask);
-#endif
-       if (!error) {
-               list_for_each_entry(d, &intc_list, list) {
-                       d->sysdev.id = id;
-                       d->sysdev.cls = &intc_sysdev_class;
-                       error = sysdev_register(&d->sysdev);
-                       if (error == 0)
-                               error = sysdev_create_file(&d->sysdev,
-                                                          &attr_name);
-                       if (error)
-                               break;
-
-                       id++;
-               }
-       }
-
-       if (error)
-               pr_err("sysdev registration error\n");
-
-       return error;
-}
-device_initcall(register_intc_sysdevs);
-
-/*
- * Dynamic IRQ allocation and deallocation
- */
-unsigned int create_irq_nr(unsigned int irq_want, int node)
-{
-       unsigned int irq = 0, new;
-       unsigned long flags;
-       struct irq_desc *desc;
-
-       spin_lock_irqsave(&vector_lock, flags);
-
-       /*
-        * First try the wanted IRQ
-        */
-       if (test_and_set_bit(irq_want, intc_irq_map) == 0) {
-               new = irq_want;
-       } else {
-               /* .. then fall back to scanning. */
-               new = find_first_zero_bit(intc_irq_map, nr_irqs);
-               if (unlikely(new == nr_irqs))
-                       goto out_unlock;
-
-               __set_bit(new, intc_irq_map);
-       }
-
-       desc = irq_to_desc_alloc_node(new, node);
-       if (unlikely(!desc)) {
-               pr_err("can't get irq_desc for %d\n", new);
-               goto out_unlock;
-       }
-
-       desc = move_irq_desc(desc, node);
-       irq = new;
-
-out_unlock:
-       spin_unlock_irqrestore(&vector_lock, flags);
-
-       if (irq > 0) {
-               dynamic_irq_init(irq);
-#ifdef CONFIG_ARM
-               set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */
-#endif
-       }
-
-       return irq;
-}
-
-int create_irq(void)
-{
-       int nid = cpu_to_node(smp_processor_id());
-       int irq;
-
-       irq = create_irq_nr(NR_IRQS_LEGACY, nid);
-       if (irq == 0)
-               irq = -1;
-
-       return irq;
-}
-
-void destroy_irq(unsigned int irq)
-{
-       unsigned long flags;
-
-       dynamic_irq_cleanup(irq);
-
-       spin_lock_irqsave(&vector_lock, flags);
-       __clear_bit(irq, intc_irq_map);
-       spin_unlock_irqrestore(&vector_lock, flags);
-}
-
-int reserve_irq_vector(unsigned int irq)
-{
-       unsigned long flags;
-       int ret = 0;
-
-       spin_lock_irqsave(&vector_lock, flags);
-       if (test_and_set_bit(irq, intc_irq_map))
-               ret = -EBUSY;
-       spin_unlock_irqrestore(&vector_lock, flags);
-
-       return ret;
-}
-
-void reserve_irq_legacy(void)
-{
-       unsigned long flags;
-       int i, j;
-
-       spin_lock_irqsave(&vector_lock, flags);
-       j = find_first_bit(intc_irq_map, nr_irqs);
-       for (i = 0; i < j; i++)
-               __set_bit(i, intc_irq_map);
-       spin_unlock_irqrestore(&vector_lock, flags);
-}
diff --git a/drivers/sh/intc/Kconfig b/drivers/sh/intc/Kconfig
new file mode 100644 (file)
index 0000000..c88cbcc
--- /dev/null
@@ -0,0 +1,35 @@
+comment "Interrupt controller options"
+
+config INTC_USERIMASK
+       bool "Userspace interrupt masking support"
+       depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A)
+       help
+         This enables support for hardware-assisted userspace hardirq
+         masking.
+
+         SH-4A and newer interrupt blocks all support a special shadowed
+         page with all non-masking registers obscured when mapped in to
+         userspace. This is primarily for use by userspace device
+         drivers that are using special priority levels.
+
+         If in doubt, say N.
+
+config INTC_BALANCING
+       bool "Hardware IRQ balancing support"
+       depends on SMP && SUPERH && CPU_SHX3
+       help
+         This enables support for IRQ auto-distribution mode on SH-X3
+         SMP parts. All of the balancing and CPU wakeup decisions are
+         taken care of automatically by hardware for distributed
+         vectors.
+
+         If in doubt, say N.
+
+config INTC_MAPPING_DEBUG
+       bool "Expose IRQ to per-controller id mapping via debugfs"
+       depends on DEBUG_FS
+       help
+         This will create a debugfs entry for showing the relationship
+         between system IRQs and the per-controller id tables.
+
+         If in doubt, say N.
diff --git a/drivers/sh/intc/Makefile b/drivers/sh/intc/Makefile
new file mode 100644 (file)
index 0000000..bb5df86
--- /dev/null
@@ -0,0 +1,5 @@
+obj-y  := access.o chip.o core.o dynamic.o handle.o virq.o
+
+obj-$(CONFIG_INTC_BALANCING)           += balancing.o
+obj-$(CONFIG_INTC_USERIMASK)           += userimask.o
+obj-$(CONFIG_INTC_MAPPING_DEBUG)       += virq-debugfs.o
diff --git a/drivers/sh/intc/access.c b/drivers/sh/intc/access.c
new file mode 100644 (file)
index 0000000..f892ae1
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * Common INTC2 register accessors
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 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/io.h>
+#include "internals.h"
+
+unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address)
+{
+       struct intc_window *window;
+       int k;
+
+       /* scan through physical windows and convert address */
+       for (k = 0; k < d->nr_windows; k++) {
+               window = d->window + k;
+
+               if (address < window->phys)
+                       continue;
+
+               if (address >= (window->phys + window->size))
+                       continue;
+
+               address -= window->phys;
+               address += (unsigned long)window->virt;
+
+               return address;
+       }
+
+       /* no windows defined, register must be 1:1 mapped virt:phys */
+       return address;
+}
+
+unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address)
+{
+       unsigned int k;
+
+       address = intc_phys_to_virt(d, address);
+
+       for (k = 0; k < d->nr_reg; k++) {
+               if (d->reg[k] == address)
+                       return k;
+       }
+
+       BUG();
+       return 0;
+}
+
+unsigned int intc_set_field_from_handle(unsigned int value,
+                                       unsigned int field_value,
+                                       unsigned int handle)
+{
+       unsigned int width = _INTC_WIDTH(handle);
+       unsigned int shift = _INTC_SHIFT(handle);
+
+       value &= ~(((1 << width) - 1) << shift);
+       value |= field_value << shift;
+       return value;
+}
+
+unsigned long intc_get_field_from_handle(unsigned int value, unsigned int handle)
+{
+       unsigned int width = _INTC_WIDTH(handle);
+       unsigned int shift = _INTC_SHIFT(handle);
+       unsigned int mask = ((1 << width) - 1) << shift;
+
+       return (value & mask) >> shift;
+}
+
+static unsigned long test_8(unsigned long addr, unsigned long h,
+                           unsigned long ignore)
+{
+       return intc_get_field_from_handle(__raw_readb(addr), h);
+}
+
+static unsigned long test_16(unsigned long addr, unsigned long h,
+                            unsigned long ignore)
+{
+       return intc_get_field_from_handle(__raw_readw(addr), h);
+}
+
+static unsigned long test_32(unsigned long addr, unsigned long h,
+                            unsigned long ignore)
+{
+       return intc_get_field_from_handle(__raw_readl(addr), h);
+}
+
+static unsigned long write_8(unsigned long addr, unsigned long h,
+                            unsigned long data)
+{
+       __raw_writeb(intc_set_field_from_handle(0, data, h), addr);
+       (void)__raw_readb(addr);        /* Defeat write posting */
+       return 0;
+}
+
+static unsigned long write_16(unsigned long addr, unsigned long h,
+                             unsigned long data)
+{
+       __raw_writew(intc_set_field_from_handle(0, data, h), addr);
+       (void)__raw_readw(addr);        /* Defeat write posting */
+       return 0;
+}
+
+static unsigned long write_32(unsigned long addr, unsigned long h,
+                             unsigned long data)
+{
+       __raw_writel(intc_set_field_from_handle(0, data, h), addr);
+       (void)__raw_readl(addr);        /* Defeat write posting */
+       return 0;
+}
+
+static unsigned long modify_8(unsigned long addr, unsigned long h,
+                             unsigned long data)
+{
+       unsigned long flags;
+       unsigned int value;
+       local_irq_save(flags);
+       value = intc_set_field_from_handle(__raw_readb(addr), data, h);
+       __raw_writeb(value, addr);
+       (void)__raw_readb(addr);        /* Defeat write posting */
+       local_irq_restore(flags);
+       return 0;
+}
+
+static unsigned long modify_16(unsigned long addr, unsigned long h,
+                              unsigned long data)
+{
+       unsigned long flags;
+       unsigned int value;
+       local_irq_save(flags);
+       value = intc_set_field_from_handle(__raw_readw(addr), data, h);
+       __raw_writew(value, addr);
+       (void)__raw_readw(addr);        /* Defeat write posting */
+       local_irq_restore(flags);
+       return 0;
+}
+
+static unsigned long modify_32(unsigned long addr, unsigned long h,
+                              unsigned long data)
+{
+       unsigned long flags;
+       unsigned int value;
+       local_irq_save(flags);
+       value = intc_set_field_from_handle(__raw_readl(addr), data, h);
+       __raw_writel(value, addr);
+       (void)__raw_readl(addr);        /* Defeat write posting */
+       local_irq_restore(flags);
+       return 0;
+}
+
+static unsigned long intc_mode_field(unsigned long addr,
+                                    unsigned long handle,
+                                    unsigned long (*fn)(unsigned long,
+                                               unsigned long,
+                                               unsigned long),
+                                    unsigned int irq)
+{
+       return fn(addr, handle, ((1 << _INTC_WIDTH(handle)) - 1));
+}
+
+static unsigned long intc_mode_zero(unsigned long addr,
+                                   unsigned long handle,
+                                   unsigned long (*fn)(unsigned long,
+                                              unsigned long,
+                                              unsigned long),
+                                   unsigned int irq)
+{
+       return fn(addr, handle, 0);
+}
+
+static unsigned long intc_mode_prio(unsigned long addr,
+                                   unsigned long handle,
+                                   unsigned long (*fn)(unsigned long,
+                                              unsigned long,
+                                              unsigned long),
+                                   unsigned int irq)
+{
+       return fn(addr, handle, intc_get_prio_level(irq));
+}
+
+unsigned long (*intc_reg_fns[])(unsigned long addr,
+                               unsigned long h,
+                               unsigned long data) = {
+       [REG_FN_TEST_BASE + 0] = test_8,
+       [REG_FN_TEST_BASE + 1] = test_16,
+       [REG_FN_TEST_BASE + 3] = test_32,
+       [REG_FN_WRITE_BASE + 0] = write_8,
+       [REG_FN_WRITE_BASE + 1] = write_16,
+       [REG_FN_WRITE_BASE + 3] = write_32,
+       [REG_FN_MODIFY_BASE + 0] = modify_8,
+       [REG_FN_MODIFY_BASE + 1] = modify_16,
+       [REG_FN_MODIFY_BASE + 3] = modify_32,
+};
+
+unsigned long (*intc_enable_fns[])(unsigned long addr,
+                                  unsigned long handle,
+                                  unsigned long (*fn)(unsigned long,
+                                           unsigned long,
+                                           unsigned long),
+                                  unsigned int irq) = {
+       [MODE_ENABLE_REG] = intc_mode_field,
+       [MODE_MASK_REG] = intc_mode_zero,
+       [MODE_DUAL_REG] = intc_mode_field,
+       [MODE_PRIO_REG] = intc_mode_prio,
+       [MODE_PCLR_REG] = intc_mode_prio,
+};
+
+unsigned long (*intc_disable_fns[])(unsigned long addr,
+                                   unsigned long handle,
+                                   unsigned long (*fn)(unsigned long,
+                                            unsigned long,
+                                            unsigned long),
+                                   unsigned int irq) = {
+       [MODE_ENABLE_REG] = intc_mode_zero,
+       [MODE_MASK_REG] = intc_mode_field,
+       [MODE_DUAL_REG] = intc_mode_field,
+       [MODE_PRIO_REG] = intc_mode_zero,
+       [MODE_PCLR_REG] = intc_mode_field,
+};
+
+unsigned long (*intc_enable_noprio_fns[])(unsigned long addr,
+                                         unsigned long handle,
+                                         unsigned long (*fn)(unsigned long,
+                                               unsigned long,
+                                               unsigned long),
+                                         unsigned int irq) = {
+       [MODE_ENABLE_REG] = intc_mode_field,
+       [MODE_MASK_REG] = intc_mode_zero,
+       [MODE_DUAL_REG] = intc_mode_field,
+       [MODE_PRIO_REG] = intc_mode_field,
+       [MODE_PCLR_REG] = intc_mode_field,
+};
diff --git a/drivers/sh/intc/balancing.c b/drivers/sh/intc/balancing.c
new file mode 100644 (file)
index 0000000..cec7a96
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Support for hardware-managed IRQ auto-distribution.
+ *
+ * Copyright (C) 2010  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 "internals.h"
+
+static unsigned long dist_handle[NR_IRQS];
+
+void intc_balancing_enable(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = dist_handle[irq];
+       unsigned long addr;
+
+       if (irq_balancing_disabled(irq) || !handle)
+               return;
+
+       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+       intc_reg_fns[_INTC_FN(handle)](addr, handle, 1);
+}
+
+void intc_balancing_disable(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = dist_handle[irq];
+       unsigned long addr;
+
+       if (irq_balancing_disabled(irq) || !handle)
+               return;
+
+       addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+       intc_reg_fns[_INTC_FN(handle)](addr, handle, 0);
+}
+
+static unsigned int intc_dist_data(struct intc_desc *desc,
+                                  struct intc_desc_int *d,
+                                  intc_enum enum_id)
+{
+       struct intc_mask_reg *mr = desc->hw.mask_regs;
+       unsigned int i, j, fn, mode;
+       unsigned long reg_e, reg_d;
+
+       for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) {
+               mr = desc->hw.mask_regs + i;
+
+               /*
+                * Skip this entry if there's no auto-distribution
+                * register associated with it.
+                */
+               if (!mr->dist_reg)
+                       continue;
+
+               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
+                       if (mr->enum_ids[j] != enum_id)
+                               continue;
+
+                       fn = REG_FN_MODIFY_BASE;
+                       mode = MODE_ENABLE_REG;
+                       reg_e = mr->dist_reg;
+                       reg_d = mr->dist_reg;
+
+                       fn += (mr->reg_width >> 3) - 1;
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       1,
+                                       (mr->reg_width - 1) - j);
+               }
+       }
+
+       /*
+        * It's possible we've gotten here with no distribution options
+        * available for the IRQ in question, so we just skip over those.
+        */
+       return 0;
+}
+
+void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
+                         struct intc_desc_int *d, intc_enum id)
+{
+       unsigned long flags;
+
+       /*
+        * Nothing to do for this IRQ.
+        */
+       if (!desc->hw.mask_regs)
+               return;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       dist_handle[irq] = intc_dist_data(desc, d, id);
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
diff --git a/drivers/sh/intc/chip.c b/drivers/sh/intc/chip.c
new file mode 100644 (file)
index 0000000..35c0370
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * IRQ chip definitions for INTC IRQs.
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 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/cpumask.h>
+#include <linux/io.h>
+#include "internals.h"
+
+void _intc_enable(unsigned int irq, unsigned long handle)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long addr;
+       unsigned int cpu;
+
+       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
+#ifdef CONFIG_SMP
+               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
+                       continue;
+#endif
+               addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
+               intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
+                                                   [_INTC_FN(handle)], irq);
+       }
+
+       intc_balancing_enable(irq);
+}
+
+static void intc_enable(unsigned int irq)
+{
+       _intc_enable(irq, (unsigned long)get_irq_chip_data(irq));
+}
+
+static void intc_disable(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = (unsigned long)get_irq_chip_data(irq);
+       unsigned long addr;
+       unsigned int cpu;
+
+       intc_balancing_disable(irq);
+
+       for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
+#ifdef CONFIG_SMP
+               if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity))
+                       continue;
+#endif
+               addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
+               intc_disable_fns[_INTC_MODE(handle)](addr, handle,intc_reg_fns\
+                                                    [_INTC_FN(handle)], irq);
+       }
+}
+
+static int intc_set_wake(unsigned int irq, unsigned int on)
+{
+       return 0; /* allow wakeup, but setup hardware in intc_suspend() */
+}
+
+#ifdef CONFIG_SMP
+/*
+ * This is held with the irq desc lock held, so we don't require any
+ * additional locking here at the intc desc level. The affinity mask is
+ * later tested in the enable/disable paths.
+ */
+static int intc_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+{
+       if (!cpumask_intersects(cpumask, cpu_online_mask))
+               return -1;
+
+       cpumask_copy(irq_to_desc(irq)->affinity, cpumask);
+
+       return 0;
+}
+#endif
+
+static void intc_mask_ack(unsigned int irq)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned long handle = intc_get_ack_handle(irq);
+       unsigned long addr;
+
+       intc_disable(irq);
+
+       /* read register and write zero only to the associated bit */
+       if (handle) {
+               unsigned int value;
+
+               addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
+               value = intc_set_field_from_handle(0, 1, handle);
+
+               switch (_INTC_FN(handle)) {
+               case REG_FN_MODIFY_BASE + 0:    /* 8bit */
+                       __raw_readb(addr);
+                       __raw_writeb(0xff ^ value, addr);
+                       break;
+               case REG_FN_MODIFY_BASE + 1:    /* 16bit */
+                       __raw_readw(addr);
+                       __raw_writew(0xffff ^ value, addr);
+                       break;
+               case REG_FN_MODIFY_BASE + 3:    /* 32bit */
+                       __raw_readl(addr);
+                       __raw_writel(0xffffffff ^ value, addr);
+                       break;
+               default:
+                       BUG();
+                       break;
+               }
+       }
+}
+
+static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp,
+                                            unsigned int nr_hp,
+                                            unsigned int irq)
+{
+       int i;
+
+       /*
+        * this doesn't scale well, but...
+        *
+        * this function should only be used for cerain uncommon
+        * operations such as intc_set_priority() and intc_set_type()
+        * and in those rare cases performance doesn't matter that much.
+        * keeping the memory footprint low is more important.
+        *
+        * one rather simple way to speed this up and still keep the
+        * memory footprint down is to make sure the array is sorted
+        * and then perform a bisect to lookup the irq.
+        */
+       for (i = 0; i < nr_hp; i++) {
+               if ((hp + i)->irq != irq)
+                       continue;
+
+               return hp + i;
+       }
+
+       return NULL;
+}
+
+int intc_set_priority(unsigned int irq, unsigned int prio)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       struct intc_handle_int *ihp;
+
+       if (!intc_get_prio_level(irq) || prio <= 1)
+               return -EINVAL;
+
+       ihp = intc_find_irq(d->prio, d->nr_prio, irq);
+       if (ihp) {
+               if (prio >= (1 << _INTC_WIDTH(ihp->handle)))
+                       return -EINVAL;
+
+               intc_set_prio_level(irq, prio);
+
+               /*
+                * only set secondary masking method directly
+                * primary masking method is using intc_prio_level[irq]
+                * priority level will be set during next enable()
+                */
+               if (_INTC_FN(ihp->handle) != REG_FN_ERR)
+                       _intc_enable(irq, ihp->handle);
+       }
+       return 0;
+}
+
+#define VALID(x) (x | 0x80)
+
+static unsigned char intc_irq_sense_table[IRQ_TYPE_SENSE_MASK + 1] = {
+       [IRQ_TYPE_EDGE_FALLING] = VALID(0),
+       [IRQ_TYPE_EDGE_RISING] = VALID(1),
+       [IRQ_TYPE_LEVEL_LOW] = VALID(2),
+       /* SH7706, SH7707 and SH7709 do not support high level triggered */
+#if !defined(CONFIG_CPU_SUBTYPE_SH7706) && \
+    !defined(CONFIG_CPU_SUBTYPE_SH7707) && \
+    !defined(CONFIG_CPU_SUBTYPE_SH7709)
+       [IRQ_TYPE_LEVEL_HIGH] = VALID(3),
+#endif
+};
+
+static int intc_set_type(unsigned int irq, unsigned int type)
+{
+       struct intc_desc_int *d = get_intc_desc(irq);
+       unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
+       struct intc_handle_int *ihp;
+       unsigned long addr;
+
+       if (!value)
+               return -EINVAL;
+
+       ihp = intc_find_irq(d->sense, d->nr_sense, irq);
+       if (ihp) {
+               addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
+               intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
+       }
+
+       return 0;
+}
+
+struct irq_chip intc_irq_chip  = {
+       .mask           = intc_disable,
+       .unmask         = intc_enable,
+       .mask_ack       = intc_mask_ack,
+       .enable         = intc_enable,
+       .disable        = intc_disable,
+       .shutdown       = intc_disable,
+       .set_type       = intc_set_type,
+       .set_wake       = intc_set_wake,
+#ifdef CONFIG_SMP
+       .set_affinity   = intc_set_affinity,
+#endif
+};
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
new file mode 100644 (file)
index 0000000..306ed28
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Shared interrupt handling code for IPR and INTC2 types of IRQs.
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 Paul Mundt
+ *
+ * Based on intc2.c and ipr.c
+ *
+ * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000  Kazumoto Kojima
+ * Copyright (C) 2001  David J. Mckay (david.mckay@st.com)
+ * Copyright (C) 2003  Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp>
+ * Copyright (C) 2005, 2006  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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/sh_intc.h>
+#include <linux/sysdev.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/radix-tree.h>
+#include "internals.h"
+
+LIST_HEAD(intc_list);
+DEFINE_RAW_SPINLOCK(intc_big_lock);
+unsigned int nr_intc_controllers;
+
+/*
+ * Default priority level
+ * - this needs to be at least 2 for 5-bit priorities on 7780
+ */
+static unsigned int default_prio_level = 2;    /* 2 - 16 */
+static unsigned int intc_prio_level[NR_IRQS];  /* for now */
+
+unsigned int intc_get_dfl_prio_level(void)
+{
+       return default_prio_level;
+}
+
+unsigned int intc_get_prio_level(unsigned int irq)
+{
+       return intc_prio_level[irq];
+}
+
+void intc_set_prio_level(unsigned int irq, unsigned int level)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       intc_prio_level[irq] = level;
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
+
+static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
+{
+       generic_handle_irq((unsigned int)get_irq_data(irq));
+}
+
+static void __init intc_register_irq(struct intc_desc *desc,
+                                    struct intc_desc_int *d,
+                                    intc_enum enum_id,
+                                    unsigned int irq)
+{
+       struct intc_handle_int *hp;
+       unsigned int data[2], primary;
+       unsigned long flags;
+
+       /*
+        * Register the IRQ position with the global IRQ map, then insert
+        * it in to the radix tree.
+        */
+       reserve_irq_vector(irq);
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       radix_tree_insert(&d->tree, enum_id, intc_irq_xlate_get(irq));
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+
+       /*
+        * Prefer single interrupt source bitmap over other combinations:
+        *
+        * 1. bitmap, single interrupt source
+        * 2. priority, single interrupt source
+        * 3. bitmap, multiple interrupt sources (groups)
+        * 4. priority, multiple interrupt sources (groups)
+        */
+       data[0] = intc_get_mask_handle(desc, d, enum_id, 0);
+       data[1] = intc_get_prio_handle(desc, d, enum_id, 0);
+
+       primary = 0;
+       if (!data[0] && data[1])
+               primary = 1;
+
+       if (!data[0] && !data[1])
+               pr_warning("missing unique irq mask for irq %d (vect 0x%04x)\n",
+                          irq, irq2evt(irq));
+
+       data[0] = data[0] ? data[0] : intc_get_mask_handle(desc, d, enum_id, 1);
+       data[1] = data[1] ? data[1] : intc_get_prio_handle(desc, d, enum_id, 1);
+
+       if (!data[primary])
+               primary ^= 1;
+
+       BUG_ON(!data[primary]); /* must have primary masking method */
+
+       disable_irq_nosync(irq);
+       set_irq_chip_and_handler_name(irq, &d->chip,
+                                     handle_level_irq, "level");
+       set_irq_chip_data(irq, (void *)data[primary]);
+
+       /*
+        * set priority level
+        */
+       intc_set_prio_level(irq, intc_get_dfl_prio_level());
+
+       /* enable secondary masking method if present */
+       if (data[!primary])
+               _intc_enable(irq, data[!primary]);
+
+       /* add irq to d->prio list if priority is available */
+       if (data[1]) {
+               hp = d->prio + d->nr_prio;
+               hp->irq = irq;
+               hp->handle = data[1];
+
+               if (primary) {
+                       /*
+                        * only secondary priority should access registers, so
+                        * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
+                        */
+                       hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
+                       hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
+               }
+               d->nr_prio++;
+       }
+
+       /* add irq to d->sense list if sense is available */
+       data[0] = intc_get_sense_handle(desc, d, enum_id);
+       if (data[0]) {
+               (d->sense + d->nr_sense)->irq = irq;
+               (d->sense + d->nr_sense)->handle = data[0];
+               d->nr_sense++;
+       }
+
+       /* irq should be disabled by default */
+       d->chip.mask(irq);
+
+       intc_set_ack_handle(irq, desc, d, enum_id);
+       intc_set_dist_handle(irq, desc, d, enum_id);
+
+       activate_irq(irq);
+}
+
+static unsigned int __init save_reg(struct intc_desc_int *d,
+                                   unsigned int cnt,
+                                   unsigned long value,
+                                   unsigned int smp)
+{
+       if (value) {
+               value = intc_phys_to_virt(d, value);
+
+               d->reg[cnt] = value;
+#ifdef CONFIG_SMP
+               d->smp[cnt] = smp;
+#endif
+               return 1;
+       }
+
+       return 0;
+}
+
+int __init register_intc_controller(struct intc_desc *desc)
+{
+       unsigned int i, k, smp;
+       struct intc_hw_desc *hw = &desc->hw;
+       struct intc_desc_int *d;
+       struct resource *res;
+
+       pr_info("Registered controller '%s' with %u IRQs\n",
+               desc->name, hw->nr_vectors);
+
+       d = kzalloc(sizeof(*d), GFP_NOWAIT);
+       if (!d)
+               goto err0;
+
+       INIT_LIST_HEAD(&d->list);
+       list_add_tail(&d->list, &intc_list);
+
+       raw_spin_lock_init(&d->lock);
+
+       d->index = nr_intc_controllers;
+
+       if (desc->num_resources) {
+               d->nr_windows = desc->num_resources;
+               d->window = kzalloc(d->nr_windows * sizeof(*d->window),
+                                   GFP_NOWAIT);
+               if (!d->window)
+                       goto err1;
+
+               for (k = 0; k < d->nr_windows; k++) {
+                       res = desc->resource + k;
+                       WARN_ON(resource_type(res) != IORESOURCE_MEM);
+                       d->window[k].phys = res->start;
+                       d->window[k].size = resource_size(res);
+                       d->window[k].virt = ioremap_nocache(res->start,
+                                                        resource_size(res));
+                       if (!d->window[k].virt)
+                               goto err2;
+               }
+       }
+
+       d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0;
+#ifdef CONFIG_INTC_BALANCING
+       if (d->nr_reg)
+               d->nr_reg += hw->nr_mask_regs;
+#endif
+       d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0;
+       d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0;
+       d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0;
+       d->nr_reg += hw->subgroups ? hw->nr_subgroups : 0;
+
+       d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
+       if (!d->reg)
+               goto err2;
+
+#ifdef CONFIG_SMP
+       d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
+       if (!d->smp)
+               goto err3;
+#endif
+       k = 0;
+
+       if (hw->mask_regs) {
+               for (i = 0; i < hw->nr_mask_regs; i++) {
+                       smp = IS_SMP(hw->mask_regs[i]);
+                       k += save_reg(d, k, hw->mask_regs[i].set_reg, smp);
+                       k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp);
+#ifdef CONFIG_INTC_BALANCING
+                       k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0);
+#endif
+               }
+       }
+
+       if (hw->prio_regs) {
+               d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio),
+                                 GFP_NOWAIT);
+               if (!d->prio)
+                       goto err4;
+
+               for (i = 0; i < hw->nr_prio_regs; i++) {
+                       smp = IS_SMP(hw->prio_regs[i]);
+                       k += save_reg(d, k, hw->prio_regs[i].set_reg, smp);
+                       k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp);
+               }
+       }
+
+       if (hw->sense_regs) {
+               d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense),
+                                  GFP_NOWAIT);
+               if (!d->sense)
+                       goto err5;
+
+               for (i = 0; i < hw->nr_sense_regs; i++)
+                       k += save_reg(d, k, hw->sense_regs[i].reg, 0);
+       }
+
+       if (hw->subgroups)
+               for (i = 0; i < hw->nr_subgroups; i++)
+                       if (hw->subgroups[i].reg)
+                               k+= save_reg(d, k, hw->subgroups[i].reg, 0);
+
+       memcpy(&d->chip, &intc_irq_chip, sizeof(struct irq_chip));
+       d->chip.name = desc->name;
+
+       if (hw->ack_regs)
+               for (i = 0; i < hw->nr_ack_regs; i++)
+                       k += save_reg(d, k, hw->ack_regs[i].set_reg, 0);
+       else
+               d->chip.mask_ack = d->chip.disable;
+
+       /* disable bits matching force_disable before registering irqs */
+       if (desc->force_disable)
+               intc_enable_disable_enum(desc, d, desc->force_disable, 0);
+
+       /* disable bits matching force_enable before registering irqs */
+       if (desc->force_enable)
+               intc_enable_disable_enum(desc, d, desc->force_enable, 0);
+
+       BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
+
+       /* register the vectors one by one */
+       for (i = 0; i < hw->nr_vectors; i++) {
+               struct intc_vect *vect = hw->vectors + i;
+               unsigned int irq = evt2irq(vect->vect);
+               struct irq_desc *irq_desc;
+
+               if (!vect->enum_id)
+                       continue;
+
+               irq_desc = irq_to_desc_alloc_node(irq, numa_node_id());
+               if (unlikely(!irq_desc)) {
+                       pr_err("can't get irq_desc for %d\n", irq);
+                       continue;
+               }
+
+               intc_irq_xlate_set(irq, vect->enum_id, d);
+               intc_register_irq(desc, d, vect->enum_id, irq);
+
+               for (k = i + 1; k < hw->nr_vectors; k++) {
+                       struct intc_vect *vect2 = hw->vectors + k;
+                       unsigned int irq2 = evt2irq(vect2->vect);
+
+                       if (vect->enum_id != vect2->enum_id)
+                               continue;
+
+                       /*
+                        * In the case of multi-evt handling and sparse
+                        * IRQ support, each vector still needs to have
+                        * its own backing irq_desc.
+                        */
+                       irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id());
+                       if (unlikely(!irq_desc)) {
+                               pr_err("can't get irq_desc for %d\n", irq2);
+                               continue;
+                       }
+
+                       vect2->enum_id = 0;
+
+                       /* redirect this interrupts to the first one */
+                       set_irq_chip(irq2, &dummy_irq_chip);
+                       set_irq_chained_handler(irq2, intc_redirect_irq);
+                       set_irq_data(irq2, (void *)irq);
+               }
+       }
+
+       intc_subgroup_init(desc, d);
+
+       /* enable bits matching force_enable after registering irqs */
+       if (desc->force_enable)
+               intc_enable_disable_enum(desc, d, desc->force_enable, 1);
+
+       nr_intc_controllers++;
+
+       return 0;
+err5:
+       kfree(d->prio);
+err4:
+#ifdef CONFIG_SMP
+       kfree(d->smp);
+err3:
+#endif
+       kfree(d->reg);
+err2:
+       for (k = 0; k < d->nr_windows; k++)
+               if (d->window[k].virt)
+                       iounmap(d->window[k].virt);
+
+       kfree(d->window);
+err1:
+       kfree(d);
+err0:
+       pr_err("unable to allocate INTC memory\n");
+
+       return -ENOMEM;
+}
+
+static ssize_t
+show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
+{
+       struct intc_desc_int *d;
+
+       d = container_of(dev, struct intc_desc_int, sysdev);
+
+       return sprintf(buf, "%s\n", d->chip.name);
+}
+
+static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
+
+static int intc_suspend(struct sys_device *dev, pm_message_t state)
+{
+       struct intc_desc_int *d;
+       struct irq_desc *desc;
+       int irq;
+
+       /* get intc controller associated with this sysdev */
+       d = container_of(dev, struct intc_desc_int, sysdev);
+
+       switch (state.event) {
+       case PM_EVENT_ON:
+               if (d->state.event != PM_EVENT_FREEZE)
+                       break;
+
+               for_each_irq_desc(irq, desc) {
+                       /*
+                        * This will catch the redirect and VIRQ cases
+                        * due to the dummy_irq_chip being inserted.
+                        */
+                       if (desc->chip != &d->chip)
+                               continue;
+                       if (desc->status & IRQ_DISABLED)
+                               desc->chip->disable(irq);
+                       else
+                               desc->chip->enable(irq);
+               }
+               break;
+       case PM_EVENT_FREEZE:
+               /* nothing has to be done */
+               break;
+       case PM_EVENT_SUSPEND:
+               /* enable wakeup irqs belonging to this intc controller */
+               for_each_irq_desc(irq, desc) {
+                       if (desc->chip != &d->chip)
+                               continue;
+                       if ((desc->status & IRQ_WAKEUP))
+                               desc->chip->enable(irq);
+               }
+               break;
+       }
+
+       d->state = state;
+
+       return 0;
+}
+
+static int intc_resume(struct sys_device *dev)
+{
+       return intc_suspend(dev, PMSG_ON);
+}
+
+struct sysdev_class intc_sysdev_class = {
+       .name           = "intc",
+       .suspend        = intc_suspend,
+       .resume         = intc_resume,
+};
+
+/* register this intc as sysdev to allow suspend/resume */
+static int __init register_intc_sysdevs(void)
+{
+       struct intc_desc_int *d;
+       int error;
+
+       error = sysdev_class_register(&intc_sysdev_class);
+       if (!error) {
+               list_for_each_entry(d, &intc_list, list) {
+                       d->sysdev.id = d->index;
+                       d->sysdev.cls = &intc_sysdev_class;
+                       error = sysdev_register(&d->sysdev);
+                       if (error == 0)
+                               error = sysdev_create_file(&d->sysdev,
+                                                          &attr_name);
+                       if (error)
+                               break;
+               }
+       }
+
+       if (error)
+               pr_err("sysdev registration error\n");
+
+       return error;
+}
+device_initcall(register_intc_sysdevs);
diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
new file mode 100644 (file)
index 0000000..6caecdf
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Dynamic IRQ management
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * Modelled after arch/x86/kernel/apic/io_apic.c
+ *
+ * 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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/irq.h>
+#include <linux/bitmap.h>
+#include <linux/spinlock.h>
+#include "internals.h" /* only for activate_irq() damage.. */
+
+/*
+ * The intc_irq_map provides a global map of bound IRQ vectors for a
+ * given platform. Allocation of IRQs are either static through the CPU
+ * vector map, or dynamic in the case of board mux vectors or MSI.
+ *
+ * As this is a central point for all IRQ controllers on the system,
+ * each of the available sources are mapped out here. This combined with
+ * sparseirq makes it quite trivial to keep the vector map tightly packed
+ * when dynamically creating IRQs, as well as tying in to otherwise
+ * unused irq_desc positions in the sparse array.
+ */
+static DECLARE_BITMAP(intc_irq_map, NR_IRQS);
+static DEFINE_RAW_SPINLOCK(vector_lock);
+
+/*
+ * Dynamic IRQ allocation and deallocation
+ */
+unsigned int create_irq_nr(unsigned int irq_want, int node)
+{
+       unsigned int irq = 0, new;
+       unsigned long flags;
+       struct irq_desc *desc;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+
+       /*
+        * First try the wanted IRQ
+        */
+       if (test_and_set_bit(irq_want, intc_irq_map) == 0) {
+               new = irq_want;
+       } else {
+               /* .. then fall back to scanning. */
+               new = find_first_zero_bit(intc_irq_map, nr_irqs);
+               if (unlikely(new == nr_irqs))
+                       goto out_unlock;
+
+               __set_bit(new, intc_irq_map);
+       }
+
+       desc = irq_to_desc_alloc_node(new, node);
+       if (unlikely(!desc)) {
+               pr_err("can't get irq_desc for %d\n", new);
+               goto out_unlock;
+       }
+
+       desc = move_irq_desc(desc, node);
+       irq = new;
+
+out_unlock:
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+
+       if (irq > 0) {
+               dynamic_irq_init(irq);
+               activate_irq(irq);
+       }
+
+       return irq;
+}
+
+int create_irq(void)
+{
+       int nid = cpu_to_node(smp_processor_id());
+       int irq;
+
+       irq = create_irq_nr(NR_IRQS_LEGACY, nid);
+       if (irq == 0)
+               irq = -1;
+
+       return irq;
+}
+
+void destroy_irq(unsigned int irq)
+{
+       unsigned long flags;
+
+       dynamic_irq_cleanup(irq);
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       __clear_bit(irq, intc_irq_map);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+}
+
+int reserve_irq_vector(unsigned int irq)
+{
+       unsigned long flags;
+       int ret = 0;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       if (test_and_set_bit(irq, intc_irq_map))
+               ret = -EBUSY;
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+
+       return ret;
+}
+
+void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs)
+{
+       unsigned long flags;
+       int i;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       for (i = 0; i < nr_vecs; i++)
+               __set_bit(evt2irq(vectors[i].vect), intc_irq_map);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+}
+
+void reserve_irq_legacy(void)
+{
+       unsigned long flags;
+       int i, j;
+
+       raw_spin_lock_irqsave(&vector_lock, flags);
+       j = find_first_bit(intc_irq_map, nr_irqs);
+       for (i = 0; i < j; i++)
+               __set_bit(i, intc_irq_map);
+       raw_spin_unlock_irqrestore(&vector_lock, flags);
+}
diff --git a/drivers/sh/intc/handle.c b/drivers/sh/intc/handle.c
new file mode 100644 (file)
index 0000000..057ce56
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Shared interrupt handling code for IPR and INTC2 types of IRQs.
+ *
+ * Copyright (C) 2007, 2008 Magnus Damm
+ * Copyright (C) 2009, 2010 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/irq.h>
+#include <linux/spinlock.h>
+#include "internals.h"
+
+static unsigned long ack_handle[NR_IRQS];
+
+static intc_enum __init intc_grp_id(struct intc_desc *desc,
+                                   intc_enum enum_id)
+{
+       struct intc_group *g = desc->hw.groups;
+       unsigned int i, j;
+
+       for (i = 0; g && enum_id && i < desc->hw.nr_groups; i++) {
+               g = desc->hw.groups + i;
+
+               for (j = 0; g->enum_ids[j]; j++) {
+                       if (g->enum_ids[j] != enum_id)
+                               continue;
+
+                       return g->enum_id;
+               }
+       }
+
+       return 0;
+}
+
+static unsigned int __init _intc_mask_data(struct intc_desc *desc,
+                                          struct intc_desc_int *d,
+                                          intc_enum enum_id,
+                                          unsigned int *reg_idx,
+                                          unsigned int *fld_idx)
+{
+       struct intc_mask_reg *mr = desc->hw.mask_regs;
+       unsigned int fn, mode;
+       unsigned long reg_e, reg_d;
+
+       while (mr && enum_id && *reg_idx < desc->hw.nr_mask_regs) {
+               mr = desc->hw.mask_regs + *reg_idx;
+
+               for (; *fld_idx < ARRAY_SIZE(mr->enum_ids); (*fld_idx)++) {
+                       if (mr->enum_ids[*fld_idx] != enum_id)
+                               continue;
+
+                       if (mr->set_reg && mr->clr_reg) {
+                               fn = REG_FN_WRITE_BASE;
+                               mode = MODE_DUAL_REG;
+                               reg_e = mr->clr_reg;
+                               reg_d = mr->set_reg;
+                       } else {
+                               fn = REG_FN_MODIFY_BASE;
+                               if (mr->set_reg) {
+                                       mode = MODE_ENABLE_REG;
+                                       reg_e = mr->set_reg;
+                                       reg_d = mr->set_reg;
+                               } else {
+                                       mode = MODE_MASK_REG;
+                                       reg_e = mr->clr_reg;
+                                       reg_d = mr->clr_reg;
+                               }
+                       }
+
+                       fn += (mr->reg_width >> 3) - 1;
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       1,
+                                       (mr->reg_width - 1) - *fld_idx);
+               }
+
+               *fld_idx = 0;
+               (*reg_idx)++;
+       }
+
+       return 0;
+}
+
+unsigned int __init
+intc_get_mask_handle(struct intc_desc *desc, struct intc_desc_int *d,
+                    intc_enum enum_id, int do_grps)
+{
+       unsigned int i = 0;
+       unsigned int j = 0;
+       unsigned int ret;
+
+       ret = _intc_mask_data(desc, d, enum_id, &i, &j);
+       if (ret)
+               return ret;
+
+       if (do_grps)
+               return intc_get_mask_handle(desc, d, intc_grp_id(desc, enum_id), 0);
+
+       return 0;
+}
+
+static unsigned int __init _intc_prio_data(struct intc_desc *desc,
+                                          struct intc_desc_int *d,
+                                          intc_enum enum_id,
+                                          unsigned int *reg_idx,
+                                          unsigned int *fld_idx)
+{
+       struct intc_prio_reg *pr = desc->hw.prio_regs;
+       unsigned int fn, n, mode, bit;
+       unsigned long reg_e, reg_d;
+
+       while (pr && enum_id && *reg_idx < desc->hw.nr_prio_regs) {
+               pr = desc->hw.prio_regs + *reg_idx;
+
+               for (; *fld_idx < ARRAY_SIZE(pr->enum_ids); (*fld_idx)++) {
+                       if (pr->enum_ids[*fld_idx] != enum_id)
+                               continue;
+
+                       if (pr->set_reg && pr->clr_reg) {
+                               fn = REG_FN_WRITE_BASE;
+                               mode = MODE_PCLR_REG;
+                               reg_e = pr->set_reg;
+                               reg_d = pr->clr_reg;
+                       } else {
+                               fn = REG_FN_MODIFY_BASE;
+                               mode = MODE_PRIO_REG;
+                               if (!pr->set_reg)
+                                       BUG();
+                               reg_e = pr->set_reg;
+                               reg_d = pr->set_reg;
+                       }
+
+                       fn += (pr->reg_width >> 3) - 1;
+                       n = *fld_idx + 1;
+
+                       BUG_ON(n * pr->field_width > pr->reg_width);
+
+                       bit = pr->reg_width - (n * pr->field_width);
+
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       pr->field_width, bit);
+               }
+
+               *fld_idx = 0;
+               (*reg_idx)++;
+       }
+
+       return 0;
+}
+
+unsigned int __init
+intc_get_prio_handle(struct intc_desc *desc, struct intc_desc_int *d,
+                    intc_enum enum_id, int do_grps)
+{
+       unsigned int i = 0;
+       unsigned int j = 0;
+       unsigned int ret;
+
+       ret = _intc_prio_data(desc, d, enum_id, &i, &j);
+       if (ret)
+               return ret;
+
+       if (do_grps)
+               return intc_get_prio_handle(desc, d, intc_grp_id(desc, enum_id), 0);
+
+       return 0;
+}
+
+static unsigned int __init intc_ack_data(struct intc_desc *desc,
+                                         struct intc_desc_int *d,
+                                         intc_enum enum_id)
+{
+       struct intc_mask_reg *mr = desc->hw.ack_regs;
+       unsigned int i, j, fn, mode;
+       unsigned long reg_e, reg_d;
+
+       for (i = 0; mr && enum_id && i < desc->hw.nr_ack_regs; i++) {
+               mr = desc->hw.ack_regs + i;
+
+               for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) {
+                       if (mr->enum_ids[j] != enum_id)
+                               continue;
+
+                       fn = REG_FN_MODIFY_BASE;
+                       mode = MODE_ENABLE_REG;
+                       reg_e = mr->set_reg;
+                       reg_d = mr->set_reg;
+
+                       fn += (mr->reg_width >> 3) - 1;
+                       return _INTC_MK(fn, mode,
+                                       intc_get_reg(d, reg_e),
+                                       intc_get_reg(d, reg_d),
+                                       1,
+                                       (mr->reg_width - 1) - j);
+               }
+       }
+
+       return 0;
+}
+
+static void intc_enable_disable(struct intc_desc_int *d,
+                               unsigned long handle, int do_enable)
+{
+       unsigned long addr;
+       unsigned int cpu;
+       unsigned long (*fn)(unsigned long, unsigned long,
+                  unsigned long (*)(unsigned long, unsigned long,
+                                    unsigned long),
+                  unsigned int);
+
+       if (do_enable) {
+               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
+                       addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
+                       fn = intc_enable_noprio_fns[_INTC_MODE(handle)];
+                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
+               }
+       } else {
+               for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
+                       addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
+                       fn = intc_disable_fns[_INTC_MODE(handle)];
+                       fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
+               }
+       }
+}
+
+void __init intc_enable_disable_enum(struct intc_desc *desc,
+                                    struct intc_desc_int *d,
+                                    intc_enum enum_id, int enable)
+{
+       unsigned int i, j, data;
+
+       /* go through and enable/disable all mask bits */
+       i = j = 0;
+       do {
+               data = _intc_mask_data(desc, d, enum_id, &i, &j);
+               if (data)
+                       intc_enable_disable(d, data, enable);
+               j++;
+       } while (data);
+
+       /* go through and enable/disable all priority fields */
+       i = j = 0;
+       do {
+               data = _intc_prio_data(desc, d, enum_id, &i, &j);
+               if (data)
+                       intc_enable_disable(d, data, enable);
+
+               j++;
+       } while (data);
+}
+
+unsigned int __init
+intc_get_sense_handle(struct intc_desc *desc, struct intc_desc_int *d,
+                     intc_enum enum_id)
+{
+       struct intc_sense_reg *sr = desc->hw.sense_regs;
+       unsigned int i, j, fn, bit;
+
+       for (i = 0; sr && enum_id && i < desc->hw.nr_sense_regs; i++) {
+               sr = desc->hw.sense_regs + i;
+
+               for (j = 0; j < ARRAY_SIZE(sr->enum_ids); j++) {
+                       if (sr->enum_ids[j] != enum_id)
+                               continue;
+
+                       fn = REG_FN_MODIFY_BASE;
+                       fn += (sr->reg_width >> 3) - 1;
+
+                       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);
+               }
+       }
+
+       return 0;
+}
+
+
+void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc,
+                        struct intc_desc_int *d, intc_enum id)
+{
+       unsigned long flags;
+
+       /*
+        * Nothing to do for this IRQ.
+        */
+       if (!desc->hw.ack_regs)
+               return;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       ack_handle[irq] = intc_ack_data(desc, d, id);
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
+
+unsigned long intc_get_ack_handle(unsigned int irq)
+{
+       return ack_handle[irq];
+}
diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h
new file mode 100644 (file)
index 0000000..d49482c
--- /dev/null
@@ -0,0 +1,186 @@
+#include <linux/sh_intc.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/radix-tree.h>
+#include <linux/sysdev.h>
+
+#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
+       ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
+        ((addr_e) << 16) | ((addr_d << 24)))
+
+#define _INTC_SHIFT(h)         (h & 0x1f)
+#define _INTC_WIDTH(h)         ((h >> 5) & 0xf)
+#define _INTC_FN(h)            ((h >> 9) & 0xf)
+#define _INTC_MODE(h)          ((h >> 13) & 0x7)
+#define _INTC_ADDR_E(h)                ((h >> 16) & 0xff)
+#define _INTC_ADDR_D(h)                ((h >> 24) & 0xff)
+
+#ifdef CONFIG_SMP
+#define IS_SMP(x)              (x.smp)
+#define INTC_REG(d, x, c)      (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
+#define SMP_NR(d, x)           ((d->smp[(x)] >> 8) ? (d->smp[(x)] >> 8) : 1)
+#else
+#define IS_SMP(x)              0
+#define INTC_REG(d, x, c)      (d->reg[(x)])
+#define SMP_NR(d, x)           1
+#endif
+
+struct intc_handle_int {
+       unsigned int irq;
+       unsigned long handle;
+};
+
+struct intc_window {
+       phys_addr_t phys;
+       void __iomem *virt;
+       unsigned long size;
+};
+
+struct intc_map_entry {
+       intc_enum enum_id;
+       struct intc_desc_int *desc;
+};
+
+struct intc_subgroup_entry {
+       unsigned int pirq;
+       intc_enum enum_id;
+       unsigned long handle;
+};
+
+struct intc_desc_int {
+       struct list_head list;
+       struct sys_device sysdev;
+       struct radix_tree_root tree;
+       pm_message_t state;
+       raw_spinlock_t lock;
+       unsigned int index;
+       unsigned long *reg;
+#ifdef CONFIG_SMP
+       unsigned long *smp;
+#endif
+       unsigned int nr_reg;
+       struct intc_handle_int *prio;
+       unsigned int nr_prio;
+       struct intc_handle_int *sense;
+       unsigned int nr_sense;
+       struct intc_window *window;
+       unsigned int nr_windows;
+       struct irq_chip chip;
+};
+
+
+enum {
+       REG_FN_ERR = 0,
+       REG_FN_TEST_BASE = 1,
+       REG_FN_WRITE_BASE = 5,
+       REG_FN_MODIFY_BASE = 9
+};
+
+enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */
+       MODE_MASK_REG,       /* Bit(s) set -> interrupt disabled */
+       MODE_DUAL_REG,       /* Two registers, set bit to enable / disable */
+       MODE_PRIO_REG,       /* Priority value written to enable interrupt */
+       MODE_PCLR_REG,       /* Above plus all bits set to disable interrupt */
+};
+
+static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
+{
+       struct irq_chip *chip = get_irq_chip(irq);
+
+       return container_of(chip, struct intc_desc_int, chip);
+}
+
+/*
+ * Grumble.
+ */
+static inline void activate_irq(int irq)
+{
+#ifdef CONFIG_ARM
+       /* ARM requires an extra step to clear IRQ_NOREQUEST, which it
+        * sets on behalf of every irq_chip.  Also sets IRQ_NOPROBE.
+        */
+       set_irq_flags(irq, IRQF_VALID);
+#else
+       /* same effect on other architectures */
+       set_irq_noprobe(irq);
+#endif
+}
+
+/* access.c */
+extern unsigned long
+(*intc_reg_fns[])(unsigned long addr, unsigned long h, unsigned long data);
+
+extern unsigned long
+(*intc_enable_fns[])(unsigned long addr, unsigned long handle,
+                    unsigned long (*fn)(unsigned long,
+                               unsigned long, unsigned long),
+                    unsigned int irq);
+extern unsigned long
+(*intc_disable_fns[])(unsigned long addr, unsigned long handle,
+                     unsigned long (*fn)(unsigned long,
+                               unsigned long, unsigned long),
+                     unsigned int irq);
+extern unsigned long
+(*intc_enable_noprio_fns[])(unsigned long addr, unsigned long handle,
+                           unsigned long (*fn)(unsigned long,
+                               unsigned long, unsigned long),
+                           unsigned int irq);
+
+unsigned long intc_phys_to_virt(struct intc_desc_int *d, unsigned long address);
+unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address);
+unsigned int intc_set_field_from_handle(unsigned int value,
+                           unsigned int field_value,
+                           unsigned int handle);
+unsigned long intc_get_field_from_handle(unsigned int value,
+                                        unsigned int handle);
+
+/* balancing.c */
+#ifdef CONFIG_INTC_BALANCING
+void intc_balancing_enable(unsigned int irq);
+void intc_balancing_disable(unsigned int irq);
+void intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
+                         struct intc_desc_int *d, intc_enum id);
+#else
+static inline void intc_balancing_enable(unsigned int irq) { }
+static inline void intc_balancing_disable(unsigned int irq) { }
+static inline void
+intc_set_dist_handle(unsigned int irq, struct intc_desc *desc,
+                    struct intc_desc_int *d, intc_enum id) { }
+#endif
+
+/* chip.c */
+extern struct irq_chip intc_irq_chip;
+void _intc_enable(unsigned int irq, unsigned long handle);
+
+/* core.c */
+extern struct list_head intc_list;
+extern raw_spinlock_t intc_big_lock;
+extern unsigned int nr_intc_controllers;
+extern struct sysdev_class intc_sysdev_class;
+
+unsigned int intc_get_dfl_prio_level(void);
+unsigned int intc_get_prio_level(unsigned int irq);
+void intc_set_prio_level(unsigned int irq, unsigned int level);
+
+/* handle.c */
+unsigned int intc_get_mask_handle(struct intc_desc *desc,
+                                 struct intc_desc_int *d,
+                                 intc_enum enum_id, int do_grps);
+unsigned int intc_get_prio_handle(struct intc_desc *desc,
+                                 struct intc_desc_int *d,
+                                 intc_enum enum_id, int do_grps);
+unsigned int intc_get_sense_handle(struct intc_desc *desc,
+                                  struct intc_desc_int *d,
+                                  intc_enum enum_id);
+void intc_set_ack_handle(unsigned int irq, struct intc_desc *desc,
+                        struct intc_desc_int *d, intc_enum id);
+unsigned long intc_get_ack_handle(unsigned int irq);
+void intc_enable_disable_enum(struct intc_desc *desc, struct intc_desc_int *d,
+                             intc_enum enum_id, int enable);
+
+/* virq.c */
+void intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d);
+void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d);
+struct intc_map_entry *intc_irq_xlate_get(unsigned int irq);
diff --git a/drivers/sh/intc/userimask.c b/drivers/sh/intc/userimask.c
new file mode 100644 (file)
index 0000000..e32304b
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Support for hardware-assisted userspace interrupt masking.
+ *
+ * Copyright (C) 2010  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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/errno.h>
+#include <linux/sysdev.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/sizes.h>
+#include "internals.h"
+
+static void __iomem *uimask;
+
+static ssize_t
+show_intc_userimask(struct sysdev_class *cls,
+                   struct sysdev_class_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf);
+}
+
+static ssize_t
+store_intc_userimask(struct sysdev_class *cls,
+                    struct sysdev_class_attribute *attr,
+                    const char *buf, size_t count)
+{
+       unsigned long level;
+
+       level = simple_strtoul(buf, NULL, 10);
+
+       /*
+        * Minimal acceptable IRQ levels are in the 2 - 16 range, but
+        * these are chomped so as to not interfere with normal IRQs.
+        *
+        * Level 1 is a special case on some CPUs in that it's not
+        * directly settable, but given that USERIMASK cuts off below a
+        * certain level, we don't care about this limitation here.
+        * Level 0 on the other hand equates to user masking disabled.
+        *
+        * We use the default priority level as a cut off so that only
+        * special case opt-in IRQs can be mangled.
+        */
+       if (level >= intc_get_dfl_prio_level())
+               return -EINVAL;
+
+       __raw_writel(0xa5 << 24 | level << 4, uimask);
+
+       return count;
+}
+
+static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR,
+                        show_intc_userimask, store_intc_userimask);
+
+
+static int __init userimask_sysdev_init(void)
+{
+       if (unlikely(!uimask))
+               return -ENXIO;
+
+       return sysdev_class_create_file(&intc_sysdev_class, &attr_userimask);
+}
+late_initcall(userimask_sysdev_init);
+
+int register_intc_userimask(unsigned long addr)
+{
+       if (unlikely(uimask))
+               return -EBUSY;
+
+       uimask = ioremap_nocache(addr, SZ_4K);
+       if (unlikely(!uimask))
+               return -ENOMEM;
+
+       pr_info("userimask support registered for levels 0 -> %d\n",
+               intc_get_dfl_prio_level() - 1);
+
+       return 0;
+}
diff --git a/drivers/sh/intc/virq-debugfs.c b/drivers/sh/intc/virq-debugfs.c
new file mode 100644 (file)
index 0000000..9e62ba9
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Support for virtual IRQ subgroups debugfs mapping.
+ *
+ * Copyright (C) 2010  Paul Mundt
+ *
+ * Modelled after arch/powerpc/kernel/irq.c.
+ *
+ * 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/seq_file.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/debugfs.h>
+#include "internals.h"
+
+static int intc_irq_xlate_debug(struct seq_file *m, void *priv)
+{
+       int i;
+
+       seq_printf(m, "%-5s  %-7s  %-15s\n", "irq", "enum", "chip name");
+
+       for (i = 1; i < nr_irqs; i++) {
+               struct intc_map_entry *entry = intc_irq_xlate_get(i);
+               struct intc_desc_int *desc = entry->desc;
+
+               if (!desc)
+                       continue;
+
+               seq_printf(m, "%5d  ", i);
+               seq_printf(m, "0x%05x  ", entry->enum_id);
+               seq_printf(m, "%-15s\n", desc->chip.name);
+       }
+
+       return 0;
+}
+
+static int intc_irq_xlate_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, intc_irq_xlate_debug, inode->i_private);
+}
+
+static const struct file_operations intc_irq_xlate_fops = {
+       .open = intc_irq_xlate_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static int __init intc_irq_xlate_init(void)
+{
+       /*
+        * XXX.. use arch_debugfs_dir here when all of the intc users are
+        * converted.
+        */
+       if (debugfs_create_file("intc_irq_xlate", S_IRUGO, NULL, NULL,
+                               &intc_irq_xlate_fops) == NULL)
+               return -ENOMEM;
+
+       return 0;
+}
+fs_initcall(intc_irq_xlate_init);
diff --git a/drivers/sh/intc/virq.c b/drivers/sh/intc/virq.c
new file mode 100644 (file)
index 0000000..643dfd4
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Support for virtual IRQ subgroups.
+ *
+ * Copyright (C) 2010  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.
+ */
+#define pr_fmt(fmt) "intc: " fmt
+
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/list.h>
+#include <linux/radix-tree.h>
+#include <linux/spinlock.h>
+#include "internals.h"
+
+static struct intc_map_entry intc_irq_xlate[NR_IRQS];
+
+struct intc_virq_list {
+       unsigned int irq;
+       struct intc_virq_list *next;
+};
+
+#define for_each_virq(entry, head) \
+       for (entry = head; entry; entry = entry->next)
+
+/*
+ * Tags for the radix tree
+ */
+#define INTC_TAG_VIRQ_NEEDS_ALLOC      0
+
+void intc_irq_xlate_set(unsigned int irq, intc_enum id, struct intc_desc_int *d)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&intc_big_lock, flags);
+       intc_irq_xlate[irq].enum_id = id;
+       intc_irq_xlate[irq].desc = d;
+       raw_spin_unlock_irqrestore(&intc_big_lock, flags);
+}
+
+struct intc_map_entry *intc_irq_xlate_get(unsigned int irq)
+{
+       return intc_irq_xlate + irq;
+}
+
+int intc_irq_lookup(const char *chipname, intc_enum enum_id)
+{
+       struct intc_map_entry *ptr;
+       struct intc_desc_int *d;
+       int irq = -1;
+
+       list_for_each_entry(d, &intc_list, list) {
+               int tagged;
+
+               if (strcmp(d->chip.name, chipname) != 0)
+                       continue;
+
+               /*
+                * Catch early lookups for subgroup VIRQs that have not
+                * yet been allocated an IRQ. This already includes a
+                * fast-path out if the tree is untagged, so there is no
+                * need to explicitly test the root tree.
+                */
+               tagged = radix_tree_tag_get(&d->tree, enum_id,
+                                           INTC_TAG_VIRQ_NEEDS_ALLOC);
+               if (unlikely(tagged))
+                       break;
+
+               ptr = radix_tree_lookup(&d->tree, enum_id);
+               if (ptr) {
+                       irq = ptr - intc_irq_xlate;
+                       break;
+               }
+       }
+
+       return irq;
+}
+EXPORT_SYMBOL_GPL(intc_irq_lookup);
+
+static int add_virq_to_pirq(unsigned int irq, unsigned int virq)
+{
+       struct intc_virq_list **last, *entry;
+       struct irq_desc *desc = irq_to_desc(irq);
+
+       /* scan for duplicates */
+       last = (struct intc_virq_list **)&desc->handler_data;
+       for_each_virq(entry, desc->handler_data) {
+               if (entry->irq == virq)
+                       return 0;
+               last = &entry->next;
+       }
+
+       entry = kzalloc(sizeof(struct intc_virq_list), GFP_ATOMIC);
+       if (!entry) {
+               pr_err("can't allocate VIRQ mapping for %d\n", virq);
+               return -ENOMEM;
+       }
+
+       entry->irq = virq;
+
+       *last = entry;
+
+       return 0;
+}
+
+static void intc_virq_handler(unsigned int irq, struct irq_desc *desc)
+{
+       struct intc_virq_list *entry, *vlist = get_irq_data(irq);
+       struct intc_desc_int *d = get_intc_desc(irq);
+
+       desc->chip->mask_ack(irq);
+
+       for_each_virq(entry, vlist) {
+               unsigned long addr, handle;
+
+               handle = (unsigned long)get_irq_data(entry->irq);
+               addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
+
+               if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
+                       generic_handle_irq(entry->irq);
+       }
+
+       desc->chip->unmask(irq);
+}
+
+static unsigned long __init intc_subgroup_data(struct intc_subgroup *subgroup,
+                                              struct intc_desc_int *d,
+                                              unsigned int index)
+{
+       unsigned int fn = REG_FN_TEST_BASE + (subgroup->reg_width >> 3) - 1;
+
+       return _INTC_MK(fn, MODE_ENABLE_REG, intc_get_reg(d, subgroup->reg),
+                       0, 1, (subgroup->reg_width - 1) - index);
+}
+
+static void __init intc_subgroup_init_one(struct intc_desc *desc,
+                                         struct intc_desc_int *d,
+                                         struct intc_subgroup *subgroup)
+{
+       struct intc_map_entry *mapped;
+       unsigned int pirq;
+       unsigned long flags;
+       int i;
+
+       mapped = radix_tree_lookup(&d->tree, subgroup->parent_id);
+       if (!mapped) {
+               WARN_ON(1);
+               return;
+       }
+
+       pirq = mapped - intc_irq_xlate;
+
+       raw_spin_lock_irqsave(&d->lock, flags);
+
+       for (i = 0; i < ARRAY_SIZE(subgroup->enum_ids); i++) {
+               struct intc_subgroup_entry *entry;
+               int err;
+
+               if (!subgroup->enum_ids[i])
+                       continue;
+
+               entry = kmalloc(sizeof(*entry), GFP_NOWAIT);
+               if (!entry)
+                       break;
+
+               entry->pirq = pirq;
+               entry->enum_id = subgroup->enum_ids[i];
+               entry->handle = intc_subgroup_data(subgroup, d, i);
+
+               err = radix_tree_insert(&d->tree, entry->enum_id, entry);
+               if (unlikely(err < 0))
+                       break;
+
+               radix_tree_tag_set(&d->tree, entry->enum_id,
+                                  INTC_TAG_VIRQ_NEEDS_ALLOC);
+       }
+
+       raw_spin_unlock_irqrestore(&d->lock, flags);
+}
+
+void __init intc_subgroup_init(struct intc_desc *desc, struct intc_desc_int *d)
+{
+       int i;
+
+       if (!desc->hw.subgroups)
+               return;
+
+       for (i = 0; i < desc->hw.nr_subgroups; i++)
+               intc_subgroup_init_one(desc, d, desc->hw.subgroups + i);
+}
+
+static void __init intc_subgroup_map(struct intc_desc_int *d)
+{
+       struct intc_subgroup_entry *entries[32];
+       unsigned long flags;
+       unsigned int nr_found;
+       int i;
+
+       raw_spin_lock_irqsave(&d->lock, flags);
+
+restart:
+       nr_found = radix_tree_gang_lookup_tag_slot(&d->tree,
+                       (void ***)entries, 0, ARRAY_SIZE(entries),
+                       INTC_TAG_VIRQ_NEEDS_ALLOC);
+
+       for (i = 0; i < nr_found; i++) {
+               struct intc_subgroup_entry *entry;
+               int irq;
+
+               entry = radix_tree_deref_slot((void **)entries[i]);
+               if (unlikely(!entry))
+                       continue;
+               if (unlikely(entry == RADIX_TREE_RETRY))
+                       goto restart;
+
+               irq = create_irq();
+               if (unlikely(irq < 0)) {
+                       pr_err("no more free IRQs, bailing..\n");
+                       break;
+               }
+
+               pr_info("Setting up a chained VIRQ from %d -> %d\n",
+                       irq, entry->pirq);
+
+               intc_irq_xlate_set(irq, entry->enum_id, d);
+
+               set_irq_chip_and_handler_name(irq, get_irq_chip(entry->pirq),
+                                             handle_simple_irq, "virq");
+               set_irq_chip_data(irq, get_irq_chip_data(entry->pirq));
+
+               set_irq_data(irq, (void *)entry->handle);
+
+               set_irq_chained_handler(entry->pirq, intc_virq_handler);
+               add_virq_to_pirq(entry->pirq, irq);
+
+               radix_tree_tag_clear(&d->tree, entry->enum_id,
+                                    INTC_TAG_VIRQ_NEEDS_ALLOC);
+               radix_tree_replace_slot((void **)entries[i],
+                                       &intc_irq_xlate[irq]);
+       }
+
+       raw_spin_unlock_irqrestore(&d->lock, flags);
+}
+
+void __init intc_finalize(void)
+{
+       struct intc_desc_int *d;
+
+       list_for_each_entry(d, &intc_list, list)
+               if (radix_tree_tagged(&d->tree, INTC_TAG_VIRQ_NEEDS_ALLOC))
+                       intc_subgroup_map(d);
+}
index cf0303a..75934e3 100644 (file)
@@ -7,6 +7,8 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -559,10 +561,8 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
        struct pinmux_data_reg *dr = NULL;
        int bit = 0;
 
-       if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0) {
-               BUG();
-               return 0;
-       }
+       if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
+               return -EINVAL;
 
        return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
 }
@@ -581,7 +581,7 @@ int register_pinmux(struct pinmux_info *pip)
 {
        struct gpio_chip *chip = &pip->chip;
 
-       pr_info("sh pinmux: %s handling gpio %d -> %d\n",
+       pr_info("%s handling gpio %d -> %d\n",
                pip->name, pip->first_gpio, pip->last_gpio);
 
        setup_data_regs(pip);
@@ -602,3 +602,10 @@ int register_pinmux(struct pinmux_info *pip)
 
        return gpiochip_add(chip);
 }
+
+int unregister_pinmux(struct pinmux_info *pip)
+{
+       pr_info("%s deregistering\n", pip->name);
+
+       return gpiochip_remove(&pip->chip);
+}
index 335311a..8e03e76 100644 (file)
@@ -139,8 +139,6 @@ source "drivers/staging/adis16255/Kconfig"
 
 source "drivers/staging/xgifb/Kconfig"
 
-source "drivers/staging/mrst-touchscreen/Kconfig"
-
 source "drivers/staging/msm/Kconfig"
 
 source "drivers/staging/lirc/Kconfig"
index e3f1e1b..0e7d755 100644 (file)
@@ -51,7 +51,6 @@ obj-$(CONFIG_CXT1E1)          += cxt1e1/
 obj-$(CONFIG_TI_ST)            += ti-st/
 obj-$(CONFIG_ADIS16255)                += adis16255/
 obj-$(CONFIG_FB_XGI)           += xgifb/
-obj-$(CONFIG_TOUCHSCREEN_MRSTOUCH)     += mrst-touchscreen/
 obj-$(CONFIG_MSM_STAGING)      += msm/
 obj-$(CONFIG_EASYCAP)          += easycap/
 obj-$(CONFIG_SOLO6X10)         += solo6x10/
diff --git a/drivers/staging/mrst-touchscreen/Kconfig b/drivers/staging/mrst-touchscreen/Kconfig
deleted file mode 100644 (file)
index c2af492..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-config TOUCHSCREEN_INTEL_MID
-       tristate "Intel MID platform resistive touchscreen"
-       depends on INTEL_SCU_IPC
-       default y
-       help
-         Say Y here if you have a Intel MID based touchscreen
-         If unsure, say N.
diff --git a/drivers/staging/mrst-touchscreen/Makefile b/drivers/staging/mrst-touchscreen/Makefile
deleted file mode 100644 (file)
index 2d638b0..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) := intel_mid_touch.o
-
-
diff --git a/drivers/staging/mrst-touchscreen/TODO b/drivers/staging/mrst-touchscreen/TODO
deleted file mode 100644 (file)
index 7157028..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-- Move the driver to not think it is SPI (requires fixing some of the SFI
-  and firmware side)
diff --git a/drivers/staging/mrst-touchscreen/intel-mid-touch.c b/drivers/staging/mrst-touchscreen/intel-mid-touch.c
deleted file mode 100644 (file)
index abba22f..0000000
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * intel_mid_touch.c - Intel MID Resistive Touch Screen Driver
- *
- * Copyright (C) 2008 Intel Corp
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; ifnot, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * Questions/Comments/Bug fixes to Sreedhara (sreedhara.ds@intel.com)
- *                         Ramesh Agarwal (ramesh.agarwal@intel.com)
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * TODO:
- *     kill off mrstouch_debug eventually
- *     review conversion of r/m/w sequences
- *     Replace interrupt mutex abuse
- *     Kill of mrstouchdevp pointer
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/param.h>
-#include <linux/spi/spi.h>
-#include <linux/irq.h>
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <asm/intel_scu_ipc.h>
-
-
-#if defined(MRSTOUCH_DEBUG)
-#define mrstouch_debug(fmt, args...)\
-       do { \
-               printk(KERN_DEBUG "\n[MRSTOUCH(%d)] - ", __LINE__); \
-               printk(KERN_DEBUG fmt, ##args); \
-       } while (0);
-#else
-#define mrstouch_debug(fmt, args...)
-#endif
-
-/* PMIC Interrupt registers */
-#define PMIC_REG_ID1   0x00 /*PMIC ID1 register */
-
-/* PMIC Interrupt registers */
-#define PMIC_REG_INT   0x04 /*PMIC interrupt register */
-#define PMIC_REG_MINT  0x05 /*PMIC interrupt mask register */
-
-/* ADC Interrupt registers */
-#define PMIC_REG_ADCINT   0x5F /*ADC interrupt register */
-#define PMIC_REG_MADCINT  0x60 /*ADC interrupt mask register */
-
-/* ADC Control registers */
-#define PMIC_REG_ADCCNTL1    0x61 /*ADC control register */
-
-/* ADC Channel Selection registers */
-#define PMICADDR0     0xA4
-#define END_OF_CHANNEL 0x1F
-
-/* ADC Result register */
-#define PMIC_REG_ADCSNS0H   0x64
-
-/* ADC channels for touch screen */
-#define MRST_TS_CHAN10   0xA /* Touch screen X+ connection */
-#define MRST_TS_CHAN11   0xB /* Touch screen X- connection */
-#define MRST_TS_CHAN12   0xC /* Touch screen Y+ connection */
-#define MRST_TS_CHAN13   0xD /* Touch screen Y- connection */
-
-/* Touch screen coordinate constants */
-#define TOUCH_PRESSURE         50
-#define TOUCH_PRESSURE_FS      100
-
-#define XMOVE_LIMIT    5
-#define YMOVE_LIMIT    5
-#define XYMOVE_CNT     3
-
-#define MAX_10BIT      ((1<<10)-1)
-
-/* Touch screen channel BIAS constants */
-#define XBIAS          0x20
-#define YBIAS          0x40
-#define ZBIAS          0x80
-
-/* Touch screen coordinates */
-#define MIN_X          10
-#define MAX_X          1024
-#define MIN_Y          10
-#define MAX_Y          1024
-#define WAIT_ADC_COMPLETION 10
-
-/* PMIC ADC round robin delays */
-#define ADC_LOOP_DELAY0 0x0 /* Continuous loop */
-#define ADC_LOOP_DELAY1 0x1 /* 4.5  ms approximate */
-
-/* PMIC Vendor Identifiers */
-#define PMIC_VENDOR_FS  0 /* PMIC vendor FreeScale */
-#define PMIC_VENDOR_MAXIM 1 /* PMIC vendor MAXIM */
-#define PMIC_VENDOR_NEC 2 /* PMIC vendor NEC */
-#define MRSTOUCH_MAX_CHANNELS 32 /* Maximum ADC channels */
-
-/* Touch screen device structure */
-struct mrstouch_dev {
-       struct spi_device *spi; /* SPI device associated with touch screen */
-       struct input_dev *input; /* input device for touchscreen*/
-       char            phys[32]; /* Device name */
-       struct task_struct *pendet_thrd; /* PENDET interrupt handler */
-       struct mutex lock; /* Sync between interrupt and PENDET handler */
-       bool            busy; /* Busy flag */
-       u16             asr; /* Address selection register */
-       int             irq;    /* Touch screen IRQ # */
-       uint            vendor;  /* PMIC vendor */
-       uint            rev;  /* PMIC revision */
-       bool            suspended; /* Device suspended status */
-       bool            disabled;  /* Device disabled status */
-       u16             x;  /* X coordinate */
-       u16             y;  /* Y coordinate */
-       bool            pendown;  /* PEN position */
-} ;
-
-
-/* Global Pointer to Touch screen device */
-static struct mrstouch_dev *mrstouchdevp;
-
-/* Utility to read PMIC ID */
-static int mrstouch_pmic_id(uint *vendor, uint *rev)
-{
-       int err;
-       u8 r;
-
-       err = intel_scu_ipc_ioread8(PMIC_REG_ID1, &r);
-       if (err)
-               return err;
-
-       *vendor = r & 0x7;
-       *rev = (r >> 3) & 0x7;
-
-       return 0;
-}
-
-/*
- * Parse ADC channels to find end of the channel configured by other ADC user
- * NEC and MAXIM requires 4 channels and FreeScale needs 18 channels
- */
-static int mrstouch_chan_parse(struct mrstouch_dev *tsdev)
-{
-       int err, i, j, found;
-       u32 r32;
-
-       found = -1;
-
-       for (i = 0; i < MRSTOUCH_MAX_CHANNELS; i++) {
-               if (found >= 0)
-                       break;
-
-               err = intel_scu_ipc_ioread32(PMICADDR0, &r32);
-               if (err)
-                       return err;
-
-               for (j = 0; j < 32; j+= 8) {
-                       if (((r32 >> j) & 0xFF) == END_OF_CHANNEL) {
-                               found = i;
-                               break;
-                       }
-               }
-       }
-       if (found < 0)
-               return 0;
-
-       if (tsdev->vendor == PMIC_VENDOR_FS) {
-               if (found && found > (MRSTOUCH_MAX_CHANNELS - 18))
-                       return -ENOSPC;
-       } else {
-               if (found && found > (MRSTOUCH_MAX_CHANNELS - 4))
-                       return -ENOSPC;
-       }
-       return found;
-}
-
-/* Utility to enable/disable pendet.
- * pendet set to true enables PENDET interrupt
- * pendet set to false disables PENDET interrupt
- * Also clears RND mask bit
-*/
-static int pendet_enable(struct mrstouch_dev *tsdev, bool pendet)
-{
-       u16 reg;
-       u8 r;
-       u8 pendet_enabled = 0;
-       int retry = 0;
-       int err;
-
-       err = intel_scu_ipc_ioread16(PMIC_REG_MADCINT, &reg);
-       if (err)
-               return err;
-
-       if (pendet) {
-               reg &= ~0x0005;
-               reg |= 0x2000; /* Enable pendet */
-       } else
-               reg &= 0xDFFF; /* Disable pendet */
-
-       /* Set MADCINT and update ADCCNTL1 (next reg byte) */
-       err = intel_scu_ipc_iowrite16(PMIC_REG_MADCINT, reg);
-       if (!pendet || err)
-               return err;
-
-       /*
-        * Sometimes even after the register write succeeds
-        * the PMIC register value is not updated. Retry few iterations
-        * to enable pendet.
-        */
-
-       err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
-       pendet_enabled = (r >> 5) & 0x01;
-
-       retry = 0;
-       while (!err && !pendet_enabled) {
-               retry++;
-               msleep(10);
-               err = intel_scu_ipc_iowrite8(PMIC_REG_ADCCNTL1, reg >> 8);
-               if (err)
-                       break;
-               err = intel_scu_ipc_ioread8(PMIC_REG_ADCCNTL1, &r);
-               if (err == 0)
-                       pendet_enabled = (r >> 5) & 0x01;
-               if (retry >= 10) {
-                       dev_err(&tsdev->spi->dev, "Touch screen disabled.\n");
-                       return -EIO;
-               }
-       }
-       return 0;
-}
-
-/* To read PMIC ADC touch screen result
- * Reads ADC storage registers for higher 7 and lower 3 bits
- * converts the two readings to single value and turns off gain bit
- */
-static int mrstouch_ts_chan_read(u16 offset, u16 chan, u16 *vp, u16 *vm)
-{
-       int err;
-       u16 result;
-       u32 res;
-
-       result = PMIC_REG_ADCSNS0H + offset;
-
-       if (chan == MRST_TS_CHAN12)
-               result += 4;
-
-       err = intel_scu_ipc_ioread32(result, &res);
-       if (err)
-               return err;
-
-       /* Mash the bits up */
-
-       *vp = (res & 0xFF) << 3;        /* Highest 7 bits */
-       *vp |= (res >> 8) & 0x07;       /* Lower 3 bits */
-       *vp &= 0x3FF;
-
-       res >>= 16;
-
-       *vm = (res & 0xFF) << 3;        /* Highest 7 bits */
-       *vm |= (res >> 8) & 0x07;       /* Lower 3 bits */
-       *vm &= 0x3FF;
-
-       return 0;
-}
-
-/* To configure touch screen channels
- * Writes touch screen channels to ADC address selection registers
- */
-static int mrstouch_ts_chan_set(uint offset)
-{
-       int count;
-       u16 chan;
-       u16 reg[5];
-       u8 data[5];
-
-       chan = PMICADDR0 + offset;
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = MRST_TS_CHAN10 + count;
-       }
-       reg[count] = chan;
-       data[count] = END_OF_CHANNEL;
-
-       return intel_scu_ipc_writev(reg, data, 5);
-}
-
-/* Initialize ADC */
-static int mrstouch_adc_init(struct mrstouch_dev *tsdev)
-{
-       int err, start;
-       u8 ra, rm;
-
-       err = mrstouch_pmic_id(&tsdev->vendor, &tsdev->rev);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "Unable to read PMIC id\n");
-               return err;
-       }
-
-       start = mrstouch_chan_parse(tsdev);
-       if (start < 0) {
-               dev_err(&tsdev->spi->dev, "Unable to parse channels\n");
-               return start;
-       }
-
-       tsdev->asr = start;
-
-       mrstouch_debug("Channel offset(%d): 0x%X\n", tsdev->asr, tsdev->vendor);
-
-       /* ADC power on, start, enable PENDET and set loop delay
-        * ADC loop delay is set to 4.5 ms approximately
-        * Loop delay more than this results in jitter in adc readings
-        * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
-        * interrupt generation sometimes.
-        */
-
-       if (tsdev->vendor == PMIC_VENDOR_FS) {
-               ra = 0xE0 | ADC_LOOP_DELAY0;
-               rm = 0x5;
-       } else {
-               /* NEC and MAXIm not consistent with loop delay 0 */
-               ra = 0xE0 | ADC_LOOP_DELAY1;
-               rm = 0x0;
-
-               /* configure touch screen channels */
-               err = mrstouch_ts_chan_set(tsdev->asr);
-               if (err)
-                       return err;
-       }
-       err = intel_scu_ipc_update_register(PMIC_REG_ADCCNTL1, ra, 0xE7);
-       if (err == 0)
-               err = intel_scu_ipc_update_register(PMIC_REG_MADCINT, rm, 0x03);
-       return err;
-}
-
-/* Reports x,y coordinates to event subsystem */
-static void mrstouch_report_xy(struct mrstouch_dev *tsdev, u16 x, u16 y, u16 z)
-{
-       int xdiff, ydiff;
-
-       if (tsdev->pendown && z <= TOUCH_PRESSURE) {
-               /* Pen removed, report button release */
-               mrstouch_debug("BTN REL(%d)", z);
-               input_report_key(tsdev->input, BTN_TOUCH, 0);
-               tsdev->pendown = false;
-       }
-
-       xdiff = abs(x - tsdev->x);
-       ydiff = abs(y - tsdev->y);
-
-       /*
-       if x and y values changes for XYMOVE_CNT readings it is considered
-       as stylus is moving. This is required to differentiate between stylus
-       movement and jitter
-       */
-       if (x < MIN_X || x > MAX_X || y < MIN_Y || y > MAX_Y) {
-               /* Spurious values, release button if touched and return */
-               if (tsdev->pendown) {
-                       mrstouch_debug("BTN REL(%d)", z);
-                       input_report_key(tsdev->input, BTN_TOUCH, 0);
-                       tsdev->pendown = false;
-               }
-               return;
-       } else if (xdiff >= XMOVE_LIMIT || ydiff >= YMOVE_LIMIT) {
-               tsdev->x = x;
-               tsdev->y = y;
-
-               input_report_abs(tsdev->input, ABS_X, x);
-               input_report_abs(tsdev->input, ABS_Y, y);
-               input_sync(tsdev->input);
-       }
-
-
-       if (!tsdev->pendown && z > TOUCH_PRESSURE) {
-               /* Pen touched, report button touch */
-               mrstouch_debug("BTN TCH(%d, %d, %d)", x, y, z);
-               input_report_key(tsdev->input, BTN_TOUCH, 1);
-               tsdev->pendown = true;
-       }
-}
-
-
-/* Utility to start ADC, used by freescale handler */
-static int pendet_mask(void)
-{
-       return  intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x02, 0x02);
-}
-
-/* Utility to stop ADC, used by freescale handler */
-static int pendet_umask(void)
-{
-       return  intel_scu_ipc_update_register(PMIC_REG_MADCINT, 0x00, 0x02);
-}
-
-/* Utility to read ADC, used by freescale handler */
-static int mrstouch_pmic_fs_adc_read(struct mrstouch_dev *tsdev)
-{
-       int err;
-       u16 x, y, z, result;
-       u16 reg[4];
-       u8 data[4];
-
-       result = PMIC_REG_ADCSNS0H + tsdev->asr;
-
-       reg[0] = result + 4;
-       reg[1] = result + 5;
-       reg[2] = result + 16;
-       reg[3] = result + 17;
-
-       err = intel_scu_ipc_readv(reg, data, 4);
-       if (err)
-               goto ipc_error;
-
-       x = data[0] << 3; /* Higher 7 bits */
-       x |= data[1] & 0x7; /* Lower 3 bits */
-       x &= 0x3FF;
-
-       y = data[2] << 3; /* Higher 7 bits */
-       y |= data[3] & 0x7; /* Lower 3 bits */
-       y &= 0x3FF;
-
-       /* Read Z value */
-       reg[0] = result + 28;
-       reg[1] = result + 29;
-
-       err = intel_scu_ipc_readv(reg, data, 4);
-       if (err)
-               goto ipc_error;
-
-       z = data[0] << 3; /* Higher 7 bits */
-       z |= data[1] & 0x7; /* Lower 3 bits */
-       z &= 0x3FF;
-
-#if defined(MRSTOUCH_PRINT_XYZP)
-       mrstouch_debug("X: %d, Y: %d, Z: %d", x, y, z);
-#endif
-
-       if (z >= TOUCH_PRESSURE_FS) {
-               mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE - 1); /* Pen Removed */
-               return TOUCH_PRESSURE - 1;
-       } else {
-               mrstouch_report_xy(tsdev, x, y, TOUCH_PRESSURE + 1); /* Pen Touched */
-               return TOUCH_PRESSURE + 1;
-       }
-
-       return 0;
-
-ipc_error:
-       dev_err(&tsdev->spi->dev, "ipc error during fs_adc read\n");
-       return err;
-}
-
-/* To handle free scale pmic pendet interrupt */
-static int pmic0_pendet(void *dev_id)
-{
-       int err, count;
-       u16 chan;
-       unsigned int touched;
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)dev_id;
-       u16 reg[5];
-       u8 data[5];
-
-       chan = PMICADDR0 + tsdev->asr;
-
-       /* Set X BIAS */
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = 0x2A;
-       }
-       reg[count] =  chan++; /* Dummy */
-       data[count] = 0;
-
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* Set Y BIAS */
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = 0x4A;
-       }
-       reg[count] = chan++; /* Dummy */
-       data[count] = 0;
-
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* Set Z BIAS */
-       err = intel_scu_ipc_iowrite32(chan + 2, 0x8A8A8A8A);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /*Read touch screen channels till pen removed
-        * Freescale reports constant value of z for all points
-        * z is high when screen is not touched and low when touched
-        * Map high z value to not touched and low z value to pen touched
-        */
-       touched = mrstouch_pmic_fs_adc_read(tsdev);
-       while (touched > TOUCH_PRESSURE) {
-               touched = mrstouch_pmic_fs_adc_read(tsdev);
-               msleep(WAIT_ADC_COMPLETION);
-       }
-
-       /* Clear all TS channels */
-       chan = PMICADDR0 + tsdev->asr;
-       for (count = 0; count <= 4; count++) {
-               reg[count] = chan++;
-               data[count] = 0;
-       }
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       for (count = 0; count <= 4; count++) {
-               reg[count] = chan++;
-               data[count] = 0;
-       }
-       err = intel_scu_ipc_writev(reg, data, 5);
-       if (err)
-               goto ipc_error;
-
-       err = intel_scu_ipc_iowrite32(chan + 2, 0x00000000);
-       if (err)
-               goto ipc_error;
-
-       return 0;
-
-ipc_error:
-       dev_err(&tsdev->spi->dev, "ipc error during pendet\n");
-       return err;
-}
-
-
-/* To enable X, Y and Z bias values
- * Enables YPYM for X channels and XPXM for Y channels
- */
-static int mrstouch_ts_bias_set(uint offset, uint bias)
-{
-       int count;
-       u16 chan, start;
-       u16 reg[4];
-       u8 data[4];
-
-       chan = PMICADDR0 + offset;
-       start = MRST_TS_CHAN10;
-
-       for (count = 0; count <= 3; count++) {
-               reg[count] = chan++;
-               data[count] = bias | (start + count);
-       }
-       return intel_scu_ipc_writev(reg, data, 4);
-}
-
-/* To read touch screen channel values */
-static int mrstouch_adc_read(struct mrstouch_dev *tsdev)
-{
-       int err;
-       u16 xp, xm, yp, ym, zp, zm;
-
-       /* configure Y bias for X channels */
-       err = mrstouch_ts_bias_set(tsdev->asr, YBIAS);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* read x+ and x- channels */
-       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &xp, &xm);
-       if (err)
-               goto ipc_error;
-
-       /* configure x bias for y channels */
-       err = mrstouch_ts_bias_set(tsdev->asr, XBIAS);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* read y+ and y- channels */
-       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN12, &yp, &ym);
-       if (err)
-               goto ipc_error;
-
-       /* configure z bias for x and y channels */
-       err = mrstouch_ts_bias_set(tsdev->asr, ZBIAS);
-       if (err)
-               goto ipc_error;
-
-       msleep(WAIT_ADC_COMPLETION);
-
-       /* read z+ and z- channels */
-       err = mrstouch_ts_chan_read(tsdev->asr, MRST_TS_CHAN10, &zp, &zm);
-       if (err)
-               goto ipc_error;
-
-#if defined(MRSTOUCH_PRINT_XYZP)
-       printk(KERN_INFO "X+: %d, Y+: %d, Z+: %d\n", xp, yp, zp);
-#endif
-
-#if defined(MRSTOUCH_PRINT_XYZM)
-       printk(KERN_INFO "X-: %d, Y-: %d, Z-: %d\n", xm, ym, zm);
-#endif
-
-       mrstouch_report_xy(tsdev, xp, yp, zp); /* report x and y to eventX */
-
-       return zp;
-
-ipc_error:
-       dev_err(&tsdev->spi->dev, "ipc error during adc read\n");
-       return err;
-}
-
-/* PENDET interrupt handler function for NEC and MAXIM */
-static void pmic12_pendet(void *data)
-{
-       unsigned int touched;
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
-
-       /* read touch screen channels till pen removed */
-       do {
-               touched = mrstouch_adc_read(tsdev);
-       } while (touched > TOUCH_PRESSURE);
-}
-
-/* Handler to process PENDET interrupt */
-int mrstouch_pendet(void *data)
-{
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)data;
-       while (1) {
-               /* Wait for PENDET interrupt */
-               if (mutex_lock_interruptible(&tsdev->lock)) {
-                       msleep(WAIT_ADC_COMPLETION);
-                       continue;
-               }
-
-               if (tsdev->busy)
-                       return 0;
-
-               tsdev->busy = true;
-
-               if (tsdev->vendor == PMIC_VENDOR_NEC ||
-                       tsdev->vendor == PMIC_VENDOR_MAXIM) {
-                       /* PENDET must be disabled in NEC before reading ADC */
-                       pendet_enable(tsdev,false); /* Disbale PENDET */
-                       pmic12_pendet(tsdev);
-                       pendet_enable(tsdev, true); /*Enable PENDET */
-               } else if (tsdev->vendor == PMIC_VENDOR_FS) {
-                       pendet_umask(); /* Stop ADC */
-                       pmic0_pendet(tsdev);
-                       pendet_mask(); /* Stop ADC */
-               } else
-               dev_err(&tsdev->spi->dev, "Unsupported touchscreen: %d\n",
-                               tsdev->vendor);
-
-               tsdev->busy = false;
-
-       }
-       return 0;
-}
-
-/* PENDET interrupt handler */
-static irqreturn_t pendet_intr_handler(int irq, void *handle)
-{
-       struct mrstouch_dev *tsdev = (struct mrstouch_dev *)handle;
-
-       mutex_unlock(&tsdev->lock);
-       return IRQ_HANDLED;
-}
-
-/* Intializes input device and registers with input subsystem */
-static int ts_input_dev_init(struct mrstouch_dev *tsdev, struct spi_device *spi)
-{
-       int err = 0;
-
-       mrstouch_debug("%s", __func__);
-
-       tsdev->input = input_allocate_device();
-       if (!tsdev->input) {
-               dev_err(&tsdev->spi->dev, "Unable to allocate input device.\n");
-               return -EINVAL;
-       }
-
-       tsdev->input->name = "mrst_touchscreen";
-       snprintf(tsdev->phys, sizeof(tsdev->phys),
-                       "%s/input0", dev_name(&spi->dev));
-       tsdev->input->phys = tsdev->phys;
-       tsdev->input->dev.parent = &spi->dev;
-
-       tsdev->input->id.vendor = tsdev->vendor;
-       tsdev->input->id.version = tsdev->rev;
-
-       tsdev->input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
-       tsdev->input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
-
-       input_set_abs_params(tsdev->input, ABS_X, MIN_X, MIN_Y, 0, 0);
-       input_set_abs_params(tsdev->input, ABS_Y, MIN_X, MIN_Y, 0, 0);
-
-       err = input_register_device(tsdev->input);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "unable to register input device\n");
-               input_free_device(tsdev->input);
-               return err;
-       }
-
-       mrstouch_debug("%s", "mrstouch initialized");
-
-       return 0;
-
-}
-
-/* Probe function for touch screen driver */
-static int __devinit mrstouch_probe(struct spi_device *mrstouch_spi)
-{
-       int err;
-       unsigned int myirq;
-       struct mrstouch_dev *tsdev;
-
-       mrstouch_debug("%s(%p)", __func__, mrstouch_spi);
-
-       mrstouchdevp = NULL;
-       myirq = mrstouch_spi->irq;
-
-       if (!mrstouch_spi->irq) {
-               dev_err(&mrstouch_spi->dev, "no interrupt assigned\n");
-               return -EINVAL;
-       }
-
-       tsdev = kzalloc(sizeof(struct mrstouch_dev), GFP_KERNEL);
-       if (!tsdev) {
-               dev_err(&mrstouch_spi->dev, "unable to allocate memory\n");
-               return -ENOMEM;
-       }
-
-       tsdev->irq = myirq;
-       mrstouchdevp = tsdev;
-
-       err = mrstouch_adc_init(tsdev);
-       if (err) {
-               dev_err(&mrstouch_spi->dev, "ADC init failed\n");
-               goto mrstouch_err_free_mem;
-       }
-
-       dev_set_drvdata(&mrstouch_spi->dev, tsdev);
-       tsdev->spi = mrstouch_spi;
-
-       err = ts_input_dev_init(tsdev, mrstouch_spi);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "ts_input_dev_init failed");
-               goto mrstouch_err_free_mem;
-       }
-
-       mutex_init(&tsdev->lock);
-       mutex_lock(&tsdev->lock)
-
-       mrstouch_debug("Requesting IRQ-%d", myirq);
-       err = request_irq(myirq, pendet_intr_handler,
-                               0, "mrstouch", tsdev);
-       if (err) {
-               dev_err(&tsdev->spi->dev, "unable to allocate irq\n");
-               goto mrstouch_err_free_mem;
-       }
-
-       tsdev->pendet_thrd = kthread_run(mrstouch_pendet,
-                               (void *)tsdev, "pendet handler");
-       if (IS_ERR(tsdev->pendet_thrd)) {
-               dev_err(&tsdev->spi->dev, "kthread_run failed\n");
-               err = PTR_ERR(tsdev->pendet_thrd);
-               goto mrstouch_err_free_mem;
-       }
-       mrstouch_debug("%s", "Driver initialized");
-       return 0;
-
-mrstouch_err_free_mem:
-       kfree(tsdev);
-       return err;
-}
-
-static int mrstouch_suspend(struct spi_device *spi, pm_message_t msg)
-{
-       mrstouch_debug("%s", __func__);
-       mrstouchdevp->suspended = 1;
-       return 0;
-}
-
-static int mrstouch_resume(struct spi_device *spi)
-{
-       mrstouch_debug("%s", __func__);
-       mrstouchdevp->suspended = 0;
-       return 0;
-}
-
-static int mrstouch_remove(struct spi_device *spi)
-{
-       mrstouch_debug("%s", __func__);
-       free_irq(mrstouchdevp->irq, mrstouchdevp);
-       input_unregister_device(mrstouchdevp->input);
-       input_free_device(mrstouchdevp->input);
-       if (mrstouchdevp->pendet_thrd)
-               kthread_stop(mrstouchdevp->pendet_thrd);
-       kfree(mrstouchdevp);
-       return 0;
-}
-
-static struct spi_driver mrstouch_driver = {
-       .driver = {
-               .name   = "pmic_touch",
-               .bus    = &spi_bus_type,
-               .owner  = THIS_MODULE,
-       },
-       .probe          = mrstouch_probe,
-       .suspend        = mrstouch_suspend,
-       .resume         = mrstouch_resume,
-       .remove         = mrstouch_remove,
-};
-
-static int __init mrstouch_module_init(void)
-{
-       int err;
-
-       mrstouch_debug("%s", __func__);
-       err = spi_register_driver(&mrstouch_driver);
-       if (err) {
-               mrstouch_debug("%s(%d)", "SPI PENDET failed", err);
-               return -1;
-       }
-
-       return 0;
-}
-
-static void __exit mrstouch_module_exit(void)
-{
-       mrstouch_debug("%s", __func__);
-       spi_unregister_driver(&mrstouch_driver);
-       return;
-}
-
-module_init(mrstouch_module_init);
-module_exit(mrstouch_module_exit);
-
-MODULE_AUTHOR("Sreedhara Murthy. D.S, sreedhara.ds@intel.com");
-MODULE_DESCRIPTION("Intel Moorestown Resistive Touch Screen Driver");
-MODULE_LICENSE("GPL");
index 77be3c2..3076b1c 100644 (file)
@@ -2397,7 +2397,7 @@ static const struct dev_pm_ops r8a66597_dev_pm_ops = {
 #define R8A66597_DEV_PM_OPS    NULL
 #endif
 
-static int __init_or_module r8a66597_remove(struct platform_device *pdev)
+static int __devexit r8a66597_remove(struct platform_device *pdev)
 {
        struct r8a66597         *r8a66597 = dev_get_drvdata(&pdev->dev);
        struct usb_hcd          *hcd = r8a66597_to_hcd(r8a66597);
@@ -2542,7 +2542,7 @@ clean_up:
 
 static struct platform_driver r8a66597_driver = {
        .probe =        r8a66597_probe,
-       .remove =       r8a66597_remove,
+       .remove =       __devexit_p(r8a66597_remove),
        .driver         = {
                .name = (char *) hcd_name,
                .owner  = THIS_MODULE,
index f8d69ad..5bf9123 100644 (file)
@@ -2970,7 +2970,8 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
        struct atyfb_par *par = info->par;
        struct device_node *dp;
        char prop[128];
-       int node, len, i, j, ret;
+       phandle node;
+       int len, i, j, ret;
        u32 mem, chip_id;
 
        /*
index d72075a..7a14192 100644 (file)
@@ -1243,8 +1243,10 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev)
                if (priv->ch[i].sglist)
                        vfree(priv->ch[i].sglist);
 
-               dma_free_coherent(&pdev->dev, info->fix.smem_len,
-                                 info->screen_base, priv->ch[i].dma_handle);
+               if (info->screen_base)
+                       dma_free_coherent(&pdev->dev, info->fix.smem_len,
+                                         info->screen_base,
+                                         priv->ch[i].dma_handle);
                fb_dealloc_cmap(&info->cmap);
                framebuffer_release(info);
        }
index a5bf577..9060f08 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/string.h>
 #include <linux/list.h>
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
@@ -31,19 +32,23 @@ void coda_cache_enter(struct inode *inode, int mask)
 {
        struct coda_inode_info *cii = ITOC(inode);
 
+       spin_lock(&cii->c_lock);
        cii->c_cached_epoch = atomic_read(&permission_epoch);
        if (cii->c_uid != current_fsuid()) {
                cii->c_uid = current_fsuid();
                 cii->c_cached_perm = mask;
         } else
                 cii->c_cached_perm |= mask;
+       spin_unlock(&cii->c_lock);
 }
 
 /* remove cached acl from an inode */
 void coda_cache_clear_inode(struct inode *inode)
 {
        struct coda_inode_info *cii = ITOC(inode);
+       spin_lock(&cii->c_lock);
        cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
+       spin_unlock(&cii->c_lock);
 }
 
 /* remove all acl caches */
@@ -57,13 +62,15 @@ void coda_cache_clear_all(struct super_block *sb)
 int coda_cache_check(struct inode *inode, int mask)
 {
        struct coda_inode_info *cii = ITOC(inode);
-        int hit;
+       int hit;
        
-        hit = (mask & cii->c_cached_perm) == mask &&
-               cii->c_uid == current_fsuid() &&
-               cii->c_cached_epoch == atomic_read(&permission_epoch);
+       spin_lock(&cii->c_lock);
+       hit = (mask & cii->c_cached_perm) == mask &&
+           cii->c_uid == current_fsuid() &&
+           cii->c_cached_epoch == atomic_read(&permission_epoch);
+       spin_unlock(&cii->c_lock);
 
-        return hit;
+       return hit;
 }
 
 
index a7a7809..6022405 100644 (file)
@@ -45,13 +45,15 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
 static int coda_test_inode(struct inode *inode, void *data)
 {
        struct CodaFid *fid = (struct CodaFid *)data;
-       return coda_fideq(&(ITOC(inode)->c_fid), fid);
+       struct coda_inode_info *cii = ITOC(inode);
+       return coda_fideq(&cii->c_fid, fid);
 }
 
 static int coda_set_inode(struct inode *inode, void *data)
 {
        struct CodaFid *fid = (struct CodaFid *)data;
-       ITOC(inode)->c_fid = *fid;
+       struct coda_inode_info *cii = ITOC(inode);
+       cii->c_fid = *fid;
        return 0;
 }
 
@@ -71,6 +73,7 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
                cii = ITOC(inode);
                /* we still need to set i_ino for things like stat(2) */
                inode->i_ino = hash;
+               /* inode is locked and unique, no need to grab cii->c_lock */
                cii->c_mapcount = 0;
                unlock_new_inode(inode);
        }
@@ -107,14 +110,20 @@ int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_bloc
 }
 
 
+/* Although we treat Coda file identifiers as immutable, there is one
+ * special case for files created during a disconnection where they may
+ * not be globally unique. When an identifier collision is detected we
+ * first try to flush the cached inode from the kernel and finally
+ * resort to renaming/rehashing in-place. Userspace remembers both old
+ * and new values of the identifier to handle any in-flight upcalls.
+ * The real solution is to use globally unique UUIDs as identifiers, but
+ * retrofitting the existing userspace code for this is non-trivial. */
 void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
                      struct CodaFid *newfid)
 {
-       struct coda_inode_info *cii;
+       struct coda_inode_info *cii = ITOC(inode);
        unsigned long hash = coda_f2i(newfid);
        
-       cii = ITOC(inode);
-
        BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
 
        /* replace fid and rehash inode */
index ccd98b0..96fbeab 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
 
@@ -116,15 +116,11 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
                goto exit;
        }
 
-       lock_kernel();
-
        error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
                             &type, &resfid);
        if (!error)
                error = coda_cnode_make(&inode, &resfid, dir->i_sb);
 
-       unlock_kernel();
-
        if (error && error != -ENOENT)
                return ERR_PTR(error);
 
@@ -140,28 +136,24 @@ exit:
 
 int coda_permission(struct inode *inode, int mask)
 {
-        int error = 0;
+       int error;
 
        mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
  
        if (!mask)
-               return 0; 
+               return 0;
 
        if ((mask & MAY_EXEC) && !execute_ok(inode))
                return -EACCES;
 
-       lock_kernel();
-
        if (coda_cache_check(inode, mask))
-               goto out; 
+               return 0;
 
-        error = venus_access(inode->i_sb, coda_i2f(inode), mask);
+       error = venus_access(inode->i_sb, coda_i2f(inode), mask);
     
        if (!error)
                coda_cache_enter(inode, mask);
 
- out:
-       unlock_kernel();
        return error;
 }
 
@@ -200,41 +192,34 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
 /* creation routines: create, mknod, mkdir, link, symlink */
 static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
 {
-        int error=0;
+       int error;
        const char *name=de->d_name.name;
        int length=de->d_name.len;
        struct inode *inode;
        struct CodaFid newfid;
        struct coda_vattr attrs;
 
-       lock_kernel();
-
-       if (coda_isroot(dir) && coda_iscontrol(name, length)) {
-               unlock_kernel();
+       if (coda_isroot(dir) && coda_iscontrol(name, length))
                return -EPERM;
-       }
 
        error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 
                                0, mode, &newfid, &attrs);
-
-        if ( error ) {
-               unlock_kernel();
-               d_drop(de);
-               return error;
-       }
+       if (error)
+               goto err_out;
 
        inode = coda_iget(dir->i_sb, &newfid, &attrs);
-       if ( IS_ERR(inode) ) {
-               unlock_kernel();
-               d_drop(de);
-               return PTR_ERR(inode);
+       if (IS_ERR(inode)) {
+               error = PTR_ERR(inode);
+               goto err_out;
        }
 
        /* invalidate the directory cnode's attributes */
        coda_dir_update_mtime(dir);
-       unlock_kernel();
        d_instantiate(de, inode);
        return 0;
+err_out:
+       d_drop(de);
+       return error;
 }
 
 static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
@@ -246,36 +231,29 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
        int error;
        struct CodaFid newfid;
 
-       lock_kernel();
-
-       if (coda_isroot(dir) && coda_iscontrol(name, len)) {
-               unlock_kernel();
+       if (coda_isroot(dir) && coda_iscontrol(name, len))
                return -EPERM;
-       }
 
        attrs.va_mode = mode;
        error = venus_mkdir(dir->i_sb, coda_i2f(dir), 
                               name, len, &newfid, &attrs);
-        
-        if ( error ) {
-               unlock_kernel();
-               d_drop(de);
-               return error;
-        }
+       if (error)
+               goto err_out;
          
        inode = coda_iget(dir->i_sb, &newfid, &attrs);
-       if ( IS_ERR(inode) ) {
-               unlock_kernel();
-               d_drop(de);
-               return PTR_ERR(inode);
+       if (IS_ERR(inode)) {
+               error = PTR_ERR(inode);
+               goto err_out;
        }
 
        /* invalidate the directory cnode's attributes */
        coda_dir_inc_nlink(dir);
        coda_dir_update_mtime(dir);
-       unlock_kernel();
        d_instantiate(de, inode);
        return 0;
+err_out:
+       d_drop(de);
+       return error;
 }
 
 /* try to make de an entry in dir_inodde linked to source_de */ 
@@ -287,52 +265,38 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
        int len = de->d_name.len;
        int error;
 
-       lock_kernel();
-
-       if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
-               unlock_kernel();
+       if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
                return -EPERM;
-       }
 
        error = venus_link(dir_inode->i_sb, coda_i2f(inode),
                           coda_i2f(dir_inode), (const char *)name, len);
-
        if (error) {
                d_drop(de);
-               goto out;
+               return error;
        }
 
        coda_dir_update_mtime(dir_inode);
        atomic_inc(&inode->i_count);
        d_instantiate(de, inode);
        inc_nlink(inode);
-
-out:
-       unlock_kernel();
-       return(error);
+       return 0;
 }
 
 
 static int coda_symlink(struct inode *dir_inode, struct dentry *de,
                        const char *symname)
 {
-        const char *name = de->d_name.name;
+       const char *name = de->d_name.name;
        int len = de->d_name.len;
        int symlen;
-       int error = 0;
-
-       lock_kernel();
+       int error;
 
-       if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
-               unlock_kernel();
+       if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
                return -EPERM;
-       }
 
        symlen = strlen(symname);
-       if ( symlen > CODA_MAXPATHLEN ) {
-               unlock_kernel();
+       if (symlen > CODA_MAXPATHLEN)
                return -ENAMETOOLONG;
-       }
 
        /*
         * This entry is now negative. Since we do not create
@@ -343,10 +307,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
                              symname, symlen);
 
        /* mtime is no good anymore */
-       if ( !error )
+       if (!error)
                coda_dir_update_mtime(dir_inode);
 
-       unlock_kernel();
        return error;
 }
 
@@ -357,17 +320,12 @@ static int coda_unlink(struct inode *dir, struct dentry *de)
        const char *name = de->d_name.name;
        int len = de->d_name.len;
 
-       lock_kernel();
-
        error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
-       if ( error ) {
-               unlock_kernel();
+       if (error)
                return error;
-       }
 
        coda_dir_update_mtime(dir);
        drop_nlink(de->d_inode);
-       unlock_kernel();
        return 0;
 }
 
@@ -377,8 +335,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
        int len = de->d_name.len;
        int error;
 
-       lock_kernel();
-
        error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
        if (!error) {
                /* VFS may delete the child */
@@ -389,7 +345,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
                coda_dir_drop_nlink(dir);
                coda_dir_update_mtime(dir);
        }
-       unlock_kernel();
        return error;
 }
 
@@ -403,15 +358,12 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
        int new_length = new_dentry->d_name.len;
        int error;
 
-       lock_kernel();
-
        error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
                             coda_i2f(new_dir), old_length, new_length,
                             (const char *) old_name, (const char *)new_name);
-
-       if ( !error ) {
-               if ( new_dentry->d_inode ) {
-                       if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
+       if (!error) {
+               if (new_dentry->d_inode) {
+                       if (S_ISDIR(new_dentry->d_inode->i_mode)) {
                                coda_dir_drop_nlink(old_dir);
                                coda_dir_inc_nlink(new_dir);
                        }
@@ -423,8 +375,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
                        coda_flag_inode(new_dir, C_VATTR);
                }
        }
-       unlock_kernel();
-
        return error;
 }
 
@@ -594,10 +544,7 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
        struct inode *inode = de->d_inode;
        struct coda_inode_info *cii;
 
-       if (!inode)
-               return 1;
-       lock_kernel();
-       if (coda_isroot(inode))
+       if (!inode || coda_isroot(inode))
                goto out;
        if (is_bad_inode(inode))
                goto bad;
@@ -617,13 +564,12 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
                goto out;
 
        /* clear the flags. */
+       spin_lock(&cii->c_lock);
        cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
-
+       spin_unlock(&cii->c_lock);
 bad:
-       unlock_kernel();
        return 0;
 out:
-       unlock_kernel();
        return 1;
 }
 
@@ -656,20 +602,19 @@ static int coda_dentry_delete(struct dentry * dentry)
 int coda_revalidate_inode(struct dentry *dentry)
 {
        struct coda_vattr attr;
-       int error = 0;
+       int error;
        int old_mode;
        ino_t old_ino;
        struct inode *inode = dentry->d_inode;
        struct coda_inode_info *cii = ITOC(inode);
 
-       lock_kernel();
-       if ( !cii->c_flags )
-               goto ok;
+       if (!cii->c_flags)
+               return 0;
 
        if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
                error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
-               if ( error )
-                       goto return_bad;
+               if (error)
+                       return -EIO;
 
                /* this inode may be lost if:
                   - it's ino changed 
@@ -688,17 +633,13 @@ int coda_revalidate_inode(struct dentry *dentry)
                /* the following can happen when a local fid is replaced 
                   with a global one, here we lose and declare the inode bad */
                if (inode->i_ino != old_ino)
-                       goto return_bad;
+                       return -EIO;
                
                coda_flag_inode_children(inode, C_FLUSH);
+
+               spin_lock(&cii->c_lock);
                cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
+               spin_unlock(&cii->c_lock);
        }
-
-ok:
-       unlock_kernel();
        return 0;
-
-return_bad:
-       unlock_kernel();
-       return -EIO;
 }
index ad3cd2a..c8b50ba 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/stat.h>
 #include <linux/cred.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
@@ -109,19 +109,24 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
 
        coda_inode = coda_file->f_path.dentry->d_inode;
        host_inode = host_file->f_path.dentry->d_inode;
+
+       cii = ITOC(coda_inode);
+       spin_lock(&cii->c_lock);
        coda_file->f_mapping = host_file->f_mapping;
        if (coda_inode->i_mapping == &coda_inode->i_data)
                coda_inode->i_mapping = host_inode->i_mapping;
 
        /* only allow additional mmaps as long as userspace isn't changing
         * the container file on us! */
-       else if (coda_inode->i_mapping != host_inode->i_mapping)
+       else if (coda_inode->i_mapping != host_inode->i_mapping) {
+               spin_unlock(&cii->c_lock);
                return -EBUSY;
+       }
 
        /* keep track of how often the coda_inode/host_file has been mmapped */
-       cii = ITOC(coda_inode);
        cii->c_mapcount++;
        cfi->cfi_mapcount++;
+       spin_unlock(&cii->c_lock);
 
        return host_file->f_op->mmap(host_file, vma);
 }
@@ -138,8 +143,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
        if (!cfi)
                return -ENOMEM;
 
-       lock_kernel();
-
        error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
                           &host_file);
        if (!host_file)
@@ -147,7 +150,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
 
        if (error) {
                kfree(cfi);
-               unlock_kernel();
                return error;
        }
 
@@ -159,8 +161,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
 
        BUG_ON(coda_file->private_data != NULL);
        coda_file->private_data = cfi;
-
-       unlock_kernel();
        return 0;
 }
 
@@ -171,9 +171,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
        struct coda_file_info *cfi;
        struct coda_inode_info *cii;
        struct inode *host_inode;
-       int err = 0;
-
-       lock_kernel();
+       int err;
 
        cfi = CODA_FTOC(coda_file);
        BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
@@ -185,18 +183,18 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
        cii = ITOC(coda_inode);
 
        /* did we mmap this file? */
+       spin_lock(&cii->c_lock);
        if (coda_inode->i_mapping == &host_inode->i_data) {
                cii->c_mapcount -= cfi->cfi_mapcount;
                if (!cii->c_mapcount)
                        coda_inode->i_mapping = &coda_inode->i_data;
        }
+       spin_unlock(&cii->c_lock);
 
        fput(cfi->cfi_container);
        kfree(coda_file->private_data);
        coda_file->private_data = NULL;
 
-       unlock_kernel();
-
        /* VFS fput ignores the return value from file_operations->release, so
         * there is no use returning an error here */
        return 0;
@@ -207,7 +205,7 @@ int coda_fsync(struct file *coda_file, int datasync)
        struct file *host_file;
        struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
        struct coda_file_info *cfi;
-       int err = 0;
+       int err;
 
        if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
              S_ISLNK(coda_inode->i_mode)))
@@ -218,11 +216,8 @@ int coda_fsync(struct file *coda_file, int datasync)
        host_file = cfi->cfi_container;
 
        err = vfs_fsync(host_file, datasync);
-       if ( !err && !datasync ) {
-               lock_kernel();
+       if (!err && !datasync)
                err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
-               unlock_kernel();
-       }
 
        return err;
 }
index bfe8179..7993b96 100644 (file)
@@ -15,7 +15,8 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/file.h>
 #include <linux/vfs.h>
 #include <linux/slab.h>
@@ -51,6 +52,7 @@ static struct inode *coda_alloc_inode(struct super_block *sb)
        ei->c_flags = 0;
        ei->c_uid = 0;
        ei->c_cached_perm = 0;
+       spin_lock_init(&ei->c_lock);
        return &ei->vfs_inode;
 }
 
@@ -143,13 +145,11 @@ static int get_device_index(struct coda_mount_data *data)
 static int coda_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct inode *root = NULL;
-       struct venus_comm *vc = NULL;
+       struct venus_comm *vc;
        struct CodaFid fid;
        int error;
        int idx;
 
-       lock_kernel();
-
        idx = get_device_index((struct coda_mount_data *) data);
 
        /* Ignore errors in data, for backward compatibility */
@@ -159,23 +159,26 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
 
        vc = &coda_comms[idx];
+       mutex_lock(&vc->vc_mutex);
+
        if (!vc->vc_inuse) {
                printk("coda_read_super: No pseudo device\n");
-               unlock_kernel();
-               return -EINVAL;
+               error = -EINVAL;
+               goto unlock_out;
        }
 
-        if ( vc->vc_sb ) {
+       if (vc->vc_sb) {
                printk("coda_read_super: Device already mounted\n");
-               unlock_kernel();
-               return -EBUSY;
+               error = -EBUSY;
+               goto unlock_out;
        }
 
        error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY);
        if (error)
-               goto bdi_err;
+               goto unlock_out;
 
        vc->vc_sb = sb;
+       mutex_unlock(&vc->vc_mutex);
 
        sb->s_fs_info = vc;
        sb->s_flags |= MS_NOATIME;
@@ -204,28 +207,33 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
        printk("coda_read_super: rootinode is %ld dev %s\n", 
               root->i_ino, root->i_sb->s_id);
        sb->s_root = d_alloc_root(root);
-       if (!sb->s_root)
+       if (!sb->s_root) {
+               error = -EINVAL;
                goto error;
-       unlock_kernel();
+       }
        return 0;
 
- error:
-       bdi_destroy(&vc->bdi);
- bdi_err:
+error:
        if (root)
                iput(root);
-       if (vc)
-               vc->vc_sb = NULL;
 
-       unlock_kernel();
-       return -EINVAL;
+       mutex_lock(&vc->vc_mutex);
+       bdi_destroy(&vc->bdi);
+       vc->vc_sb = NULL;
+       sb->s_fs_info = NULL;
+unlock_out:
+       mutex_unlock(&vc->vc_mutex);
+       return error;
 }
 
 static void coda_put_super(struct super_block *sb)
 {
-       bdi_destroy(&coda_vcp(sb)->bdi);
-       coda_vcp(sb)->vc_sb = NULL;
+       struct venus_comm *vcp = coda_vcp(sb);
+       mutex_lock(&vcp->vc_mutex);
+       bdi_destroy(&vcp->bdi);
+       vcp->vc_sb = NULL;
        sb->s_fs_info = NULL;
+       mutex_unlock(&vcp->vc_mutex);
 
        printk("Coda: Bye bye.\n");
 }
@@ -251,8 +259,6 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
        struct coda_vattr vattr;
        int error;
 
-       lock_kernel();
-       
        memset(&vattr, 0, sizeof(vattr)); 
 
        inode->i_ctime = CURRENT_TIME_SEC;
@@ -262,13 +268,10 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
        /* Venus is responsible for truncating the container-file!!! */
        error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
 
-       if ( !error ) {
+       if (!error) {
                coda_vattr_to_iattr(inode, &vattr); 
                coda_cache_clear_inode(inode);
        }
-
-       unlock_kernel();
-
        return error;
 }
 
@@ -282,12 +285,8 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
 {
        int error;
        
-       lock_kernel();
-
        error = venus_statfs(dentry, buf);
 
-       unlock_kernel();
-
        if (error) {
                /* fake something like AFS does */
                buf->f_blocks = 9000000;
index 028a9a0..2fd89b5 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/coda_fs_i.h>
 #include <linux/coda_psdev.h>
 
-#include <linux/smp_lock.h>
-
 /* pioctl ops */
 static int coda_ioctl_permission(struct inode *inode, int mask);
 static long coda_pioctl(struct file *filp, unsigned int cmd,
@@ -58,13 +56,9 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
        struct inode *target_inode = NULL;
        struct coda_inode_info *cnp;
 
-       lock_kernel();
-
        /* get the Pioctl data arguments from user space */
-       if (copy_from_user(&data, (void __user *)user_data, sizeof(data))) {
-               error = -EINVAL;
-               goto out;
-       }
+       if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
+               return -EINVAL;
 
        /*
         * Look up the pathname. Note that the pathname is in
@@ -76,13 +70,12 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
                error = user_lpath(data.path, &path);
 
        if (error)
-               goto out;
-       else
-               target_inode = path.dentry->d_inode;
+               return error;
+
+       target_inode = path.dentry->d_inode;
 
        /* return if it is not a Coda inode */
        if (target_inode->i_sb != inode->i_sb) {
-               path_put(&path);
                error = -EINVAL;
                goto out;
        }
@@ -91,10 +84,7 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
        cnp = ITOC(target_inode);
 
        error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
-
-       path_put(&path);
-
 out:
-       unlock_kernel();
+       path_put(&path);
        return error;
 }
index fdc2f3e..62647a8 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/smp_lock.h>
+#include <linux/mutex.h>
 #include <linux/device.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -67,8 +67,10 @@ static unsigned int coda_psdev_poll(struct file *file, poll_table * wait)
        unsigned int mask = POLLOUT | POLLWRNORM;
 
        poll_wait(file, &vcp->vc_waitq, wait);
+       mutex_lock(&vcp->vc_mutex);
        if (!list_empty(&vcp->vc_pending))
                 mask |= POLLIN | POLLRDNORM;
+       mutex_unlock(&vcp->vc_mutex);
 
        return mask;
 }
@@ -108,16 +110,9 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
                return -EFAULT;
 
         if (DOWNCALL(hdr.opcode)) {
-               struct super_block *sb = NULL;
-                union outputArgs *dcbuf;
+               union outputArgs *dcbuf;
                int size = sizeof(*dcbuf);
 
-               sb = vcp->vc_sb;
-               if ( !sb ) {
-                        count = nbytes;
-                        goto out;
-               }
-
                if  ( nbytes < sizeof(struct coda_out_hdr) ) {
                        printk("coda_downcall opc %d uniq %d, not enough!\n",
                               hdr.opcode, hdr.unique);
@@ -137,9 +132,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
                }
 
                /* what downcall errors does Venus handle ? */
-               lock_kernel();
-               error = coda_downcall(hdr.opcode, dcbuf, sb);
-               unlock_kernel();
+               error = coda_downcall(vcp, hdr.opcode, dcbuf);
 
                CODA_FREE(dcbuf, nbytes);
                if (error) {
@@ -152,7 +145,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
        }
         
        /* Look for the message on the processing queue. */
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
        list_for_each(lh, &vcp->vc_processing) {
                tmp = list_entry(lh, struct upc_req , uc_chain);
                if (tmp->uc_unique == hdr.unique) {
@@ -161,7 +154,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
                        break;
                }
        }
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
 
        if (!req) {
                printk("psdev_write: msg (%d, %d) not found\n", 
@@ -216,7 +209,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
        if (nbytes == 0)
                return 0;
 
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
 
        add_wait_queue(&vcp->vc_waitq, &wait);
        set_current_state(TASK_INTERRUPTIBLE);
@@ -230,7 +223,9 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
                        retval = -ERESTARTSYS;
                        break;
                }
+               mutex_unlock(&vcp->vc_mutex);
                schedule();
+               mutex_lock(&vcp->vc_mutex);
        }
 
        set_current_state(TASK_RUNNING);
@@ -263,7 +258,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
        CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
        kfree(req);
 out:
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return (count ? count : retval);
 }
 
@@ -276,10 +271,10 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
        if (idx < 0 || idx >= MAX_CODADEVS)
                return -ENODEV;
 
-       lock_kernel();
-
        err = -EBUSY;
        vcp = &coda_comms[idx];
+       mutex_lock(&vcp->vc_mutex);
+
        if (!vcp->vc_inuse) {
                vcp->vc_inuse++;
 
@@ -293,7 +288,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
                err = 0;
        }
 
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return err;
 }
 
@@ -308,7 +303,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
                return -1;
        }
 
-       lock_kernel();
+       mutex_lock(&vcp->vc_mutex);
 
        /* Wakeup clients so they can return. */
        list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
@@ -333,7 +328,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
 
        file->private_data = NULL;
        vcp->vc_inuse--;
-       unlock_kernel();
+       mutex_unlock(&vcp->vc_mutex);
        return 0;
 }
 
@@ -362,9 +357,11 @@ static int init_coda_psdev(void)
                err = PTR_ERR(coda_psdev_class);
                goto out_chrdev;
        }               
-       for (i = 0; i < MAX_CODADEVS; i++)
+       for (i = 0; i < MAX_CODADEVS; i++) {
+               mutex_init(&(&coda_comms[i])->vc_mutex);
                device_create(coda_psdev_class, NULL,
                              MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
+       }
        coda_sysctl_init();
        goto out;
 
index 4513b72..af78f00 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/pagemap.h>
-#include <linux/smp_lock.h>
 
 #include <linux/coda.h>
 #include <linux/coda_linux.h>
@@ -29,11 +28,9 @@ static int coda_symlink_filler(struct file *file, struct page *page)
        unsigned int len = PAGE_SIZE;
        char *p = kmap(page);
 
-       lock_kernel();
        cii = ITOC(inode);
 
        error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
-       unlock_kernel();
        if (error)
                goto fail;
        SetPageUptodate(page);
index b8893ab..c3563ca 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <linux/vmalloc.h>
 #include <linux/vfs.h>
@@ -606,7 +607,8 @@ static void coda_unblock_signals(sigset_t *old)
                                 (r)->uc_opcode != CODA_RELEASE) || \
                                (r)->uc_flags & CODA_REQ_READ))
 
-static inline void coda_waitfor_upcall(struct upc_req *req)
+static inline void coda_waitfor_upcall(struct venus_comm *vcp,
+                                      struct upc_req *req)
 {
        DECLARE_WAITQUEUE(wait, current);
        unsigned long timeout = jiffies + coda_timeout * HZ;
@@ -639,10 +641,12 @@ static inline void coda_waitfor_upcall(struct upc_req *req)
                        break;
                }
 
+               mutex_unlock(&vcp->vc_mutex);
                if (blocked)
                        schedule_timeout(HZ);
                else
                        schedule();
+               mutex_lock(&vcp->vc_mutex);
        }
        if (blocked)
                coda_unblock_signals(&old);
@@ -667,18 +671,23 @@ static int coda_upcall(struct venus_comm *vcp,
 {
        union outputArgs *out;
        union inputArgs *sig_inputArgs;
-       struct upc_req *req, *sig_req;
-       int error = 0;
+       struct upc_req *req = NULL, *sig_req;
+       int error;
+
+       mutex_lock(&vcp->vc_mutex);
 
        if (!vcp->vc_inuse) {
                printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
-               return -ENXIO;
+               error = -ENXIO;
+               goto exit;
        }
 
        /* Format the request message. */
        req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
-       if (!req)
-               return -ENOMEM;
+       if (!req) {
+               error = -ENOMEM;
+               goto exit;
+       }
 
        req->uc_data = (void *)buffer;
        req->uc_flags = 0;
@@ -705,7 +714,7 @@ static int coda_upcall(struct venus_comm *vcp,
         * ENODEV.  */
 
        /* Go to sleep.  Wake up on signals only after the timeout. */
-       coda_waitfor_upcall(req);
+       coda_waitfor_upcall(vcp, req);
 
        /* Op went through, interrupt or not... */
        if (req->uc_flags & CODA_REQ_WRITE) {
@@ -759,6 +768,7 @@ static int coda_upcall(struct venus_comm *vcp,
 
 exit:
        kfree(req);
+       mutex_unlock(&vcp->vc_mutex);
        return error;
 }
 
@@ -796,21 +806,24 @@ exit:
  *
  * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
 
-int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
+int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
 {
        struct inode *inode = NULL;
-       struct CodaFid *fid, *newfid;
+       struct CodaFid *fid = NULL, *newfid;
+       struct super_block *sb;
 
        /* Handle invalidation requests. */
-       if ( !sb || !sb->s_root)
-               return 0;
+       mutex_lock(&vcp->vc_mutex);
+       sb = vcp->vc_sb;
+       if (!sb || !sb->s_root)
+               goto unlock_out;
 
        switch (opcode) {
        case CODA_FLUSH:
                coda_cache_clear_all(sb);
                shrink_dcache_sb(sb);
                if (sb->s_root->d_inode)
-                   coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
+                       coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
                break;
 
        case CODA_PURGEUSER:
@@ -819,45 +832,53 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
 
        case CODA_ZAPDIR:
                fid = &out->coda_zapdir.CodaFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode) {
-                       coda_flag_inode_children(inode, C_PURGE);
-                       coda_flag_inode(inode, C_VATTR);
-               }
                break;
 
        case CODA_ZAPFILE:
                fid = &out->coda_zapfile.CodaFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode)
-                       coda_flag_inode(inode, C_VATTR);
                break;
 
        case CODA_PURGEFID:
                fid = &out->coda_purgefid.CodaFid;
+               break;
+
+       case CODA_REPLACE:
+               fid = &out->coda_replace.OldFid;
+               break;
+       }
+       if (fid)
                inode = coda_fid_to_inode(fid, sb);
-               if (inode) {
-                       coda_flag_inode_children(inode, C_PURGE);
 
-                       /* catch the dentries later if some are still busy */
-                       coda_flag_inode(inode, C_PURGE);
-                       d_prune_aliases(inode);
+unlock_out:
+       mutex_unlock(&vcp->vc_mutex);
 
-               }
+       if (!inode)
+               return 0;
+
+       switch (opcode) {
+       case CODA_ZAPDIR:
+               coda_flag_inode_children(inode, C_PURGE);
+               coda_flag_inode(inode, C_VATTR);
+               break;
+
+       case CODA_ZAPFILE:
+               coda_flag_inode(inode, C_VATTR);
+               break;
+
+       case CODA_PURGEFID:
+               coda_flag_inode_children(inode, C_PURGE);
+
+               /* catch the dentries later if some are still busy */
+               coda_flag_inode(inode, C_PURGE);
+               d_prune_aliases(inode);
                break;
 
        case CODA_REPLACE:
-               fid = &out->coda_replace.OldFid;
                newfid = &out->coda_replace.NewFid;
-               inode = coda_fid_to_inode(fid, sb);
-               if (inode)
-                       coda_replace_fid(inode, fid, newfid);
+               coda_replace_fid(inode, fid, newfid);
                break;
        }
-
-       if (inode)
-               iput(inode);
-
+       iput(inode);
        return 0;
 }
 
index b81bfc0..0a8b0ad 100644 (file)
@@ -365,25 +365,17 @@ struct device_type part_type = {
 static void delete_partition_rcu_cb(struct rcu_head *head)
 {
        struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);
-       struct gendisk *disk = part_to_disk(part);
-       struct request_queue *q = disk->queue;
-       unsigned long flags;
 
        part->start_sect = 0;
        part->nr_sects = 0;
        part_stat_set_all(part, 0);
        put_device(part_to_dev(part));
-
-       spin_lock_irqsave(q->queue_lock, flags);
-       elv_quiesce_end(q);
-       spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
 void delete_partition(struct gendisk *disk, int partno)
 {
        struct disk_part_tbl *ptbl = disk->part_tbl;
        struct hd_struct *part;
-       struct request_queue *q = disk->queue;
 
        if (partno >= ptbl->len)
                return;
@@ -398,10 +390,6 @@ void delete_partition(struct gendisk *disk, int partno)
        kobject_put(part->holder_dir);
        device_del(part_to_dev(part));
 
-       spin_lock_irq(q->queue_lock);
-       elv_quiesce_start(q);
-       spin_unlock_irq(q->queue_lock);
-
        call_rcu(&part->rcu_head, delete_partition_rcu_cb);
 }
 
index 009b80e..646b462 100644 (file)
@@ -115,7 +115,6 @@ struct request {
        void *elevator_private3;
 
        struct gendisk *rq_disk;
-       struct hd_struct *part;
        unsigned long start_time;
 #ifdef CONFIG_BLK_CGROUP
        unsigned long long start_time_ns;
index b3ef0c4..e35071b 100644 (file)
 
 #include <linux/types.h>
 #include <linux/list.h>
+#include <linux/spinlock.h>
 #include <linux/coda.h>
 
 /*
  * coda fs inode data
+ * c_lock protects accesses to c_flags, c_mapcount, c_cached_epoch, c_uid and
+ * c_cached_perm.
+ * vfs_inode is set only when the inode is created and never changes.
+ * c_fid is set when the inode is created and should be considered immutable.
  */
 struct coda_inode_info {
-        struct CodaFid    c_fid;       /* Coda identifier */
-        u_short                   c_flags;     /* flags (see below) */
-       struct list_head   c_cilist;    /* list of all coda inodes */
+       struct CodaFid     c_fid;       /* Coda identifier */
+       u_short            c_flags;     /* flags (see below) */
        unsigned int       c_mapcount;  /* nr of times this inode is mapped */
        unsigned int       c_cached_epoch; /* epoch for cached permissions */
        vuid_t             c_uid;       /* fsuid for cached permissions */
-        unsigned int       c_cached_perm; /* cached access permissions */
+       unsigned int       c_cached_perm; /* cached access permissions */
+       spinlock_t         c_lock;
        struct inode       vfs_inode;
 };
 
index dcc228a..2e914d0 100644 (file)
@@ -89,7 +89,11 @@ static __inline__ char *coda_i2s(struct inode *inode)
 /* this will not zap the inode away */
 static __inline__ void coda_flag_inode(struct inode *inode, int flag)
 {
-       ITOC(inode)->c_flags |= flag;
+       struct coda_inode_info *cii = ITOC(inode);
+
+       spin_lock(&cii->c_lock);
+       cii->c_flags |= flag;
+       spin_unlock(&cii->c_lock);
 }              
 
 #endif
index 284b520..72f2d2f 100644 (file)
@@ -8,6 +8,7 @@
 
 #ifdef __KERNEL__
 #include <linux/backing-dev.h>
+#include <linux/mutex.h>
 
 struct kstatfs;
 
@@ -20,6 +21,7 @@ struct venus_comm {
        int                 vc_inuse;
        struct super_block *vc_sb;
        struct backing_dev_info bdi;
+       struct mutex        vc_mutex;
 };
 
 
@@ -63,7 +65,7 @@ int venus_symlink(struct super_block *sb, struct CodaFid *fid,
 int venus_access(struct super_block *sb, struct CodaFid *fid, int mask);
 int venus_pioctl(struct super_block *sb, struct CodaFid *fid,
                 unsigned int cmd, struct PioctlData *data);
-int coda_downcall(int opcode, union outputArgs *out, struct super_block *sb);
+int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out);
 int venus_fsync(struct super_block *sb, struct CodaFid *fid);
 int venus_statfs(struct dentry *dentry, struct kstatfs *sfs);
 
index 80a0ece..4fd978e 100644 (file)
@@ -122,8 +122,6 @@ extern void elv_completed_request(struct request_queue *, struct request *);
 extern int elv_set_request(struct request_queue *, struct request *, gfp_t);
 extern void elv_put_request(struct request_queue *, struct request *);
 extern void elv_drain_elevator(struct request_queue *);
-extern void elv_quiesce_start(struct request_queue *);
-extern void elv_quiesce_end(struct request_queue *);
 
 /*
  * io scheduler registration
index 361d1cc..b65a6f4 100644 (file)
@@ -53,9 +53,7 @@ struct gameport {
 #define to_gameport_port(d)    container_of(d, struct gameport, dev)
 
 struct gameport_driver {
-
-       void *private;
-       char *description;
+       const char *description;
 
        int (*connect)(struct gameport *, struct gameport_driver *drv);
        int (*reconnect)(struct gameport *);
index 557c392..7a7b9c1 100644 (file)
@@ -140,7 +140,6 @@ struct disk_part_tbl {
        struct rcu_head rcu_head;
        int len;
        struct hd_struct __rcu *last_lookup;
-       struct gendisk *disk;
        struct hd_struct __rcu *part[];
 };
 
index d6ae176..51af441 100644 (file)
@@ -34,7 +34,7 @@ struct input_event {
  * Protocol version.
  */
 
-#define EV_VERSION             0x010000
+#define EV_VERSION             0x010001
 
 /*
  * IOCTLs (0x00 - 0x7f)
@@ -56,25 +56,50 @@ struct input_absinfo {
        __s32 resolution;
 };
 
+/**
+ * struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
+ * @scancode: scancode represented in machine-endian form.
+ * @len: length of the scancode that resides in @scancode buffer.
+ * @index: index in the keymap, may be used instead of scancode
+ * @flags: allows to specify how kernel should handle the request. For
+ *     example, setting INPUT_KEYMAP_BY_INDEX flag indicates that kernel
+ *     should perform lookup in keymap by @index instead of @scancode
+ * @keycode: key code assigned to this scancode
+ *
+ * The structure is used to retrieve and modify keymap data. Users have
+ * option of performing lookup either by @scancode itself or by @index
+ * in keymap entry. EVIOCGKEYCODE will also return scancode or index
+ * (depending on which element was used to perform lookup).
+ */
+struct input_keymap_entry {
+#define INPUT_KEYMAP_BY_INDEX  (1 << 0)
+       __u8  flags;
+       __u8  len;
+       __u16 index;
+       __u32 keycode;
+       __u8  scancode[32];
+};
+
 #define EVIOCGVERSION          _IOR('E', 0x01, int)                    /* get driver version */
 #define EVIOCGID               _IOR('E', 0x02, struct input_id)        /* get device ID */
 #define EVIOCGREP              _IOR('E', 0x03, unsigned int[2])        /* get repeat settings */
 #define EVIOCSREP              _IOW('E', 0x03, unsigned int[2])        /* set repeat settings */
-#define EVIOCGKEYCODE          _IOR('E', 0x04, unsigned int[2])        /* get keycode */
-#define EVIOCSKEYCODE          _IOW('E', 0x04, unsigned int[2])        /* set keycode */
+
+#define EVIOCGKEYCODE          _IOR('E', 0x04, struct input_keymap_entry)      /* get keycode */
+#define EVIOCSKEYCODE          _IOW('E', 0x04, struct input_keymap_entry)      /* set keycode */
 
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x06, len)         /* get device name */
 #define EVIOCGPHYS(len)                _IOC(_IOC_READ, 'E', 0x07, len)         /* get physical location */
 #define EVIOCGUNIQ(len)                _IOC(_IOC_READ, 'E', 0x08, len)         /* get unique identifier */
 
-#define EVIOCGKEY(len)         _IOC(_IOC_READ, 'E', 0x18, len)         /* get global keystate */
+#define EVIOCGKEY(len)         _IOC(_IOC_READ, 'E', 0x18, len)         /* get global key state */
 #define EVIOCGLED(len)         _IOC(_IOC_READ, 'E', 0x19, len)         /* get all LEDs */
 #define EVIOCGSND(len)         _IOC(_IOC_READ, 'E', 0x1a, len)         /* get all sounds status */
 #define EVIOCGSW(len)          _IOC(_IOC_READ, 'E', 0x1b, len)         /* get all switch states */
 
 #define EVIOCGBIT(ev,len)      _IOC(_IOC_READ, 'E', 0x20 + ev, len)    /* get event bits */
-#define EVIOCGABS(abs)         _IOR('E', 0x40 + abs, struct input_absinfo)             /* get abs value/limits */
-#define EVIOCSABS(abs)         _IOW('E', 0xc0 + abs, struct input_absinfo)             /* set abs value/limits */
+#define EVIOCGABS(abs)         _IOR('E', 0x40 + abs, struct input_absinfo)     /* get abs value/limits */
+#define EVIOCSABS(abs)         _IOW('E', 0xc0 + abs, struct input_absinfo)     /* set abs value/limits */
 
 #define EVIOCSFF               _IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))   /* send a force effect to a force feedback device */
 #define EVIOCRMFF              _IOW('E', 0x81, int)                    /* Erase a force effect */
@@ -1088,13 +1113,13 @@ struct input_mt_slot {
  * @keycodemax: size of keycode table
  * @keycodesize: size of elements in keycode table
  * @keycode: map of scancodes to keycodes for this device
+ * @getkeycode: optional legacy method to retrieve current keymap.
  * @setkeycode: optional method to alter current keymap, used to implement
  *     sparse keymaps. If not supplied default mechanism will be used.
  *     The method is being called while holding event_lock and thus must
  *     not sleep
- * @getkeycode: optional method to retrieve current keymap. If not supplied
- *     default mechanism will be used. The method is being called while
- *     holding event_lock and thus must not sleep
+ * @getkeycode_new: transition method
+ * @setkeycode_new: transition method
  * @ff: force feedback structure associated with the device if device
  *     supports force feedback effects
  * @repeat_key: stores key code of the last key pressed; used to implement
@@ -1168,10 +1193,16 @@ struct input_dev {
        unsigned int keycodemax;
        unsigned int keycodesize;
        void *keycode;
+
        int (*setkeycode)(struct input_dev *dev,
                          unsigned int scancode, unsigned int keycode);
        int (*getkeycode)(struct input_dev *dev,
                          unsigned int scancode, unsigned int *keycode);
+       int (*setkeycode_new)(struct input_dev *dev,
+                             const struct input_keymap_entry *ke,
+                             unsigned int *old_keycode);
+       int (*getkeycode_new)(struct input_dev *dev,
+                             struct input_keymap_entry *ke);
 
        struct ff_device *ff;
 
@@ -1478,10 +1509,12 @@ INPUT_GENERATE_ABS_ACCESSORS(fuzz, fuzz)
 INPUT_GENERATE_ABS_ACCESSORS(flat, flat)
 INPUT_GENERATE_ABS_ACCESSORS(res, resolution)
 
-int input_get_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int *keycode);
+int input_scancode_to_scalar(const struct input_keymap_entry *ke,
+                            unsigned int *scancode);
+
+int input_get_keycode(struct input_dev *dev, struct input_keymap_entry *ke);
 int input_set_keycode(struct input_dev *dev,
-                     unsigned int scancode, unsigned int keycode);
+                     const struct input_keymap_entry *ke);
 
 extern struct class input_class;
 
diff --git a/include/linux/input/bu21013.h b/include/linux/input/bu21013.h
new file mode 100644 (file)
index 0000000..e470d38
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Naveen Kumar G <naveen.gaddipati@stericsson.com> for ST-Ericsson
+ * License terms:GNU General Public License (GPL) version 2
+ */
+
+#ifndef _BU21013_H
+#define _BU21013_H
+
+/**
+ * struct bu21013_platform_device - Handle the platform data
+ * @cs_en:     pointer to the cs enable function
+ * @cs_dis:    pointer to the cs disable function
+ * @irq_read_val:    pointer to read the pen irq value function
+ * @x_max_res: xmax resolution
+ * @y_max_res: ymax resolution
+ * @touch_x_max: touch x max
+ * @touch_y_max: touch y max
+ * @cs_pin: chip select pin
+ * @irq: irq pin
+ * @ext_clk: external clock flag
+ * @x_flip: x flip flag
+ * @y_flip: y flip flag
+ * @wakeup: wakeup flag
+ *
+ * This is used to handle the platform data
+ */
+struct bu21013_platform_device {
+       int (*cs_en)(int reset_pin);
+       int (*cs_dis)(int reset_pin);
+       int (*irq_read_val)(void);
+       int x_max_res;
+       int y_max_res;
+       int touch_x_max;
+       int touch_y_max;
+       unsigned int cs_pin;
+       unsigned int irq;
+       bool ext_clk;
+       bool x_flip;
+       bool y_flip;
+       bool wakeup;
+};
+
+#endif
index 835f85e..975d347 100644 (file)
@@ -27,20 +27,19 @@ static inline int of_driver_match_device(const struct device *dev,
 extern struct platform_device *of_dev_get(struct platform_device *dev);
 extern void of_dev_put(struct platform_device *dev);
 
+extern int of_device_add(struct platform_device *pdev);
 extern int of_device_register(struct platform_device *ofdev);
 extern void of_device_unregister(struct platform_device *ofdev);
-extern void of_release_dev(struct device *dev);
-
-static inline void of_device_free(struct platform_device *dev)
-{
-       of_release_dev(&dev->dev);
-}
 
 extern ssize_t of_device_get_modalias(struct device *dev,
                                        char *str, ssize_t len);
 
 extern int of_device_uevent(struct device *dev, struct kobj_uevent_env *env);
 
+static inline void of_device_node_put(struct device *dev)
+{
+       of_node_put(dev->of_node);
+}
 
 #else /* CONFIG_OF_DEVICE */
 
@@ -56,6 +55,8 @@ static inline int of_device_uevent(struct device *dev,
        return -ENODEV;
 }
 
+static inline void of_device_node_put(struct device *dev) { }
+
 #endif /* CONFIG_OF_DEVICE */
 
 #endif /* _LINUX_OF_DEVICE_H */
index 71e1a91..7bbf5b3 100644 (file)
@@ -72,7 +72,7 @@ extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
                                 unsigned long *size);
 extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
 extern unsigned long of_get_flat_dt_root(void);
-extern void early_init_dt_scan_chosen_arch(unsigned long node);
+
 extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
                                     int depth, void *data);
 extern void early_init_dt_check_for_initrd(unsigned long node);
index 5929781..109e013 100644 (file)
@@ -5,6 +5,7 @@
 struct of_irq;
 #include <linux/types.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
 
@@ -64,6 +65,9 @@ extern unsigned int irq_create_of_mapping(struct device_node *controller,
                                          unsigned int intsize);
 extern int of_irq_to_resource(struct device_node *dev, int index,
                              struct resource *r);
+extern int of_irq_count(struct device_node *dev);
+extern int of_irq_to_resource_table(struct device_node *dev,
+               struct resource *res, int nr_irqs);
 
 #endif /* CONFIG_OF_IRQ */
 #endif /* CONFIG_OF */
diff --git a/include/linux/of_pdt.h b/include/linux/of_pdt.h
new file mode 100644 (file)
index 0000000..c65a18a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Definitions for building a device tree by calling into the
+ * Open Firmware PROM.
+ *
+ * Copyright (C) 2010  Andres Salomon <dilinger@queued.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef _LINUX_OF_PDT_H
+#define _LINUX_OF_PDT_H
+
+/* overridable operations for calling into the PROM */
+struct of_pdt_ops {
+       /*
+        * buf should be 32 bytes; return 0 on success.
+        * If prev is NULL, the first property will be returned.
+        */
+       int (*nextprop)(phandle node, char *prev, char *buf);
+
+       /* for both functions, return proplen on success; -1 on error */
+       int (*getproplen)(phandle node, const char *prop);
+       int (*getproperty)(phandle node, const char *prop, char *buf,
+                       int bufsize);
+
+       /* phandles are 0 if no child or sibling exists */
+       phandle (*getchild)(phandle parent);
+       phandle (*getsibling)(phandle node);
+
+       /* return 0 on success; fill in 'len' with number of bytes in path */
+       int (*pkg2path)(phandle node, char *buf, const int buflen, int *len);
+};
+
+extern void *prom_early_alloc(unsigned long size);
+
+/* for building the device tree */
+extern void of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops);
+
+extern void (*of_pdt_build_more)(struct device_node *dp,
+               struct device_node ***nextp);
+
+#endif /* _LINUX_OF_PDT_H */
index d278dd9..b4c3d1b 100644 (file)
 
 #define PCI_VENDOR_ID_SILAN            0x1904
 
+#define PCI_VENDOR_ID_RENESAS          0x1912
+#define PCI_DEVICE_ID_RENESAS_SH7781   0x0001
+#define PCI_DEVICE_ID_RENESAS_SH7780   0x0002
+#define PCI_DEVICE_ID_RENESAS_SH7763   0x0004
+#define PCI_DEVICE_ID_RENESAS_SH7785   0x0007
+#define PCI_DEVICE_ID_RENESAS_SH7786   0x0010
+
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
index b555256..e26f478 100644 (file)
@@ -41,7 +41,9 @@ struct serio {
        int (*start)(struct serio *);
        void (*stop)(struct serio *);
 
-       struct serio *parent, *child;
+       struct serio *parent;
+       struct list_head child_node;    /* Entry in parent->children list */
+       struct list_head children;
        unsigned int depth;             /* level of nesting in serio hierarchy */
 
        struct serio_driver *drv;       /* accessed from interrupt, must be protected by serio->lock and serio->sem */
@@ -54,10 +56,9 @@ struct serio {
 #define to_serio_port(d)       container_of(d, struct serio, dev)
 
 struct serio_driver {
-       void *private;
-       char *description;
+       const char *description;
 
-       struct serio_device_id *id_table;
+       const struct serio_device_id *id_table;
        bool manual_bind;
 
        void (*write_wakeup)(struct serio *);
@@ -197,5 +198,6 @@ static inline void serio_continue_rx(struct serio *serio)
 #define SERIO_W8001    0x39
 #define SERIO_DYNAPRO  0x3a
 #define SERIO_HAMPSHIRE        0x3b
+#define SERIO_PS2MULT  0x3c
 
 #endif
index 875ce50..4dca992 100644 (file)
@@ -4,11 +4,20 @@
 #include <linux/list.h>
 #include <linux/seq_file.h>
 #include <linux/cpufreq.h>
+#include <linux/types.h>
+#include <linux/kref.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 
 struct clk;
 
+struct clk_mapping {
+       phys_addr_t             phys;
+       void __iomem            *base;
+       unsigned long           len;
+       struct kref             ref;
+};
+
 struct clk_ops {
        void (*init)(struct clk *clk);
        int (*enable)(struct clk *clk);
@@ -21,9 +30,6 @@ struct clk_ops {
 
 struct clk {
        struct list_head        node;
-       const char              *name;
-       int                     id;
-
        struct clk              *parent;
        struct clk              **parent_table; /* list of parents to */
        unsigned short          parent_num;     /* choose between */
@@ -45,7 +51,9 @@ struct clk {
        unsigned long           arch_flags;
        void                    *priv;
        struct dentry           *dentry;
+       struct clk_mapping      *mapping;
        struct cpufreq_frequency_table *freq_table;
+       unsigned int            nr_freqs;
 };
 
 #define CLK_ENABLE_ON_INIT     (1 << 0)
@@ -111,6 +119,9 @@ int clk_rate_table_find(struct clk *clk,
                        struct cpufreq_frequency_table *freq_table,
                        unsigned long rate);
 
+long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
+                             unsigned int div_max, unsigned long rate);
+
 #define SH_CLK_MSTP32(_parent, _enable_reg, _enable_bit, _flags)       \
 {                                                                      \
        .parent         = _parent,                                      \
index 0d6cd38..b4f183a 100644 (file)
@@ -20,6 +20,12 @@ struct intc_group {
 
 #define INTC_GROUP(enum_id, ids...) { enum_id, { ids } }
 
+struct intc_subgroup {
+       unsigned long reg, reg_width;
+       intc_enum parent_id;
+       intc_enum enum_ids[32];
+};
+
 struct intc_mask_reg {
        unsigned long set_reg, clr_reg, reg_width;
        intc_enum enum_ids[32];
@@ -69,9 +75,12 @@ struct intc_hw_desc {
        unsigned int nr_sense_regs;
        struct intc_mask_reg *ack_regs;
        unsigned int nr_ack_regs;
+       struct intc_subgroup *subgroups;
+       unsigned int nr_subgroups;
 };
 
-#define _INTC_ARRAY(a) a, sizeof(a)/sizeof(*a)
+#define _INTC_ARRAY(a) a, a == NULL ? 0 : sizeof(a)/sizeof(*a)
+
 #define INTC_HW_DESC(vectors, groups, mask_regs,       \
                     prio_regs, sense_regs, ack_regs)   \
 {                                                      \
@@ -105,8 +114,11 @@ struct intc_desc symbol __initdata = {                                     \
                           prio_regs, sense_regs, ack_regs),            \
 }
 
-int __init register_intc_controller(struct intc_desc *desc);
+int register_intc_controller(struct intc_desc *desc);
+void reserve_intc_vectors(struct intc_vect *vectors, unsigned int nr_vecs);
 int intc_set_priority(unsigned int irq, unsigned int prio);
+int intc_irq_lookup(const char *chipname, intc_enum enum_id);
+void intc_finalize(void);
 
 #ifdef CONFIG_INTC_USERIMASK
 int register_intc_userimask(unsigned long addr);
index 07c08af..30cae70 100644 (file)
@@ -92,5 +92,6 @@ struct pinmux_info {
 };
 
 int register_pinmux(struct pinmux_info *pip);
+int unregister_pinmux(struct pinmux_info *pip);
 
 #endif /* __SH_PFC_H */
index a9c041d..9b201ec 100644 (file)
@@ -35,7 +35,7 @@ struct ir_scancode_table {
        unsigned int            len;    /* Used number of entries */
        unsigned int            alloc;  /* Size of *scan in bytes */
        u64                     ir_type;
-       char                    *name;
+       const char              *name;
        spinlock_t              lock;
 };
 
index 36170be..b0ccd0b 100644 (file)
@@ -127,6 +127,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
        sg_init_table(&sg, 1);
        sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
                    size, offset_in_page(buff));
+       sg_dma_len(&sg) = size;
        sg_dma_address(&sg) = buff;
 
        desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
@@ -176,6 +177,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
        sg_init_table(&sg, 1);
        sg_set_page(&sg, pfn_to_page(PFN_DOWN(buff)),
                    size, offset_in_page(buff));
+       sg_dma_len(&sg) = size;
        sg_dma_address(&sg) = buff;
 
        desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,